diff --git a/Controls.md b/Controls.md index 56907cc..fc06a98 100644 --- a/Controls.md +++ b/Controls.md @@ -47,7 +47,7 @@ You can connect one or two encoders to replace/complete the buttons. One encoder - ENCODER2\ rotate left: (ENC2_BTNL) if not pressed - switch to PLAYLIST mode and move up, if pressed - volume down\ rotate right: (ENC2_BTNR) if not pressed - switch to PLAYLIST mode and move down, if pressed - volume up\ - click, dblclick: (ENC2_BTNB) same as BTN_CENTER + click, dblclick: (ENC2_BTNB) toggle between PLAYER/VOLUME mode --- ### IR receiver diff --git a/README.md b/README.md index cd06d9c..8c4e318 100644 --- a/README.md +++ b/README.md @@ -281,8 +281,15 @@ Work is in progress... --- ## Version history -#### v0.6.121 -- fixed compiling error with DSP_GC9106 option +#### v0.6.200 +- please backup your playlist and wifi settings before updating (export) +- accelerated displays up to ~30fps (everything except LCD) +- corrections/additions in the WEB interface (a [full update](#update) is required) +- rewrote [plugin example](https://github.com/e2002/yoradio/blob/main/exsamples/displayhandlers.ino) +- fixed compilation errors on macOS +- changed the logic of the second encoder (switching to the volume control mode by double click) +- optimization, bug fixes +- probably some other things that I forgot about %) #### v0.6.120 - added support for GC9106 160x80 SPI displays diff --git a/exsamples/displayhandlers.ino b/exsamples/displayhandlers.ino index 56d8474..1882168 100644 --- a/exsamples/displayhandlers.ino +++ b/exsamples/displayhandlers.ino @@ -5,23 +5,19 @@ **************************************************************/ -#if DSP_MODEL==DSP_ST7735 -// 3600s = 60 minutes to not flooding -#define WEATHER_REQUEST_INTERVAL 3600 // 60min +#if (DSP_MODEL==DSP_ST7735) || (DSP_MODEL==DSP_ST7789) || (DSP_MODEL==DSP_SSD1327) || (DSP_MODEL==DSP_ILI9341) -#include // https://github.com/Bodmer/OpenWeather -#include // https://github.com/Bodmer/JSON_Decoder +#define WEATHER_REQUEST_INTERVAL 1800 //30min +#define WEATHER_REQUEST_INTERVAL_FAULTY 30 + +#include #include -String api_key = "********************************"; // openweathermap.org API key +const char* host = "api.openweathermap.org"; +const char* lat = "55.7512"; +const char* lon = "37.6184"; +const char* key = "********************************"; -String latitude = "55.7512"; -String longitude = "37.6184"; - -String units = "metric"; -String language = "ru"; - -OW_Weather ow; Ticker ticker; /*********************************************** @@ -33,14 +29,100 @@ char weather[140] = { 0 }; bool weatherRequest = false; TaskHandle_t weatherUpdateTaskHandle; +bool getForecast() { + WiFiClient client; + if (!client.connect(host, 80)) { + Serial.println("## OPENWEATHERMAP ###: connection failed"); + return false; + } + char httpget[250] = {0}; + sprintf(httpget, "GET /data/2.5/weather?lat=%s&lon=%s&units=metric&lang=ru&appid=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", lat, lon, key, host); + client.print(httpget); + unsigned long timeout = millis(); + while (client.available() == 0) { + if (millis() - timeout > 2000UL) { + Serial.println("## OPENWEATHERMAP ###: client available timeout !"); + client.stop(); + return false; + } + } + timeout = millis(); + String line = ""; + if (client.connected()) { + while (client.available()) + { + line = client.readStringUntil('\n'); + if (strstr(line.c_str(), "\"temp\"") != NULL) { + client.stop(); + break; + } + if ((millis() - timeout) > 500) + { + client.stop(); + Serial.println("## OPENWEATHERMAP ###: client read timeout !"); + return false; + } + } + } + if (strstr(line.c_str(), "\"temp\"") == NULL) { + Serial.println("## OPENWEATHERMAP ###: weather not found !"); + return false; + } + char *tmpe; + char *tmps; + const char* cursor = line.c_str(); + char desc[120], temp[20], hum[20], press[20]; + + tmps = strstr(cursor, "\"description\":\""); + if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: description not found !"); return false;} + tmps += 15; + tmpe = strstr(tmps, "\",\""); + if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: description not found !"); return false;} + strlcpy(desc, tmps, tmpe - tmps + 1); + cursor = tmpe + 3; + + tmps = strstr(cursor, "\"temp\":"); + if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: temp not found !"); return false;} + tmps += 7; + tmpe = strstr(tmps, ",\""); + if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: temp not found !"); return false;} + strlcpy(temp, tmps, tmpe - tmps + 1); + cursor = tmpe + 2; + float tempf = atof(temp); + + tmps = strstr(cursor, "\"pressure\":"); + if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: pressure not found !"); return false;} + tmps += 11; + tmpe = strstr(tmps, ",\""); + if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: pressure not found !"); return false;} + strlcpy(press, tmps, tmpe - tmps + 1); + cursor = tmpe + 2; + int pressi = (float)atoi(press) / 1.333; + + tmps = strstr(cursor, "humidity\":"); + if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: humidity not found !"); return false;} + tmps += 10; + tmpe = strstr(tmps, ",\""); + if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: humidity not found !"); return false;} + strlcpy(hum, tmps, tmpe - tmps + 1); + + Serial.printf("## OPENWEATHERMAP ###: description: %s, temp:%.1f C, pressure:%dmmHg, humidity:%s%%\n", desc, tempf, pressi, hum); + sprintf(weather, "%s, %.1f C * давление: %d мм * влажность: %s%%", desc, tempf, pressi, hum); + + return true; + +} + void getWeather( void * pvParameters ) { - OW_current *current = new OW_current; - OW_hourly *hourly = new OW_hourly; - OW_daily *daily = new OW_daily; - delay(5000); - ow.getForecast(current, hourly, daily, api_key, latitude, longitude, units, language); - sprintf(weather, "TEMP: %.1f C * PRESS: %d HG * HUM: %d%%", current->temp, (int)(current->pressure / 1.333), current->humidity); - weatherRequest = true; + delay(200); + if (getForecast()) { + weatherRequest = true; + ticker.detach(); + ticker.attach(WEATHER_REQUEST_INTERVAL, updateWeather); + } else { + ticker.detach(); + ticker.attach(WEATHER_REQUEST_INTERVAL_FAULTY, updateWeather); + } vTaskDelete( NULL ); } @@ -48,18 +130,17 @@ void updateWeather() { xTaskCreatePinnedToCore( getWeather, /* Task function. */ "getWeather1", /* name of task. */ - 8192, /* Stack size of task */ + 1024 * 4, /* Stack size of task */ NULL, /* parameter of the task */ 0, /* priority of the task */ &weatherUpdateTaskHandle, /* Task handle to keep track of created task */ - 0); /* pin task to core CORE_FOR_LOOP_CONTROLS */ + 1); /* pin task to core CORE_FOR_LOOP_CONTROLS */ } /*********************************************** Occurs when the network is connected ***********************************************/ void network_on_connect() { - ticker.attach(WEATHER_REQUEST_INTERVAL, updateWeather); updateWeather(); } @@ -75,17 +156,20 @@ void dsp_on_start(DspCore *dsp) { Occurs when the display is initialized ***********************************************/ void dsp_on_init() { - hello.init(5, " * ", 1, TFT_LINEHGHT*4+6, 0, ORANGE, TFT_BG); - Serial.println(TFT_LINEHGHT*4+6); + if (DSP_MODEL == DSP_ST7735 || (DSP_MODEL == DSP_SSD1327)) { + hello.init(5, " * ", 1, TFT_LINEHGHT * 4 + 6, 0, ORANGE, TFT_BG); + } else { + hello.init(5, " * ", 2, TFT_LINEHGHT * 9 + 5, 0, ORANGE, TFT_BG); + } } /************************ The loop cycle ************************/ -void dsp_on_loop() { +void dsp_on_loop(DspCore *dsp) { if (weatherRequest) { weatherRequest = false; - hello.setText(weather); + hello.setText(dsp->utf8Rus(weather, true)); } if (display.mode == PLAYER) hello.loop(); } diff --git a/yoRadio/audiohandlers.ino b/yoRadio/audiohandlers.ino index b919e84..eac008f 100644 --- a/yoRadio/audiohandlers.ino +++ b/yoRadio/audiohandlers.ino @@ -1,6 +1,6 @@ void audio_info(const char *info) { if(config.store.audioinfo) telnet.printf("##AUDIO.INFO#: %s\n", info); - if (strstr(info, "failed!") != NULL || strstr(info, "404") != NULL) { + if (strstr(info, "failed!") != NULL || strstr(info, " 404") != NULL) { config.setTitle("[request failed]"); //config.setTitle(info); player.mode = STOPPED; @@ -28,7 +28,6 @@ bool printable(const char *info) { void audio_showstation(const char *info) { if (strlen(info) > 0) { bool p = printable(info); - //display.title(p?info:"*****"); config.setTitle(p?info:"*****"); netserver.requestOnChange(TITLE, 0); } @@ -37,7 +36,6 @@ void audio_showstation(const char *info) { void audio_showstreamtitle(const char *info) { if (strlen(info) > 0) { bool p = printable(info); - //display.title(p?info:"*****"); config.setTitle(p?info:"*****"); netserver.requestOnChange(TITLE, 0); } diff --git a/yoRadio/config.cpp b/yoRadio/config.cpp index 6881bdb..674af08 100644 --- a/yoRadio/config.cpp +++ b/yoRadio/config.cpp @@ -132,7 +132,7 @@ byte Config::setLastSSID(byte val) { void Config::setTitle(const char* title) { memset(config.station.title, 0, BUFLEN); strlcpy(config.station.title, title, BUFLEN); - display.title(); + display.putRequest({NEWTITLE, 0}); } void Config::setStation(const char* station) { diff --git a/yoRadio/controls.cpp b/yoRadio/controls.cpp index 1371ad1..a8dc26d 100644 --- a/yoRadio/controls.cpp +++ b/yoRadio/controls.cpp @@ -153,7 +153,7 @@ void encoder2Loop() { if (ENC2_BTNB != 255) { bp = digitalRead(ENC2_BTNB); } - if (bp == HIGH && display.mode != STATIONS) display.swichMode(STATIONS); + if (bp == HIGH && display.mode == PLAYER) display.putRequest({NEWMODE, STATIONS}); //display.swichMode(STATIONS); controlsEvent(encNewPosition > 0); } } @@ -172,13 +172,12 @@ void irBlink() { void irNum(byte num) { uint16_t s; if (display.numOfNextStation == 0 && num == 0) return; - //if (display.mode == PLAYER) display.swichMode(NUMBERS); - display.swichMode(NUMBERS); + display.putRequest({NEWMODE, NUMBERS}); if (display.numOfNextStation > UINT16_MAX / 10) return; s = display.numOfNextStation * 10 + num; if (s > config.store.countStation) return; display.numOfNextStation = s; - display.drawNextStationNum(s); + display.putRequest({NEXTSTATION, s}); } void irLoop() { @@ -204,10 +203,8 @@ void irLoop() { case IR_CODE_PLAY: { irBlink(); if (display.mode == NUMBERS) { - display.swichMode(PLAYER); + display.putRequest({NEWMODE, PLAYER}); player.play(display.numOfNextStation); - //player.request.station = display.numOfNextStation; - //player.request.doSave = true; display.numOfNextStation = 0; break; } @@ -234,12 +231,12 @@ void irLoop() { } case IR_CODE_HASH: { if (display.mode == NUMBERS) { - display.returnTile(); - display.swichMode(PLAYER); + display.putRequest({RETURNTITLE, 0}); + display.putRequest({NEWMODE, PLAYER}); display.numOfNextStation = 0; break; } - display.swichMode(display.mode == PLAYER ? STATIONS : PLAYER); + display.putRequest({NEWMODE, display.mode == PLAYER ? STATIONS : PLAYER}); break; } case IR_CODE_NUM0: { @@ -355,7 +352,7 @@ void touchLoop() { touchLongPress=millis(); if(display.mode==PLAYER || display.mode==VOL){ int16_t xDelta = map(abs(touchVol - touchX), 0, display.screenwidth, 0, TS_STEPS); - display.swichMode(VOL); + display.putRequest({NEWMODE, VOL}); if (xDelta>1) { controlsEvent((touchVol - touchX)<0); touchVol = touchX; @@ -368,7 +365,7 @@ void touchLoop() { touchLongPress=millis(); if(display.mode==PLAYER || display.mode==STATIONS){ int16_t yDelta = map(abs(touchStation - touchY), 0, display.screenheight, 0, TS_STEPS); - display.swichMode(STATIONS); + display.putRequest({NEWMODE, STATIONS}); if (yDelta>1) { controlsEvent((touchStation - touchY)>0); touchStation = touchY; @@ -390,7 +387,7 @@ void touchLoop() { if(millis()-touchLongPress < BTN_PRESS_TICKS*2){ onBtnClick(EVT_BTNCENTER); }else{ - display.swichMode(display.mode == PLAYER ? STATIONS : PLAYER); + display.putRequest({NEWMODE, display.mode == PLAYER ? STATIONS : PLAYER}); } } direct = TSD_STAY; @@ -411,9 +408,15 @@ void onBtnLongPressStart(int id) { } case EVT_BTNCENTER: case EVT_ENCBTNB: { - display.swichMode(display.mode == PLAYER ? STATIONS : PLAYER); + display.putRequest({NEWMODE, display.mode == PLAYER ? STATIONS : PLAYER}); break; } + case EVT_ENC2BTNB: { + display.putRequest({NEWMODE, display.mode == PLAYER ? VOL : PLAYER}); + break; + } + default: + break; } } @@ -426,6 +429,8 @@ void onBtnLongPressStop(int id) { lpId = -1; break; } + default: + break; } } @@ -453,13 +458,15 @@ void onBtnDuringLongPress(int id) { case EVT_BTNUP: case EVT_BTNDOWN: { if (display.mode == PLAYER) { - display.swichMode(STATIONS); + display.putRequest({NEWMODE, STATIONS}); } if (display.mode == STATIONS) { controlsEvent(id == EVT_BTNDOWN); } break; } + default: + break; } } } @@ -467,19 +474,16 @@ void onBtnDuringLongPress(int id) { void controlsEvent(bool toRight) { if (display.mode == NUMBERS) { display.numOfNextStation = 0; - display.swichMode(PLAYER); + display.putRequest({NEWMODE, PLAYER}); } if (display.mode != STATIONS) { - display.swichMode(VOL); + display.putRequest({NEWMODE, VOL}); player.stepVol(toRight); } if (display.mode == STATIONS) { - int p = toRight ? display.currentPlItem + 1 : display.currentPlItem - 1; - if (p < 1) p = config.store.countStation; - if (p > config.store.countStation) p = 1; - display.currentPlItem = p; - //display.clear(); - display.drawPlaylist(); + display.resetQueue(); + display.putRequest({DRAWPLAYLIST, toRight}); + } } @@ -494,16 +498,14 @@ void onBtnClick(int id) { case EVT_ENC2BTNB: { if (display.mode == NUMBERS) { display.numOfNextStation = 0; - display.swichMode(PLAYER); + display.putRequest({NEWMODE, PLAYER}); } if (display.mode == PLAYER) { player.toggle(); } if (display.mode == STATIONS) { - display.swichMode(PLAYER); + display.putRequest({NEWMODE, PLAYER}); player.play(display.currentPlItem); - //player.request.station = display.currentPlItem; - //player.request.doSave = true; } break; } @@ -521,7 +523,7 @@ void onBtnClick(int id) { } } else { if (display.mode == PLAYER) { - display.swichMode(STATIONS); + display.putRequest({NEWMODE, STATIONS}); } if (display.mode == STATIONS) { controlsEvent(id == EVT_BTNDOWN); @@ -542,7 +544,7 @@ void onBtnDoubleClick(int id) { case EVT_BTNCENTER: case EVT_ENCBTNB: case EVT_ENC2BTNB: { - display.swichMode(display.mode == PLAYER ? STATIONS : PLAYER); + display.putRequest({NEWMODE, display.mode == PLAYER ? VOL : PLAYER}); break; } case EVT_BTNRIGHT: { @@ -550,5 +552,7 @@ void onBtnDoubleClick(int id) { player.next(); break; } + default: + break; } } diff --git a/yoRadio/data/www/dragpl.js b/yoRadio/data/www/dragpl.js deleted file mode 100644 index 90c4b69..0000000 --- a/yoRadio/data/www/dragpl.js +++ /dev/null @@ -1,40 +0,0 @@ -let dragged; -let id; -let index; -let indexDrop; -let list; - -document.addEventListener("dragstart", ({target}) => { - dragged = target.parentNode; - id = target.parentNode.id; - list = target.parentNode.parentNode.children; - for(let i = 0; i < list.length; i += 1) { - if(list[i] === dragged){ - index = i; - } - } -}); - -document.addEventListener("dragover", (event) => { - event.preventDefault(); -}); - -document.addEventListener("drop", ({target}) => { - if(target.parentNode.className == "pleitem" && target.parentNode.id !== id) { - dragged.remove( dragged ); - for(let i = 0; i < list.length; i += 1) { - if(list[i] === target.parentNode){ - indexDrop = i; - } - } - if(index > indexDrop) { - target.parentNode.before( dragged ); - } else { - target.parentNode.after( dragged ); - } - let items=document.getElementById('pleditorcontent').getElementsByTagName('li'); - for (let i = 0; i <= items.length-1; i++) { - items[i].getElementsByTagName('span')[0].innerText=("00"+(i+1)).slice(-3); - } - } -}); diff --git a/yoRadio/data/www/dragpl.js.gz b/yoRadio/data/www/dragpl.js.gz new file mode 100644 index 0000000..9d5b729 Binary files /dev/null and b/yoRadio/data/www/dragpl.js.gz differ diff --git a/yoRadio/data/www/elogo.png b/yoRadio/data/www/elogo.png index bdc932f..cb92ffd 100644 Binary files a/yoRadio/data/www/elogo.png and b/yoRadio/data/www/elogo.png differ diff --git a/yoRadio/data/www/elogo100.png b/yoRadio/data/www/elogo100.png index 8e5cdc5..d1508d5 100644 Binary files a/yoRadio/data/www/elogo100.png and b/yoRadio/data/www/elogo100.png differ diff --git a/yoRadio/data/www/index.html b/yoRadio/data/www/index.html index fc2e92f..99695d6 100644 --- a/yoRadio/data/www/index.html +++ b/yoRadio/data/www/index.html @@ -6,7 +6,7 @@ - + ёRadio @@ -105,7 +105,7 @@