This commit is contained in:
e2002
2023-09-26 13:30:43 +03:00
parent e823f97f72
commit 60601dac1e
14 changed files with 193 additions and 86 deletions

View File

@@ -229,6 +229,9 @@ Work is in progress...
---
## Version history
#### v0.9.300
- added the ability to play SDCARD without an Internet connection. More in [Wiki](https://github.com/e2002/yoradio/wiki/A-little-about-SD-CARD-and-RTC)
#### v0.9.280
- fixed an issue where it was impossible to reconnect when the WiFi connection was lost

View File

@@ -3,6 +3,7 @@
//#include <SPIFFS.h>
#include "display.h"
#include "player.h"
#include "network.h"
#include "netserver.h"
#include "spidog.h"
@@ -149,6 +150,13 @@ void Config::_mountSD(){
}
void Config::changeMode(int newmode){
if(SDC_CS==255) return;
if(network.status==SOFT_AP || display.mode()==LOST){
store.play_mode=PM_SDCARD;
save();
delay(50);
ESP.restart();
}
if(!SDinit) {
_mountSD();
if(!SDinit){
@@ -174,7 +182,8 @@ void Config::changeMode(int newmode){
delay(10);
delay(50);
}
if(getMode()==PM_WEB) player.setResumeFilePos(0);
//if(getMode()==PM_WEB) player.setResumeFilePos(0);
if((getMode()==PM_WEB && network.status==SDREADY)) ESP.restart();
initPlaylistMode();
if (store.smartstart == 1) player.sendCommand({PR_PLAY, store.lastStation});
//else

View File

@@ -4,6 +4,7 @@
#include "config.h"
#include "player.h"
#include "display.h"
#include "network.h"
#include "netserver.h"
long encOldPosition = 0;
@@ -67,14 +68,14 @@ decode_results irResults;
#if ENC_BTNL!=255
void IRAM_ATTR readEncoderISR()
{
if(display.mode()==LOST || display.mode()==UPDATING) return;
if((SDC_CS==255 && display.mode()==LOST) || display.mode()==UPDATING) return;
encoder.readEncoder_ISR();
}
#endif
#if ENC2_BTNL!=255
void IRAM_ATTR readEncoder2ISR()
{
if(display.mode()==LOST || display.mode()==UPDATING) return;
if((SDC_CS==255 && display.mode()==LOST) || display.mode()==UPDATING) return;
encoder2.readEncoder_ISR();
}
#endif
@@ -129,8 +130,9 @@ void initControls() {
}
void loopControls() {
if(display.mode()==LOST || display.mode()==UPDATING || display.mode()==SDCHANGE) return;
if (ctrls_on_loop) ctrls_on_loop();
if(display.mode()==UPDATING || display.mode()==SDCHANGE) return;
if(SDC_CS==255 && display.mode()==LOST) return;
if(ctrls_on_loop) ctrls_on_loop();
#if ENC_BTNL!=255
encoder1Loop();
#endif
@@ -152,11 +154,13 @@ void loopControls() {
irLoop();
#endif
#if (TS_MODEL!=TS_MODEL_UNDEFINED) && (DSP_MODEL!=DSP_DUMMY)
touchscreen.loop();
if (network.status == CONNECTED || network.status==SDREADY) touchscreen.loop();
#endif
}
#if ENC_BTNL!=255 || ENC2_BTNL!=255
void encodersLoop(yoEncoder *enc, bool first){
if (network.status != CONNECTED && network.status!=SDREADY) return;
if(display.mode()==LOST) return;
int8_t encoderDelta = enc->encoderChanged();
if (encoderDelta!=0)
{
@@ -246,6 +250,8 @@ void irLoop() {
for(int target=0; target<17; target++){
for(int j=0; j<3; j++){
if(config.ircodes.irVals[target][j]==irResults.value){
if (network.status != CONNECTED && network.status!=SDREADY && target!=IR_AST) return;
if(target!=IR_AST && display.mode()==LOST) return;
switch (target){
case IR_PLAY: {
irBlink();
@@ -402,6 +408,7 @@ boolean checklpdelay(int m, unsigned long &tstamp) {
}
void onBtnDuringLongPress(int id) {
if (network.status != CONNECTED && network.status!=SDREADY) return;
if (checklpdelay(BTN_LONGPRESS_LOOP_DELAY, lpdelay)) {
switch ((controlEvt_e)id) {
case EVT_BTNLEFT: {
@@ -457,6 +464,8 @@ void controlsEvent(bool toRight, int8_t volDelta) {
}
void onBtnClick(int id) {
bool passBnCenter = (controlEvt_e)id==EVT_BTNCENTER || (controlEvt_e)id==EVT_ENCBTNB || (controlEvt_e)id==EVT_ENC2BTNB;
if (network.status != CONNECTED && network.status!=SDREADY && (controlEvt_e)id!=EVT_BTNMODE && !passBnCenter) return;
switch ((controlEvt_e)id) {
case EVT_BTNLEFT: {
controlsEvent(false);
@@ -479,6 +488,11 @@ void onBtnClick(int id) {
#endif
player.sendCommand({PR_PLAY, display.currentPlItem});
}
if(network.status==SOFT_AP || display.mode()==LOST){
#ifdef USE_SD
config.changeMode();
#endif
}
break;
}
case EVT_BTNRIGHT: {
@@ -517,6 +531,7 @@ void onBtnDoubleClick(int id) {
switch ((controlEvt_e)id) {
case EVT_BTNLEFT: {
if (display.mode() != PLAYER) return;
if (network.status != CONNECTED && network.status!=SDREADY) return;
player.prev();
break;
}
@@ -529,6 +544,7 @@ void onBtnDoubleClick(int id) {
}
case EVT_BTNRIGHT: {
if (display.mode() != PLAYER) return;
if (network.status != CONNECTED && network.status!=SDREADY) return;
player.next();
break;
}

View File

@@ -209,7 +209,7 @@ void Display::_start() {
#ifdef USE_NEXTION
nextion.wake();
#endif
if (network.status != CONNECTED) {
if (network.status != CONNECTED && network.status != SDREADY) {
_apScreen();
#ifdef USE_NEXTION
nextion.apScreen();
@@ -262,7 +262,7 @@ void Display::_swichMode(displayMode_e newmode) {
//nextion.swichMode(newmode);
nextion.putRequest({NEWMODE, newmode});
#endif
if (newmode == _mode || network.status != CONNECTED) return;
if (newmode == _mode || (network.status != CONNECTED && network.status != SDREADY)) return;
_mode = newmode;
dsp.setScrollId(NULL);
if (newmode == PLAYER) {
@@ -436,6 +436,12 @@ void Display::loop() {
case PSTART: _layoutChange(true); break;
case PSTOP: _layoutChange(false); break;
case DSP_START: _start(); break;
case NEWIP: {
#ifndef HIDE_IP
if(_volip) _volip->setText(WiFi.localIP().toString().c_str(), iptxtFmt);
#endif
break;
}
default: break;
}
}

View File

@@ -12,7 +12,7 @@ enum displayMode_e { PLAYER, VOL, STATIONS, NUMBERS, LOST, UPDATING, INFO, SETTI
enum pages_e : uint8_t { PG_PLAYER=0, PG_DIALOG=1, PG_PLAYLIST=2 };
//enum dialogType_e : uint8_t { DG_NONE=0, DG_VOLUME=1, DG_LOST=2, DG_UPDATING=3, DG_NEXTION=4 };
enum displayRequestType_e { BOOTSTRING, NEWMODE, CLOCK, NEWTITLE, NEWSTATION, NEXTSTATION, DRAWPLAYLIST, DRAWVOL, DBITRATE, AUDIOINFO, SHOWVUMETER, DSPRSSI, SHOWWEATHER, NEWWEATHER, PSTOP, PSTART, DSP_START, WAITFORSD, SDFILEINDEX };
enum displayRequestType_e { BOOTSTRING, NEWMODE, CLOCK, NEWTITLE, NEWSTATION, NEXTSTATION, DRAWPLAYLIST, DRAWVOL, DBITRATE, AUDIOINFO, SHOWVUMETER, DSPRSSI, SHOWWEATHER, NEWWEATHER, PSTOP, PSTART, DSP_START, WAITFORSD, SDFILEINDEX, NEWIP };
struct requestParams_t
{
displayRequestType_e type;

View File

@@ -59,8 +59,9 @@ char* updateError() {
return ret;
}
bool NetServer::begin() {
Serial.print("##[BOOT]#\tnetserver.begin\t");
bool NetServer::begin(bool quiet) {
if(network.status==SDREADY) return true;
if(!quiet) Serial.print("##[BOOT]#\tnetserver.begin\t");
importRequest = IMDONE;
irRecordEnable = false;
nsQueue = xQueueCreate( 20, sizeof( nsRequestParams_t ) );
@@ -112,7 +113,7 @@ bool NetServer::begin() {
packet.println(WiFi.localIP());
});
}
Serial.println("done");
if(!quiet) Serial.println("done");
return true;
}
@@ -313,6 +314,7 @@ void NetServer::processQueue(){
}
void NetServer::loop() {
if(network.status==SDREADY) return;
if (shouldReboot) {
Serial.println("Rebooting...");
delay(100);

View File

@@ -55,7 +55,7 @@ class NetServer {
char chunkedPathBuffer[40];
public:
NetServer() {};
bool begin();
bool begin(bool quiet=false);
void loop();
void requestOnChange(requestType_e request, uint8_t clientId);
void setRSSI(int val) { rssi = val; };

View File

@@ -7,9 +7,15 @@
#include "player.h"
#include "mqtt.h"
#ifndef WIFI_ATTEMPTS
#define WIFI_ATTEMPTS 16
#endif
Network network;
TaskHandle_t syncTaskHandle;
//TaskHandle_t reconnectTaskHandle;
bool getWeather(char *wstr);
void doSync(void * pvParameters);
@@ -30,16 +36,18 @@ void ticks() {
timeSyncTicks++;
weatherSyncTicks++;
divrssi = !divrssi;
if(network.forceTimeSync || network.forceWeather){
xTaskCreatePinnedToCore(doSync, "doSync", 1024 * 4, NULL, 0, &syncTaskHandle, 0);
}
if(timeSyncTicks >= timeSyncInterval){
timeSyncTicks=0;
network.forceTimeSync = true;
}
if(weatherSyncTicks >= weatherSyncInterval){
weatherSyncTicks=0;
network.forceWeather = true;
if(network.status == CONNECTED){
if(network.forceTimeSync || network.forceWeather){
xTaskCreatePinnedToCore(doSync, "doSync", 1024 * 4, NULL, 0, &syncTaskHandle, 0);
}
if(timeSyncTicks >= timeSyncInterval){
timeSyncTicks=0;
network.forceTimeSync = true;
}
if(weatherSyncTicks >= weatherSyncInterval){
weatherSyncTicks=0;
network.forceWeather = true;
}
}
#if RTCSUPPORTED
rtc.getTime(&network.timeinfo);
@@ -54,9 +62,11 @@ void ticks() {
#endif
if(player.isRunning() && config.getMode()==PM_SDCARD) netserver.requestOnChange(SDPOS, 0);
if(divrssi) {
netserver.setRSSI(WiFi.RSSI());
netserver.requestOnChange(NRSSI, 0);
display.putRequest(DSPRSSI, netserver.getRSSI());
if(network.status == CONNECTED){
netserver.setRSSI(WiFi.RSSI());
netserver.requestOnChange(NRSSI, 0);
display.putRequest(DSPRSSI, netserver.getRSSI());
}
#ifdef USE_SD
if(display.mode()!=SDCHANGE) player.sendCommand({PR_CHECKSD, 0});
#endif
@@ -68,9 +78,12 @@ void Network::WiFiReconnected(WiFiEvent_t event, WiFiEventInfo_t info){
player.lockOutput = false;
delay(100);
display.putRequest(NEWMODE, PLAYER);
if (network.lostPlaying) {
config.setTitle(const_PlConnect);
player.sendCommand({PR_PLAY, config.store.lastStation});
if(config.getMode()==PM_SDCARD) {
network.status=CONNECTED;
display.putRequest(NEWIP, 0);
}else{
display.putRequest(NEWMODE, PLAYER);
if (network.lostPlaying) player.sendCommand({PR_PLAY, config.store.lastStation});
}
#ifdef MQTT_ROOT_TOPIC
connectToMqtt();
@@ -80,12 +93,67 @@ void Network::WiFiReconnected(WiFiEvent_t event, WiFiEventInfo_t info){
void Network::WiFiLostConnection(WiFiEvent_t event, WiFiEventInfo_t info){
if(!network.beginReconnect){
Serial.printf("Lost connection, reconnecting to %s...\n", config.ssids[config.store.lastSSID-1].ssid);
network.lostPlaying = player.isRunning();
if (network.lostPlaying) { player.lockOutput = true; player.sendCommand({PR_STOP, 0}); }
display.putRequest(NEWMODE, LOST);
if(config.getMode()==PM_SDCARD) {
network.status=SDREADY;
display.putRequest(NEWIP, 0);
}else{
network.lostPlaying = player.isRunning();
if (network.lostPlaying) { player.lockOutput = true; player.sendCommand({PR_STOP, 0}); }
display.putRequest(NEWMODE, LOST);
}
}
network.beginReconnect = true;
WiFi.begin(config.ssids[config.store.lastSSID-1].ssid, config.ssids[config.store.lastSSID-1].password);
WiFi.reconnect();
}
bool Network::wifiBegin(bool silent){
uint8_t ls = (config.store.lastSSID == 0 || config.store.lastSSID > config.ssidsCount) ? 0 : config.store.lastSSID - 1;
uint8_t startedls = ls;
uint8_t errcnt = 0;
WiFi.mode(WIFI_STA);
while (true) {
if(!silent){
Serial.printf("##[BOOT]#\tAttempt to connect to %s\n", config.ssids[ls].ssid);
Serial.print("##[BOOT]#\t");
display.putRequest(BOOTSTRING, ls);
}
WiFi.begin(config.ssids[ls].ssid, config.ssids[ls].password);
while (WiFi.status() != WL_CONNECTED) {
if(!silent) Serial.print(".");
delay(500);
if(LED_BUILTIN!=255 && !silent) digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
errcnt++;
if (errcnt > WIFI_ATTEMPTS) {
errcnt = 0;
ls++;
if (ls > config.ssidsCount - 1) ls = 0;
if(!silent) Serial.println();
break;
}
}
if (WiFi.status() != WL_CONNECTED && ls == startedls) {
return false; break;
}
if (WiFi.status() == WL_CONNECTED) {
config.setLastSSID(ls + 1);
return true; break;
}
}
return false;
}
void searchWiFi(void * pvParameters){
if(!network.wifiBegin(true)){
delay(10000);
xTaskCreatePinnedToCore(searchWiFi, "searchWiFi", 1024 * 4, NULL, 0, NULL, 0);
}else{
network.status = CONNECTED;
netserver.begin(true);
telnet.begin(true);
network.setWifiParams();
display.putRequest(NEWIP, 0);
}
vTaskDelete( NULL );
}
#define DBGAP false
@@ -99,42 +167,33 @@ void Network::begin() {
raiseSoftAP();
return;
}
byte ls = (config.store.lastSSID == 0 || config.store.lastSSID > config.ssidsCount) ? 0 : config.store.lastSSID - 1;
byte startedls = ls;
byte errcnt = 0;
WiFi.mode(WIFI_STA);
while (true) {
Serial.printf("##[BOOT]#\tAttempt to connect to %s\n", config.ssids[ls].ssid);
Serial.print("##[BOOT]#\t");
display.putRequest(BOOTSTRING, ls);
WiFi.begin(config.ssids[ls].ssid, config.ssids[ls].password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
if(LED_BUILTIN!=255) digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
errcnt++;
if (errcnt > 16) {
errcnt = 0;
ls++;
if (ls > config.ssidsCount - 1) ls = 0;
Serial.println();
break;
}
}
if (WiFi.status() != WL_CONNECTED && ls == startedls) {
if(config.getMode()!=PM_SDCARD){
if(!wifiBegin()){
raiseSoftAP();
Serial.println("##[BOOT]#\tdone");
return;
}
if (WiFi.status() == WL_CONNECTED) {
config.setLastSSID(ls + 1);
break; // отстрелялись
}
Serial.println(".");
status = CONNECTED;
setWifiParams();
}else{
status = SDREADY;
xTaskCreatePinnedToCore(searchWiFi, "searchWiFi", 1024 * 4, NULL, 0, NULL, 0);
}
Serial.println(".");
Serial.println("##[BOOT]#\tdone");
if(LED_BUILTIN!=255) digitalWrite(LED_BUILTIN, LOW);
status = CONNECTED;
#if RTCSUPPORTED
rtc.getTime(&network.timeinfo);
mktime(&network.timeinfo);
display.putRequest(CLOCK);
#endif
ctimer.attach(1, ticks);
if (network_on_connect) network_on_connect();
}
void Network::setWifiParams(){
WiFi.setSleep(false);
WiFi.onEvent(WiFiReconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
WiFi.onEvent(WiFiLostConnection, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
@@ -144,19 +203,11 @@ void Network::begin() {
weatherBuf = (char *) malloc(sizeof(char) * WEATHER_STRING_L);
memset(weatherBuf, 0, WEATHER_STRING_L);
#endif
if(strlen(config.store.sntp1)>0 && strlen(config.store.sntp2)>0){
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2);
}else if(strlen(config.store.sntp1)>0){
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1);
}
#if RTCSUPPORTED
rtc.getTime(&network.timeinfo);
mktime(&network.timeinfo);
display.putRequest(CLOCK);
#endif
ctimer.attach(1, ticks);
if (network_on_connect) network_on_connect();
}
void Network::requestTimeSync(bool withTelnetOutput, uint8_t clientId) {

View File

@@ -20,14 +20,16 @@ class Network {
bool firstRun, forceTimeSync, forceWeather;
bool lostPlaying = false, beginReconnect = false;
//uint8_t tsFailCnt, wsFailCnt;
Ticker ctimer;
char *weatherBuf;
bool trueWeather;
public:
Network() {};
void begin();
void requestTimeSync(bool withTelnetOutput=false, uint8_t clientId=0);
void requestWeatherSync();
Ticker ctimer;
char *weatherBuf;
bool trueWeather;
void setWifiParams();
bool wifiBegin(bool silent=false);
private:
Ticker rtimer;
void raiseSoftAP();

View File

@@ -1,7 +1,7 @@
#ifndef options_h
#define options_h
#define YOVERSION "0.9.280"
#define YOVERSION "0.9.300"
/*******************************************************
DO NOT EDIT THIS FILE.

View File

@@ -181,8 +181,12 @@ void Player::_play(uint16_t stationId) {
remoteStationName = false;
config.setDspOn(1);
//display.putRequest(PSTOP);
if(config.getMode()!=PM_SDCARD) {
display.putRequest(PSTOP);
}
setOutputPins(false);
config.setTitle(config.getMode()==PM_WEB?const_PlConnect:"");
//config.setTitle(config.getMode()==PM_WEB?const_PlConnect:"");
config.setTitle(config.getMode()==PM_WEB?const_PlConnect:"[next track]");
config.station.bitrate=0;
config.setBitrateFormat(BF_UNCNOWN);
config.loadStation(stationId);

View File

@@ -12,16 +12,24 @@ bool Telnet::_isIPSet(IPAddress ip) {
return ip.toString() == "0.0.0.0";
}
bool Telnet::begin() {
Serial.print("##[BOOT]#\ttelnet.begin\t");
bool Telnet::begin(bool quiet) {
if(network.status==SDREADY) {
BOOTLOG("Ready in SD Mode!");
BOOTLOG("------------------------------------------------");
Serial.println("##[BOOT]#");
return true;
}
if(!quiet) Serial.print("##[BOOT]#\ttelnet.begin\t");
if (WiFi.status() == WL_CONNECTED || _isIPSet(WiFi.softAPIP())) {
server.begin();
server.setNoDelay(true);
Serial.println("done");
Serial.println("##[BOOT]#");
BOOTLOG("Ready! Go to http:/%s/ to configure", WiFi.localIP().toString().c_str());
BOOTLOG("------------------------------------------------");
Serial.println("##[BOOT]#");
if(!quiet){
Serial.println("done");
Serial.println("##[BOOT]#");
BOOTLOG("Ready! Go to http:/%s/ to configure", WiFi.localIP().toString().c_str());
BOOTLOG("------------------------------------------------");
Serial.println("##[BOOT]#");
}
return true;
} else {
return false;
@@ -59,6 +67,10 @@ void Telnet::handleSerial(){
}
void Telnet::loop() {
if(network.status==SDREADY || network.status!=CONNECTED) {
handleSerial();
return;
}
uint8_t i;
if (WiFi.status() == WL_CONNECTED) {
if (server.hasClient()) {

View File

@@ -9,7 +9,7 @@
class Telnet {
public:
Telnet() {};
bool begin();
bool begin(bool quiet=false);
void loop();
void stop();
void print(byte id, const char *buf);

View File

@@ -37,8 +37,9 @@ void setup() {
display.init();
player.init();
network.begin();
if (network.status != CONNECTED) {
if (network.status != CONNECTED && network.status!=SDREADY) {
netserver.begin();
initControls();
display.putRequest(DSP_START);
while(!display.ready()) delay(10);
return;
@@ -63,10 +64,11 @@ void setup() {
void loop() {
telnet.loop();
if (network.status == CONNECTED) {
if (network.status == CONNECTED || network.status==SDREADY) {
player.loop();
loopControls();
//loopControls();
}
loopControls();
netserver.loop();
}