diff --git a/README.md b/README.md index 3a1fdf4..a3fc5f9 100644 --- a/README.md +++ b/README.md @@ -234,6 +234,14 @@ Work is in progress... --- ## Version history +### 0.9.561 +**!!! a [full update](#update-over-web-interface) with Sketch data upload is required !!!**\ + or-> just upload `yoRadio/data/www/script.js.gz` to Webboard Uploader http://radioipaddr/webboard\ + After updating please clear browser cache. +- fixed error when switching to SD Card mode +- fixed issue causing random reboots +- fixed preview playback bug in Playlist Editor + ### 0.9.555 - fixed error "assert failed: udp_new_ip_type /IDF/components/lwip/lwip/src/core/udp.c:1278 (Required to lock TCPIP core functionality!)"\ part #2 diff --git a/yoRadio/data/www/script.js.gz b/yoRadio/data/www/script.js.gz index 4787539..10fdd22 100644 Binary files a/yoRadio/data/www/script.js.gz and b/yoRadio/data/www/script.js.gz differ diff --git a/yoRadio/src/AsyncWebServer/AsyncWebSocket.cpp b/yoRadio/src/AsyncWebServer/AsyncWebSocket.cpp index 1fe20ae..c6451e5 100644 --- a/yoRadio/src/AsyncWebServer/AsyncWebSocket.cpp +++ b/yoRadio/src/AsyncWebServer/AsyncWebSocket.cpp @@ -1225,12 +1225,14 @@ AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(uint8_t * data, size_t void AsyncWebSocket::_cleanBuffers() { AsyncWebLockGuard l(_lock); - - for(AsyncWebSocketMessageBuffer * c: _buffers){ + while (_buffers.remove_first([](AsyncWebSocketMessageBuffer* b) { + return b && b->canDelete(); + })); + /*for(AsyncWebSocketMessageBuffer * c: _buffers){ if(c && c->canDelete()){ _buffers.remove(c); } - } + }*/ } AsyncWebSocket::AsyncWebSocketClientLinkedList AsyncWebSocket::getClients() const { diff --git a/yoRadio/src/AsyncWebServer/AsyncWebSocket.h b/yoRadio/src/AsyncWebServer/AsyncWebSocket.h index 05dc53f..0578277 100644 --- a/yoRadio/src/AsyncWebServer/AsyncWebSocket.h +++ b/yoRadio/src/AsyncWebServer/AsyncWebSocket.h @@ -86,9 +86,8 @@ class AsyncWebSocketMessageBuffer { private: uint8_t * _data; size_t _len; - bool _lock; + volatile bool _lock; uint32_t _count; - public: AsyncWebSocketMessageBuffer(); AsyncWebSocketMessageBuffer(size_t size); diff --git a/yoRadio/src/audioVS1053/audioVS1053Ex.cpp b/yoRadio/src/audioVS1053/audioVS1053Ex.cpp index e6dea96..00f6e3a 100644 --- a/yoRadio/src/audioVS1053/audioVS1053Ex.cpp +++ b/yoRadio/src/audioVS1053/audioVS1053Ex.cpp @@ -1717,7 +1717,6 @@ void Audio::setConnectionTimeout(uint16_t timeout_ms, uint16_t timeout_ms_ssl){ void Audio::connectTask(void* pvParams) { ConnectParams* params = static_cast(pvParams); Audio* self = params->instance; - bool res = true; if(self->_client){ self->_connectionResult = self->_client->connect(params->hostwoext, params->port/*, self->m_f_ssl ? self->m_timeout_ms_ssl : self->m_timeout_ms*/); }else{ diff --git a/yoRadio/src/core/config.cpp b/yoRadio/src/core/config.cpp index 21bba5f..039c0cc 100644 --- a/yoRadio/src/core/config.cpp +++ b/yoRadio/src/core/config.cpp @@ -175,8 +175,10 @@ void Config::changeMode(int newmode){ if(getMode()==PM_SDCARD){ if(pir) player.sendCommand({PR_STOP, 0}); display.putRequest(NEWMODE, SDCHANGE); + #ifdef NETSERVER_LOOP1 while(display.mode()!=SDCHANGE) delay(10); + #endif delay(50); } if(getMode()==PM_WEB) { @@ -222,6 +224,11 @@ bool Config::spiffsCleanup(){ return ret; } +void Config::waitConnection(){ + while(!player.connproc) vTaskDelay(50); + vTaskDelay(500); +} + char * Config::ipToStr(IPAddress ip){ snprintf(ipBuf, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); return ipBuf; diff --git a/yoRadio/src/core/config.h b/yoRadio/src/core/config.h index bbd577c..feeb4d0 100644 --- a/yoRadio/src/core/config.h +++ b/yoRadio/src/core/config.h @@ -280,6 +280,7 @@ class Config { #endif void resetSystem(const char *val, uint8_t clientId); bool spiffsCleanup(); + void waitConnection(); char * ipToStr(IPAddress ip); bool prepareForPlaying(uint16_t stationId); void configPostPlaying(uint16_t stationId); diff --git a/yoRadio/src/core/display.cpp b/yoRadio/src/core/display.cpp index 170f77e..f8ee071 100644 --- a/yoRadio/src/core/display.cpp +++ b/yoRadio/src/core/display.cpp @@ -22,6 +22,16 @@ Nextion nextion; #ifndef DSP_TASK_CORE_ID #define DSP_TASK_CORE_ID 0 #endif +#ifndef DSP_TASK_DELAY + #define DSP_TASK_DELAY pdMS_TO_TICKS(10) // cap for 50 fps +#endif + +#define DSP_QUEUE_TICKS 0 + +#ifndef DSQ_SEND_DELAY + //#define DSQ_SEND_DELAY portMAX_DELAY + #define DSQ_SEND_DELAY pdMS_TO_TICKS(200) +#endif QueueHandle_t displayQueue; @@ -29,16 +39,19 @@ static void loopDspTask(void * pvParameters){ while(true){ #ifndef DUMMYDISPLAY if(displayQueue==NULL) break; - netserver.loop(); - if(timekeeper.loop0()) + if(timekeeper.loop0()){ display.loop(); - // will NOT delay here, would use message dequeue timeout instead - //vTaskDelay(DSP_TASK_DELAY); + #ifndef NETSERVER_LOOP1 + netserver.loop(); + #endif + } #else - netserver.loop(); timekeeper.loop0(); - vTaskDelay(10); + #ifndef NETSERVER_LOOP1 + netserver.loop(); + #endif #endif + vTaskDelay(DSP_TASK_DELAY); } vTaskDelete( NULL ); } @@ -53,18 +66,6 @@ DspCore dsp; Page *pages[] = { new Page(), new Page(), new Page(), new Page() }; -#ifndef DSQ_SEND_DELAY - //#define DSQ_SEND_DELAY portMAX_DELAY - #define DSQ_SEND_DELAY pdMS_TO_TICKS(200) -#endif - -#ifndef DSP_TASK_DELAY - #define DSP_TASK_DELAY pdMS_TO_TICKS(20) // cap for 50 fps -#endif - -// will use DSP_QUEUE_TICKS as delay interval for display task runner when there are no msgs in a queue to process -#define DSP_QUEUE_TICKS DSP_TASK_DELAY - #if !((DSP_MODEL==DSP_ST7735 && DTYPE==INITR_BLACKTAB) || DSP_MODEL==DSP_ST7789 || DSP_MODEL==DSP_ST7796 || DSP_MODEL==DSP_ILI9488 || DSP_MODEL==DSP_ILI9486 || DSP_MODEL==DSP_ILI9341 || DSP_MODEL==DSP_ILI9225) #undef BITRATE_FULL #define BITRATE_FULL false @@ -397,7 +398,7 @@ void Display::loop() { _bootScreen(); return; } - if(displayQueue==NULL) return; + if(displayQueue==NULL || _locked) return; _pager.loop(); #ifdef USE_NEXTION nextion.loop(); diff --git a/yoRadio/src/core/display.h b/yoRadio/src/core/display.h index cb3b14c..4df0bf8 100644 --- a/yoRadio/src/core/display.h +++ b/yoRadio/src/core/display.h @@ -37,6 +37,8 @@ class Display { void wakeup(); void setContrast(); void printPLitem(uint8_t pos, const char* item); + void lock() { _locked=true; } + void unlock() { _locked=false; } private: ScrollWidget _meta, _title1, _plcurrent; ScrollWidget *_weather; @@ -52,6 +54,7 @@ class Display { ClockWidget _clock; Page *_boot; TextWidget *_bootstring, *_volip, *_voltxt, *_rssi, *_bitrate; + bool _locked = false; uint8_t _bootStep; void _time(bool redraw = false); void _apScreen(); diff --git a/yoRadio/src/core/mqtt.cpp b/yoRadio/src/core/mqtt.cpp index 7e26585..c818bed 100644 --- a/yoRadio/src/core/mqtt.cpp +++ b/yoRadio/src/core/mqtt.cpp @@ -12,7 +12,7 @@ TimerHandle_t mqttReconnectTimer; char topic[100], status[BUFLEN+50]; void connectToMqtt() { - while(!player.connproc) vTaskDelay(50); + //config.waitConnection(); mqttClient.connect(); } diff --git a/yoRadio/src/core/netserver.cpp b/yoRadio/src/core/netserver.cpp index 048d503..c83d7c8 100644 --- a/yoRadio/src/core/netserver.cpp +++ b/yoRadio/src/core/netserver.cpp @@ -11,7 +11,7 @@ #include "commandhandler.h" #include "timekeeper.h" #include -#include + //#include #ifdef USE_SD @@ -21,7 +21,12 @@ #define MIN_MALLOC 24112 #endif #ifndef NSQ_SEND_DELAY - #define NSQ_SEND_DELAY pdMS_TO_TICKS(100) //portMAX_DELAY? + //#define NSQ_SEND_DELAY portMAX_DELAY + #define NSQ_SEND_DELAY pdMS_TO_TICKS(300) +#endif +#ifndef NS_QUEUE_TICKS + //#define NS_QUEUE_TICKS pdMS_TO_TICKS(2) + #define NS_QUEUE_TICKS 0 #endif //#define CORS_DEBUG //Enable CORS policy: 'Access-Control-Allow-Origin' (for testing) @@ -72,8 +77,8 @@ bool NetServer::begin(bool quiet) { DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), F("content-type")); #endif webserver.begin(); - if(strlen(config.store.mdnsname)>0) - MDNS.begin(config.store.mdnsname); + //if(strlen(config.store.mdnsname)>0) + // MDNS.begin(config.store.mdnsname); websocket.onEvent(onWsEvent); webserver.addHandler(&websocket); if(!quiet) Serial.println("done"); @@ -93,10 +98,12 @@ size_t NetServer::chunkedHtmlPageCallback(uint8_t* buffer, size_t maxLen, size_t size_t needread = filesize - index; if (!needread) { requiredfile.close(); + display.unlock(); 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); + //netserver.loop(); requiredfile.seek(index, SeekSet); requiredfile.read(buffer, canread); index += canread; @@ -108,6 +115,9 @@ void NetServer::chunkedHtmlPage(const String& contentType, AsyncWebServerRequest memset(chunkedPathBuffer, 0, sizeof(chunkedPathBuffer)); strlcpy(chunkedPathBuffer, path, sizeof(chunkedPathBuffer)-1); AsyncWebServerResponse *response; + #ifndef NETSERVER_LOOP1 + display.lock(); + #endif response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback); response->addHeader("Cache-Control","max-age=31536000"); request->send(response); @@ -124,10 +134,6 @@ void NetServer::chunkedHtmlPage(const String& contentType, AsyncWebServerRequest #define SHOW_WEATHER false #endif -#ifndef NS_QUEUE_TICKS - #define NS_QUEUE_TICKS 2 -#endif - const char *getFormat(BitrateFormat _format) { switch (_format) { case BF_MP3: return "MP3"; @@ -308,13 +314,14 @@ void NetServer::loop() { delay(100); ESP.restart(); } + processQueue(); websocket.cleanupClients(); switch (importRequest) { case IMPL: importPlaylist(); importRequest = IMDONE; break; case IMWIFI: config.saveWifi(); importRequest = IMDONE; break; default: break; } - processQueue(); + //processQueue(); } #if IR_PIN!=255 diff --git a/yoRadio/src/core/network.cpp b/yoRadio/src/core/network.cpp index d16d4b2..5eac81e 100644 --- a/yoRadio/src/core/network.cpp +++ b/yoRadio/src/core/network.cpp @@ -7,6 +7,7 @@ #include "player.h" #include "mqtt.h" #include "timekeeper.h" +#include #ifndef WIFI_ATTEMPTS #define WIFI_ATTEMPTS 16 @@ -154,6 +155,8 @@ void MyNetwork::setWifiParams(){ WiFi.onEvent(WiFiReconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP); WiFi.onEvent(WiFiLostConnection, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED); //config.setTimeConf(); //?? + if(strlen(config.store.mdnsname)>0) + MDNS.begin(config.store.mdnsname); } void MyNetwork::requestTimeSync(bool withTelnetOutput, uint8_t clientId) { diff --git a/yoRadio/src/core/options.h b/yoRadio/src/core/options.h index ed51ff4..e86b507 100644 --- a/yoRadio/src/core/options.h +++ b/yoRadio/src/core/options.h @@ -1,7 +1,7 @@ #ifndef options_h #define options_h -#define YOVERSION "0.9.555" +#define YOVERSION "0.9.561" /******************************************************* DO NOT EDIT THIS FILE. diff --git a/yoRadio/src/core/timekeeper.cpp b/yoRadio/src/core/timekeeper.cpp index 94db7a3..8abdb76 100644 --- a/yoRadio/src/core/timekeeper.cpp +++ b/yoRadio/src/core/timekeeper.cpp @@ -206,6 +206,7 @@ void TimeKeeper::_upSDPos(){ void TimeKeeper::timeTask(){ static uint8_t tsFailCnt = 0; + config.waitConnection(); if(getLocalTime(&network.timeinfo)){ tsFailCnt = 0; forceTimeSync = false; @@ -226,8 +227,8 @@ void TimeKeeper::timeTask(){ } } void TimeKeeper::weatherTask(){ - if(!weatherBuf || strlen(config.store.weatherkey)==0 || !config.store.showweather) return; forceWeather = false; + if(!weatherBuf || strlen(config.store.weatherkey)==0 || !config.store.showweather) return; _getWeather(); } @@ -328,7 +329,7 @@ bool _getWeather() { } }, NULL); // <-- client->onData }, NULL); // <-- weatherClient->onConnect - while(!player.connproc) vTaskDelay(50); + config.waitConnection(); if(!weatherClient->connect(host, 80)){ Serial.println("##WEATHER###: connection failed"); AsyncClient * client = weatherClient; diff --git a/yoRadio/src/main.cpp b/yoRadio/src/main.cpp index 6a39482..2000e30 100644 --- a/yoRadio/src/main.cpp +++ b/yoRadio/src/main.cpp @@ -99,7 +99,6 @@ void setup() { if (config.getMode()==PM_SDCARD) player.initHeaders(config.station.url); player.lockOutput=false; if (config.store.smartstart == 1) { - delay(250); player.sendCommand({PR_PLAY, config.lastStation()}); } pm.on_end_setup(); @@ -115,7 +114,9 @@ void loop() { #endif } loopControls(); - //netserver.loop(); + #ifdef NETSERVER_LOOP1 + netserver.loop(); + #endif } #include "core/audiohandlers.h"