From 8b1e0a3d25db14a5334f619f634f6f1d74cda92c Mon Sep 17 00:00:00 2001 From: e2002 Date: Sat, 2 Aug 2025 15:36:25 +0300 Subject: [PATCH] v0.9.561 --- README.md | 8 ++++ yoRadio/data/www/script.js.gz | Bin 7493 -> 7530 bytes yoRadio/src/AsyncWebServer/AsyncWebSocket.cpp | 8 ++-- yoRadio/src/AsyncWebServer/AsyncWebSocket.h | 3 +- yoRadio/src/audioVS1053/audioVS1053Ex.cpp | 1 - yoRadio/src/core/config.cpp | 7 ++++ yoRadio/src/core/config.h | 1 + yoRadio/src/core/display.cpp | 39 +++++++++--------- yoRadio/src/core/display.h | 3 ++ yoRadio/src/core/mqtt.cpp | 2 +- yoRadio/src/core/netserver.cpp | 25 +++++++---- yoRadio/src/core/network.cpp | 3 ++ yoRadio/src/core/options.h | 2 +- yoRadio/src/core/timekeeper.cpp | 5 ++- yoRadio/src/main.cpp | 5 ++- 15 files changed, 72 insertions(+), 40 deletions(-) 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 47875396f20a139b1ab5740bc7238b6d672e6ed4..10fdd22f0a4d0be54b3288192921ba9ccd2fb8e1 100644 GIT binary patch literal 7530 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 PiX-&DC#oQR)NTL(-XVnT 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"