From b574b4ab8d554304675e91a3cbf21238f2167680 Mon Sep 17 00:00:00 2001 From: e2002 Date: Mon, 29 Aug 2022 10:23:53 +0300 Subject: [PATCH] v0.7.490 --- README.md | 18 + yoRadio/audiohandlers.ino | 18 +- yoRadio/config.cpp | 10 +- yoRadio/config.h | 3 +- yoRadio/data/www/script.js.gz | Bin 5125 -> 5251 bytes yoRadio/data/www/settings.html | 1 + yoRadio/display.cpp | 4 +- yoRadio/netserver.cpp | 1005 ++++++++------------- yoRadio/netserver.h | 26 +- yoRadio/options.h | 2 +- yoRadio/player.cpp | 6 +- yoRadio/src/audioI2S/AudioEx.h | 6 +- yoRadio/src/audioVS1053/audioVS1053Ex.cpp | 8 +- yoRadio/src/audioVS1053/audioVS1053Ex.h | 6 +- yoRadio/src/displays/nextion.cpp | 2 +- 15 files changed, 435 insertions(+), 680 deletions(-) diff --git a/README.md b/README.md index f9f703b..b743641 100644 --- a/README.md +++ b/README.md @@ -317,6 +317,24 @@ Work is in progress... --- ## Version history +#### v0.7.490 +**!!! a [full update](#update-over-web-interface) with Sketch data upload is required. After updating please press CTRL+F5 in browser !!!** \ +**Please backup playlist.csv and wifi.csv before updating.** +- fixed playlist break down when saving it +- fixed bug with cropped song titles on single line displays (GC9106, ST7735mini, N5110 etc.) +- netserver - optimization and refactoring +- web interface optimization +- the AUDIOBUFFER_MULTIPLIER parameter is deprecated. New parameter AUDIOBUFFER_MULTIPLIER2. If everything works fine, then it is better not to touch it. +- new setting VS_PATCH_ENABLE (see PS) +- fixing other bugs + +_**PS:** A bug was found with the lack of sound on some (not all) green VS1053 boards. +If there is no sound, you need to assign in myoptions_ +``` +#define VS_PATCH_ENABLE false +``` +_On red boards and normally working green boards, nothing else needs to be done._ + #### v0.7.414 - fixed non latin long titles of songs error diff --git a/yoRadio/audiohandlers.ino b/yoRadio/audiohandlers.ino index 18139c4..74bff8e 100644 --- a/yoRadio/audiohandlers.ino +++ b/yoRadio/audiohandlers.ino @@ -15,7 +15,7 @@ void audio_info(const char *info) { player.mode = STOPPED; player.stopInfo(); } - if (strstr(info, "not supported") != NULL){ + if (strstr(info, "not supported") != NULL || strstr(info, "Account already in use") != NULL){ config.setTitle(info); netserver.requestOnChange(TITLE, 0); player.setOutputPins(false); @@ -47,20 +47,32 @@ bool printable(const char *info) { } void audio_showstation(const char *info) { + DBGVB("[%s] info = %s", __func__, info); if (strlen(info) > 0) { bool p = printable(info); - config.setTitle(p?info:"*****"); + config.setTitle(p?info:config.station.name); netserver.requestOnChange(TITLE, 0); } } void audio_showstreamtitle(const char *info) { + DBGVB("[%s] info = %s", __func__, info); + if (strstr(info, "Account already in use") != NULL){ + config.setTitle(info); + netserver.requestOnChange(TITLE, 0); + player.setOutputPins(false); + player.setDefaults(); + if (player_on_stop_play) player_on_stop_play(); + player.mode = STOPPED; + player.stopInfo(); + return; + } if (strlen(info) > 0) { bool p = printable(info); #ifdef DEBUG_TITLES config.setTitle(DEBUG_TITLES); #else - config.setTitle(p?info:"*****"); + config.setTitle(p?info:config.station.name); #endif netserver.requestOnChange(TITLE, 0); } diff --git a/yoRadio/config.cpp b/yoRadio/config.cpp index ea8ace8..74c8d60 100644 --- a/yoRadio/config.cpp +++ b/yoRadio/config.cpp @@ -443,7 +443,7 @@ bool Config::parseSsid(const char* line, char* ssid, char* pass) { return true; } -bool Config::saveWifi(const char* post) { +bool Config::saveWifiFromNextion(const char* post){ File file = SPIFFS.open(SSIDS_PATH, "w"); if (!file) { return false; @@ -455,6 +455,14 @@ bool Config::saveWifi(const char* post) { } } +bool Config::saveWifi() { + if (!SPIFFS.exists(TMP_PATH)) return false; + SPIFFS.remove(SSIDS_PATH); + SPIFFS.rename(TMP_PATH, SSIDS_PATH); + ESP.restart(); + return true; +} + bool Config::initNetwork() { File file = SPIFFS.open(SSIDS_PATH, "r"); if (!file || file.isDirectory()) { diff --git a/yoRadio/config.h b/yoRadio/config.h index 4c3e599..b046946 100644 --- a/yoRadio/config.h +++ b/yoRadio/config.h @@ -147,7 +147,8 @@ class Config { bool parseSsid(const char* line, char* ssid, char* pass); void loadStation(uint16_t station); bool initNetwork(); - bool saveWifi(const char* post); + bool saveWifi(); + bool saveWifiFromNextion(const char* post); void setSmartStart(byte ss); void initPlaylist(); void indexPlaylist(); diff --git a/yoRadio/data/www/script.js.gz b/yoRadio/data/www/script.js.gz index ba3ea9fc124084ca7dc3631bb07b5e11e6d8c15e..aa35f08668ac1d9c64896bbe98ff6f5ed6be0def 100644 GIT binary patch literal 5251 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 J&c_Z_001MY2EPCR literal 5125 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 diff --git a/yoRadio/data/www/settings.html b/yoRadio/data/www/settings.html index cbc32e1..2a381f3 100644 --- a/yoRadio/data/www/settings.html +++ b/yoRadio/data/www/settings.html @@ -177,6 +177,7 @@
+
Save & Reboot
diff --git a/yoRadio/display.cpp b/yoRadio/display.cpp index ef16f8b..5b0f940 100644 --- a/yoRadio/display.cpp +++ b/yoRadio/display.cpp @@ -580,7 +580,7 @@ char *split(char *str, const char *delim) { } void Display::title() { - DBGVB("call of %s(), config.station.title=%s", __func__, config.station.title); + DBGVB("[%s] config.station.title = %s", __func__, config.station.title); if (strlen(config.station.title) > 0) { char tmpbuf[strlen(config.station.title)+1]; strlcpy(tmpbuf, config.station.title, strlen(config.station.title)+1); @@ -589,7 +589,7 @@ void Display::title() { title1.setText(dsp.utf8Rus(tmpbuf, true)); title2.setText(dsp.utf8Rus(stitle, true)); }else{ - title1.setText(dsp.utf8Rus(tmpbuf, true)); + title1.setText(dsp.utf8Rus(config.station.title, true)); title2.setText(dsp.utf8Rus("", true)); } #ifdef USE_NEXTION diff --git a/yoRadio/netserver.cpp b/yoRadio/netserver.cpp index 9520921..8b38b18 100644 --- a/yoRadio/netserver.cpp +++ b/yoRadio/netserver.cpp @@ -25,123 +25,41 @@ AsyncUDP udp; String processor(const String& var); void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final); +void handleUpdate(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final); +void handleHTTPArgs(AsyncWebServerRequest * request); void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len); -void handleHTTPPost(AsyncWebServerRequest * request); bool shouldReboot = false; +#ifdef MQTT_HOST +Ticker mqttplaylistticker; +bool mqttplaylistblock = false; +void mqttplaylistSend() { + mqttplaylistblock = true; + mqttplaylistticker.detach(); + mqttPublishPlaylist(); + mqttplaylistblock = false; +} +#endif -char* updateError(){ +char* updateError() { static char ret[140] = {0}; sprintf(ret, "Update failed with error (%d)
%s", (int)Update.getError(), Update.errorString()); return ret; } -void NetServer::takeMallocDog(){ - int mcb = heap_caps_get_free_size(MALLOC_CAP_8BIT); - int mci = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); - (void)mci; - DBGVB("MALLOC_CAP_8BIT=%d, MALLOC_CAP_INTERNAL=%d", mcb, mci); - resumePlay = mcb < MIN_MALLOC; - if (resumePlay) { - player.toggle(); - vTaskDelay(150); - xSemaphoreTake(player.playmutex, portMAX_DELAY); - } -} - -void NetServer::giveMallocDog(){ - if (resumePlay) { - resumePlay = false; - vTaskDelay(150); - xSemaphoreGive(player.playmutex); - player.toggle(); - } -} - bool NetServer::begin() { - importRequest = false; + importRequest = IMDONE; irRecordEnable = false; - webserver.on("/", HTTP_GET, [](AsyncWebServerRequest * request) { - if (network.status == CONNECTED) { - netserver.htmlPath = PINDEX; - netserver.chunkedHtmlPage(String(), request); - }else{ - netserver.htmlPath = PSETTINGS; - netserver.chunkedHtmlPage(String(), request); - } - }); - + webserver.on("/", HTTP_ANY, handleHTTPArgs); + webserver.on(PLAYLIST_PATH, HTTP_GET, handleHTTPArgs); + webserver.on(INDEX_PATH, HTTP_GET, handleHTTPArgs); + webserver.on(SSIDS_PATH, HTTP_GET, handleHTTPArgs); + webserver.on("/upload", HTTP_POST, beginUpload, handleUpload); + webserver.on("/update", HTTP_GET, handleHTTPArgs); + webserver.on("/update", HTTP_POST, beginUpdate, handleUpdate); + webserver.on("/settings", HTTP_GET, handleHTTPArgs); + if (IR_PIN != 255) webserver.on("/ir", HTTP_GET, handleHTTPArgs); webserver.serveStatic("/", SPIFFS, "/www/").setCacheControl("max-age=31536000"); - - webserver.on("/", HTTP_POST, [](AsyncWebServerRequest * request) { - handleHTTPPost(request); - }); - webserver.on(PLAYLIST_PATH, HTTP_GET, [](AsyncWebServerRequest * request) { - netserver.takeMallocDog(); - request->send(SPIFFS, PLAYLIST_PATH, "application/octet-stream"); - netserver.giveMallocDog(); - DBGVB("PLAYLIST_PATH client ip=%s", request->client()->remoteIP().toString().c_str()); - /*netserver.htmlPath = PPLAYLIST; // TODO - netserver.chunkedHtmlPage("application/octet-stream", request); - netserver.giveMallocDog();*/ - }); - webserver.on(INDEX_PATH, HTTP_GET, [](AsyncWebServerRequest * request) { - request->send(SPIFFS, INDEX_PATH, "application/octet-stream"); - }); - webserver.on(SSIDS_PATH, HTTP_GET, [](AsyncWebServerRequest * request) { - netserver.htmlPath = PSSIDS; - netserver.chunkedHtmlPage("application/octet-stream", request); - }); - webserver.on("/upload", HTTP_POST, [](AsyncWebServerRequest * request) { - //request->send(200); - - }, handleUpload); - webserver.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){ - netserver.htmlPath = PUPDATE; - netserver.chunkedHtmlPage(String(), request); - }); - webserver.on("/settings", HTTP_GET, [](AsyncWebServerRequest *request){ - netserver.htmlPath = PSETTINGS; - netserver.chunkedHtmlPage(String(), request); - }); - -#if IR_PIN!=255 - webserver.on("/ir", HTTP_GET, [](AsyncWebServerRequest *request){ - netserver.htmlPath = PIR; - netserver.chunkedHtmlPage(String(), request); - }); -#endif - webserver.on("/update", HTTP_POST, [](AsyncWebServerRequest *request){ - shouldReboot = !Update.hasError(); - AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", shouldReboot?"OK": updateError()); - response->addHeader("Connection", "close"); - request->send(response); - },[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ - if(!index){ - int target = (request->getParam("updatetarget", true)->value() == "spiffs") ? U_SPIFFS : U_FLASH; - Serial.printf("Update Start: %s\n", filename.c_str()); - player.mode = STOPPED; - display.putRequest({NEWMODE, UPDATING}); - if(!Update.begin(UPDATE_SIZE_UNKNOWN, target)){ - Update.printError(Serial); - request->send(200, "text/html", updateError()); - } - } - if(!Update.hasError()){ - if(Update.write(data, len) != len){ - Update.printError(Serial); - request->send(200, "text/html", updateError()); - } - } - if(final){ - if(Update.end(true)){ - Serial.printf("Update Success: %uB\n", index+len); - } else { - Update.printError(Serial); - request->send(200, "text/html", updateError()); - } - } - }); #ifdef CORS_DEBUG DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), F("*")); DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), F("content-type")); @@ -160,504 +78,439 @@ bool NetServer::begin() { return true; } -void NetServer::chunkedHtmlPage(const String& contentType, AsyncWebServerRequest *request){ - max = heap_caps_get_free_size(MALLOC_CAP_8BIT) / 32; - htmlpos = 0; - theend = false; - DBGVB("chunkedHtmlPage client ip=%s", request->client()->remoteIP().toString().c_str()); - AsyncWebServerResponse *response = request->beginChunkedResponse(contentType, [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { - if(netserver.theend) return 0; - File htmlpage; - switch(netserver.htmlPath){ - case PINDEX: { - htmlpage = SPIFFS.open("/www/index.html", "r"); - break; - } - case PSETTINGS: { - htmlpage = SPIFFS.open("/www/settings.html", "r"); - break; - } - case PUPDATE: { - htmlpage = SPIFFS.open("/www/update.html", "r"); - break; - } - case PIR: { - htmlpage = SPIFFS.open("/www/ir.html", "r"); - break; - } - case PPLAYLIST: { - htmlpage = SPIFFS.open(PLAYLIST_PATH, "r"); - DBGVB("SPIFFS.open(PLAYLIST_PATH)"); - break; - } - case PSSIDS: { - htmlpage = SPIFFS.open(SSIDS_PATH, "r"); - break; - } - default: { - return 0; - break; - } - } - if(!htmlpage) return 0; - uint32_t htmlpagesize = htmlpage.size(); - uint32_t len = htmlpagesize - netserver.htmlpos; - if (len > maxLen) len = maxLen; - if (len > netserver.max) len = netserver.max; - if (len + netserver.htmlpos > htmlpagesize) { - netserver.theend = true; - len = htmlpagesize - netserver.htmlpos; - } - if (len > 0) { - DBGVB("seek to %d in %s and read %d bytes", netserver.htmlpos, htmlpage.name(), len); - htmlpage.seek(netserver.htmlpos, SeekSet); - htmlpage.read(buffer, len); - netserver.htmlpos = netserver.htmlpos + len; - } - if(htmlpage) htmlpage.close(); - return len; - }, processor); // AsyncWebServerResponse +void NetServer::beginUpdate(AsyncWebServerRequest *request) { + shouldReboot = !Update.hasError(); + AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", shouldReboot ? "OK" : updateError()); + response->addHeader("Connection", "close"); request->send(response); } +void handleUpdate(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { + if (!index) { + int target = (request->getParam("updatetarget", true)->value() == "spiffs") ? U_SPIFFS : U_FLASH; + Serial.printf("Update Start: %s\n", filename.c_str()); + player.mode = STOPPED; + display.putRequest({NEWMODE, UPDATING}); + if (!Update.begin(UPDATE_SIZE_UNKNOWN, target)) { + Update.printError(Serial); + request->send(200, "text/html", updateError()); + } + } + if (!Update.hasError()) { + if (Update.write(data, len) != len) { + Update.printError(Serial); + request->send(200, "text/html", updateError()); + } + } + if (final) { + if (Update.end(true)) { + Serial.printf("Update Success: %uB\n", index + len); + } else { + Update.printError(Serial); + request->send(200, "text/html", updateError()); + } + } +} + +void NetServer::beginUpload(AsyncWebServerRequest *request) { + if (request->hasParam("plfile", true, true)) { + netserver.importRequest = IMPL; + request->send(200); + } else if (request->hasParam("wifile", true, true)) { + netserver.importRequest = IMWIFI; + request->send(200); + } else { + request->send(404); + } +} + +size_t NetServer::chunkedHtmlPageCallback(uint8_t* buffer, size_t maxLen, size_t index){ + File requiredfile = SPIFFS.open(netserver.chunkedPathBuffer, "r"); + if (!requiredfile) return 0; + size_t filesize = requiredfile.size(); + size_t needread = filesize - index; + if (!needread) return 0; + size_t canread = (needread > maxLen) ? maxLen : needread; + DBGVB("[%s] seek to %d in %s and read %d bytes with maxLen=%d", __func__, index, netserver.chunkedPathBuffer, canread, maxLen); + requiredfile.seek(index, SeekSet); + requiredfile.read(buffer, canread); + index += canread; + if (requiredfile) requiredfile.close(); + return canread; +} + +void NetServer::chunkedHtmlPage(const String& contentType, AsyncWebServerRequest *request, const char * path, bool gzip) { + memset(chunkedPathBuffer, 0, sizeof(chunkedPathBuffer)); + strlcpy(chunkedPathBuffer, path, sizeof(chunkedPathBuffer)-1); + PLOW(); + AsyncWebServerResponse *response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback, processor); + xSemaphoreTake(player.playmutex, portMAX_DELAY); + request->send(response); + xSemaphoreGive(player.playmutex); PHIG(); +} +/* +void NetServer::chunkedHtmlPage(const String& contentType, AsyncWebServerRequest *request, const char * path, bool gzip) { + static char pathbuffer[40] = { 0 }; + strlcpy(pathbuffer, path, 39); + PLOW(); + AsyncWebServerResponse *response = request->beginChunkedResponse(contentType, [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { + File requiredfile = SPIFFS.open(pathbuffer, "r"); + if (!requiredfile) return 0; + size_t filesize = requiredfile.size(); + size_t needread = filesize - index; + if (!needread) return 0; + size_t canread = (needread > maxLen) ? maxLen : needread; + DBGVB("[%s] seek to %d in %s and read %d bytes with maxLen=%d", __func__, index, pathbuffer, canread, maxLen); + requiredfile.seek(index, SeekSet); + requiredfile.read(buffer, canread); + index += canread; + if (requiredfile) requiredfile.close(); + return canread; + }, processor); // AsyncWebServerResponse + + xSemaphoreTake(player.playmutex, portMAX_DELAY); + request->send(response); + xSemaphoreGive(player.playmutex); + PHIG(); +} + */ void NetServer::loop() { - if(shouldReboot){ + if (shouldReboot) { Serial.println("Rebooting..."); delay(100); ESP.restart(); } websocket.cleanupClients(); - if (playlistrequest > 0) { - requestOnChange(PLAYLIST, playlistrequest); - playlistrequest = 0; - } - if (importRequest) { - if (importPlaylist()) { - requestOnChange(PLAYLIST, 0); - } - importRequest = false; - } - if (rssi < 255) { - requestOnChange(NRSSI, 0); + //if (playlistrequest > 0) { requestOnChange(PLAYLIST, playlistrequest); playlistrequest = 0; } /* Cleanup this */ + switch (importRequest) { + case IMPL: importPlaylist(); importRequest = IMDONE; break; + case IMWIFI: config.saveWifi(); importRequest = IMDONE; break; + default: break; } + if (rssi < 255) requestOnChange(NRSSI, 0); } + #if IR_PIN!=255 void NetServer::irToWs(const char* protocol, uint64_t irvalue) { char buf[BUFLEN] = { 0 }; sprintf (buf, "{\"ircode\": %llu, \"protocol\": \"%s\"}", irvalue, protocol); websocket.textAll(buf); } -void NetServer::irValsToWs(){ - if(!irRecordEnable) return; +void NetServer::irValsToWs() { + if (!irRecordEnable) return; char buf[BUFLEN] = { 0 }; sprintf (buf, "{\"irvals\": [%llu, %llu, %llu]}", config.ircodes.irVals[config.irindex][0], config.ircodes.irVals[config.irindex][1], config.ircodes.irVals[config.irindex][2]); websocket.textAll(buf); } #endif + void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t clientId) { AwsFrameInfo *info = (AwsFrameInfo*)arg; if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) { data[len] = 0; char cmd[65], val[65]; if (config.parseWsCommand((const char*)data, cmd, val, 65)) { - if (strcmp(cmd, "getmode") == 0) { - requestOnChange(GETMODE,clientId); - return; - } - if (strcmp(cmd, "getindex") == 0) { - requestOnChange(GETINDEX,clientId); - return; - } - if (strcmp(cmd, "getsystem") == 0) { - requestOnChange(GETSYSTEM,clientId); - return; - } - if (strcmp(cmd, "getscreen") == 0) { - requestOnChange(GETSCREEN,clientId); - return; - } - if (strcmp(cmd, "gettimezone") == 0) { - requestOnChange(GETTIMEZONE,clientId); - return; - } - if (strcmp(cmd, "getcontrols") == 0) { - requestOnChange(GETCONTROLS,clientId); - return; - } - if (strcmp(cmd, "getweather") == 0) { - requestOnChange(GETWEATHER,clientId); - return; - } - if (strcmp(cmd, "getactive") == 0) { - requestOnChange(GETACTIVE,clientId); - return; - } - + if (strcmp(cmd, "getmode") == 0 ) { requestOnChange(GETMODE, clientId); return; } + if (strcmp(cmd, "getindex") == 0 ) { requestOnChange(GETINDEX, clientId); return; } + if (strcmp(cmd, "getsystem") == 0 ) { requestOnChange(GETSYSTEM, clientId); return; } + if (strcmp(cmd, "getscreen") == 0 ) { requestOnChange(GETSCREEN, clientId); return; } + if (strcmp(cmd, "gettimezone") == 0 ) { requestOnChange(GETTIMEZONE, clientId); return; } + if (strcmp(cmd, "getcontrols") == 0 ) { requestOnChange(GETCONTROLS, clientId); return; } + if (strcmp(cmd, "getweather") == 0 ) { requestOnChange(GETWEATHER, clientId); return; } + if (strcmp(cmd, "getactive") == 0 ) { requestOnChange(GETACTIVE, clientId); return; } if (strcmp(cmd, "smartstart") == 0) { - byte valb=atoi(val); - config.store.smartstart=valb==1?1:2; - if(!player.isRunning() && config.store.smartstart==1) config.store.smartstart=0; + byte valb = atoi(val); + config.store.smartstart = valb == 1 ? 1 : 2; + if (!player.isRunning() && config.store.smartstart == 1) config.store.smartstart = 0; config.save(); return; } if (strcmp(cmd, "audioinfo") == 0) { - byte valb=atoi(val); - config.store.audioinfo=valb; + byte valb = atoi(val); + config.store.audioinfo = valb; config.save(); - display.putRequest({NEWMODE, CLEAR}); - display.putRequest({NEWMODE, PLAYER}); + display.putRequest({NEWMODE, CLEAR}); display.putRequest({NEWMODE, PLAYER}); return; } if (strcmp(cmd, "vumeter") == 0) { - byte valb=atoi(val); - config.store.vumeter=valb; + byte valb = atoi(val); + config.store.vumeter = valb; config.save(); - display.putRequest({NEWMODE, CLEAR}); - display.putRequest({NEWMODE, PLAYER}); + display.putRequest({NEWMODE, CLEAR}); display.putRequest({NEWMODE, PLAYER}); return; } if (strcmp(cmd, "softap") == 0) { - byte valb=atoi(val); - config.store.softapdelay=valb; + byte valb = atoi(val); + config.store.softapdelay = valb; config.save(); return; } if (strcmp(cmd, "invertdisplay") == 0) { - byte valb=atoi(val); - config.store.invertdisplay=valb; + byte valb = atoi(val); + config.store.invertdisplay = valb; config.save(); display.invert(); return; } if (strcmp(cmd, "numplaylist") == 0) { - byte valb=atoi(val); - config.store.numplaylist=valb; + byte valb = atoi(val); + config.store.numplaylist = valb; config.save(); - display.putRequest({NEWMODE, CLEAR}); - display.putRequest({NEWMODE, PLAYER}); + display.putRequest({NEWMODE, CLEAR}); display.putRequest({NEWMODE, PLAYER}); return; } - if (strcmp(cmd, "fliptouch") == 0) { - byte valb=atoi(val); - config.store.fliptouch=valb==1; + byte valb = atoi(val); + config.store.fliptouch = valb == 1; config.save(); flipTS(); return; } if (strcmp(cmd, "dbgtouch") == 0) { - byte valb=atoi(val); - config.store.dbgtouch=valb==1; + byte valb = atoi(val); + config.store.dbgtouch = valb == 1; config.save(); return; } if (strcmp(cmd, "flipscreen") == 0) { - byte valb=atoi(val); - config.store.flipscreen=valb; + byte valb = atoi(val); + config.store.flipscreen = valb; config.save(); display.flip(); - display.putRequest({NEWMODE, CLEAR}); - display.putRequest({NEWMODE, PLAYER}); + display.putRequest({NEWMODE, CLEAR}); display.putRequest({NEWMODE, PLAYER}); return; } if (strcmp(cmd, "brightness") == 0) { - byte valb=atoi(val); - if(!config.store.dspon) requestOnChange(DSPON, 0); - config.store.brightness=valb; - //display.setContrast(); + byte valb = atoi(val); + if (!config.store.dspon) requestOnChange(DSPON, 0); + config.store.brightness = valb; config.setBrightness(true); return; } if (strcmp(cmd, "screenon") == 0) { - byte valb=atoi(val); - //config.store.dspon=valb==1; - //config.setBrightness(true); - config.setDspOn(valb==1); + byte valb = atoi(val); + config.setDspOn(valb == 1); return; } if (strcmp(cmd, "contrast") == 0) { - byte valb=atoi(val); - config.store.contrast=valb; + byte valb = atoi(val); + config.store.contrast = valb; config.save(); display.setContrast(); return; } if (strcmp(cmd, "tzh") == 0) { - int vali=atoi(val); - config.store.tzHour=vali; + int vali = atoi(val); + config.store.tzHour = vali; return; } if (strcmp(cmd, "tzm") == 0) { - int vali=atoi(val); - config.store.tzMin=vali; + int vali = atoi(val); + config.store.tzMin = vali; return; } if (strcmp(cmd, "sntp2") == 0) { - strlcpy(config.store.sntp2,val, 35); + strlcpy(config.store.sntp2, val, 35); return; } if (strcmp(cmd, "sntp1") == 0) { - strlcpy(config.store.sntp1,val, 35); - bool tzdone=false; - if(strlen(config.store.sntp1)>0 && strlen(config.store.sntp2)>0){ + strlcpy(config.store.sntp1, val, 35); + bool tzdone = false; + if (strlen(config.store.sntp1) > 0 && strlen(config.store.sntp2) > 0) { configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2); - tzdone=true; - }else if(strlen(config.store.sntp1)>0){ + tzdone = true; + } else if (strlen(config.store.sntp1) > 0) { configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1); - tzdone=true; + tzdone = true; } - if(tzdone){ + if (tzdone) { network.requestTimeSync(true); config.save(); } return; } - if (strcmp(cmd, "volsteps") == 0) { - uint8_t valb=atoi(val); - config.store.volsteps=valb; + uint8_t valb = atoi(val); + config.store.volsteps = valb; config.save(); return; } if (strcmp(cmd, "encacceleration") == 0) { - uint16_t valb=atoi(val); + uint16_t valb = atoi(val); setEncAcceleration(valb); - config.store.encacc=valb; + config.store.encacc = valb; config.save(); return; } if (strcmp(cmd, "irtlp") == 0) { - uint8_t valb=atoi(val); + uint8_t valb = atoi(val); setIRTolerance(valb); return; } if (strcmp(cmd, "showweather") == 0) { - uint8_t valb=atoi(val); - config.store.showweather=valb==1; + uint8_t valb = atoi(val); + config.store.showweather = valb == 1; config.save(); display.showWeather(); #ifdef USE_NEXTION nextion.startWeather(); #endif - display.putRequest({NEWMODE, CLEAR}); - display.putRequest({NEWMODE, PLAYER}); + display.putRequest({NEWMODE, CLEAR}); display.putRequest({NEWMODE, PLAYER}); return; } if (strcmp(cmd, "lat") == 0) { - strlcpy(config.store.weatherlat,val, 10); + strlcpy(config.store.weatherlat, val, 10); return; } if (strcmp(cmd, "lon") == 0) { - strlcpy(config.store.weatherlon,val, 10); + strlcpy(config.store.weatherlon, val, 10); return; } if (strcmp(cmd, "key") == 0) { - strlcpy(config.store.weatherkey,val, 64); + strlcpy(config.store.weatherkey, val, 64); config.save(); display.showWeather(); #ifdef USE_NEXTION nextion.startWeather(); #endif - display.putRequest({NEWMODE, CLEAR}); - display.putRequest({NEWMODE, PLAYER}); + display.putRequest({NEWMODE, CLEAR}); display.putRequest({NEWMODE, PLAYER}); return; } /* RESETS */ if (strcmp(cmd, "reset") == 0) { if (strcmp(val, "system") == 0) { - config.store.smartstart=2; - config.store.audioinfo=false; - config.store.vumeter=false; - config.store.softapdelay=0; + config.store.smartstart = 2; + config.store.audioinfo = false; + config.store.vumeter = false; + config.store.softapdelay = 0; config.save(); - display.putRequest({NEWMODE, CLEAR}); - display.putRequest({NEWMODE, PLAYER}); - requestOnChange(GETSYSTEM,clientId); + display.putRequest({NEWMODE, CLEAR}); display.putRequest({NEWMODE, PLAYER}); + requestOnChange(GETSYSTEM, clientId); return; } if (strcmp(val, "screen") == 0) { - config.store.flipscreen=false; + config.store.flipscreen = false; display.flip(); - config.store.invertdisplay=false; + config.store.invertdisplay = false; display.invert(); - config.store.dspon=true; - config.store.brightness=100; + config.store.dspon = true; + config.store.brightness = 100; config.setBrightness(false); - config.store.contrast=55; + config.store.contrast = 55; display.setContrast(); - config.store.numplaylist=false; + config.store.numplaylist = false; config.save(); - display.putRequest({NEWMODE, CLEAR}); - display.putRequest({NEWMODE, PLAYER}); - requestOnChange(GETSCREEN,clientId); + display.putRequest({NEWMODE, CLEAR}); display.putRequest({NEWMODE, PLAYER}); + requestOnChange(GETSCREEN, clientId); return; } if (strcmp(val, "timezone") == 0) { - config.store.tzHour=3; - config.store.tzMin=0; - strlcpy(config.store.sntp1,"pool.ntp.org", 35); - strlcpy(config.store.sntp2,"0.ru.pool.ntp.org", 35); + config.store.tzHour = 3; + config.store.tzMin = 0; + strlcpy(config.store.sntp1, "pool.ntp.org", 35); + strlcpy(config.store.sntp2, "0.ru.pool.ntp.org", 35); config.save(); configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2); network.requestTimeSync(true); - requestOnChange(GETTIMEZONE,clientId); + requestOnChange(GETTIMEZONE, clientId); return; } if (strcmp(val, "weather") == 0) { - config.store.showweather=0; - strlcpy(config.store.weatherlat,"55.7512", 10); - strlcpy(config.store.weatherlon,"37.6184", 10); - strlcpy(config.store.weatherkey,"", 64); + config.store.showweather = 0; + strlcpy(config.store.weatherlat, "55.7512", 10); + strlcpy(config.store.weatherlon, "37.6184", 10); + strlcpy(config.store.weatherkey, "", 64); config.save(); display.showWeather(); #ifdef USE_NEXTION nextion.startWeather(); #endif - display.putRequest({NEWMODE, CLEAR}); - display.putRequest({NEWMODE, PLAYER}); - requestOnChange(GETWEATHER,clientId); + display.putRequest({NEWMODE, CLEAR}); display.putRequest({NEWMODE, PLAYER}); + requestOnChange(GETWEATHER, clientId); return; } if (strcmp(val, "controls") == 0) { - config.store.volsteps=1; - config.store.fliptouch=false; - config.store.dbgtouch=false; + config.store.volsteps = 1; + config.store.fliptouch = false; + config.store.dbgtouch = false; setEncAcceleration(200); setIRTolerance(40); - requestOnChange(GETCONTROLS,clientId); + requestOnChange(GETCONTROLS, clientId); return; } - } /* RESETS */ + } /* EOF RESETS */ if (strcmp(cmd, "volume") == 0) { byte v = atoi(val); player.setVol(v, false); } - - /* REMOVE FROM POST - * if (request->hasParam("trebble", true)) { - AsyncWebParameter* pt = request->getParam("trebble", true); - AsyncWebParameter* pm = request->getParam("middle", true); - AsyncWebParameter* pb = request->getParam("bass", true); - int t = atoi(pt->value().c_str()); - int m = atoi(pm->value().c_str()); - int b = atoi(pb->value().c_str()); - //setTone(int8_t gainLowPass, int8_t gainBandPass, int8_t gainHighPass) - player.setTone(b, m, t); - config.setTone(b, m, t); - netserver.requestOnChange(EQUALIZER, 0); - request->send(200); - return; - } - if (request->hasParam("ballance", true)) { - AsyncWebParameter* p = request->getParam("ballance", true); - int b = atoi(p->value().c_str()); - player.setBalance(b); - config.setBalance(b); - netserver.requestOnChange(BALANCE, 0); - request->send(200); - return; - } - */ if (strcmp(cmd, "balance") == 0) { - int8_t valb=atoi(val); + int8_t valb = atoi(val); player.setBalance(valb); config.setBalance(valb); netserver.requestOnChange(BALANCE, 0); return; } if (strcmp(cmd, "treble") == 0) { - int8_t valb=atoi(val); + int8_t valb = atoi(val); player.setTone(config.store.bass, config.store.middle, valb); config.setTone(config.store.bass, config.store.middle, valb); netserver.requestOnChange(EQUALIZER, 0); return; } if (strcmp(cmd, "middle") == 0) { - int8_t valb=atoi(val); + int8_t valb = atoi(val); player.setTone(config.store.bass, valb, config.store.trebble); config.setTone(config.store.bass, valb, config.store.trebble); netserver.requestOnChange(EQUALIZER, 0); return; } if (strcmp(cmd, "bass") == 0) { - int8_t valb=atoi(val); + int8_t valb = atoi(val); player.setTone(valb, config.store.middle, config.store.trebble); config.setTone(valb, config.store.middle, config.store.trebble); netserver.requestOnChange(EQUALIZER, 0); return; } if (strcmp(cmd, "submitplaylist") == 0) { - if(player.isRunning()){ - player.toggle(); - while (player.isRunning()) { - vTaskDelay(10); - } - vTaskDelay(50); - resumePlay=true; - } + // xSemaphoreTake(player.playmutex, portMAX_DELAY); return; } if (strcmp(cmd, "submitplaylistdone") == 0) { - if(resumePlay){ - vTaskDelay(100); - player.toggle(); - resumePlay=false; - } #ifdef MQTT_HOST - mqttPublishPlaylist(); + //mqttPublishPlaylist(); + mqttplaylistticker.attach(5, mqttplaylistSend); #endif + // xSemaphoreGive(player.playmutex); + if (player.isRunning()) { + player.request.station = config.store.lastStation; + player.request.doSave = false; + } return; } #if IR_PIN!=255 if (strcmp(cmd, "irbtn") == 0) { - config.irindex=atoi(val); - irRecordEnable=(config.irindex>=0); - config.irchck=0; + config.irindex = atoi(val); + irRecordEnable = (config.irindex >= 0); + config.irchck = 0; irValsToWs(); - if(config.irindex<0) config.saveIR(); + if (config.irindex < 0) config.saveIR(); } if (strcmp(cmd, "chkid") == 0) { - config.irchck=atoi(val); + config.irchck = atoi(val); } if (strcmp(cmd, "irclr") == 0) { byte cl = atoi(val); - config.ircodes.irVals[config.irindex][cl]=0; + config.ircodes.irVals[config.irindex][cl] = 0; } #endif } } } -void NetServer::setRSSI(int val) { - rssi = val; - //requestOnChange(NRSSI, 0); -} - void NetServer::getPlaylist(uint8_t clientId) { char buf[160] = {0}; sprintf(buf, "{\"file\": \"http://%s%s\"}", WiFi.localIP().toString().c_str(), PLAYLIST_PATH); - if (clientId == 0) { - websocket.textAll(buf); - } else { - websocket.text(clientId, buf); - } - if (resumePlay) { - resumePlay = false; - player.toggle(); - } -} - -bool NetServer::savePlaylist(const char* post) { - File file = SPIFFS.open(PLAYLIST_PATH, "w"); - if (!file) { - return false; - } else { - file.print(post); - file.close(); - vTaskDelay(150); - netserver.requestOnChange(PLAYLISTSAVED, 0); - return true; - } + if (clientId == 0) { websocket.textAll(buf); } else { websocket.text(clientId, buf); } } bool NetServer::importPlaylist() { @@ -708,180 +561,71 @@ bool NetServer::importPlaylist() { void NetServer::requestOnChange(requestType_e request, uint8_t clientId) { char buf[BUFLEN * 2] = { 0 }; switch (request) { - case PLAYLIST: { - getPlaylist(clientId); - break; - } - case PLAYLISTSAVED: { - config.indexPlaylist(); - config.initPlaylist(); - getPlaylist(clientId); -/*#ifdef MQTT_HOST - mqttPublishPlaylist(); -#endif*/ - break; - } + case PLAYLIST: getPlaylist(clientId); break; + case PLAYLISTSAVED: config.indexPlaylist(); config.initPlaylist(); getPlaylist(clientId); break; case GETACTIVE: { bool dbgact = false; - String act="\"group_wifi\","; + String act = "\"group_wifi\","; if (network.status == CONNECTED) { - act+="\"group_system\","; - if(BRIGHTNESS_PIN!=255 || DSP_FLIPPED==1 || DSP_MODEL==DSP_NOKIA5110 || dbgact){ - act+="\"group_display\","; - } + act += "\"group_system\","; + if (BRIGHTNESS_PIN != 255 || DSP_FLIPPED == 1 || DSP_MODEL == DSP_NOKIA5110 || dbgact) act += "\"group_display\","; #ifdef USE_NEXTION - act+="\"group_nextion\","; - if (WEATHER_READY==0 || dbgact){ - act+="\"group_weather\","; - } + act += "\"group_nextion\","; + if (WEATHER_READY == 0 || dbgact) act += "\"group_weather\","; #endif #if defined(LCD_I2C) || DSP_OLED - act+="\"group_oled\","; + act += "\"group_oled\","; #endif - if(VU_READY==1 || dbgact){ - act+="\"group_vu\","; - } - if(BRIGHTNESS_PIN!=255 || dbgact){ - act+="\"group_brightness\","; - } - if(DSP_FLIPPED==1 || dbgact){ - act+="\"group_tft\","; - } - if(TS_CS!=255 || dbgact){ - act+="\"group_touch\","; - } - if(DSP_MODEL==DSP_NOKIA5110){ - act+="\"group_nokia\","; - } - if(DSP_MODEL!=DSP_DUMMY || dbgact){ - act+="\"group_timezone\","; - - } - if (WEATHER_READY==1 || dbgact){ - act+="\"group_weather\","; - } - act+="\"group_controls\","; - if(ENC_BTNL!=255 || ENC2_BTNL!=255 || dbgact){ - act+="\"group_encoder\","; - } - if(IR_PIN!=255 || dbgact){ - act+="\"group_ir\","; - } + if (VU_READY == 1 || dbgact) act += "\"group_vu\","; + if (BRIGHTNESS_PIN != 255 || dbgact) act += "\"group_brightness\","; + if (DSP_FLIPPED == 1 || dbgact) act += "\"group_tft\","; + if (TS_CS != 255 || dbgact) act += "\"group_touch\","; + if (DSP_MODEL == DSP_NOKIA5110) act += "\"group_nokia\","; + if (DSP_MODEL != DSP_DUMMY || dbgact) act += "\"group_timezone\","; + if (WEATHER_READY == 1 || dbgact) act += "\"group_weather\","; + act += "\"group_controls\","; + if (ENC_BTNL != 255 || ENC2_BTNL != 255 || dbgact) act += "\"group_encoder\","; + if (IR_PIN != 255 || dbgact) act += "\"group_ir\","; } - act = act.substring(0, act.length()-1); + act = act.substring(0, act.length() - 1); sprintf (buf, "{\"act\":[%s]}", act.c_str()); break; - } - case GETMODE: { - sprintf (buf, "{\"pmode\":\"%s\"}", network.status == CONNECTED?"player":"ap"); - break; - } - case GETINDEX: { - requestOnChange(STATION, clientId); - requestOnChange(TITLE, clientId); - requestOnChange(VOLUME, clientId); - requestOnChange(EQUALIZER, clientId); - requestOnChange(BALANCE, clientId); - requestOnChange(BITRATE, clientId); - requestOnChange(MODE, clientId); - //playlistrequest = clientId; /* Cleanup this */ - return; - break; - } - case GETSYSTEM: { - sprintf (buf, "{\"sst\":%d,\"aif\":%d,\"vu\":%d,\"softr\":%d}", config.store.smartstart!=2, config.store.audioinfo, config.store.vumeter, config.store.softapdelay); - break; - } - case GETSCREEN: { - sprintf (buf, "{\"flip\":%d,\"inv\":%d,\"nump\":%d,\"tsf\":%d,\"tsd\":%d,\"dspon\":%d,\"br\":%d,\"con\":%d}", config.store.flipscreen, config.store.invertdisplay, config.store.numplaylist, config.store.fliptouch, config.store.dbgtouch, config.store.dspon, config.store.brightness, config.store.contrast); - break; - } - case GETTIMEZONE: { - sprintf (buf, "{\"tzh\":%d,\"tzm\":%d,\"sntp1\":\"%s\",\"sntp2\":\"%s\"}", config.store.tzHour, config.store.tzMin, config.store.sntp1, config.store.sntp2); - break; - } - case GETWEATHER: { - sprintf (buf, "{\"wen\":%d,\"wlat\":\"%s\",\"wlon\":\"%s\",\"wkey\":\"%s\"}", config.store.showweather, config.store.weatherlat, config.store.weatherlon, config.store.weatherkey); - break; - } - case GETCONTROLS: { - sprintf (buf, "{\"vols\":%d,\"enca\":%d,\"irtl\":%d}", config.store.volsteps, config.store.encacc, config.store.irtlp); - break; - } - case DSPON: { - sprintf (buf, "{\"dspontrue\":%d}", 1); - break; - } - case STATION: { - sprintf (buf, "{\"nameset\": \"%s\"}", config.station.name); - requestOnChange(ITEM, clientId); - break; - } - case ITEM: { - sprintf (buf, "{\"current\": %d}", config.store.lastStation); - break; - } - case TITLE: { - sprintf (buf, "{\"meta\": \"%s\"}", config.station.title); - if (player.requestToStart) { - telnet.info(); - player.requestToStart = false; - } else { - telnet.printf("##CLI.META#: %s\n> ", config.station.title); - } - break; - } - case VOLUME: { - sprintf (buf, "{\"vol\": %d}", config.store.volume); -#ifdef MQTT_HOST - if (clientId == 0) mqttPublishVolume(); -#endif - break; - } - case NRSSI: { - sprintf (buf, "{\"rssi\": %d}", rssi); - rssi = 255; - break; - } - case BITRATE: { - sprintf (buf, "{\"bitrate\": %d}", config.station.bitrate); - break; - } - case MODE: { - sprintf (buf, "{\"mode\": \"%s\"}", player.mode == PLAYING ? "playing" : "stopped"); - break; - } - case EQUALIZER: { - sprintf (buf, "{\"bass\": %d, \"middle\": %d, \"trebble\": %d}", config.store.bass, config.store.middle, config.store.trebble); - break; - } - case BALANCE: { - sprintf (buf, "{\"balance\": %d}", config.store.balance); - break; } + case GETMODE: sprintf (buf, "{\"pmode\":\"%s\"}", network.status == CONNECTED ? "player" : "ap"); break; + case GETINDEX: requestOnChange(STATION, clientId); requestOnChange(TITLE, clientId); requestOnChange(VOLUME, clientId); requestOnChange(EQUALIZER, clientId); requestOnChange(BALANCE, clientId); requestOnChange(BITRATE, clientId); requestOnChange(MODE, clientId); return; break; + case GETSYSTEM: sprintf (buf, "{\"sst\":%d,\"aif\":%d,\"vu\":%d,\"softr\":%d}", config.store.smartstart != 2, config.store.audioinfo, config.store.vumeter, config.store.softapdelay); break; + case GETSCREEN: sprintf (buf, "{\"flip\":%d,\"inv\":%d,\"nump\":%d,\"tsf\":%d,\"tsd\":%d,\"dspon\":%d,\"br\":%d,\"con\":%d}", config.store.flipscreen, config.store.invertdisplay, config.store.numplaylist, config.store.fliptouch, config.store.dbgtouch, config.store.dspon, config.store.brightness, config.store.contrast); break; + case GETTIMEZONE: sprintf (buf, "{\"tzh\":%d,\"tzm\":%d,\"sntp1\":\"%s\",\"sntp2\":\"%s\"}", config.store.tzHour, config.store.tzMin, config.store.sntp1, config.store.sntp2); break; + case GETWEATHER: sprintf (buf, "{\"wen\":%d,\"wlat\":\"%s\",\"wlon\":\"%s\",\"wkey\":\"%s\"}", config.store.showweather, config.store.weatherlat, config.store.weatherlon, config.store.weatherkey); break; + case GETCONTROLS: sprintf (buf, "{\"vols\":%d,\"enca\":%d,\"irtl\":%d}", config.store.volsteps, config.store.encacc, config.store.irtlp); break; + case DSPON: sprintf (buf, "{\"dspontrue\":%d}", 1); break; + case STATION: sprintf (buf, "{\"nameset\": \"%s\"}", config.station.name); requestOnChange(ITEM, clientId); break; + case ITEM: sprintf (buf, "{\"current\": %d}", config.store.lastStation); break; + case TITLE: sprintf (buf, "{\"meta\": \"%s\"}", config.station.title); if (player.requestToStart) { telnet.info(); player.requestToStart = false; } else { telnet.printf("##CLI.META#: %s\n> ", config.station.title); } break; + case VOLUME: sprintf (buf, "{\"vol\": %d}", config.store.volume); break; + case NRSSI: sprintf (buf, "{\"rssi\": %d}", rssi); rssi = 255; break; + case BITRATE: sprintf (buf, "{\"bitrate\": %d}", config.station.bitrate); break; + case MODE: sprintf (buf, "{\"mode\": \"%s\"}", player.mode == PLAYING ? "playing" : "stopped"); break; + case EQUALIZER: sprintf (buf, "{\"bass\": %d, \"middle\": %d, \"trebble\": %d}", config.store.bass, config.store.middle, config.store.trebble); DBGVB("[%s] %s", __func__, buf); break; + case BALANCE: sprintf (buf, "{\"balance\": %d}", config.store.balance); break; } if (strlen(buf) > 0) { - if (clientId == 0) { - websocket.textAll(buf); + if (clientId == 0) { websocket.textAll(buf); }else{ websocket.text(clientId, buf); } #ifdef MQTT_HOST - if (request == STATION || request == ITEM || request == TITLE || request == MODE) mqttPublishStatus(); + if (clientId == 0 && (request == STATION || request == ITEM || request == TITLE || request == MODE)) mqttPublishStatus(); + if (clientId == 0 && request == VOLUME) mqttPublishVolume(); #endif - } else { - websocket.text(clientId, buf); - } } } String processor(const String& var) { // %Templates% - if (var == "VERSION") { - return VERSION; - } + if (var == "VERSION") return VERSION; return String(); } void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { if (!index) { - netserver.takeMallocDog(); + PLOW(); request->_tempFile = SPIFFS.open(TMP_PATH , "w"); } if (len) { @@ -890,130 +634,97 @@ void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, } if (final) { request->_tempFile.close(); - netserver.importRequest = true; - request->send(200); + PHIG(); } } void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { switch (type) { - case WS_EVT_CONNECT: - if(config.store.audioinfo) Serial.printf("[WEBSOCKET] client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str()); - /*netserver.requestOnChange(STATION, client->id()); - netserver.requestOnChange(TITLE, client->id()); - netserver.requestOnChange(VOLUME, client->id()); - netserver.requestOnChange(EQUALIZER, client->id()); - netserver.requestOnChange(BALANCE, client->id()); - netserver.requestOnChange(BITRATE, client->id()); - netserver.requestOnChange(MODE, client->id()); - netserver.playlistrequest = client->id();*/ - - break; - case WS_EVT_DISCONNECT: - if(config.store.audioinfo) Serial.printf("[WEBSOCKET] client #%u disconnected\n", client->id()); - break; - case WS_EVT_DATA: - netserver.onWsMessage(arg, data, len, client->id()); - break; + case WS_EVT_CONNECT: if (config.store.audioinfo) Serial.printf("[WEBSOCKET] client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str()); break; + case WS_EVT_DISCONNECT: if (config.store.audioinfo) Serial.printf("[WEBSOCKET] client #%u disconnected\n", client->id()); break; + case WS_EVT_DATA: netserver.onWsMessage(arg, data, len, client->id()); break; case WS_EVT_PONG: case WS_EVT_ERROR: break; } } -void handleHTTPPost(AsyncWebServerRequest * request) { - if (request->hasParam("wifisettings", true)) { - AsyncWebParameter* p = request->getParam("wifisettings", true); - if (p->value() != "") { - config.saveWifi(p->value().c_str()); +void handleHTTPArgs(AsyncWebServerRequest * request) { + if (request->method() == HTTP_GET) { + DBGVB("[%s] client ip=%s request of %s", __func__, request->client()->remoteIP().toString().c_str(), request->url().c_str()); + if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 || strcmp(request->url().c_str(), SSIDS_PATH) == 0 || strcmp(request->url().c_str(), INDEX_PATH) == 0 || strcmp(request->url().c_str(), TMP_PATH) == 0) { +#ifdef MQTT_HOST + if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0) while (mqttplaylistblock) vTaskDelay(5); +#endif + netserver.chunkedHtmlPage("application/octet-stream", request, request->url().c_str()); + return; + } + if (strcmp(request->url().c_str(), "/") == 0 && request->params() == 0) { + netserver.chunkedHtmlPage(String(), request, network.status == CONNECTED ? "/www/index.html" : "/www/settings.html"); + return; + } + if (strcmp(request->url().c_str(), "/update") == 0 || strcmp(request->url().c_str(), "/settings") == 0 || strcmp(request->url().c_str(), "/ir") == 0) { + char buf[40] = { 0 }; + sprintf(buf, "/www%s.html", request->url().c_str()); + netserver.chunkedHtmlPage(String(), request, buf); + return; } - request->send(200); - return; - } - if (request->hasParam("playlist", true)) { - AsyncWebParameter* p = request->getParam("playlist", true); - netserver.savePlaylist(p->value().c_str()); - request->send(200); - return; - } - if (network.status != CONNECTED) { - request->send(404); - return; - } - if (request->hasParam("start", true)) { - player.request.station = config.store.lastStation; - request->send(200); - return; - } - if (request->hasParam("stop", true)) { - player.mode = STOPPED; - //display.title("[stopped]"); - config.setTitle("[stopped]"); - request->send(200); - return; - } - if (request->hasParam("prev", true)) { - player.prev(); - request->send(200); - return; - } - if (request->hasParam("next", true)) { - player.next(); - request->send(200); - return; - } - if (request->hasParam("volm", true)) { - player.stepVol(false); - request->send(200); - return; - } - if (request->hasParam("volp", true)) { - player.stepVol(true); - request->send(200); - return; - } - if (request->hasParam("vol", true)) { - AsyncWebParameter* p = request->getParam("vol", true); - int v = atoi(p->value().c_str()); - if (v < 0) v = 0; - if (v > 254) v = 254; - player.setVol(v, false); - request->send(200); - return; - } - if (request->hasParam("trebble", true)) { - AsyncWebParameter* pt = request->getParam("trebble", true); - AsyncWebParameter* pm = request->getParam("middle", true); - AsyncWebParameter* pb = request->getParam("bass", true); - int t = atoi(pt->value().c_str()); - int m = atoi(pm->value().c_str()); - int b = atoi(pb->value().c_str()); - //setTone(int8_t gainLowPass, int8_t gainBandPass, int8_t gainHighPass) - player.setTone(b, m, t); - config.setTone(b, m, t); - netserver.requestOnChange(EQUALIZER, 0); - request->send(200); - return; - } - if (request->hasParam("ballance", true)) { - AsyncWebParameter* p = request->getParam("ballance", true); - int b = atoi(p->value().c_str()); - player.setBalance(b); - config.setBalance(b); - netserver.requestOnChange(BALANCE, 0); - request->send(200); - return; - } - if (request->hasParam("playstation", true)) { - AsyncWebParameter* p = request->getParam("playstation", true); - int id = atoi(p->value().c_str()); - if (id < 1) id = 1; - if (id > config.store.countStation) id = config.store.countStation; - player.request.station = id; - player.request.doSave = true; - request->send(200); - return; } + if (network.status == CONNECTED) { + if (request->hasArg("start")) player.request.station = config.store.lastStation; + if (request->hasArg("stop")) { + player.mode = STOPPED; + config.setTitle("[stopped]"); + } + if (request->hasArg("prev")) player.prev(); + if (request->hasArg("next")) player.next(); + if (request->hasArg("volm")) player.stepVol(false); + if (request->hasArg("volp")) player.stepVol(true); - request->send(404); + if (request->hasArg("trebble") && request->hasArg("middle") && request->hasArg("bass")) { + AsyncWebParameter* pt = request->getParam("trebble", request->method() == HTTP_POST); + AsyncWebParameter* pm = request->getParam("middle", request->method() == HTTP_POST); + AsyncWebParameter* pb = request->getParam("bass", request->method() == HTTP_POST); + int t = atoi(pt->value().c_str()); + int m = atoi(pm->value().c_str()); + int b = atoi(pb->value().c_str()); + player.setTone(b, m, t); + config.setTone(b, m, t); + netserver.requestOnChange(EQUALIZER, 0); + } + if (request->hasArg("ballance")) { + AsyncWebParameter* p = request->getParam("ballance", request->method() == HTTP_POST); + int b = atoi(p->value().c_str()); + player.setBalance(b); + config.setBalance(b); + netserver.requestOnChange(BALANCE, 0); + } + if (request->hasArg("playstation") || request->hasArg("play")) { + AsyncWebParameter* p = request->getParam(request->hasArg("playstation") ? "playstation" : "play", request->method() == HTTP_POST); + int id = atoi(p->value().c_str()); + if (id < 1) id = 1; + if (id > config.store.countStation) id = config.store.countStation; + player.request.station = id; + player.request.doSave = true; + DBGVB("[%s] play=%d", __func__, id); + } + if (request->hasArg("vol")) { + AsyncWebParameter* p = request->getParam("vol", request->method() == HTTP_POST); + int v = atoi(p->value().c_str()); + if (v < 0) v = 0; + if (v > 254) v = 254; + config.store.volume = v; + player.setVol(v, false); + DBGVB("[%s] vol=%d", __func__, v); + } + if (request->params() > 0) { + request->send(200); + return; + } + } else { + if (request->params() > 0) { + request->send(404); + return; + } + } } diff --git a/yoRadio/netserver.h b/yoRadio/netserver.h index 437e599..914faf6 100644 --- a/yoRadio/netserver.h +++ b/yoRadio/netserver.h @@ -6,38 +6,38 @@ #include "AsyncUDP.h" enum requestType_e : uint8_t { PLAYLIST=1, STATION=2, ITEM=3, TITLE=4, VOLUME=5, NRSSI=6, BITRATE=7, MODE=8, EQUALIZER=9, BALANCE=10, PLAYLISTSAVED=11, GETMODE=12, GETINDEX=13, GETACTIVE=14, GETSYSTEM=15, GETSCREEN=16, GETTIMEZONE=17, GETWEATHER=18, GETCONTROLS=19, DSPON=20 }; -enum htmlPath_e : uint8_t { PINDEX=1, PSETTINGS=2, PUPDATE=3, PIR=4, PPLAYLIST=5, PSSIDS=6 }; +enum import_e : uint8_t { IMDONE=0, IMPL=1, IMWIFI=2 }; + +#define PLOW() //player.setBufsize(1600*2, -1); vTaskDelay(150) +#define PHIG() //vTaskDelay(150); player.setBufsize(1600*AUDIOBUFFER_MULTIPLIER2, -1) class NetServer { public: - uint8_t playlistrequest; // ClientId want the playlist - bool importRequest; + //uint8_t playlistrequest; // ClientId want the playlist/* Cleanup this */ + import_e importRequest; bool resumePlay; - htmlPath_e htmlPath; + char chunkedPathBuffer[40]; public: NetServer() {}; bool begin(); void loop(); void requestOnChange(requestType_e request, uint8_t clientId); - void setRSSI(int val); + void setRSSI(int val) { rssi = val; }; + void chunkedHtmlPage(const String& contentType, AsyncWebServerRequest *request, const char * path, bool gzip = false); void onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t clientId); - bool savePlaylist(const char* post); - void takeMallocDog(); - void giveMallocDog(); - uint32_t max, htmlpos; - bool theend; #if IR_PIN!=255 bool irRecordEnable; void irToWs(const char* protocol, uint64_t irvalue); - void irValsToWs(); - void chunkedHtmlPage(const String& contentType, AsyncWebServerRequest *request); + void irValsToWs(); #endif private: requestType_e request; int rssi; - void getPlaylist(uint8_t clientId); bool importPlaylist(); + static size_t chunkedHtmlPageCallback(uint8_t* buffer, size_t maxLen, size_t index); + static void beginUpload(AsyncWebServerRequest *request); + static void beginUpdate(AsyncWebServerRequest *request); }; extern NetServer netserver; diff --git a/yoRadio/options.h b/yoRadio/options.h index a216f1f..63d0fc6 100644 --- a/yoRadio/options.h +++ b/yoRadio/options.h @@ -1,7 +1,7 @@ #ifndef options_h #define options_h -#define VERSION "0.7.414" +#define VERSION "0.7.490" /******************************************************* DO NOT EDIT THIS FILE. diff --git a/yoRadio/player.cpp b/yoRadio/player.cpp index f200d01..40810b8 100644 --- a/yoRadio/player.cpp +++ b/yoRadio/player.cpp @@ -61,7 +61,10 @@ void Player::stopInfo() { void Player::loop() { if (mode == PLAYING) { + xSemaphoreTake(playmutex, portMAX_DELAY); Audio::loop(); + xSemaphoreGive(playmutex); + vTaskDelay(2); } else { if (isRunning()) { //digitalWrite(LED_BUILTIN, LOW); @@ -71,7 +74,6 @@ void Player::loop() { //stopSong(); setDefaults(); stopInfo(); - xSemaphoreGive(playmutex); if (player_on_stop_play) player_on_stop_play(); } } @@ -112,8 +114,6 @@ void Player::setOutputPins(bool isPlaying) { void Player::play(uint16_t stationId) { //stopSong(); - xSemaphoreGive(playmutex); - xSemaphoreTake(playmutex, portMAX_DELAY); setDefaults(); setOutputPins(false); config.setTitle("[connecting]"); diff --git a/yoRadio/src/audioI2S/AudioEx.h b/yoRadio/src/audioI2S/AudioEx.h index 6236d31..5d6ab3f 100644 --- a/yoRadio/src/audioI2S/AudioEx.h +++ b/yoRadio/src/audioI2S/AudioEx.h @@ -32,8 +32,8 @@ #include #endif // SDFATFS_USED -#ifndef AUDIOBUFFER_MULTIPLIER -#define AUDIOBUFFER_MULTIPLIER 12 +#ifndef AUDIOBUFFER_MULTIPLIER2 +#define AUDIOBUFFER_MULTIPLIER2 8 #endif #ifdef SDFATFS_USED @@ -140,7 +140,7 @@ public: protected: size_t m_buffSizePSRAM = 300000; // most webstreams limit the advance to 100...300Kbytes //size_t m_buffSizeRAM = 1600 * 5; - size_t m_buffSizeRAM = 1600 * AUDIOBUFFER_MULTIPLIER; + size_t m_buffSizeRAM = 1600 * AUDIOBUFFER_MULTIPLIER2; size_t m_buffSize = 0; size_t m_freeSpace = 0; size_t m_writeSpace = 0; diff --git a/yoRadio/src/audioVS1053/audioVS1053Ex.cpp b/yoRadio/src/audioVS1053/audioVS1053Ex.cpp index 52fb031..f9ff3ef 100644 --- a/yoRadio/src/audioVS1053/audioVS1053Ex.cpp +++ b/yoRadio/src/audioVS1053/audioVS1053Ex.cpp @@ -7,7 +7,9 @@ * Updated on: Aug 15.2022 * Author: Wolle */ - +#ifndef VS_PATCH_ENABLE +#define VS_PATCH_ENABLE true +#endif #include "audioVS1053Ex.h" //--------------------------------------------------------------------------------------------------------------------- @@ -325,7 +327,7 @@ void Audio::begin(){ setVUmeter(); m_endFillByte = wram_read(0x1E06) & 0xFF; // printDetails("After last clocksetting \n"); - loadUserCode(); // load in VS1053B if you want to play flac + if(VS_PATCH_ENABLE) loadUserCode(); // load in VS1053B if you want to play flac startSong(); } //--------------------------------------------------------------------------------------------------------------------- @@ -1613,6 +1615,7 @@ void Audio::setDefaults(){ * \n The VU meter takes about 0.2MHz of processing power with 48 kHz samplerate. */ void Audio::setVUmeter() { + if(!VS_PATCH_ENABLE) return; uint16_t MP3Status = read_register(SCI_STATUS); if(MP3Status==0) { Serial.println("VS1053 Error: Unable to write SCI_STATUS"); @@ -1636,6 +1639,7 @@ void Audio::setVUmeter() { * \warning This feature is only available with patches that support VU meter. */ void Audio::getVUlevel() { + if(!VS_PATCH_ENABLE) return; if(!_vuInitalized) return; int16_t reg = read_register(SCI_AICTRL3); uint8_t rl = map((uint8_t)reg, 85, 92, 0, 255); diff --git a/yoRadio/src/audioVS1053/audioVS1053Ex.h b/yoRadio/src/audioVS1053/audioVS1053Ex.h index d9b17c5..b7020ba 100644 --- a/yoRadio/src/audioVS1053/audioVS1053Ex.h +++ b/yoRadio/src/audioVS1053/audioVS1053Ex.h @@ -9,8 +9,8 @@ #ifndef _vs1053_ext #define _vs1053_ext -#ifndef AUDIOBUFFER_MULTIPLIER -#define AUDIOBUFFER_MULTIPLIER 12 +#ifndef AUDIOBUFFER_MULTIPLIER2 +#define AUDIOBUFFER_MULTIPLIER2 10 #endif #define VS1053VOLM 128 // 128 or 96 only @@ -97,7 +97,7 @@ public: protected: const size_t m_buffSizePSRAM = 300000; // most webstreams limit the advance to 100...300Kbytes //const size_t m_buffSizeRAM = 1600 * 10; - const size_t m_buffSizeRAM = 1600 * AUDIOBUFFER_MULTIPLIER; + const size_t m_buffSizeRAM = 1600 * AUDIOBUFFER_MULTIPLIER2; size_t m_buffSize = 0; size_t m_freeSpace = 0; size_t m_writeSpace = 0; diff --git a/yoRadio/src/displays/nextion.cpp b/yoRadio/src/displays/nextion.cpp index 5d55817..e4beb6c 100644 --- a/yoRadio/src/displays/nextion.cpp +++ b/yoRadio/src/displays/nextion.cpp @@ -353,7 +353,7 @@ void Nextion::loop() { wifisettings+=(String(scanBuf)+"\n"); } if (sscanf(rxbuf, "wifidone=%d", &scanDigit) == 1){ - config.saveWifi(wifisettings.c_str()); + config.saveWifiFromNextion(wifisettings.c_str()); } } }