This commit is contained in:
e2002
2025-07-17 15:33:24 +03:00
parent d8981ae3a7
commit f173dad9b5
14 changed files with 606 additions and 652 deletions

View File

@@ -234,6 +234,19 @@ Work is in progress...
--- ---
## Version history ## Version history
### 0.9.530
- optimization of webserver/socket code in netserver.cpp, part#1
- added support for ArduinoOTA (OTA update from Arduino IDE) (disabled by default)\
to enable you need to add to myoptions.h: `#define USE_OTA true`\
set password: in myoptions.h `#define OTA_PASS "myotapassword12345"`
- in web interface added basic HTTP authentication capability (disabled by default)\
to enable you need to add to myoptions.h:\
`#define HTTP_USER "user"`\
`#define HTTP_PASS "password"`
- added "emergency firmware uploader" form (for unforeseen cases) http://ipaddress/emergency
- added config (sys.config) telnet command that displays the same information usually shown over serial at boot.
- bug fixes 🪲
### 0.9.515 ### 0.9.515
- fixed a bug with resetting all parameters when resetting only one section of parameters - fixed a bug with resetting all parameters when resetting only one section of parameters

View File

@@ -3613,7 +3613,7 @@ bool Audio::parseHttpResponseHeader() { // this is the response to a GET / reque
if(audio_showstation) audio_showstation(""); if(audio_showstation) audio_showstation("");
if(audio_icydescription) audio_icydescription(""); if(audio_icydescription) audio_icydescription("");
if(audio_icyurl) audio_icyurl(""); if(audio_icyurl) audio_icyurl("");
AUDIO_ERROR("Host %s not available", m_lastHost); AUDIO_ERROR("Host not available");
m_lastHost[0] = '\0'; m_lastHost[0] = '\0';
setDatamode(AUDIO_NONE); setDatamode(AUDIO_NONE);
stopSong(); stopSong();
@@ -3883,6 +3883,7 @@ bool Audio:: initializeDecoder(){
return true; return true;
exit: exit:
AUDIO_ERROR("Not enough free memory to initialize the decoder: %u bytes free", ESP.getFreeHeap());
stopSong(); stopSong();
return false; return false;
} }

View File

@@ -36,10 +36,6 @@
#define AUDIOBUFFER_MULTIPLIER2 8 #define AUDIOBUFFER_MULTIPLIER2 8
#endif #endif
#ifndef HEADER_TIMEOUT
#define HEADER_TIMEOUT 5000
#endif
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) #if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
#include "hal/gpio_ll.h" #include "hal/gpio_ll.h"
#endif #endif

View File

@@ -1203,10 +1203,23 @@ bool Audio::latinToUTF8(char* buff, size_t bufflen){
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool Audio::parseHttpResponseHeader() { // this is the response to a GET / request bool Audio::parseHttpResponseHeader() { // this is the response to a GET / request
static uint32_t notavailablefor = 0;
if(getDatamode() != HTTP_RESPONSE_HEADER) return false; if(getDatamode() != HTTP_RESPONSE_HEADER) return false;
if(_client->available() == 0) return false; if(_client->available() == 0) {
if (notavailablefor == 0) notavailablefor = millis();
if (millis() - notavailablefor > HEADER_TIMEOUT) {
notavailablefor = 0;
if(audio_showstation) audio_showstation("");
if(audio_icydescription) audio_icydescription("");
if(audio_icyurl) audio_icyurl("");
AUDIO_ERROR("Host not available");
m_lastHost[0] = '\0';
setDatamode(AUDIO_NONE);
stopSong();
}
return false;
}
notavailablefor = 0;
char rhl[512]; // responseHeaderline char rhl[512]; // responseHeaderline
bool ct_seen = false; bool ct_seen = false;
uint32_t ctime = millis(); uint32_t ctime = millis();

View File

@@ -0,0 +1,117 @@
#include "commandhandler.h"
#include "player.h"
#include "display.h"
#include "netserver.h"
#include "config.h"
#include "controls.h"
#include "options.h"
CommandHandler cmd;
bool CommandHandler::exec(const char *command, const char *value, uint8_t cid) {
if (strEquals(command, "start")) { player.sendCommand({PR_PLAY, config.lastStation()}); return true; }
if (strEquals(command, "stop")) { player.sendCommand({PR_STOP, 0}); return true; }
if (strEquals(command, "toggle")) { player.toggle(); return true; }
if (strEquals(command, "prev")) { player.prev(); return true; }
if (strEquals(command, "next")) { player.next(); return true; }
if (strEquals(command, "volm")) { player.stepVol(false); return true; }
if (strEquals(command, "volp")) { player.stepVol(true); return true; }
#ifdef USE_SD
if (strEquals(command, "mode")) { config.changeMode(atoi(value)); return true; }
#endif
if (strEquals(command, "reset") && cid==0) { config.reset(); return true; }
if (strEquals(command, "ballance")) { config.setBalance(atoi(value)); return true; }
if (strEquals(command, "playstation") || strEquals(command, "play")){
int id = atoi(value);
if (id < 1) id = 1;
uint16_t cs = config.playlistLength();
if (id > cs) id = cs;
player.sendCommand({PR_PLAY, id});
return true;
}
if (strEquals(command, "vol")){
int v = atoi(value);
config.store.volume = v < 0 ? 0 : (v > 254 ? 254 : v);
player.setVol(v);
return true;
}
if (strEquals(command, "dspon")) { config.setDspOn(atoi(value)!=0); return true; }
if (strEquals(command, "dim")) { int d=atoi(value); config.store.brightness = (uint8_t)(d < 0 ? 0 : (d > 100 ? 100 : d)); config.setBrightness(true); return true; }
if (strEquals(command, "clearspiffs")){ config.spiffsCleanup(); config.saveValue(&config.store.play_mode, static_cast<uint8_t>(PM_WEB)); return true; }
/*********************************************/
/****************** WEBSOCKET ****************/
/*********************************************/
if (strEquals(command, "getindex")) { netserver.requestOnChange(GETINDEX, cid); return true; }
if (strEquals(command, "getsystem")) { netserver.requestOnChange(GETSYSTEM, cid); return true; }
if (strEquals(command, "getscreen")) { netserver.requestOnChange(GETSCREEN, cid); return true; }
if (strEquals(command, "gettimezone")){ netserver.requestOnChange(GETTIMEZONE, cid); return true; }
if (strEquals(command, "getcontrols")){ netserver.requestOnChange(GETCONTROLS, cid); return true; }
if (strEquals(command, "getweather")) { netserver.requestOnChange(GETWEATHER, cid); return true; }
if (strEquals(command, "getactive")) { netserver.requestOnChange(GETACTIVE, cid); return true; }
if (strEquals(command, "newmode")) { config.newConfigMode = atoi(value); netserver.requestOnChange(CHANGEMODE, cid); return true; }
if (strEquals(command, "invertdisplay")){ config.saveValue(&config.store.invertdisplay, static_cast<bool>(atoi(value))); display.invert(); return true; }
if (strEquals(command, "numplaylist")) { config.saveValue(&config.store.numplaylist, static_cast<bool>(atoi(value))); display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER); return true; }
if (strEquals(command, "fliptouch")) { config.saveValue(&config.store.fliptouch, static_cast<bool>(atoi(value))); flipTS(); return true; }
if (strEquals(command, "dbgtouch")) { config.saveValue(&config.store.dbgtouch, static_cast<bool>(atoi(value))); return true; }
if (strEquals(command, "flipscreen")) { config.saveValue(&config.store.flipscreen, static_cast<bool>(atoi(value))); display.flip(); display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER); return true; }
if (strEquals(command, "brightness")) { if (!config.store.dspon) netserver.requestOnChange(DSPON, 0); config.store.brightness = static_cast<bool>(atoi(value)); config.setBrightness(true); return true; }
if (strEquals(command, "screenon")) { config.setDspOn(static_cast<bool>(atoi(value))); return true; }
if (strEquals(command, "contrast")) { config.saveValue(&config.store.contrast, static_cast<uint8_t>(atoi(value))); display.setContrast(); return true; }
if (strEquals(command, "screensaverenabled")){ config.enableScreensaver(static_cast<bool>(atoi(value))); return true; }
if (strEquals(command, "screensavertimeout")){ config.setScreensaverTimeout(static_cast<uint16_t>(atoi(value))); return true; }
if (strEquals(command, "screensaverblank")) { config.setScreensaverBlank(static_cast<bool>(atoi(value))); return true; }
if (strEquals(command, "screensaverplayingenabled")){ config.setScreensaverPlayingEnabled(static_cast<bool>(atoi(value))); return true; }
if (strEquals(command, "screensaverplayingtimeout")){ config.setScreensaverPlayingTimeout(static_cast<uint16_t>(atoi(value))); return true; }
if (strEquals(command, "screensaverplayingblank")) { config.setScreensaverPlayingBlank(static_cast<bool>(atoi(value))); return true; }
if (strEquals(command, "tzh")) { config.saveValue(&config.store.tzHour, static_cast<int8_t>(atoi(value))); return true; }
if (strEquals(command, "tzm")) { config.saveValue(&config.store.tzMin, static_cast<int8_t>(atoi(value))); return true; }
if (strEquals(command, "sntp2")) { config.saveValue(config.store.sntp2, value, 35, false); return true; }
if (strEquals(command, "sntp1")) { config.setSntpOne(value); return true; }
if (strEquals(command, "volsteps")) { config.saveValue(&config.store.volsteps, static_cast<uint8_t>(atoi(value))); return true; }
if (strEquals(command, "encacc")) { setEncAcceleration(static_cast<uint16_t>(atoi(value))); return true; }
if (strEquals(command, "irtlp")) { setIRTolerance(static_cast<uint8_t>(atoi(value))); return true; }
if (strEquals(command, "oneclickswitching")){ config.saveValue(&config.store.skipPlaylistUpDown, static_cast<bool>(atoi(value))); return true; }
if (strEquals(command, "showweather")) { config.setShowweather(static_cast<bool>(atoi(value))); return true; }
if (strEquals(command, "lat")) { config.saveValue(config.store.weatherlat, value, 10, false); return true; }
if (strEquals(command, "lon")) { config.saveValue(config.store.weatherlon, value, 10, false); return true; }
if (strEquals(command, "key")) { config.setWeatherKey(value); return true; }
//<-----TODO
if (strEquals(command, "volume")) { player.setVol(static_cast<uint8_t>(atoi(value))); return true; }
if (strEquals(command, "sdpos")) { config.setSDpos(static_cast<uint32_t>(atoi(value))); return true; }
if (strEquals(command, "snuffle")) { config.setSnuffle(strcmp(value, "true") == 0); return true; }
if (strEquals(command, "balance")) { config.setBalance(static_cast<uint8_t>(atoi(value))); return true; }
if (strEquals(command, "reboot")) { ESP.restart(); return true; }
if (strEquals(command, "format")) { SPIFFS.format(); ESP.restart(); return true; }
if (strEquals(command, "submitplaylist")) { return true; }
#if IR_PIN!=255
if (strEquals(command, "irbtn")) { config.setIrBtn(atoi(value)); return true; }
if (strEquals(command, "chkid")) { config.irchck = static_cast<uint8_t>(atoi(value)); return true; }
if (strEquals(command, "irclr")) { config.ircodes.irVals[config.irindex][static_cast<uint8_t>(atoi(value))] = 0; return true; }
#endif
if (strEquals(command, "reset")) { config.resetSystem(value, cid); return true; }
if (strEquals(command, "smartstart")){ uint8_t ss = atoi(value) == 1 ? 1 : 2; if (!player.isRunning() && ss == 1) ss = 0; config.setSmartStart(ss); return true; }
if (strEquals(command, "audioinfo")) { config.saveValue(&config.store.audioinfo, static_cast<bool>(atoi(value))); display.putRequest(AUDIOINFO); return true; }
if (strEquals(command, "vumeter")) { config.saveValue(&config.store.vumeter, static_cast<bool>(atoi(value))); display.putRequest(SHOWVUMETER); return true; }
if (strEquals(command, "softap")) { config.saveValue(&config.store.softapdelay, static_cast<uint8_t>(atoi(value))); return true; }
if (strEquals(command, "mdnsname")) { config.saveValue(config.store.mdnsname, value, MDNS_LENGTH); return true; }
if (strEquals(command, "rebootmdns")){
char buf[MDNS_LENGTH*2];
if(strlen(config.store.mdnsname)>0) snprintf(buf, MDNS_LENGTH*2, "{\"redirect\": \"http://%s.local\"}", config.store.mdnsname);
else snprintf(buf, MDNS_LENGTH*2, "{\"redirect\": \"http://%s/\"}", WiFi.localIP().toString().c_str());
websocket.text(cid, buf); delay(500); ESP.restart();
return true;
}
return false;
}

