今回は、ラジオ局の登録、削除、変更を行う機能を追加します。今回の主な変更箇所は、
- ラジオ局の登録、削除、変更用に、”Entry”というボタンを追加。
- 選局用のプルダウンリストとボリュームの順序を変更
です。例によって前回から修正で説明します。
#include <Arduino.h>
#include <WiFi.h>
#include "AudioFileSourceICYStream.h"
#include "AudioFileSourceBuffer.h"
#include "AudioGeneratorMP3.h"
#include "AudioGeneratorAAC.h"
#include "AudioOutputI2S.h"
#include <WebServer.h>
#include <ESPmDNS.h>
#include "SPIFFS.h"
// Enter your WiFi setup here:
const char *SSID = "XXXXXX";
const char *PASSWORD = "YYYYYY";
AudioGenerator *decoder = NULL;
AudioFileSourceICYStream *file;
AudioFileSourceBuffer *buff;
AudioOutputI2S *out;
// Controll flg
static int8_t flg[10];
#define play 0
#define volume 1
#define total 2
#define now 3
WebServer server(80);
String index_Dt =
"<!DOCTYPE html>\n<html>\n<head>\n"
"<title>ESP32 WebRadio</title>\n</head>\n"
"<body>\n<center>\n<h2>ESP32 WebRadio</h2>\n"
"<form id='pull_list' method='get'>\n"
"<select name='5' id='pull_item' onchange='getItem()'>\n";
String index_Dt1 =
"</select><br><br>\n"
"</form>\n"
"<form id='cmd_vol' method='get'>\n"
"<input type='range' min='0' max='100' step='1' name='3' onchange='showValue()' id='s_value' value='50'>\n"
"<span id='p_value'>50</span><br>\n"
"</form><br><br>\n"
"<form method='get'>\n"
"<button type='submit' name='1' id='b_play' style='background:#90ee90'>PLAY</button>\n"
"<button type='submit' name='2' style='background:#90ee90'>STOP</button>\n"
"<button type='submit' name='4' id='b_mute' style='background:#90ee90'>MUTE</button><br><br>\n"
"<button type='submit' name='6' style='background:#90ee90'>Entry</button>\n"
"</form>\n"
"<script>\n"
"function showValue() {\n"
"target = document.getElementById('cmd_vol');\n"
"target.submit();\n}\n"
"function getItem() {\n"
"target = document.getElementById('pull_list');\n"
"target.submit();\n}\n";
void setup()
{
Serial.begin(115200);
delay(1000);
Serial.println("Connecting to WiFi");
WiFi.disconnect();
WiFi.softAPdisconnect(true);
WiFi.mode(WIFI_STA);
WiFi.begin(SSID, PASSWORD);
// Try forever
while (WiFi.status() != WL_CONNECTED) {
Serial.println("...Connecting to WiFi");
delay(1000);
}
Serial.println("Connected");
Serial.println(SSID);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (MDNS.begin("esp32")) {
Serial.println("MDNS responder started");
}
server.on("/", handleRoot);
server.begin();
Serial.println("HTTP server started");
out = new AudioOutputI2S();
//Initialize File System
SPIFFS.begin();
Serial.println("File System Initialized"); //Initialize File System
flg[play]=0;
flg[volume]=30;
flg[total]=6;
flg[now]=1;
out->SetGain((float)flg[volume]/100.0);
}
void loop()
{
if(flg[play])
{
if (decoder->isRunning()) {
if (!decoder->loop()) decoder->stop();
}
else {
Serial.print("decoder done\n");
StopPlaying();
delay(500);
radio_play(flg[now]);
}
}
server.handleClient();
}
void handleRoot()
{
String cmd;
int a,fl;
fl=1;
cmd=server.argName(0);
switch(cmd.toInt())
{
case 1: // Play
if(flg[play] == 0)
if(flg[total] != flg[now])
radio_play(flg[now]);
break;
case 2: // Stop
StopPlaying();
break;
case 3: // Volume
cmd=server.arg("3");
flg[volume]=cmd.toInt();
out->SetGain((float)flg[volume]/100.0);
break;
case 4: // Mute
flg[volume] *= -1;
a=flg[volume];
if(flg[volume] < 0) a=0;
out->SetGain(((float)a)/100.0);
break;
case 5: // List
cmd = server.arg("5");
flg[now] = cmd.toInt();
break;
case 6: // Entry Sheet
entry_sheet();
fl=0;
break;
case 7: //Edit(0) / ADD(1) / delete(2) OK
cmd = server.arg("7");
a=1;
if(flg[total] == flg[now])
if(cmd.charAt(0) != '1') a=0;
if(a) make_file(flg[now],cmd);
break;
}
if(fl) load_index();
else server.send(204, "text/plane","");
}
void load_index()
{
int a;
File dataFile;
String line,line1,stbuf;
//Pull Down List
flg[total] = 0;
a = flg[now];
dataFile = SPIFFS.open("/title.txt", FILE_READ);
stbuf="";
while(dataFile.available())
{
line = dataFile.readStringUntil('\n');
stbuf += "<option value='" + String(flg[total]+1) + "'";
a -= 1;
if(a) stbuf += ">";
else { stbuf += " selected>"; line1=line; }
if(line != "<--- end --->") stbuf = stbuf + String(flg[total]+1) + ": ";
stbuf = stbuf + line + "</option>\n";
flg[total] += 1;
}
dataFile.close();
stbuf = index_Dt + stbuf + index_Dt1;
stbuf += ("document.getElementById('s_value').value='" + String(abs((int)flg[volume])) + "'\n");
stbuf += ("document.getElementById('p_value').innerHTML='" + String(abs((int)flg[volume])) + "'\n");
if(flg[play])
stbuf += ("document.getElementById('b_play').style.backgroundColor='#ff6347'\n");
if(flg[volume] < 0)
stbuf += ("document.getElementById('b_mute').style.backgroundColor='#2020ff'\n");
stbuf += "</script>\n</center>\n</body>\n</html>";
server.send(200, "text/html",stbuf);
}
void radio_play(int no)
{
File l_file;
int a;
String link_data;
l_file = SPIFFS.open("/link_list.txt", FILE_READ);
for(a=0; a<no; a ++) link_data=l_file.readStringUntil('\n');
l_file.close();
file = new AudioFileSourceICYStream(link_data.substring(2).c_str());
buff = new AudioFileSourceBuffer(file, 2048*16);
if(link_data.charAt(0) == '1') decoder = (AudioGenerator*) new AudioGeneratorAAC();
else decoder = (AudioGenerator*) new AudioGeneratorMP3();
decoder->begin(buff, out);
flg[play]=1;
}
void StopPlaying()
{
if (decoder) { decoder->stop(); delete decoder; decoder = NULL; }
if (buff) { buff->close(); delete buff; buff = NULL; }
if (file) { file->close(); delete file; file = NULL; }
flg[play] = 0;
}
void entry_sheet()
{
File dataFile,dataFile1;
String line,line1,html_buf;
int a;
dataFile = SPIFFS.open("/entry.txt", FILE_READ);
html_buf="";
while(dataFile.available())
{
html_buf += dataFile.readStringUntil('\n');
html_buf += "\n";
}
dataFile.close();
dataFile = SPIFFS.open("/title.txt", FILE_READ);
dataFile1 = SPIFFS.open("/link_list.txt", FILE_READ);
for(a=0; a<flg[now]; a++)
{
line = dataFile.readStringUntil('\n');
line1 = dataFile1.readStringUntil('\n');
}
dataFile.close(); dataFile1.close();
html_buf += "document.getElementById('m_title').value='" + line + "';\n"
"document.getElementById('m_link').value='" + line1.substring(2) + "';\n"
"var mp_acc = document.getElementsByName( 'a2' ) ;\n";
if(line1.charAt(0) == '1') html_buf += "mp_acc[1].checked = true; \n";
html_buf += "</script>\n</body>\n</html>\n";
server.send(200, "text/html", html_buf);
}
void make_file(int no, String line)
{
File t,t1,l,l1;
String d_data,l_data,s_data[3];
int a,b;
s_data[0]=line.charAt(0);
b=2; a=2;
while(a)
{
while(line.charAt(b) != ',') b ++;
a --; b ++;
}
s_data[1]=line.substring(2,b-1);
s_data[2]=line.substring(b);
a = s_data[0].toInt();
t = SPIFFS.open("/title.txt",FILE_READ); t1 = SPIFFS.open("/title.tmp",FILE_WRITE);
l = SPIFFS.open("/link_list.txt",FILE_READ); l1 = SPIFFS.open("/link_list.tmp",FILE_WRITE);
while(t.available())
{
d_data = t.readStringUntil('\n'); l_data = l.readStringUntil('\n');
no --;
switch(a)
{
case 0: //Edit
if(no == 0)
{
t1.print(s_data[2] + "\n");
l1.print(s_data[1] + "\n");
}
else
{
t1.print(d_data + "\n");
l1.print(l_data + "\n");
}
break;
case 1: // Add
if(no == 0)
{
t1.print(s_data[2] + "\n");
l1.print(s_data[1] + "\n");
}
t1.print(d_data+"\n"); l1.print(l_data + "\n");
break;
case 2: // Delete
if(no != 0)
{
t1.print(d_data + "\n");
l1.print(l_data + "\n");
}
break;
}
}
t.close(); t1.close(); l.close(); l1.close();
SPIFFS.remove("/title.txt");
SPIFFS.remove("/link_list.txt");
SPIFFS.rename("/title.tmp","/title.txt");
SPIFFS.rename("/link_list.tmp","/link_list.txt");
if(s_data[0] == "1") flg[total] ++;
if(s_data[0] == "2") flg[total] --;
}
- 38行:String index_Dt1 =
- プルダウンリストの位置を変更した為。
- 162行: Entryボタンを押すと、ここが実行されます。
- 163行:entry_sheet(); 実際の処理を行う関数
- 167行:ここで選局関係のファイル、”title.txt”と”link_list.txt”の2つのファイルを書き換えます。
- 180から181行:以前は全ての処理後に基本の管理ページを表示していました。今回からラジオ局編集用の画面が追加されたので、両者を分けて表示する必要が有ります。ここで両者を切り替えています。
- 254から287行:編集用の画面を表示して値を入力を待ちます。
- 260から267行:編集画面用HTMLの大半は、”entry.txt”に保存されています。それの読み込み。以下で不足分を追加。
- 269から279行:現在選択されているタイトルとURLを表示
- 282行:MP3とAACの判別
- 286行:画面のHTMLをクライアントに送信
- 289から356行:ここで、”title.txt”と”link_list.txt”の2つファイルが編集されます。
このスケッチは、”entry.txt”,”title.txt”,”link_list.txt”の3つのファイルを使用します。スケッチの下に、”data”フォルダーを作りこれら3つのファイルを保存して下さい。
“entry.txt”
entry.txt<!DOCTYPE html>
<html>
<head>
<title>Internet Radio</title>
</head>
<body>
<center>
<h2>--- Entry Sheet ---</h2>
<form name="cmd">
<input type="radio" name="a1" value="e" checked> Edit
<input type="radio" name="a1" value="a" > Add
<input type="radio" name="a1" value="d" > Delete
</form>
<form name="add">
<br>Title
<input type="text" maxlength="50" id="m_title"
style="width:200px; overflow:auto; " /> <br>
URL
<input type="text" maxlength="250" id="m_link"
style="width:200px; overflow:auto; '"/>
</form>
<br>
<form name="M_A">
<input type="radio" name="a2" value="m" checked> MP3
<input type="radio" name="a2" value="c" > AAC
</form>
<br>
<form method="get">
<button type="submit" name="7" value="123" onclick="onButtonOk()" id="add_ok">OK</button>
<button type="submit" name="99" value="aaa" >Quit</button>
</form>
</center>
<script>
function onButtonOk() {
cmd="0,";
if(document.cmd.a1[1].checked) cmd="1,";
if(document.cmd.a1[2].checked) cmd="2,";
cmd1="0,";
if(document.M_A.a2[1].checked) cmd1="1,";
document.getElementById("add_ok").value =
cmd + cmd1 + document.getElementById("m_link").value + "," + document.getElementById("m_title").value;
}
”title.txt”
title.txtJazz Radio
CLASSIC
J-POP
SomaFM
antena
<--- end --->
“link_list.txt”
link.txt0,http://199.180.75.118:80/stream
0,http://144.217.49.251:80/stream1
0,http://158.69.38.195:20278/stream
0,http://ice1.somafm.com/secretagent-128-mp3
1,http://107.191.33.98:8232/stream/1
--- end ---
先ずはコンパイル。続いてアップロード。実行して下さい。ブラウザを上げて、”esp32.local”と入力すると、
このページのソースは
<!DOCTYPE html>
<html>
<head>
<title>ESP32 WebRadio</title>
</head>
<body>
<center>
<h2>ESP32 WebRadio</h2>
<form id='pull_list' method='get'>
<select name='5' id='pull_item' onchange='getItem()'>
<option value='1' selected>1: Jazz Radio</option>
<option value='2'>2: CLASSIC</option>
<option value='3'>3: J-POP</option>
<option value='4'>4: SomaFM</option>
<option value='5'>5: antena</option>
<option value='6'><--- end ---></option>
</select><br><br>
</form>
<form id='cmd_vol' method='get'>
<input type='range' min='0' max='100' step='1' name='3' onchange='showValue()' id='s_value' value='50'>
<span id='p_value'>50</span><br>
</form><br><br>
<form method='get'>
<button type='submit' name='1' id='b_play' style='background:#90ee90'>PLAY</button>
<button type='submit' name='2' style='background:#90ee90'>STOP</button>
<button type='submit' name='4' id='b_mute' style='background:#90ee90'>MUTE</button><br><br>
<button type='submit' name='6' style='background:#90ee90'>Entry</button>
</form>
<script>
function showValue() {
target = document.getElementById('cmd_vol');
target.submit();
}
function getItem() {
target = document.getElementById('pull_list');
target.submit();
}
document.getElementById('s_value').value='30'
document.getElementById('p_value').innerHTML='30'
</script>
</center>
</body>
</html>
ここで、”Entry”ボタンを押すと、編集画面が表示されます。
簡単な説明。
- ラジオ管理画面で選択したラジオ局に対して編集します。
- 上記の場合、”1”の局が選択されていたので、そのタイトルとURL、フォーマットが編集画面に表示されます。
- Edit
- 選択した局に対して変更します。
- Title、URLを入力。フォーマット(MP3かAAC)を選んで
- OKならOKボタン。編集をキャンセルするならQuitボタンを押す
- Add
- 現在選択されている局に上に追加されます。
- 例では、”1”の局が選択されているので、この局が新たに”1”となり、現在”1”の局は”2”となります。
- この追加方法ではリストの最後に新たに追加する事が出来まえん。そこで、ラジオのリストの最後に、”<−−− end −−−>を追加しています。リストの最後に新たに登録する場合、この項目を選んで追加します
- 必要項目を入力して、OKまたはQuitボタン
- Delete
- 選択されている局を削除します。
- OKを押せば削除。Quitでキャンセル。
このページのソースは
<!DOCTYPE html>
<html>
<head>
<title>Internet Radio</title>
</head>
<body>
<center>
<h2>--- Entry Sheet ---</h2>
<form name="cmd">
<input type="radio" name="a1" value="e" checked> Edit
<input type="radio" name="a1" value="a" > Add
<input type="radio" name="a1" value="d" > Delete
</form>
<form name="add">
<br>Title
<input type="text" maxlength="50" id="m_title"
style="width:200px; overflow:auto; " /> <br>
URL
<input type="text" maxlength="250" id="m_link"
style="width:200px; overflow:auto; '"/>
</form>
<br>
<form name="M_A">
<input type="radio" name="a2" value="m" checked> MP3
<input type="radio" name="a2" value="c" > AAC
</form>
<br>
<form method="get">
<button type="submit" name="7" value="123" onclick="onButtonOk()" id="add_ok">OK</button>
<button type="submit" name="99" value="aaa" >Quit</button>
</form>
</center>
<script>
function onButtonOk() {
cmd="0,";
if(document.cmd.a1[1].checked) cmd="1,";
if(document.cmd.a1[2].checked) cmd="2,";
cmd1="0,";
if(document.M_A.a2[1].checked) cmd1="1,";
document.getElementById("add_ok").value =
cmd + cmd1 + document.getElementById("m_link").value + "," + document.getElementById("m_title").value;
}
document.getElementById('m_title').value='Jazz Radio';
document.getElementById('m_link').value='http://199.180.75.118:80/stream';
var mp_acc = document.getElementsByName( 'a2' ) ;
</script>
</body>
</html>
これでラジオ局に変更、追加、削除が出来る様になりました。次回は電源オン時に前回の状態で再生を始める(リトーリーブ)機能を追加します。