View File

@@ -0,0 +1,18 @@
#ifndef commandhandler_h
#define commandhandler_h
#include <Arduino.h>
class CommandHandler {
public:
bool exec(const char *command, const char *value, uint8_t cid=0);
private:
static bool strEquals(const char *a, const char *b) {
return strcmp(a, b) == 0;
}
};
extern CommandHandler cmd;
#endif

View File

@@ -5,6 +5,7 @@
#include "player.h" #include "player.h"
#include "network.h" #include "network.h"
#include "netserver.h" #include "netserver.h"
#include "controls.h"
#ifdef USE_SD #ifdef USE_SD
#include "sdmanager.h" #include "sdmanager.h"
#endif #endif
@@ -43,6 +44,7 @@ void Config::init() {
sdResumePos = 0; sdResumePos = 0;
screensaverTicks = 0; screensaverTicks = 0;
screensaverPlayingTicks = 0; screensaverPlayingTicks = 0;
newConfigMode = 0;
isScreensaver = false; isScreensaver = false;
bootInfo(); bootInfo();
#if RTCSUPPORTED #if RTCSUPPORTED
@@ -140,7 +142,7 @@ void Config::changeMode(int newmode){
return; return;
} }
} }
if(newmode<0){ if(newmode<0||newmode>MAX_PLAY_MODE){
store.play_mode++; store.play_mode++;
if(getMode() > MAX_PLAY_MODE) store.play_mode=0; if(getMode() > MAX_PLAY_MODE) store.play_mode=0;
}else{ }else{
@@ -319,6 +321,160 @@ void Config::reset(){
delay(500); delay(500);
ESP.restart(); ESP.restart();
} }
void Config::enableScreensaver(bool val){
saveValue(&store.screensaverEnabled, val);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
}
void Config::setScreensaverTimeout(uint16_t val){
val=constrain(val,5,65520);
saveValue(&store.screensaverTimeout, val);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
}
void Config::setScreensaverBlank(bool val){
saveValue(&store.screensaverBlank, val);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
}
void Config::setScreensaverPlayingEnabled(bool val){
saveValue(&store.screensaverPlayingEnabled, val);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
}
void Config::setScreensaverPlayingTimeout(uint16_t val){
val=constrain(val,1,1080);
config.saveValue(&config.store.screensaverPlayingTimeout, val);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
}
void Config::setScreensaverPlayingBlank(bool val){
saveValue(&store.screensaverPlayingBlank, val);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
}
void Config::setSntpOne(const char *val){
bool tzdone = false;
if (strlen(val) > 0 && strlen(store.sntp2) > 0) {
configTime(store.tzHour * 3600 + store.tzMin * 60, getTimezoneOffset(), val, store.sntp2);
tzdone = true;
} else if (strlen(val) > 0) {
configTime(store.tzHour * 3600 + store.tzMin * 60, getTimezoneOffset(), val);
tzdone = true;
}
if (tzdone) {
network.forceTimeSync = true;
saveValue(config.store.sntp1, val, 35);
}
}
void Config::setShowweather(bool val){
config.saveValue(&config.store.showweather, val);
network.trueWeather=false;
network.forceWeather = true;
display.putRequest(SHOWWEATHER);
}
void Config::setWeatherKey(const char *val){
saveValue(store.weatherkey, val, WEATHERKEY_LENGTH);
network.trueWeather=false;
display.putRequest(NEWMODE, CLEAR);
display.putRequest(NEWMODE, PLAYER);
}
void Config::setSDpos(uint32_t val){
if (getMode()==PM_SDCARD){
sdResumePos = 0;
if(!player.isRunning()){
player.setResumeFilePos(val-player.sd_min);
player.sendCommand({PR_PLAY, config.store.lastSdStation});
}else{
player.setFilePos(val-player.sd_min);
}
}
}
#if IR_PIN!=255
void Config::setIrBtn(int val){
irindex = val;
netserver.irRecordEnable = (irindex >= 0);
irchck = 0;
netserver.irValsToWs();
if (irindex < 0) saveIR();
}
#endif
void Config::resetSystem(const char *val, uint8_t clientId){
if (strcmp(val, "system") == 0) {
saveValue(&store.smartstart, (uint8_t)2, false);
saveValue(&store.audioinfo, false, false);
saveValue(&store.vumeter, false, false);
saveValue(&store.softapdelay, (uint8_t)0, false);
snprintf(store.mdnsname, MDNS_LENGTH, "yoradio-%x", getChipId());
saveValue(store.mdnsname, store.mdnsname, MDNS_LENGTH, true, true);
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
netserver.requestOnChange(GETSYSTEM, clientId);
return;
}
if (strcmp(val, "screen") == 0) {
saveValue(&store.flipscreen, false, false);
display.flip();
saveValue(&store.invertdisplay, false, false);
display.invert();
saveValue(&store.dspon, true, false);
store.brightness = 100;
setBrightness(false);
saveValue(&store.contrast, (uint8_t)55, false);
display.setContrast();
saveValue(&store.numplaylist, false);
saveValue(&store.screensaverEnabled, false);
saveValue(&store.screensaverTimeout, (uint16_t)20);
saveValue(&store.screensaverBlank, false);
saveValue(&store.screensaverPlayingEnabled, false);
saveValue(&store.screensaverPlayingTimeout, (uint16_t)5);
saveValue(&store.screensaverPlayingBlank, false);
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
netserver.requestOnChange(GETSCREEN, clientId);
return;
}
if (strcmp(val, "timezone") == 0) {
saveValue(&store.tzHour, (int8_t)3, false);
saveValue(&store.tzMin, (int8_t)0, false);
saveValue(store.sntp1, "pool.ntp.org", 35, false);
saveValue(store.sntp2, "0.ru.pool.ntp.org", 35);
configTime(store.tzHour * 3600 + store.tzMin * 60, getTimezoneOffset(), store.sntp1, store.sntp2);
network.forceTimeSync = true;
netserver.requestOnChange(GETTIMEZONE, clientId);
return;
}
if (strcmp(val, "weather") == 0) {
saveValue(&store.showweather, false, false);
saveValue(store.weatherlat, "55.7512", 10, false);
saveValue(store.weatherlon, "37.6184", 10, false);
saveValue(store.weatherkey, "", WEATHERKEY_LENGTH);
network.trueWeather=false;
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
netserver.requestOnChange(GETWEATHER, clientId);
return;
}
if (strcmp(val, "controls") == 0) {
saveValue(&store.volsteps, (uint8_t)1, false);
saveValue(&store.fliptouch, false, false);
saveValue(&store.dbgtouch, false, false);
saveValue(&store.skipPlaylistUpDown, false);
setEncAcceleration(200);
setIRTolerance(40);
netserver.requestOnChange(GETCONTROLS, clientId);
return;
}
if (strcmp(val, "1") == 0) {
config.reset();
return;
}
}
void Config::setDefaults() { void Config::setDefaults() {
store.config_set = 4262; store.config_set = 4262;
@@ -373,10 +529,12 @@ void Config::setDefaults() {
store.rotate90 = false; store.rotate90 = false;
store.screensaverEnabled = false; store.screensaverEnabled = false;
store.screensaverTimeout = 20; store.screensaverTimeout = 20;
store.screensaverBlank = false;
snprintf(store.mdnsname, MDNS_LENGTH, "yoradio-%x", getChipId()); snprintf(store.mdnsname, MDNS_LENGTH, "yoradio-%x", getChipId());
store.skipPlaylistUpDown = false; store.skipPlaylistUpDown = false;
store.screensaverPlayingEnabled = false; store.screensaverPlayingEnabled = false;
store.screensaverPlayingTimeout = 5; store.screensaverPlayingTimeout = 5;
store.screensaverPlayingBlank = false;
eepromWrite(EEPROM_START, store); eepromWrite(EEPROM_START, store);
} }
@@ -419,6 +577,8 @@ void Config::setTone(int8_t bass, int8_t middle, int8_t trebble) {
saveValue(&store.bass, bass, false); saveValue(&store.bass, bass, false);
saveValue(&store.middle, middle, false); saveValue(&store.middle, middle, false);
saveValue(&store.trebble, trebble); saveValue(&store.trebble, trebble);
player.setTone(store.bass, store.middle, store.trebble);
netserver.requestOnChange(EQUALIZER, 0);
} }
void Config::setSmartStart(uint8_t ss) { void Config::setSmartStart(uint8_t ss) {
@@ -427,6 +587,8 @@ void Config::setSmartStart(uint8_t ss) {
void Config::setBalance(int8_t balance) { void Config::setBalance(int8_t balance) {
saveValue(&store.balance, balance); saveValue(&store.balance, balance);
player.setBalance(store.balance);
netserver.requestOnChange(BALANCE, 0);
} }
uint8_t Config::setLastStation(uint16_t val) { uint8_t Config::setLastStation(uint16_t val) {

View File

@@ -7,6 +7,7 @@
#include <EEPROM.h> #include <EEPROM.h>
//#include "SD.h" //#include "SD.h"
#include "options.h" #include "options.h"
#include "telnet.h"
#include "rtcsupport.h" #include "rtcsupport.h"
#include "../pluginsManager/pluginsManager.h" #include "../pluginsManager/pluginsManager.h"
@@ -32,7 +33,7 @@
#define DBGVB( ... ) #define DBGVB( ... )
#define DBGH() #define DBGH()
#endif #endif
#define BOOTLOG( ... ) { char buf[120]; sprintf( buf, __VA_ARGS__ ) ; Serial.print("##[BOOT]#\t"); Serial.println(buf); } #define BOOTLOG( ... ) { char buf[120]; sprintf( buf, __VA_ARGS__ ) ; telnet.print("##[BOOT]#\t"); telnet.printf("%s\n",buf); }
#define EVERY_MS(x) static uint32_t tmr; bool flag = millis() - tmr >= (x); if (flag) tmr += (x); if (flag) #define EVERY_MS(x) static uint32_t tmr; bool flag = millis() - tmr >= (x); if (flag) tmr += (x); if (flag)
#define REAL_PLAYL getMode()==PM_WEB?PLAYLIST_PATH:PLAYLIST_SD_PATH #define REAL_PLAYL getMode()==PM_WEB?PLAYLIST_PATH:PLAYLIST_SD_PATH
#define REAL_INDEX getMode()==PM_WEB?INDEX_PATH:INDEX_SD_PATH #define REAL_INDEX getMode()==PM_WEB?INDEX_PATH:INDEX_SD_PATH
@@ -187,6 +188,7 @@ class Config {
uint16_t screensaverTicks; uint16_t screensaverTicks;
uint16_t screensaverPlayingTicks; uint16_t screensaverPlayingTicks;
bool isScreensaver; bool isScreensaver;
int newConfigMode;
public: public:
Config() {}; Config() {};
//void save(); //void save();
@@ -243,6 +245,21 @@ class Config {
uint8_t getMode() { return store.play_mode/* & 0b11*/; } uint8_t getMode() { return store.play_mode/* & 0b11*/; }
void initPlaylistMode(); void initPlaylistMode();
void reset(); void reset();
void enableScreensaver(bool val);
void setScreensaverTimeout(uint16_t val);
void setScreensaverBlank(bool val);
void setScreensaverPlayingEnabled(bool val);
void setScreensaverPlayingTimeout(uint16_t val);
void setScreensaverPlayingBlank(bool val);
void setSntpOne(const char *val);
void setShowweather(bool val);
void setWeatherKey(const char *val);
void setSDpos(uint32_t val);
#if IR_PIN!=255
void setIrBtn(int val);
#endif
void resetSystem(const char *val, uint8_t clientId);
bool spiffsCleanup(); bool spiffsCleanup();
FS* SDPLFS(){ return _SDplaylistFS; } FS* SDPLFS(){ return _SDplaylistFS; }
#if RTCSUPPORTED #if RTCSUPPORTED

View File

@@ -9,8 +9,15 @@
#include "network.h" #include "network.h"
#include "mqtt.h" #include "mqtt.h"
#include "controls.h" #include "controls.h"
#include "commandhandler.h"
#include <Update.h> #include <Update.h>
#include <ESPmDNS.h> #include <ESPmDNS.h>
#if USE_OTA
#include <NetworkUdp.h>
#include <ArduinoOTA.h>
#endif
#ifdef USE_SD #ifdef USE_SD
#include "sdmanager.h" #include "sdmanager.h"
#endif #endif
@@ -27,13 +34,10 @@ NetServer netserver;
AsyncWebServer webserver(80); AsyncWebServer webserver(80);
AsyncWebSocket websocket("/ws"); AsyncWebSocket websocket("/ws");
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 handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final);
void handleUploadWeb(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final); void handleIndex(AsyncWebServerRequest * request);
void handleUpdate(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final); void handleNotFound(AsyncWebServerRequest * request);
void handleHTTPArgs(AsyncWebServerRequest * request);
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len); void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len);
bool shouldReboot = false; bool shouldReboot = false;
@@ -62,45 +66,9 @@ bool NetServer::begin(bool quiet) {
nsQueue = xQueueCreate( 20, sizeof( nsRequestParams_t ) ); nsQueue = xQueueCreate( 20, sizeof( nsRequestParams_t ) );
while(nsQueue==NULL){;} while(nsQueue==NULL){;}
if(config.emptyFS){ webserver.on("/", HTTP_ANY, handleIndex);
webserver.on("/", HTTP_GET, [](AsyncWebServerRequest * request) { request->send_P(200, "text/html", emptyfs_html); }); webserver.onNotFound(handleNotFound);
webserver.on("/webboard", HTTP_POST, [](AsyncWebServerRequest *request) { request->redirect("/"); ESP.restart(); }, handleUploadWeb); webserver.onFileUpload(handleUpload);
webserver.on("/", HTTP_POST, [](AsyncWebServerRequest *request) {
if(request->arg("ssid")!="" && request->arg("pass")!=""){
char buf[BUFLEN];
memset(buf, 0, BUFLEN);
snprintf(buf, BUFLEN, "%s\t%s", request->arg("ssid").c_str(), request->arg("pass").c_str());
request->redirect("/");
config.saveWifiFromNextion(buf);
return;
}
request->redirect("/");
ESP.restart();
}, handleUploadWeb);
}else{
webserver.on("/", HTTP_ANY, handleHTTPArgs);
webserver.on("/settings.html", HTTP_GET, handleHTTPArgs);
webserver.on("/update.html", HTTP_GET, handleHTTPArgs);
webserver.on("/ir.html", HTTP_GET, handleHTTPArgs);
webserver.on("/webboard", HTTP_GET, [](AsyncWebServerRequest * request) { request->send_P(200, "text/html", emptyfs_html); });
webserver.on("/webboard", HTTP_POST, [](AsyncWebServerRequest *request) { request->redirect("/"); }, handleUploadWeb);
}
webserver.on(PLAYLIST_PATH, HTTP_GET, handleHTTPArgs);
webserver.on(INDEX_PATH, HTTP_GET, handleHTTPArgs);
webserver.on(PLAYLIST_SD_PATH, HTTP_GET, handleHTTPArgs);
webserver.on(INDEX_SD_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("/variables.js", HTTP_GET, [](AsyncWebServerRequest * request) {
char varjsbuf[BUFLEN];
sprintf (varjsbuf, "var yoVersion='%s';\nvar formAction='%s';\nvar playMode='%s';\n", YOVERSION, (network.status == CONNECTED && !config.emptyFS)?"webboard":"", (network.status == CONNECTED)?"player":"ap");
request->send(200, "text/html", varjsbuf);
});
webserver.serveStatic("/", SPIFFS, "/www/").setCacheControl("max-age=31536000"); webserver.serveStatic("/", SPIFFS, "/www/").setCacheControl("max-age=31536000");
#ifdef CORS_DEBUG #ifdef CORS_DEBUG
@@ -110,66 +78,47 @@ bool NetServer::begin(bool quiet) {
webserver.begin(); webserver.begin();
if(strlen(config.store.mdnsname)>0) if(strlen(config.store.mdnsname)>0)
MDNS.begin(config.store.mdnsname); MDNS.begin(config.store.mdnsname);
websocket.onEvent(onWsEvent); websocket.onEvent(onWsEvent);
webserver.addHandler(&websocket); webserver.addHandler(&websocket);
#if USE_OTA
//echo -n "helle?" | socat - udp-datagram:255.255.255.255:44490,broadcast if(strlen(config.store.mdnsname)>0)
if (udp.listen(44490)) { ArduinoOTA.setHostname(config.store.mdnsname);
udp.onPacket([](AsyncUDPPacket packet) { #ifdef OTA_PASS
if (strcmp((char*)packet.data(), "helle?") == 0) ArduinoOTA.setPassword(OTA_PASS);
packet.println(WiFi.localIP()); #endif
ArduinoOTA
.onStart([]() {
display.putRequest(NEWMODE, UPDATING);
telnet.printf("Start OTA updating %s\n", ArduinoOTA.getCommand() == U_FLASH?"firmware":"filesystem");
})
.onEnd([]() {
telnet.printf("\nEnd OTA update, Rebooting...\n");
})
.onProgress([](unsigned int progress, unsigned int total) {
telnet.printf("Progress OTA: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
telnet.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) {
telnet.printf("Auth Failed\n");
} else if (error == OTA_BEGIN_ERROR) {
telnet.printf("Begin Failed\n");
} else if (error == OTA_CONNECT_ERROR) {
telnet.printf("Connect Failed\n");
} else if (error == OTA_RECEIVE_ERROR) {
telnet.printf("Receive Failed\n");
} else if (error == OTA_END_ERROR) {
telnet.printf("End Failed\n");
}
}); });
} ArduinoOTA.begin();
#endif
if(!quiet) Serial.println("done"); if(!quiet) Serial.println("done");
return true; return true;
} }
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.sendCommand({PR_STOP, 0});
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){ size_t NetServer::chunkedHtmlPageCallback(uint8_t* buffer, size_t maxLen, size_t index){
File requiredfile; File requiredfile;
bool sdpl = strcmp(netserver.chunkedPathBuffer, PLAYLIST_SD_PATH) == 0; bool sdpl = strcmp(netserver.chunkedPathBuffer, PLAYLIST_SD_PATH) == 0;
@@ -188,21 +137,17 @@ size_t NetServer::chunkedHtmlPageCallback(uint8_t* buffer, size_t maxLen, size_t
size_t canread = (needread > maxLen) ? maxLen : needread; 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); 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.seek(index, SeekSet);
//vTaskDelay(1);
requiredfile.read(buffer, canread); requiredfile.read(buffer, canread);
index += canread; index += canread;
if (requiredfile) requiredfile.close(); if (requiredfile) requiredfile.close();
return canread; return canread;
} }
void NetServer::chunkedHtmlPage(const String& contentType, AsyncWebServerRequest *request, const char * path, bool doproc) { void NetServer::chunkedHtmlPage(const String& contentType, AsyncWebServerRequest *request, const char * path) {
memset(chunkedPathBuffer, 0, sizeof(chunkedPathBuffer)); memset(chunkedPathBuffer, 0, sizeof(chunkedPathBuffer));
strlcpy(chunkedPathBuffer, path, sizeof(chunkedPathBuffer)-1); strlcpy(chunkedPathBuffer, path, sizeof(chunkedPathBuffer)-1);
AsyncWebServerResponse *response; AsyncWebServerResponse *response;
if(doproc) response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback);
response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback, processor);
else
response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback);
request->send(response); request->send(response);
} }
@@ -364,7 +309,7 @@ void NetServer::processQueue(){
case SDINIT: sprintf (wsbuf, "{\"sdinit\": %d}", SDC_CS!=255); break; case SDINIT: sprintf (wsbuf, "{\"sdinit\": %d}", SDC_CS!=255); break;
case GETPLAYERMODE: sprintf (wsbuf, "{\"playermode\": \"%s\"}", config.getMode()==PM_SDCARD?"modesd":"modeweb"); break; case GETPLAYERMODE: sprintf (wsbuf, "{\"playermode\": \"%s\"}", config.getMode()==PM_SDCARD?"modesd":"modeweb"); break;
#ifdef USE_SD #ifdef USE_SD
case CHANGEMODE: config.changeMode(newConfigMode); return; break; case CHANGEMODE: config.changeMode(config.newConfigMode); return; break;
#endif #endif
default: break; default: break;
} }
@@ -391,8 +336,10 @@ void NetServer::loop() {
case IMWIFI: config.saveWifi(); importRequest = IMDONE; break; case IMWIFI: config.saveWifi(); importRequest = IMDONE; break;
default: break; default: break;
} }
//if (rssi < 255) requestOnChange(NRSSI, 0);
processQueue(); processQueue();
#if USE_OTA
ArduinoOTA.handle();
#endif
} }
#if IR_PIN!=255 #if IR_PIN!=255
@@ -413,389 +360,34 @@ void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t client
AwsFrameInfo *info = (AwsFrameInfo*)arg; AwsFrameInfo *info = (AwsFrameInfo*)arg;
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) { if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
data[len] = 0; data[len] = 0;
char cmd[65], val[65]; char comnd[65], val[65];
if (config.parseWsCommand((const char*)data, cmd, val, 65)) { if (config.parseWsCommand((const char*)data, comnd, val, 65)) {
//if (strcmp(cmd, "getmode") == 0 ) { requestOnChange(GETMODE, clientId); return; } if (strcmp(comnd, "trebble") == 0) {
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, "newmode") == 0 ) { newConfigMode = atoi(val); requestOnChange(CHANGEMODE, 0); return; }
if (strcmp(cmd, "smartstart") == 0) {
uint8_t valb = atoi(val);
uint8_t ss = valb == 1 ? 1 : 2;
if (!player.isRunning() && ss == 1) ss = 0;
config.setSmartStart(ss);
return;
}
if (strcmp(cmd, "audioinfo") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.audioinfo, valb);
display.putRequest(AUDIOINFO);
return;
}
if (strcmp(cmd, "vumeter") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.vumeter, valb);
display.putRequest(SHOWVUMETER);
return;
}
if (strcmp(cmd, "prev") == 0) { player.prev(); return; }
if (strcmp(cmd, "toggle") == 0) { player.toggle(); return; }
if (strcmp(cmd, "next") == 0) { player.next(); return; }
if (strcmp(cmd, "volm") == 0) { player.stepVol(false); return; }
if (strcmp(cmd, "volp") == 0) { player.stepVol(true); return; }
if (strcmp(cmd, "play") == 0) { uint16_t valb = atoi(val); player.sendCommand({PR_PLAY, valb}); return; }
if (strcmp(cmd, "softap") == 0) {
uint8_t valb = atoi(val);
config.saveValue(&config.store.softapdelay, valb);
return;
}
if (strcmp(cmd, "mdnsname") == 0) {
config.saveValue(config.store.mdnsname, val, MDNS_LENGTH);
return;
}
if (strcmp(cmd, "rebootmdns") == 0) {
char buf[MDNS_LENGTH*2];
if(strlen(config.store.mdnsname)>0)
snprintf(buf, MDNS_LENGTH*2, "{\"redirect\": \"http://%s.local\"}", config.store.mdnsname);
else
snprintf(buf, MDNS_LENGTH*2, "{\"redirect\": \"http://%s/\"}", WiFi.localIP().toString().c_str());
websocket.text(clientId, buf);
delay(500);
ESP.restart();
return;
}
if (strcmp(cmd, "invertdisplay") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.invertdisplay, valb);
display.invert();
return;
}
if (strcmp(cmd, "numplaylist") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.numplaylist, valb);
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
return;
}
if (strcmp(cmd, "fliptouch") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.fliptouch, valb);
flipTS();
return;
}
if (strcmp(cmd, "dbgtouch") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.dbgtouch, valb);
return;
}
if (strcmp(cmd, "flipscreen") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.flipscreen, valb);
display.flip();
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
return;
}
if (strcmp(cmd, "brightness") == 0) {
uint8_t valb = atoi(val);
if (!config.store.dspon) requestOnChange(DSPON, 0);
config.store.brightness = valb;
config.setBrightness(true);
return;
}
if (strcmp(cmd, "screenon") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.setDspOn(valb);
return;
}
if (strcmp(cmd, "contrast") == 0) {
uint8_t valb = atoi(val);
config.saveValue(&config.store.contrast, valb);
display.setContrast();
return;
}
if (strcmp(cmd, "screensaverenabled") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.screensaverEnabled, valb);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
return;
}
if (strcmp(cmd, "screensavertimeout") == 0) {
uint16_t valb = atoi(val);
valb = constrain(valb,5,65520);
config.saveValue(&config.store.screensaverTimeout, valb);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
return;
}
if (strcmp(cmd, "screensaverblank") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.screensaverBlank, valb);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
return;
}
if (strcmp(cmd, "screensaverplayingenabled") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.screensaverPlayingEnabled, valb);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
return;
}
if (strcmp(cmd, "screensaverplayingtimeout") == 0) {
uint16_t valb = atoi(val);
valb = constrain(valb,1,1080);
config.saveValue(&config.store.screensaverPlayingTimeout, valb);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
return;
}
if (strcmp(cmd, "screensaverplayingblank") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.screensaverPlayingBlank, valb);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
return;
}
if (strcmp(cmd, "tzh") == 0) {
int8_t vali = atoi(val);
config.saveValue(&config.store.tzHour, vali);
return;
}
if (strcmp(cmd, "tzm") == 0) {
int8_t vali = atoi(val);
config.saveValue(&config.store.tzMin, vali);
return;
}
if (strcmp(cmd, "sntp2") == 0) {
config.saveValue(config.store.sntp2, val, 35, false);
return;
}
if (strcmp(cmd, "sntp1") == 0) {
//strlcpy(config.store.sntp1, val, 35);
bool tzdone = false;
if (strlen(val) > 0 && strlen(config.store.sntp2) > 0) {
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), val, config.store.sntp2);
tzdone = true;
} else if (strlen(val) > 0) {
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), val);
tzdone = true;
}
if (tzdone) {
network.forceTimeSync = true;
config.saveValue(config.store.sntp1, val, 35);
}
return;
}
if (strcmp(cmd, "volsteps") == 0) {
uint8_t valb = atoi(val);
config.saveValue(&config.store.volsteps, valb);
return;
}
if (strcmp(cmd, "encacceleration") == 0) {
uint16_t valb = atoi(val);
setEncAcceleration(valb);
config.saveValue(&config.store.encacc, valb);
return;
}
if (strcmp(cmd, "irtlp") == 0) {
uint8_t valb = atoi(val);
setIRTolerance(valb);
return;
}
if (strcmp(cmd, "oneclickswitching") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.skipPlaylistUpDown, valb);
return;
}
if (strcmp(cmd, "showweather") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.showweather, valb);
network.trueWeather=false;
network.forceWeather = true;
display.putRequest(SHOWWEATHER);
return;
}
if (strcmp(cmd, "lat") == 0) {
config.saveValue(config.store.weatherlat, val, 10, false);
return;
}
if (strcmp(cmd, "lon") == 0) {
config.saveValue(config.store.weatherlon, val, 10, false);
return;
}
if (strcmp(cmd, "key") == 0) {
config.saveValue(config.store.weatherkey, val, WEATHERKEY_LENGTH);
network.trueWeather=false;
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
return;
}
/* RESETS */
if (strcmp(cmd, "reset") == 0) {
if (strcmp(val, "system") == 0) {
config.saveValue(&config.store.smartstart, (uint8_t)2, false);
config.saveValue(&config.store.audioinfo, false, false);
config.saveValue(&config.store.vumeter, false, false);
config.saveValue(&config.store.softapdelay, (uint8_t)0, false);
snprintf(config.store.mdnsname, MDNS_LENGTH, "yoradio-%x", config.getChipId());
config.saveValue(config.store.mdnsname, config.store.mdnsname, MDNS_LENGTH, true, true);
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
requestOnChange(GETSYSTEM, clientId);
return;
}
if (strcmp(val, "screen") == 0) {
config.saveValue(&config.store.flipscreen, false, false);
display.flip();
config.saveValue(&config.store.invertdisplay, false, false);
display.invert();
config.saveValue(&config.store.dspon, true, false);
config.store.brightness = 100;
config.setBrightness(false);
config.saveValue(&config.store.contrast, (uint8_t)55, false);
display.setContrast();
config.saveValue(&config.store.numplaylist, false);
config.saveValue(&config.store.screensaverEnabled, false);
config.saveValue(&config.store.screensaverTimeout, (uint16_t)20);
config.saveValue(&config.store.screensaverBlank, false);
config.saveValue(&config.store.screensaverPlayingEnabled, false);
config.saveValue(&config.store.screensaverPlayingTimeout, (uint16_t)5);
config.saveValue(&config.store.screensaverPlayingBlank, false);
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
requestOnChange(GETSCREEN, clientId);
return;
}
if (strcmp(val, "timezone") == 0) {
config.saveValue(&config.store.tzHour, (int8_t)3, false);
config.saveValue(&config.store.tzMin, (int8_t)0, false);
config.saveValue(config.store.sntp1, "pool.ntp.org", 35, false);
config.saveValue(config.store.sntp2, "0.ru.pool.ntp.org", 35);
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2);
network.forceTimeSync = true;
requestOnChange(GETTIMEZONE, clientId);
return;
}
if (strcmp(val, "weather") == 0) {
config.saveValue(&config.store.showweather, false, false);
config.saveValue(config.store.weatherlat, "55.7512", 10, false);
config.saveValue(config.store.weatherlon, "37.6184", 10, false);
config.saveValue(config.store.weatherkey, "", WEATHERKEY_LENGTH);
network.trueWeather=false;
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
requestOnChange(GETWEATHER, clientId);
return;
}
if (strcmp(val, "controls") == 0) {
config.saveValue(&config.store.volsteps, (uint8_t)1, false);
config.saveValue(&config.store.fliptouch, false, false);
config.saveValue(&config.store.dbgtouch, false, false);
config.saveValue(&config.store.skipPlaylistUpDown, false);
setEncAcceleration(200);
setIRTolerance(40);
requestOnChange(GETCONTROLS, clientId);
return;
}
if (strcmp(val, "1") == 0) {
config.reset();
return;
}
} /* EOF RESETS */
if (strcmp(cmd, "volume") == 0) {
uint8_t v = atoi(val);
player.setVol(v);
}
if (strcmp(cmd, "sdpos") == 0) {
//return;
if (config.getMode()==PM_SDCARD){
config.sdResumePos = 0;
if(!player.isRunning()){
player.setResumeFilePos(atoi(val)-player.sd_min);
player.sendCommand({PR_PLAY, config.store.lastSdStation});
}else{
player.setFilePos(atoi(val)-player.sd_min);
}
}
return;
}
if (strcmp(cmd, "snuffle") == 0) {
config.setSnuffle(strcmp(val, "true") == 0);
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, "trebble") == 0) {
int8_t valb = atoi(val);
player.setTone(config.store.bass, config.store.middle, valb);
config.setTone(config.store.bass, config.store.middle, valb); config.setTone(config.store.bass, config.store.middle, valb);
netserver.requestOnChange(EQUALIZER, 0);
return; return;
} }
if (strcmp(cmd, "middle") == 0) { if (strcmp(comnd, "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); config.setTone(config.store.bass, valb, config.store.trebble);
netserver.requestOnChange(EQUALIZER, 0);
return; return;
} }
if (strcmp(cmd, "bass") == 0) { if (strcmp(comnd, "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); config.setTone(valb, config.store.middle, config.store.trebble);
netserver.requestOnChange(EQUALIZER, 0);
return; return;
} }
if (strcmp(cmd, "reboot") == 0) { if (strcmp(comnd, "submitplaylistdone") == 0) {
ESP.restart();
return;
}
if (strcmp(cmd, "format") == 0) {
SPIFFS.format();
ESP.restart();
return;
}
if (strcmp(cmd, "submitplaylist") == 0) {
return;
}
if (strcmp(cmd, "submitplaylistdone") == 0) {
#ifdef MQTT_ROOT_TOPIC #ifdef MQTT_ROOT_TOPIC
//mqttPublishPlaylist();
mqttplaylistticker.attach(5, mqttplaylistSend); mqttplaylistticker.attach(5, mqttplaylistSend);
#endif #endif
if (player.isRunning()) { if (player.isRunning()) player.sendCommand({PR_PLAY, -config.lastStation()});
player.sendCommand({PR_PLAY, -config.lastStation()});
}
return; return;
} }
#if IR_PIN!=255
if (strcmp(cmd, "irbtn") == 0) { if(cmd.exec(comnd, val, clientId)){
config.irindex = atoi(val); return;
irRecordEnable = (config.irindex >= 0);
config.irchck = 0;
irValsToWs();
if (config.irindex < 0) config.saveIR();
} }
if (strcmp(cmd, "chkid") == 0) {
config.irchck = atoi(val);
}
if (strcmp(cmd, "irclr") == 0) {
uint8_t cl = atoi(val);
config.ircodes.irVals[config.irindex][cl] = 0;
}
#endif
} }
} }
} }
@@ -865,48 +457,66 @@ void NetServer::resetQueue(){
if(nsQueue!=NULL) xQueueReset(nsQueue); if(nsQueue!=NULL) xQueueReset(nsQueue);
} }
String processor(const String& var) { // %Templates%
if (var == "ACTION") return (network.status == CONNECTED && !config.emptyFS)?"webboard":"";
if (var == "UPLOADWIFI") return (network.status == CONNECTED)?" hidden":"";
if (var == "VERSION") return YOVERSION;
return String();
}
int freeSpace; int freeSpace;
void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
if (!index) { if(request->url()=="/upload"){
if(filename!="tempwifi.csv"){ if (!index) {
if(SPIFFS.exists(PLAYLIST_PATH)) SPIFFS.remove(PLAYLIST_PATH); if(filename!="tempwifi.csv"){
if(SPIFFS.exists(INDEX_PATH)) SPIFFS.remove(INDEX_PATH); if(SPIFFS.exists(PLAYLIST_PATH)) SPIFFS.remove(PLAYLIST_PATH);
if(SPIFFS.exists(PLAYLIST_SD_PATH)) SPIFFS.remove(PLAYLIST_SD_PATH); if(SPIFFS.exists(INDEX_PATH)) SPIFFS.remove(INDEX_PATH);
if(SPIFFS.exists(INDEX_SD_PATH)) SPIFFS.remove(INDEX_SD_PATH); if(SPIFFS.exists(PLAYLIST_SD_PATH)) SPIFFS.remove(PLAYLIST_SD_PATH);
if(SPIFFS.exists(INDEX_SD_PATH)) SPIFFS.remove(INDEX_SD_PATH);
}
freeSpace = (float)SPIFFS.totalBytes()/100*68-SPIFFS.usedBytes();
request->_tempFile = SPIFFS.open(TMP_PATH , "w");
} }
freeSpace = (float)SPIFFS.totalBytes()/100*68-SPIFFS.usedBytes(); if (len) {
request->_tempFile = SPIFFS.open(TMP_PATH , "w"); if(freeSpace>index+len){
} request->_tempFile.write(data, len);
if (len) { }
if(freeSpace>index+len){ }
if (final) {
request->_tempFile.close();
}
}else if(request->url()=="/update"){
if (!index) {
int target = (request->getParam("updatetarget", true)->value() == "spiffs") ? U_SPIFFS : U_FLASH;
Serial.printf("Update Start: %s\n", filename.c_str());
player.sendCommand({PR_STOP, 0});
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());
}
}
}else{ // "/webboard"
DBGVB("File: %s, size:%u bytes, index: %u, final: %s\n", filename.c_str(), len, index, final?"true":"false");
if (!index) {
String spath = "/www/";
if(filename=="playlist.csv" || filename=="wifi.csv") spath = "/data/";
request->_tempFile = SPIFFS.open(spath + filename , "w");
}
if (len) {
request->_tempFile.write(data, len); request->_tempFile.write(data, len);
} }
} if (final) {
if (final) { request->_tempFile.close();
request->_tempFile.close(); if(filename=="playlist.csv") config.indexPlaylist();
} }
}
void handleUploadWeb(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
DBGVB("File: %s, size:%u bytes, index: %u, final: %s\n", filename.c_str(), len, index, final?"true":"false");
if (!index) {
String spath = "/www/";
if(filename=="playlist.csv" || filename=="wifi.csv") spath = "/data/";
request->_tempFile = SPIFFS.open(spath + filename , "w");
}
if (len) {
request->_tempFile.write(data, len);
}
if (final) {
request->_tempFile.close();
if(filename=="playlist.csv") config.indexPlaylist();
} }
} }
@@ -920,8 +530,19 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
break; break;
} }
} }
void handleNotFound(AsyncWebServerRequest * request) {
void handleHTTPArgs(AsyncWebServerRequest * request) { #if defined(HTTP_USER) && defined(HTTP_PASS)
if(network.status == CONNECTED)
if (request->url() == "/logout") {
request->send(401);
return;
}
if (!request->authenticate(HTTP_USER, HTTP_PASS)) {
return request->requestAuthentication();
}
#endif
if(request->url()=="/emergency") { request->send_P(200, "text/html", emergency_form); return; }
if(request->method() == HTTP_POST && request->url()=="/webboard" && config.emptyFS) { request->redirect("/"); ESP.restart(); return; }
if (request->method() == HTTP_GET) { if (request->method() == HTTP_GET) {
DBGVB("[%s] client ip=%s request of %s", __func__, request->client()->remoteIP().toString().c_str(), request->url().c_str()); 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 || if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 ||
@@ -934,137 +555,115 @@ void handleHTTPArgs(AsyncWebServerRequest * request) {
if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0) while (mqttplaylistblock) vTaskDelay(5); if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0) while (mqttplaylistblock) vTaskDelay(5);
#endif #endif
if(strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 && config.getMode()==PM_SDCARD){ if(strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 && config.getMode()==PM_SDCARD){
netserver.chunkedHtmlPage("application/octet-stream", request, PLAYLIST_SD_PATH, false); netserver.chunkedHtmlPage("application/octet-stream", request, PLAYLIST_SD_PATH);
}else{ }else{
netserver.chunkedHtmlPage("application/octet-stream", request, request->url().c_str(), false); netserver.chunkedHtmlPage("application/octet-stream", request, request->url().c_str());
}
return;
}// if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 ||
}// if (request->method() == HTTP_GET)
if (request->method() == HTTP_POST) {
if(request->url()=="/webboard"){ request->redirect("/"); return; } // <--post files from /data/www
if(request->url()=="/upload"){ // <--upload playlist.csv or wifi.csv
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);
} }
return; return;
} }
Serial.println(request->url()); if(request->url()=="/update"){ // <--upload firmware
if (strcmp(request->url().c_str(), "/") == 0 && request->params() == 0) { shouldReboot = !Update.hasError();
if(network.status == CONNECTED){ AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", shouldReboot ? "OK" : updateError());
request->send_P(200, "text/html", index_html); response->addHeader("Connection", "close");
}else{ request->send(response);
request->redirect("/settings.html");
}
//netserver.chunkedHtmlPage(String(), request, network.status == CONNECTED ? "/www/index.html" : "/www/settings.html", false);
return; return;
} }
}// if (request->method() == HTTP_POST)
if (request->url() == "/favicon.ico") {
request->send(200, "image/x-icon", "data:,");
return;
}
if (request->url() == "/variables.js") {
char varjsbuf[BUFLEN];
sprintf (varjsbuf, "var yoVersion='%s';\nvar formAction='%s';\nvar playMode='%s';\n", YOVERSION, (network.status == CONNECTED && !config.emptyFS)?"webboard":"", (network.status == CONNECTED)?"player":"ap");
request->send(200, "text/html", varjsbuf);
return;
} }
if (strcmp(request->url().c_str(), "/settings.html") == 0 || strcmp(request->url().c_str(), "/update.html") == 0 || strcmp(request->url().c_str(), "/ir.html") == 0){ if (strcmp(request->url().c_str(), "/settings.html") == 0 || strcmp(request->url().c_str(), "/update.html") == 0 || strcmp(request->url().c_str(), "/ir.html") == 0){
request->send_P(200, "text/html", index_html); request->send_P(200, "text/html", index_html);
return; return;
} }
if (network.status == CONNECTED) { if (request->method() == HTTP_GET && request->url() == "/webboard") {
bool commandFound=false; request->send_P(200, "text/html", emptyfs_html);
if (request->hasArg("start")) { player.sendCommand({PR_PLAY, config.lastStation()}); commandFound=true; } return;
if (request->hasArg("stop")) { player.sendCommand({PR_STOP, 0}); commandFound=true; } }
if (request->hasArg("toggle")) { player.toggle(); commandFound=true; } Serial.print("Not Found: ");
if (request->hasArg("prev")) { player.prev(); commandFound=true; } Serial.println(request->url());
if (request->hasArg("next")) { player.next(); commandFound=true; } request->send(404, "text/plain", "Not found");
if (request->hasArg("volm")) { player.stepVol(false); commandFound=true; } }
if (request->hasArg("volp")) { player.stepVol(true); commandFound=true; }
#ifdef USE_SD void handleIndex(AsyncWebServerRequest * request) {
if (request->hasArg("mode")) { if(config.emptyFS){
AsyncWebParameter* p = request->getParam("mode"); if(request->url()=="/" && request->method() == HTTP_GET ) { request->send_P(200, "text/html", emptyfs_html); return; }
int mm = atoi(p->value().c_str()); if(request->url()=="/" && request->method() == HTTP_POST) {
if(mm>2) mm=0; if(request->arg("ssid")!="" && request->arg("pass")!=""){
if(mm==2) char buf[BUFLEN];
config.changeMode(); memset(buf, 0, BUFLEN);
else snprintf(buf, BUFLEN, "%s\t%s", request->arg("ssid").c_str(), request->arg("pass").c_str());
config.changeMode(mm); request->redirect("/");
commandFound=true; config.saveWifiFromNextion(buf);
return;
}
request->redirect("/");
ESP.restart();
return;
}
Serial.print("Not Found: ");
Serial.println(request->url());
request->send(404, "text/plain", "Not found");
return;
} // end if(config.emptyFS)
#if defined(HTTP_USER) && defined(HTTP_PASS)
if(network.status == CONNECTED)
if (!request->authenticate(HTTP_USER, HTTP_PASS)) {
return request->requestAuthentication();
}
#endif
if (strcmp(request->url().c_str(), "/") == 0 && request->params() == 0) {
if(network.status == CONNECTED) request->send_P(200, "text/html", index_html); else request->redirect("/settings.html");
return;
}
if(network.status == CONNECTED){
int paramsNr = request->params();
if(paramsNr==1){
AsyncWebParameter* p = request->getParam(0);
if(cmd.exec(p->name().c_str(),p->value().c_str())) {
if(p->name()=="reset" || p->name()=="clearspiffs") request->redirect("/");
if(p->name()=="clearspiffs") { delay(100); ESP.restart(); }
request->send(200, "text/plain", "");
return;
}
} }
#endif
if (request->hasArg("reset")) { request->redirect("/"); request->send(200); config.reset(); return; }
if (request->hasArg("trebble") && request->hasArg("middle") && request->hasArg("bass")) { if (request->hasArg("trebble") && request->hasArg("middle") && request->hasArg("bass")) {
AsyncWebParameter* pt = request->getParam("trebble", request->method() == HTTP_POST); config.setTone(request->getParam("bass")->value().toInt(), request->getParam("middle")->value().toInt(), request->getParam("trebble")->value().toInt());
AsyncWebParameter* pm = request->getParam("middle", request->method() == HTTP_POST); request->send(200, "text/plain", "");
AsyncWebParameter* pb = request->getParam("bass", request->method() == HTTP_POST); return;
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);
commandFound=true;
}
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);
commandFound=true;
}
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;
uint16_t cs = config.playlistLength();
if (id > cs) id = cs;
//config.sdResumePos = 0;
player.sendCommand({PR_PLAY, id});
commandFound=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);
commandFound=true;
DBGVB("[%s] vol=%d", __func__, v);
}
if (request->hasArg("dspon")) {
AsyncWebParameter* p = request->getParam("dspon", request->method() == HTTP_POST);
int d = atoi(p->value().c_str());
config.setDspOn(d!=0);
commandFound=true;
}
if (request->hasArg("dim")) {
AsyncWebParameter* p = request->getParam("dim", request->method() == HTTP_POST);
int d = atoi(p->value().c_str());
if (d < 0) d = 0;
if (d > 100) d = 100;
config.store.brightness = (uint8_t)d;
config.setBrightness(true);
commandFound=true;
} }
if (request->hasArg("sleep")) { if (request->hasArg("sleep")) {
AsyncWebParameter* sfor = request->getParam("sleep", request->method() == HTTP_POST); int sford = request->getParam("sleep")->value().toInt();
int sford = atoi(sfor->value().c_str()); int safterd = request->hasArg("after")?request->getParam("after")->value().toInt():0;
int safterd = 0; if(sford > 0 && safterd >= 0){ request->send(200, "text/plain", ""); config.sleepForAfter(sford, safterd); return; }
if(request->hasArg("after")){
AsyncWebParameter* safter = request->getParam("after", request->method() == HTTP_POST);
safterd = atoi(safter->value().c_str());
}
if(sford > 0 && safterd >= 0){
request->send(200);
config.sleepForAfter(sford, safterd);
commandFound=true;
}
}
if (request->hasArg("clearspiffs")) {
if(config.spiffsCleanup()){
config.saveValue(&config.store.play_mode, static_cast<uint8_t>(PM_WEB));
request->redirect("/");
ESP.restart();
}else{
request->send(200);
}
return;
}
if (request->params() > 0) {
request->send(commandFound?200:404);
return;
}
} else {
if (request->params() > 0) {
request->send(404);
return;
} }
request->send(404, "text/plain", "Not found");
}else{
request->send(404, "text/plain", "Not found");
} }
} }

View File

@@ -3,7 +3,6 @@
#include "Arduino.h" #include "Arduino.h"
#include "../AsyncWebServer/ESPAsyncWebServer.h" #include "../AsyncWebServer/ESPAsyncWebServer.h"
#include "AsyncUDP.h"
enum requestType_e : uint8_t { PLAYLIST=1, STATION=2, STATIONNAME=3, ITEM=4, TITLE=5, VOLUME=6, NRSSI=7, BITRATE=8, MODE=9, EQUALIZER=10, BALANCE=11, PLAYLISTSAVED=12, STARTUP=13, GETINDEX=14, GETACTIVE=15, GETSYSTEM=16, GETSCREEN=17, GETTIMEZONE=18, GETWEATHER=19, GETCONTROLS=20, DSPON=21, SDPOS=22, SDLEN=23, SDSNUFFLE=24, SDINIT=25, GETPLAYERMODE=26, CHANGEMODE=27 }; enum requestType_e : uint8_t { PLAYLIST=1, STATION=2, STATIONNAME=3, ITEM=4, TITLE=5, VOLUME=6, NRSSI=7, BITRATE=8, MODE=9, EQUALIZER=10, BALANCE=11, PLAYLISTSAVED=12, STARTUP=13, GETINDEX=14, GETACTIVE=15, GETSYSTEM=16, GETSCREEN=17, GETTIMEZONE=18, GETWEATHER=19, GETCONTROLS=20, DSPON=21, SDPOS=22, SDLEN=23, SDSNUFFLE=24, SDINIT=25, GETPLAYERMODE=26, CHANGEMODE=27 };
enum import_e : uint8_t { IMDONE=0, IMPL=1, IMWIFI=2 }; enum import_e : uint8_t { IMDONE=0, IMPL=1, IMWIFI=2 };
@@ -45,6 +44,7 @@ input[type=text],input[type=password]{width:170px;background:#272727;color:#e3d2
</form> </form>
</div> </div>
</section> </section>
<p><a href="/emergency">emergency firmware uploader</a></p>
<div id="copy">powered by <a target="_blank" href="https://github.com/e2002/yoradio/">ёRadio</a><span id="version"></span></div> <div id="copy">powered by <a target="_blank" href="https://github.com/e2002/yoradio/">ёRadio</a><span id="version"></span></div>
</body> </body>
<script> <script>
@@ -77,6 +77,14 @@ const char index_html[] PROGMEM = R"(
</body> </body>
</html> </html>
)"; )";
const char emergency_form[] PROGMEM = R"(
<form method="POST" action="/update" enctype="multipart/form-data">
<input type="hidden" name="updatetarget" value="fw" />
<label for="uploadfile">upload firmware</label>
<input type="file" id="uploadfile" accept=".bin,.hex" name="update" />
<input type="submit" value="Update" />
</form>
)";
struct nsRequestParams_t struct nsRequestParams_t
{ {
requestType_e type; requestType_e type;
@@ -95,7 +103,7 @@ class NetServer {
void requestOnChange(requestType_e request, uint8_t clientId); void requestOnChange(requestType_e request, uint8_t clientId);
void setRSSI(int val) { rssi = val; }; void setRSSI(int val) { rssi = val; };
int getRSSI() { return rssi; }; int getRSSI() { return rssi; };
void chunkedHtmlPage(const String& contentType, AsyncWebServerRequest *request, const char * path, bool doproc = true); void chunkedHtmlPage(const String& contentType, AsyncWebServerRequest *request, const char * path);
void onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t clientId); void onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t clientId);
bool irRecordEnable; bool irRecordEnable;
#if IR_PIN!=255 #if IR_PIN!=255
@@ -106,16 +114,15 @@ class NetServer {
private: private:
requestType_e request; requestType_e request;
QueueHandle_t nsQueue; QueueHandle_t nsQueue;
int rssi, newConfigMode; int rssi;
void getPlaylist(uint8_t clientId); void getPlaylist(uint8_t clientId);
bool importPlaylist(); bool importPlaylist();
static size_t chunkedHtmlPageCallback(uint8_t* buffer, size_t maxLen, size_t index); static size_t chunkedHtmlPageCallback(uint8_t* buffer, size_t maxLen, size_t index);
static void beginUpload(AsyncWebServerRequest *request);
static void beginUpdate(AsyncWebServerRequest *request);
void processQueue(); void processQueue();
int _readPlaylistLine(File &file, char * line, size_t size); int _readPlaylistLine(File &file, char * line, size_t size);
}; };
extern NetServer netserver; extern NetServer netserver;
extern AsyncWebSocket websocket;
#endif #endif

View File

@@ -1,7 +1,7 @@
#ifndef options_h #ifndef options_h
#define options_h #define options_h
#define YOVERSION "0.9.515" #define YOVERSION "0.9.530"
/******************************************************* /*******************************************************
DO NOT EDIT THIS FILE. DO NOT EDIT THIS FILE.
@@ -480,6 +480,18 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#endif #endif
#ifndef SCREENSAVERSTARTUPDELAY #ifndef SCREENSAVERSTARTUPDELAY
#define SCREENSAVERSTARTUPDELAY 5 #define SCREENSAVERSTARTUPDELAY 5
#endif #endif
#ifndef HEADER_TIMEOUT
#define HEADER_TIMEOUT 5000
#endif
#ifndef USE_OTA
#define USE_OTA false
#endif
//#define OTA_PASS "myotapassword12345"
//#define HTTP_USER "user"
//#define HTTP_PASS "password"
#endif #endif

View File

@@ -107,7 +107,6 @@ void Telnet::loop() {
delay(1000); delay(1000);
} }
handleSerial(); handleSerial();
yield();
} }
void Telnet::print(const char *buf) { void Telnet::print(const char *buf) {
@@ -464,6 +463,11 @@ void Telnet::on_input(const char* str, uint8_t clientId) {
printf(clientId, "Free heap:\t%d bytes\n> ", xPortGetFreeHeapSize()); printf(clientId, "Free heap:\t%d bytes\n> ", xPortGetFreeHeapSize());
return; return;
} }
if (strcmp(str, "sys.config") == 0 || strcmp(str, "config") == 0) {
config.bootInfo();
printf(clientId, "Free heap:\t%d bytes\n> ", xPortGetFreeHeapSize());
return;
}
if (strcmp(str, "wifi.discon") == 0 || strcmp(str, "discon") == 0 || strcmp(str, "disconnect") == 0) { if (strcmp(str, "wifi.discon") == 0 || strcmp(str, "discon") == 0 || strcmp(str, "disconnect") == 0) {
printf(clientId, "#WIFI.DISCON#\tdisconnected...\n> "); printf(clientId, "#WIFI.DISCON#\tdisconnected...\n> ");
WiFi.disconnect(); WiFi.disconnect();

View File

@@ -234,23 +234,15 @@ void Nextion::loop() {
} }
if (sscanf(rxbuf, "balance=%d", &scanDigit) == 1){ if (sscanf(rxbuf, "balance=%d", &scanDigit) == 1){
config.setBalance((int8_t)scanDigit); config.setBalance((int8_t)scanDigit);
player.setBalance(config.store.balance);
netserver.requestOnChange(BALANCE, 0);
} }
if (sscanf(rxbuf, "treble=%d", &scanDigit) == 1){ if (sscanf(rxbuf, "treble=%d", &scanDigit) == 1){
player.setTone(config.store.bass, config.store.middle, scanDigit);
config.setTone(config.store.bass, config.store.middle, scanDigit); config.setTone(config.store.bass, config.store.middle, scanDigit);
netserver.requestOnChange(EQUALIZER, 0);
} }
if (sscanf(rxbuf, "middle=%d", &scanDigit) == 1){ if (sscanf(rxbuf, "middle=%d", &scanDigit) == 1){
player.setTone(config.store.bass, scanDigit, config.store.trebble);
config.setTone(config.store.bass, scanDigit, config.store.trebble); config.setTone(config.store.bass, scanDigit, config.store.trebble);
netserver.requestOnChange(EQUALIZER, 0);
} }
if (sscanf(rxbuf, "bass=%d", &scanDigit) == 1){ if (sscanf(rxbuf, "bass=%d", &scanDigit) == 1){
player.setTone(scanDigit, config.store.middle, config.store.trebble);
config.setTone(scanDigit, config.store.middle, config.store.trebble); config.setTone(scanDigit, config.store.middle, config.store.trebble);
netserver.requestOnChange(EQUALIZER, 0);
} }
if (sscanf(rxbuf, "tzhour=%d", &scanDigit) == 1){ if (sscanf(rxbuf, "tzhour=%d", &scanDigit) == 1){
config.setTimezone((int8_t)scanDigit, config.store.tzMin); config.setTimezone((int8_t)scanDigit, config.store.tzMin);

View File

@@ -47,7 +47,10 @@ void setup() {
#endif #endif
if (config.getMode()==PM_SDCARD) player.initHeaders(config.station.url); if (config.getMode()==PM_SDCARD) player.initHeaders(config.station.url);
player.lockOutput=false; player.lockOutput=false;
if (config.store.smartstart == 1) player.sendCommand({PR_PLAY, config.lastStation()}); if (config.store.smartstart == 1) {
delay(99);
player.sendCommand({PR_PLAY, config.lastStation()});
}
pm.on_end_setup(); pm.on_end_setup();
} }