v0.9.550
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -13,4 +13,5 @@
|
|||||||
--playlist-hover: #323232;
|
--playlist-hover: #323232;
|
||||||
--section-gradient: #111111;
|
--section-gradient: #111111;
|
||||||
--section-border: #555555;
|
--section-border: #555555;
|
||||||
|
--heapbar-color: #3ea220;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,20 +40,23 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef XTASK_MEM_SIZE
|
#ifndef XTASK_MEM_SIZE
|
||||||
#define XTASK_MEM_SIZE 6144 // 8192 / 2
|
//#define XTASK_MEM_SIZE 6144 // 8192 / 2
|
||||||
|
#define XTASK_MEM_SIZE 1024*5
|
||||||
#endif
|
#endif
|
||||||
#ifndef XTASK_PRIOTITY
|
#ifndef XTASK_PRIOTITY
|
||||||
#define XTASK_PRIOTITY 5 //3
|
#define XTASK_PRIOTITY 3 //3
|
||||||
#endif
|
#endif
|
||||||
#ifndef ATCP_TASK_DELAY
|
#ifndef ATCP_TASK_DELAY
|
||||||
#define ATCP_TASK_DELAY 2
|
#define ATCP_TASK_DELAY 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef XQUEUE_SIZE
|
#ifndef XQUEUE_SIZE
|
||||||
#define XQUEUE_SIZE 128 // (32)
|
//#define XQUEUE_SIZE 128 // (32)
|
||||||
|
#define XQUEUE_SIZE 32
|
||||||
#endif
|
#endif
|
||||||
#ifndef SEND_ASYNC_EVENT_DELAY
|
#ifndef SEND_ASYNC_EVENT_DELAY
|
||||||
#define SEND_ASYNC_EVENT_DELAY portMAX_DELAY
|
//#define SEND_ASYNC_EVENT_DELAY portMAX_DELAY
|
||||||
|
#define SEND_ASYNC_EVENT_DELAY pdMS_TO_TICKS(1000)
|
||||||
#endif
|
#endif
|
||||||
class AsyncClient;
|
class AsyncClient;
|
||||||
|
|
||||||
|
|||||||
@@ -61,9 +61,9 @@ size_t AudioBuffer::init() {
|
|||||||
if(m_buffer == NULL) {
|
if(m_buffer == NULL) {
|
||||||
// PSRAM not found, not configured or not enough available
|
// PSRAM not found, not configured or not enough available
|
||||||
m_f_psram = false;
|
m_f_psram = false;
|
||||||
m_buffSize = m_buffSizeRAM;
|
m_buffSize = m_buffSizeRAM * config.store.abuff;
|
||||||
m_buffer = (uint8_t*) calloc(m_buffSize, sizeof(uint8_t));
|
m_buffer = (uint8_t*) calloc(m_buffSize, sizeof(uint8_t));
|
||||||
m_buffSize = m_buffSizeRAM - m_resBuffSizeRAM;
|
m_buffSize = m_buffSizeRAM * config.store.abuff - m_resBuffSizeRAM;
|
||||||
}
|
}
|
||||||
if(!m_buffer)
|
if(!m_buffer)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -370,6 +370,20 @@ void Audio::setConnectionTimeout(uint16_t timeout_ms, uint16_t timeout_ms_ssl){
|
|||||||
if(timeout_ms_ssl) m_timeout_ms_ssl = timeout_ms_ssl;
|
if(timeout_ms_ssl) m_timeout_ms_ssl = timeout_ms_ssl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Audio::connectTask(void* pvParams) {
|
||||||
|
ConnectParams* params = static_cast<ConnectParams*>(pvParams);
|
||||||
|
Audio* self = params->instance;
|
||||||
|
if(self->_client){
|
||||||
|
self->_connectionResult = self->_client->connect(params->hostwoext, params->port/*, self->m_f_ssl ? self->m_timeout_ms_ssl : self->m_timeout_ms*/);
|
||||||
|
}else{
|
||||||
|
self->_connectionResult = false;
|
||||||
|
}
|
||||||
|
free((void*)params->hostwoext);
|
||||||
|
delete params;
|
||||||
|
self->_connectTaskHandle = nullptr;
|
||||||
|
vTaskDelete(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
bool Audio::connecttohost(const char* host, const char* user, const char* pwd) {
|
bool Audio::connecttohost(const char* host, const char* user, const char* pwd) {
|
||||||
// user and pwd for authentification only, can be empty
|
// user and pwd for authentification only, can be empty
|
||||||
@@ -480,7 +494,22 @@ bool Audio::connecttohost(const char* host, const char* user, const char* pwd) {
|
|||||||
|
|
||||||
uint32_t t = millis();
|
uint32_t t = millis();
|
||||||
if(m_f_Log) AUDIO_INFO("connect to %s on port %d path %s", hostwoext, port, extension);
|
if(m_f_Log) AUDIO_INFO("connect to %s on port %d path %s", hostwoext, port, extension);
|
||||||
|
if(!config.store.watchdog){
|
||||||
res = _client->connect(hostwoext, port, m_f_ssl ? m_timeout_ms_ssl : m_timeout_ms);
|
res = _client->connect(hostwoext, port, m_f_ssl ? m_timeout_ms_ssl : m_timeout_ms);
|
||||||
|
}else{
|
||||||
|
ConnectParams* params = new ConnectParams{ strdup(hostwoext), port, this }; _connectionResult = false;
|
||||||
|
xTaskCreatePinnedToCore(connectTask, "ConnectTask", WATCHDOG_TASK_SIZE, params, WATCHDOG_TASK_PRIORITY, &_connectTaskHandle, WATCHDOG_TASK_CORE_ID);
|
||||||
|
for(;;){
|
||||||
|
if(millis()-t>(m_f_ssl ? m_timeout_ms_ssl : m_timeout_ms) || _connectionResult) break;
|
||||||
|
vTaskDelay(10);
|
||||||
|
}
|
||||||
|
res = _connectionResult;
|
||||||
|
if (_connectTaskHandle!=nullptr) {
|
||||||
|
vTaskDelete(_connectTaskHandle);
|
||||||
|
_connectTaskHandle = nullptr;
|
||||||
|
AUDIO_INFO("WATCH DOG HAS FINISHED A WORK, BYE!");
|
||||||
|
}
|
||||||
|
}
|
||||||
if(res){
|
if(res){
|
||||||
uint32_t dt = millis() - t;
|
uint32_t dt = millis() - t;
|
||||||
strcpy(m_lastHost, l_host);
|
strcpy(m_lastHost, l_host);
|
||||||
|
|||||||
@@ -32,10 +32,6 @@
|
|||||||
#include <FFat.h>
|
#include <FFat.h>
|
||||||
#endif // SDFATFS_USED
|
#endif // SDFATFS_USED
|
||||||
|
|
||||||
#ifndef AUDIOBUFFER_MULTIPLIER2
|
|
||||||
#define AUDIOBUFFER_MULTIPLIER2 8
|
|
||||||
#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
|
||||||
@@ -149,7 +145,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
size_t m_buffSizePSRAM = 300000; // most webstreams limit the advance to 100...300Kbytes
|
size_t m_buffSizePSRAM = 300000; // most webstreams limit the advance to 100...300Kbytes
|
||||||
//size_t m_buffSizeRAM = 1600 * 5;
|
//size_t m_buffSizeRAM = 1600 * 5;
|
||||||
size_t m_buffSizeRAM = 1600 * AUDIOBUFFER_MULTIPLIER2;
|
size_t m_buffSizeRAM = 1600;
|
||||||
size_t m_buffSize = 0;
|
size_t m_buffSize = 0;
|
||||||
size_t m_freeSpace = 0;
|
size_t m_freeSpace = 0;
|
||||||
size_t m_writeSpace = 0;
|
size_t m_writeSpace = 0;
|
||||||
@@ -287,6 +283,7 @@ private:
|
|||||||
void IIR_calculateCoefficients(int8_t G1, int8_t G2, int8_t G3);
|
void IIR_calculateCoefficients(int8_t G1, int8_t G2, int8_t G3);
|
||||||
bool ts_parsePacket(uint8_t* packet, uint8_t* packetStart, uint8_t* packetLength);
|
bool ts_parsePacket(uint8_t* packet, uint8_t* packetStart, uint8_t* packetLength);
|
||||||
void _computeVUlevel(int16_t sample[2]);
|
void _computeVUlevel(int16_t sample[2]);
|
||||||
|
static void connectTask(void* pvParams);
|
||||||
// implement several function with respect to the index of string
|
// implement several function with respect to the index of string
|
||||||
void trim(char *s) {
|
void trim(char *s) {
|
||||||
//fb trim in place
|
//fb trim in place
|
||||||
@@ -475,6 +472,14 @@ private:
|
|||||||
std::vector<char*> m_playlistURL; // m3u8 streamURLs buffer
|
std::vector<char*> m_playlistURL; // m3u8 streamURLs buffer
|
||||||
std::vector<uint32_t> m_hashQueue;
|
std::vector<uint32_t> m_hashQueue;
|
||||||
|
|
||||||
|
struct ConnectParams {
|
||||||
|
char *hostwoext = NULL;
|
||||||
|
uint16_t port = 80;
|
||||||
|
Audio* instance;
|
||||||
|
};
|
||||||
|
volatile bool _connectionResult;
|
||||||
|
TaskHandle_t _connectTaskHandle = nullptr;
|
||||||
|
|
||||||
const size_t m_frameSizeWav = 1600;
|
const size_t m_frameSizeWav = 1600;
|
||||||
const size_t m_frameSizeMP3 = 1600;
|
const size_t m_frameSizeMP3 = 1600;
|
||||||
const size_t m_frameSizeAAC = 1600;
|
const size_t m_frameSizeAAC = 1600;
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ size_t AudioBuffer::init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // no PSRAM available, use ESP32 Flash Memory"
|
} else { // no PSRAM available, use ESP32 Flash Memory"
|
||||||
m_buffSize = m_buffSizeRAM;
|
m_buffSize = m_buffSizeRAM * config.store.abuff;
|
||||||
m_buffer = (uint8_t*) calloc(m_buffSize, sizeof(uint8_t));
|
m_buffer = (uint8_t*) calloc(m_buffSize, sizeof(uint8_t));
|
||||||
m_buffSize = m_buffSizeRAM - m_resBuffSizeRAM;
|
m_buffSize = m_buffSizeRAM * config.store.abuff - m_resBuffSizeRAM;
|
||||||
}
|
}
|
||||||
if(!m_buffer)
|
if(!m_buffer)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1713,6 +1713,22 @@ void Audio::setConnectionTimeout(uint16_t timeout_ms, uint16_t timeout_ms_ssl){
|
|||||||
if(timeout_ms) m_timeout_ms = timeout_ms;
|
if(timeout_ms) m_timeout_ms = timeout_ms;
|
||||||
if(timeout_ms_ssl) m_timeout_ms_ssl = timeout_ms_ssl;
|
if(timeout_ms_ssl) m_timeout_ms_ssl = timeout_ms_ssl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Audio::connectTask(void* pvParams) {
|
||||||
|
ConnectParams* params = static_cast<ConnectParams*>(pvParams);
|
||||||
|
Audio* self = params->instance;
|
||||||
|
bool res = true;
|
||||||
|
if(self->_client){
|
||||||
|
self->_connectionResult = self->_client->connect(params->hostwoext, params->port/*, self->m_f_ssl ? self->m_timeout_ms_ssl : self->m_timeout_ms*/);
|
||||||
|
}else{
|
||||||
|
self->_connectionResult = false;
|
||||||
|
}
|
||||||
|
free((void*)params->hostwoext);
|
||||||
|
delete params;
|
||||||
|
self->_connectTaskHandle = nullptr;
|
||||||
|
vTaskDelete(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
bool Audio::connecttohost(String host){
|
bool Audio::connecttohost(String host){
|
||||||
return connecttohost(host.c_str());
|
return connecttohost(host.c_str());
|
||||||
@@ -1827,7 +1843,23 @@ bool Audio::connecttohost(const char* host, const char* user, const char* pwd) {
|
|||||||
|
|
||||||
uint32_t t = millis();
|
uint32_t t = millis();
|
||||||
if(m_f_Log) AUDIO_INFO("connect to %s on port %d path %s", hostwoext, port, extension);
|
if(m_f_Log) AUDIO_INFO("connect to %s on port %d path %s", hostwoext, port, extension);
|
||||||
|
//res = _client->connect(hostwoext, port, m_f_ssl ? m_timeout_ms_ssl : m_timeout_ms);
|
||||||
|
if(!config.store.watchdog){
|
||||||
res = _client->connect(hostwoext, port, m_f_ssl ? m_timeout_ms_ssl : m_timeout_ms);
|
res = _client->connect(hostwoext, port, m_f_ssl ? m_timeout_ms_ssl : m_timeout_ms);
|
||||||
|
}else{
|
||||||
|
ConnectParams* params = new ConnectParams{ strdup(hostwoext), port, this }; _connectionResult = false;
|
||||||
|
xTaskCreatePinnedToCore(connectTask, "ConnectTask", WATCHDOG_TASK_SIZE, params, WATCHDOG_TASK_PRIORITY, &_connectTaskHandle, WATCHDOG_TASK_CORE_ID);
|
||||||
|
for(;;){
|
||||||
|
if(millis()-t>(m_f_ssl ? m_timeout_ms_ssl : m_timeout_ms) || _connectionResult) break;
|
||||||
|
vTaskDelay(10);
|
||||||
|
}
|
||||||
|
res = _connectionResult;
|
||||||
|
if (_connectTaskHandle!=nullptr) {
|
||||||
|
vTaskDelete(_connectTaskHandle);
|
||||||
|
_connectTaskHandle = nullptr;
|
||||||
|
AUDIO_INFO("WATCH DOG HAS FINISHED A WORK, BYE!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(res){
|
if(res){
|
||||||
uint32_t dt = millis() - t;
|
uint32_t dt = millis() - t;
|
||||||
|
|||||||
@@ -9,10 +9,6 @@
|
|||||||
#ifndef _vs1053_ext
|
#ifndef _vs1053_ext
|
||||||
#define _vs1053_ext
|
#define _vs1053_ext
|
||||||
|
|
||||||
#ifndef AUDIOBUFFER_MULTIPLIER2
|
|
||||||
#define AUDIOBUFFER_MULTIPLIER2 10
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define VS1053VOLM 128 // 128 or 96 only
|
#define VS1053VOLM 128 // 128 or 96 only
|
||||||
#define VS1053VOL(v) (VS1053VOLM==128?log10(((float)v+1)) * 50.54571334 + 128:log10(((float)v+1)) * 64.54571334 + 96)
|
#define VS1053VOL(v) (VS1053VOLM==128?log10(((float)v+1)) * 50.54571334 + 128:log10(((float)v+1)) * 64.54571334 + 96)
|
||||||
|
|
||||||
@@ -107,7 +103,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
const size_t m_buffSizePSRAM = 300000; // most webstreams limit the advance to 100...300Kbytes
|
const size_t m_buffSizePSRAM = 300000; // most webstreams limit the advance to 100...300Kbytes
|
||||||
//const size_t m_buffSizeRAM = 1600 * 10;
|
//const size_t m_buffSizeRAM = 1600 * 10;
|
||||||
const size_t m_buffSizeRAM = 1600 * AUDIOBUFFER_MULTIPLIER2;
|
const size_t m_buffSizeRAM = 1600;
|
||||||
size_t m_buffSize = 0;
|
size_t m_buffSize = 0;
|
||||||
size_t m_freeSpace = 0;
|
size_t m_freeSpace = 0;
|
||||||
size_t m_writeSpace = 0;
|
size_t m_writeSpace = 0;
|
||||||
@@ -136,6 +132,15 @@ private:
|
|||||||
std::vector<char*> m_playlistURL; // m3u8 streamURLs buffer
|
std::vector<char*> m_playlistURL; // m3u8 streamURLs buffer
|
||||||
std::vector<uint32_t> m_hashQueue;
|
std::vector<uint32_t> m_hashQueue;
|
||||||
|
|
||||||
|
struct ConnectParams {
|
||||||
|
char *hostwoext = NULL;
|
||||||
|
uint16_t port = 80;
|
||||||
|
Audio* instance;
|
||||||
|
};
|
||||||
|
volatile bool _connectionResult;
|
||||||
|
TaskHandle_t _connectTaskHandle = nullptr;
|
||||||
|
static void connectTask(void* pvParams);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum : int { AUDIO_NONE, HTTP_RESPONSE_HEADER , AUDIO_DATA, AUDIO_LOCALFILE, AUDIO_METADATA, AUDIO_PLAYLISTINIT,
|
enum : int { AUDIO_NONE, HTTP_RESPONSE_HEADER , AUDIO_DATA, AUDIO_LOCALFILE, AUDIO_METADATA, AUDIO_PLAYLISTINIT,
|
||||||
AUDIO_PLAYLISTHEADER, AUDIO_PLAYLISTDATA, VS1053_SWM, VS1053_OGG};
|
AUDIO_PLAYLISTHEADER, AUDIO_PLAYLISTDATA, VS1053_SWM, VS1053_OGG};
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ void audio_showstation(const char *info) {
|
|||||||
|
|
||||||
void audio_showstreamtitle(const char *info) {
|
void audio_showstreamtitle(const char *info) {
|
||||||
DBGH();
|
DBGH();
|
||||||
if (strstr(info, "Account already in use") != NULL || strstr(info, "HTTP/1.0 401") != NULL) player.setError(info);
|
if (strstr(info, "Account already in use") != NULL || strstr(info, "HTTP/1.0 401") != NULL || strstr(info, "HTTP/1.1 401") != NULL) player.setError(info);
|
||||||
bool p = printable(info) && (strlen(info) > 0);
|
bool p = printable(info) && (strlen(info) > 0);
|
||||||
#ifdef DEBUG_TITLES
|
#ifdef DEBUG_TITLES
|
||||||
config.setTitle(DEBUG_TITLES);
|
config.setTitle(DEBUG_TITLES);
|
||||||
@@ -73,7 +73,7 @@ void audio_showstreamtitle(const char *info) {
|
|||||||
void audio_error(const char *info) {
|
void audio_error(const char *info) {
|
||||||
//config.setTitle(info);
|
//config.setTitle(info);
|
||||||
player.setError(info);
|
player.setError(info);
|
||||||
telnet.printf("##ERROR#:\t%s\n", info);
|
//telnet.printf("##ERROR#:\t%s\n", info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_id3artist(const char *info){
|
void audio_id3artist(const char *info){
|
||||||
@@ -88,11 +88,11 @@ void audio_id3album(const char *info){
|
|||||||
if(strlen(config.station.title)==0){
|
if(strlen(config.station.title)==0){
|
||||||
config.setTitle(info);
|
config.setTitle(info);
|
||||||
}else{
|
}else{
|
||||||
char out[BUFLEN]= {0};
|
size_t tbs = sizeof(config.tmpBuf);
|
||||||
strlcat(out, config.station.title, BUFLEN);
|
strlcat(config.tmpBuf, config.station.title, tbs);
|
||||||
strlcat(out, " - ", BUFLEN);
|
strlcat(config.tmpBuf, " - ", tbs);
|
||||||
strlcat(out, info, BUFLEN);
|
strlcat(config.tmpBuf, info, tbs);
|
||||||
config.setTitle(out);
|
config.setTitle(config.tmpBuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "controls.h"
|
#include "controls.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "telnet.h"
|
||||||
|
|
||||||
CommandHandler cmd;
|
CommandHandler cmd;
|
||||||
|
|
||||||
@@ -65,11 +66,16 @@ bool CommandHandler::exec(const char *command, const char *value, uint8_t cid) {
|
|||||||
if (strEquals(command, "screensaverplayingenabled")){ config.setScreensaverPlayingEnabled(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, "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, "screensaverplayingblank")) { config.setScreensaverPlayingBlank(static_cast<bool>(atoi(value))); return true; }
|
||||||
|
if (strEquals(command, "abuff")){ config.saveValue(&config.store.abuff, static_cast<uint16_t>(atoi(value))); return true; }
|
||||||
|
if (strEquals(command, "telnet")){ config.saveValue(&config.store.telnet, static_cast<bool>(atoi(value))); telnet.toggle(); return true; }
|
||||||
|
if (strEquals(command, "watchdog")){ config.saveValue(&config.store.watchdog, 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, "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, "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, "sntp2")) { config.saveValue(config.store.sntp2, value, 35, false); return true; }
|
||||||
if (strEquals(command, "sntp1")) { config.setSntpOne(value); return true; }
|
if (strEquals(command, "sntp1")) { config.setSntpOne(value); return true; }
|
||||||
|
if (strEquals(command, "timeint")) { config.saveValue(&config.store.timeSyncInterval, static_cast<uint16_t>(atoi(value))); return true; }
|
||||||
|
if (strEquals(command, "timeintrtc")) { config.saveValue(&config.store.timeSyncIntervalRTC, static_cast<uint16_t>(atoi(value))); return true; }
|
||||||
|
|
||||||
if (strEquals(command, "volsteps")) { config.saveValue(&config.store.volsteps, static_cast<uint8_t>(atoi(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, "encacc")) { setEncAcceleration(static_cast<uint16_t>(atoi(value))); return true; }
|
||||||
@@ -79,14 +85,16 @@ bool CommandHandler::exec(const char *command, const char *value, uint8_t cid) {
|
|||||||
if (strEquals(command, "lat")) { config.saveValue(config.store.weatherlat, value, 10, false); 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, "lon")) { config.saveValue(config.store.weatherlon, value, 10, false); return true; }
|
||||||
if (strEquals(command, "key")) { config.setWeatherKey(value); return true; }
|
if (strEquals(command, "key")) { config.setWeatherKey(value); return true; }
|
||||||
//<-----TODO
|
if (strEquals(command, "wint")) { config.saveValue(&config.store.weatherSyncInterval, static_cast<uint16_t>(atoi(value))); return true; }
|
||||||
|
|
||||||
if (strEquals(command, "volume")) { player.setVol(static_cast<uint8_t>(atoi(value))); return true; }
|
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, "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, "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, "balance")) { config.setBalance(static_cast<uint8_t>(atoi(value))); return true; }
|
||||||
if (strEquals(command, "reboot")) { ESP.restart(); return true; }
|
if (strEquals(command, "reboot")) { ESP.restart(); return true; }
|
||||||
|
if (strEquals(command, "boot")) { ESP.restart(); return true; }
|
||||||
if (strEquals(command, "format")) { SPIFFS.format(); ESP.restart(); return true; }
|
if (strEquals(command, "format")) { SPIFFS.format(); ESP.restart(); return true; }
|
||||||
if (strEquals(command, "submitplaylist")) { return true; }
|
if (strEquals(command, "submitplaylist")) { player.sendCommand({PR_STOP, 0}); return true; }
|
||||||
|
|
||||||
#if IR_PIN!=255
|
#if IR_PIN!=255
|
||||||
if (strEquals(command, "irbtn")) { config.setIrBtn(atoi(value)); return true; }
|
if (strEquals(command, "irbtn")) { config.setIrBtn(atoi(value)); return true; }
|
||||||
@@ -101,10 +109,9 @@ bool CommandHandler::exec(const char *command, const char *value, uint8_t cid) {
|
|||||||
if (strEquals(command, "softap")) { config.saveValue(&config.store.softapdelay, static_cast<uint8_t>(atoi(value))); 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, "mdnsname")) { config.saveValue(config.store.mdnsname, value, MDNS_LENGTH); return true; }
|
||||||
if (strEquals(command, "rebootmdns")){
|
if (strEquals(command, "rebootmdns")){
|
||||||
char buf[MDNS_LENGTH*2];
|
if(strlen(config.store.mdnsname)>0) snprintf(config.tmpBuf, sizeof(config.tmpBuf), "{\"redirect\": \"http://%s.local/settings.html\"}", config.store.mdnsname);
|
||||||
if(strlen(config.store.mdnsname)>0) snprintf(buf, MDNS_LENGTH*2, "{\"redirect\": \"http://%s.local\"}", config.store.mdnsname);
|
else snprintf(config.tmpBuf, sizeof(config.tmpBuf), "{\"redirect\": \"http://%s/settings.html\"}", config.ipToStr(WiFi.localIP()));
|
||||||
else snprintf(buf, MDNS_LENGTH*2, "{\"redirect\": \"http://%s/\"}", WiFi.localIP().toString().c_str());
|
websocket.text(cid, config.tmpBuf); delay(500); ESP.restart();
|
||||||
websocket.text(cid, buf); delay(500); ESP.restart();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "netserver.h"
|
#include "netserver.h"
|
||||||
#include "controls.h"
|
#include "controls.h"
|
||||||
|
#include "timekeeper.h"
|
||||||
#ifdef USE_SD
|
#ifdef USE_SD
|
||||||
#include "sdmanager.h"
|
#include "sdmanager.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -13,6 +14,19 @@
|
|||||||
|
|
||||||
Config config;
|
Config config;
|
||||||
|
|
||||||
|
#ifdef HEAP_DBG
|
||||||
|
void printHeapFragmentationInfo(const char* title){
|
||||||
|
size_t freeHeap = heap_caps_get_free_size(MALLOC_CAP_DEFAULT);
|
||||||
|
size_t largestBlock = heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT);
|
||||||
|
float fragmentation = 100.0 * (1.0 - ((float)largestBlock / (float)freeHeap));
|
||||||
|
Serial.printf("\n****** %s ******\n", title);
|
||||||
|
Serial.printf("* Free heap: %u bytes\n", freeHeap);
|
||||||
|
Serial.printf("* Largest free block: %u bytes\n", largestBlock);
|
||||||
|
Serial.printf("* Fragmentation: %.2f%%\n", fragmentation);
|
||||||
|
Serial.printf("*************************************\n\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void u8fix(char *src){
|
void u8fix(char *src){
|
||||||
char last = src[strlen(src)-1];
|
char last = src[strlen(src)-1];
|
||||||
if ((uint8_t)last >= 0xC2) src[strlen(src)-1]='\0';
|
if ((uint8_t)last >= 0xC2) src[strlen(src)-1]='\0';
|
||||||
@@ -46,7 +60,8 @@ void Config::init() {
|
|||||||
screensaverPlayingTicks = 0;
|
screensaverPlayingTicks = 0;
|
||||||
newConfigMode = 0;
|
newConfigMode = 0;
|
||||||
isScreensaver = false;
|
isScreensaver = false;
|
||||||
bootInfo();
|
memset(tmpBuf, 0, BUFLEN);
|
||||||
|
//bootInfo();
|
||||||
#if RTCSUPPORTED
|
#if RTCSUPPORTED
|
||||||
_rtcFound = false;
|
_rtcFound = false;
|
||||||
BOOTLOG("RTC begin(SDA=%d,SCL=%d)", RTC_SDA, RTC_SCL);
|
BOOTLOG("RTC begin(SDA=%d,SCL=%d)", RTC_SDA, RTC_SCL);
|
||||||
@@ -69,7 +84,7 @@ void Config::init() {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
eepromRead(EEPROM_START, store);
|
eepromRead(EEPROM_START, store);
|
||||||
|
bootInfo(); // https://github.com/e2002/yoradio/pull/149
|
||||||
if (store.config_set != 4262) {
|
if (store.config_set != 4262) {
|
||||||
setDefaults();
|
setDefaults();
|
||||||
}
|
}
|
||||||
@@ -93,6 +108,7 @@ void Config::init() {
|
|||||||
_SDplaylistFS = &SPIFFS;
|
_SDplaylistFS = &SPIFFS;
|
||||||
#endif
|
#endif
|
||||||
_bootDone=false;
|
_bootDone=false;
|
||||||
|
setTimeConf();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::_setupVersion(){
|
void Config::_setupVersion(){
|
||||||
@@ -103,9 +119,8 @@ void Config::_setupVersion(){
|
|||||||
saveValue(&store.screensaverTimeout, (uint16_t)20);
|
saveValue(&store.screensaverTimeout, (uint16_t)20);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
char buf[MDNS_LENGTH];
|
snprintf(tmpBuf, MDNS_LENGTH, "yoradio-%x", (unsigned int)getChipId());
|
||||||
snprintf(buf, MDNS_LENGTH, "yoradio-%x", getChipId());
|
saveValue(store.mdnsname, tmpBuf, MDNS_LENGTH);
|
||||||
saveValue(store.mdnsname, buf, MDNS_LENGTH);
|
|
||||||
saveValue(&store.skipPlaylistUpDown, false);
|
saveValue(&store.skipPlaylistUpDown, false);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
@@ -114,6 +129,13 @@ void Config::_setupVersion(){
|
|||||||
saveValue(&store.screensaverPlayingTimeout, (uint16_t)5);
|
saveValue(&store.screensaverPlayingTimeout, (uint16_t)5);
|
||||||
saveValue(&store.screensaverPlayingBlank, false);
|
saveValue(&store.screensaverPlayingBlank, false);
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
|
saveValue(&store.abuff, (uint16_t)(VS1053_CS==255?7:10));
|
||||||
|
saveValue(&store.telnet, true);
|
||||||
|
saveValue(&store.watchdog, true);
|
||||||
|
saveValue(&store.timeSyncInterval, (uint16_t)60); //min
|
||||||
|
saveValue(&store.timeSyncIntervalRTC, (uint16_t)24); //hours
|
||||||
|
saveValue(&store.weatherSyncInterval, (uint16_t)30); // min
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -200,6 +222,44 @@ bool Config::spiffsCleanup(){
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char * Config::ipToStr(IPAddress ip){
|
||||||
|
snprintf(ipBuf, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
|
||||||
|
return ipBuf;
|
||||||
|
}
|
||||||
|
bool Config::prepareForPlaying(uint16_t stationId){
|
||||||
|
setDspOn(1);
|
||||||
|
vuThreshold = 0;
|
||||||
|
screensaverTicks=SCREENSAVERSTARTUPDELAY;
|
||||||
|
screensaverPlayingTicks=SCREENSAVERSTARTUPDELAY;
|
||||||
|
if(getMode()!=PM_SDCARD) {
|
||||||
|
display.putRequest(PSTOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!loadStation(stationId)) return false;
|
||||||
|
setTitle(getMode()==PM_WEB?const_PlConnect:"[next track]");
|
||||||
|
station.bitrate=0;
|
||||||
|
setBitrateFormat(BF_UNCNOWN);
|
||||||
|
display.putRequest(DBITRATE);
|
||||||
|
display.putRequest(NEWSTATION);
|
||||||
|
display.putRequest(NEWMODE, PLAYER);
|
||||||
|
netserver.requestOnChange(STATION, 0);
|
||||||
|
netserver.requestOnChange(MODE, 0);
|
||||||
|
netserver.loop();
|
||||||
|
netserver.loop();
|
||||||
|
if(store.smartstart!=2)
|
||||||
|
setSmartStart(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void Config::configPostPlaying(uint16_t stationId){
|
||||||
|
if(getMode()==PM_SDCARD) {
|
||||||
|
sdResumePos = 0;
|
||||||
|
saveValue(&store.lastSdStation, stationId);
|
||||||
|
}
|
||||||
|
if(store.smartstart!=2) setSmartStart(1);
|
||||||
|
netserver.requestOnChange(MODE, 0);
|
||||||
|
//display.putRequest(NEWMODE, PLAYER);
|
||||||
|
display.putRequest(PSTART);
|
||||||
|
}
|
||||||
void Config::initPlaylistMode(){
|
void Config::initPlaylistMode(){
|
||||||
uint16_t _lastStation = 0;
|
uint16_t _lastStation = 0;
|
||||||
uint16_t cs = playlistLength();
|
uint16_t cs = playlistLength();
|
||||||
@@ -369,19 +429,17 @@ void Config::setSntpOne(const char *val){
|
|||||||
tzdone = true;
|
tzdone = true;
|
||||||
}
|
}
|
||||||
if (tzdone) {
|
if (tzdone) {
|
||||||
network.forceTimeSync = true;
|
timekeeper.forceTimeSync = true;
|
||||||
saveValue(config.store.sntp1, val, 35);
|
saveValue(config.store.sntp1, val, 35);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Config::setShowweather(bool val){
|
void Config::setShowweather(bool val){
|
||||||
config.saveValue(&config.store.showweather, val);
|
config.saveValue(&config.store.showweather, val);
|
||||||
network.trueWeather=false;
|
timekeeper.forceWeather = true;
|
||||||
network.forceWeather = true;
|
|
||||||
display.putRequest(SHOWWEATHER);
|
display.putRequest(SHOWWEATHER);
|
||||||
}
|
}
|
||||||
void Config::setWeatherKey(const char *val){
|
void Config::setWeatherKey(const char *val){
|
||||||
saveValue(store.weatherkey, val, WEATHERKEY_LENGTH);
|
saveValue(store.weatherkey, val, WEATHERKEY_LENGTH);
|
||||||
network.trueWeather=false;
|
|
||||||
display.putRequest(NEWMODE, CLEAR);
|
display.putRequest(NEWMODE, CLEAR);
|
||||||
display.putRequest(NEWMODE, PLAYER);
|
display.putRequest(NEWMODE, PLAYER);
|
||||||
}
|
}
|
||||||
@@ -411,7 +469,10 @@ void Config::resetSystem(const char *val, uint8_t clientId){
|
|||||||
saveValue(&store.audioinfo, false, false);
|
saveValue(&store.audioinfo, false, false);
|
||||||
saveValue(&store.vumeter, false, false);
|
saveValue(&store.vumeter, false, false);
|
||||||
saveValue(&store.softapdelay, (uint8_t)0, false);
|
saveValue(&store.softapdelay, (uint8_t)0, false);
|
||||||
snprintf(store.mdnsname, MDNS_LENGTH, "yoradio-%x", getChipId());
|
saveValue(&store.abuff, (uint16_t)(VS1053_CS==255?7:10), false);
|
||||||
|
saveValue(&store.telnet, true);
|
||||||
|
saveValue(&store.watchdog, true);
|
||||||
|
snprintf(store.mdnsname, MDNS_LENGTH, "yoradio-%x", (unsigned int)getChipId());
|
||||||
saveValue(store.mdnsname, store.mdnsname, MDNS_LENGTH, true, true);
|
saveValue(store.mdnsname, store.mdnsname, MDNS_LENGTH, true, true);
|
||||||
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
|
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
|
||||||
netserver.requestOnChange(GETSYSTEM, clientId);
|
netserver.requestOnChange(GETSYSTEM, clientId);
|
||||||
@@ -443,8 +504,10 @@ void Config::resetSystem(const char *val, uint8_t clientId){
|
|||||||
saveValue(&store.tzMin, (int8_t)0, false);
|
saveValue(&store.tzMin, (int8_t)0, false);
|
||||||
saveValue(store.sntp1, "pool.ntp.org", 35, false);
|
saveValue(store.sntp1, "pool.ntp.org", 35, false);
|
||||||
saveValue(store.sntp2, "0.ru.pool.ntp.org", 35);
|
saveValue(store.sntp2, "0.ru.pool.ntp.org", 35);
|
||||||
|
saveValue(&store.timeSyncInterval, (uint16_t)60);
|
||||||
|
saveValue(&store.timeSyncIntervalRTC, (uint16_t)24);
|
||||||
configTime(store.tzHour * 3600 + store.tzMin * 60, getTimezoneOffset(), store.sntp1, store.sntp2);
|
configTime(store.tzHour * 3600 + store.tzMin * 60, getTimezoneOffset(), store.sntp1, store.sntp2);
|
||||||
network.forceTimeSync = true;
|
timekeeper.forceTimeSync = true;
|
||||||
netserver.requestOnChange(GETTIMEZONE, clientId);
|
netserver.requestOnChange(GETTIMEZONE, clientId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -453,7 +516,8 @@ void Config::resetSystem(const char *val, uint8_t clientId){
|
|||||||
saveValue(store.weatherlat, "55.7512", 10, false);
|
saveValue(store.weatherlat, "55.7512", 10, false);
|
||||||
saveValue(store.weatherlon, "37.6184", 10, false);
|
saveValue(store.weatherlon, "37.6184", 10, false);
|
||||||
saveValue(store.weatherkey, "", WEATHERKEY_LENGTH);
|
saveValue(store.weatherkey, "", WEATHERKEY_LENGTH);
|
||||||
network.trueWeather=false;
|
saveValue(&store.weatherSyncInterval, (uint16_t)30);
|
||||||
|
//network.trueWeather=false;
|
||||||
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
|
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
|
||||||
netserver.requestOnChange(GETWEATHER, clientId);
|
netserver.requestOnChange(GETWEATHER, clientId);
|
||||||
return;
|
return;
|
||||||
@@ -530,11 +594,17 @@ void Config::setDefaults() {
|
|||||||
store.screensaverEnabled = false;
|
store.screensaverEnabled = false;
|
||||||
store.screensaverTimeout = 20;
|
store.screensaverTimeout = 20;
|
||||||
store.screensaverBlank = false;
|
store.screensaverBlank = false;
|
||||||
snprintf(store.mdnsname, MDNS_LENGTH, "yoradio-%x", getChipId());
|
snprintf(store.mdnsname, MDNS_LENGTH, "yoradio-%x", (unsigned int)getChipId());
|
||||||
store.skipPlaylistUpDown = false;
|
store.skipPlaylistUpDown = false;
|
||||||
store.screensaverPlayingEnabled = false;
|
store.screensaverPlayingEnabled = false;
|
||||||
store.screensaverPlayingTimeout = 5;
|
store.screensaverPlayingTimeout = 5;
|
||||||
store.screensaverPlayingBlank = false;
|
store.screensaverPlayingBlank = false;
|
||||||
|
store.abuff = VS1053_CS==255?7:10;
|
||||||
|
store.telnet = true;
|
||||||
|
store.watchdog = true;
|
||||||
|
store.timeSyncInterval = 60; //min
|
||||||
|
store.timeSyncIntervalRTC = 24; //hour
|
||||||
|
store.weatherSyncInterval = 30; //min
|
||||||
eepromWrite(EEPROM_START, store);
|
eepromWrite(EEPROM_START, store);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,12 +697,11 @@ void Config::indexPlaylist() {
|
|||||||
if (!playlist) {
|
if (!playlist) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char sName[BUFLEN], sUrl[BUFLEN];
|
|
||||||
int sOvol;
|
int sOvol;
|
||||||
File index = SPIFFS.open(INDEX_PATH, "w");
|
File index = SPIFFS.open(INDEX_PATH, "w");
|
||||||
while (playlist.available()) {
|
while (playlist.available()) {
|
||||||
uint32_t pos = playlist.position();
|
uint32_t pos = playlist.position();
|
||||||
if (parseCSV(playlist.readStringUntil('\n').c_str(), sName, sUrl, sOvol)) {
|
if (parseCSV(playlist.readStringUntil('\n').c_str(), tmpBuf, tmpBuf2, sOvol)) {
|
||||||
index.write((uint8_t *) &pos, 4);
|
index.write((uint8_t *) &pos, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -661,7 +730,6 @@ uint16_t Config::playlistLength(){
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
bool Config::loadStation(uint16_t ls) {
|
bool Config::loadStation(uint16_t ls) {
|
||||||
char sName[BUFLEN], sUrl[BUFLEN];
|
|
||||||
int sOvol;
|
int sOvol;
|
||||||
uint16_t cs = playlistLength();
|
uint16_t cs = playlistLength();
|
||||||
if (cs == 0) {
|
if (cs == 0) {
|
||||||
@@ -681,11 +749,11 @@ bool Config::loadStation(uint16_t ls) {
|
|||||||
index.readBytes((char *) &pos, 4);
|
index.readBytes((char *) &pos, 4);
|
||||||
index.close();
|
index.close();
|
||||||
playlist.seek(pos, SeekSet);
|
playlist.seek(pos, SeekSet);
|
||||||
if (parseCSV(playlist.readStringUntil('\n').c_str(), sName, sUrl, sOvol)) {
|
if (parseCSV(playlist.readStringUntil('\n').c_str(), tmpBuf, tmpBuf2, sOvol)) {
|
||||||
memset(station.url, 0, BUFLEN);
|
memset(station.url, 0, BUFLEN);
|
||||||
memset(station.name, 0, BUFLEN);
|
memset(station.name, 0, BUFLEN);
|
||||||
strncpy(station.name, sName, BUFLEN);
|
strncpy(station.name, tmpBuf, BUFLEN);
|
||||||
strncpy(station.url, sUrl, BUFLEN);
|
strncpy(station.url, tmpBuf2, BUFLEN);
|
||||||
station.ovol = sOvol;
|
station.ovol = sOvol;
|
||||||
setLastStation(ls);
|
setLastStation(ls);
|
||||||
}
|
}
|
||||||
@@ -698,11 +766,11 @@ char * Config::stationByNum(uint16_t num){
|
|||||||
File index = SDPLFS()->open(REAL_INDEX, "r");
|
File index = SDPLFS()->open(REAL_INDEX, "r");
|
||||||
index.seek((num - 1) * 4, SeekSet);
|
index.seek((num - 1) * 4, SeekSet);
|
||||||
uint32_t pos;
|
uint32_t pos;
|
||||||
memset(_stationBuf, 0, BUFLEN/2);
|
memset(_stationBuf, 0, sizeof(_stationBuf));
|
||||||
index.readBytes((char *) &pos, 4);
|
index.readBytes((char *) &pos, 4);
|
||||||
index.close();
|
index.close();
|
||||||
playlist.seek(pos, SeekSet);
|
playlist.seek(pos, SeekSet);
|
||||||
strncpy(_stationBuf, playlist.readStringUntil('\t').c_str(), BUFLEN/2);
|
strncpy(_stationBuf, playlist.readStringUntil('\t').c_str(), sizeof(_stationBuf));
|
||||||
playlist.close();
|
playlist.close();
|
||||||
return _stationBuf;
|
return _stationBuf;
|
||||||
}
|
}
|
||||||
@@ -880,6 +948,14 @@ bool Config::saveWifi() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Config::setTimeConf(){
|
||||||
|
if(strlen(store.sntp1)>0 && strlen(store.sntp2)>0){
|
||||||
|
configTime(store.tzHour * 3600 + store.tzMin * 60, getTimezoneOffset(), store.sntp1, store.sntp2);
|
||||||
|
}else if(strlen(store.sntp1)>0){
|
||||||
|
configTime(store.tzHour * 3600 + store.tzMin * 60, getTimezoneOffset(), store.sntp1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Config::initNetwork() {
|
bool Config::initNetwork() {
|
||||||
File file = SPIFFS.open(SSIDS_PATH, "r");
|
File file = SPIFFS.open(SSIDS_PATH, "r");
|
||||||
if (!file || file.isDirectory()) {
|
if (!file || file.isDirectory()) {
|
||||||
@@ -973,7 +1049,7 @@ void Config::doSleepW(){
|
|||||||
|
|
||||||
void Config::sleepForAfter(uint16_t sf, uint16_t sa){
|
void Config::sleepForAfter(uint16_t sf, uint16_t sa){
|
||||||
sleepfor = sf;
|
sleepfor = sf;
|
||||||
if(sa > 0) _sleepTimer.attach(sa * 60, doSleep);
|
if(sa > 0) timekeeper.waitAndDo(sa * 60, doSleep);
|
||||||
else doSleep();
|
else doSleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#ifndef config_h
|
#ifndef config_h
|
||||||
#define config_h
|
#define config_h
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include <Ticker.h>
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <SPIFFS.h>
|
#include <SPIFFS.h>
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
@@ -47,13 +46,23 @@
|
|||||||
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
|
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
|
||||||
#define ESP_ARDUINO_3 1
|
#define ESP_ARDUINO_3 1
|
||||||
#endif
|
#endif
|
||||||
#define CONFIG_VERSION 4
|
|
||||||
|
#ifdef HEAP_DBG
|
||||||
|
#define HEAP_INFO() printHeapFragmentationInfo(__PRETTY_FUNCTION__)
|
||||||
|
void printHeapFragmentationInfo(const char* title);
|
||||||
|
#else
|
||||||
|
#define HEAP_INFO()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CONFIG_VERSION 5
|
||||||
|
|
||||||
enum playMode_e : uint8_t { PM_WEB=0, PM_SDCARD=1 };
|
enum playMode_e : uint8_t { PM_WEB=0, PM_SDCARD=1 };
|
||||||
enum BitrateFormat { BF_UNCNOWN, BF_MP3, BF_AAC, BF_FLAC, BF_OGG, BF_WAV };
|
enum BitrateFormat { BF_UNCNOWN, BF_MP3, BF_AAC, BF_FLAC, BF_OGG, BF_WAV };
|
||||||
|
|
||||||
void u8fix(char *src);
|
void u8fix(char *src);
|
||||||
|
|
||||||
|
void checkAllTasksStack();
|
||||||
|
|
||||||
struct theme_t {
|
struct theme_t {
|
||||||
uint16_t background;
|
uint16_t background;
|
||||||
uint16_t meta;
|
uint16_t meta;
|
||||||
@@ -143,6 +152,12 @@ struct config_t
|
|||||||
bool screensaverPlayingBlank;
|
bool screensaverPlayingBlank;
|
||||||
char mdnsname[24];
|
char mdnsname[24];
|
||||||
bool skipPlaylistUpDown;
|
bool skipPlaylistUpDown;
|
||||||
|
uint16_t abuff;
|
||||||
|
bool telnet;
|
||||||
|
bool watchdog;
|
||||||
|
uint16_t timeSyncInterval;
|
||||||
|
uint16_t timeSyncIntervalRTC;
|
||||||
|
uint16_t weatherSyncInterval;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if IR_PIN!=255
|
#if IR_PIN!=255
|
||||||
@@ -189,6 +204,10 @@ class Config {
|
|||||||
uint16_t screensaverPlayingTicks;
|
uint16_t screensaverPlayingTicks;
|
||||||
bool isScreensaver;
|
bool isScreensaver;
|
||||||
int newConfigMode;
|
int newConfigMode;
|
||||||
|
char tmpBuf[BUFLEN];
|
||||||
|
char tmpBuf2[BUFLEN];
|
||||||
|
char ipBuf[16];
|
||||||
|
char _stationBuf[BUFLEN/2];
|
||||||
public:
|
public:
|
||||||
Config() {};
|
Config() {};
|
||||||
//void save();
|
//void save();
|
||||||
@@ -214,6 +233,7 @@ class Config {
|
|||||||
bool loadStation(uint16_t station);
|
bool loadStation(uint16_t station);
|
||||||
bool initNetwork();
|
bool initNetwork();
|
||||||
bool saveWifi();
|
bool saveWifi();
|
||||||
|
void setTimeConf();
|
||||||
bool saveWifiFromNextion(const char* post);
|
bool saveWifiFromNextion(const char* post);
|
||||||
void setSmartStart(uint8_t ss);
|
void setSmartStart(uint8_t ss);
|
||||||
void setBitrateFormat(BitrateFormat fmt) { configFmt = fmt; }
|
void setBitrateFormat(BitrateFormat fmt) { configFmt = fmt; }
|
||||||
@@ -259,8 +279,10 @@ class Config {
|
|||||||
void setIrBtn(int val);
|
void setIrBtn(int val);
|
||||||
#endif
|
#endif
|
||||||
void resetSystem(const char *val, uint8_t clientId);
|
void resetSystem(const char *val, uint8_t clientId);
|
||||||
|
|
||||||
bool spiffsCleanup();
|
bool spiffsCleanup();
|
||||||
|
char * ipToStr(IPAddress ip);
|
||||||
|
bool prepareForPlaying(uint16_t stationId);
|
||||||
|
void configPostPlaying(uint16_t stationId);
|
||||||
FS* SDPLFS(){ return _SDplaylistFS; }
|
FS* SDPLFS(){ return _SDplaylistFS; }
|
||||||
#if RTCSUPPORTED
|
#if RTCSUPPORTED
|
||||||
bool isRTCFound(){ return _rtcFound; };
|
bool isRTCFound(){ return _rtcFound; };
|
||||||
@@ -303,7 +325,6 @@ class Config {
|
|||||||
#endif
|
#endif
|
||||||
FS* _SDplaylistFS;
|
FS* _SDplaylistFS;
|
||||||
void setDefaults();
|
void setDefaults();
|
||||||
Ticker _sleepTimer;
|
|
||||||
static void doSleep();
|
static void doSleep();
|
||||||
uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
|
uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
|
||||||
void _setupVersion();
|
void _setupVersion();
|
||||||
@@ -314,7 +335,6 @@ class Config {
|
|||||||
uint16_t station = random(1, store.countStation);
|
uint16_t station = random(1, store.countStation);
|
||||||
return station;
|
return station;
|
||||||
}
|
}
|
||||||
char _stationBuf[BUFLEN/2];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Config config;
|
extern Config config;
|
||||||
|
|||||||
@@ -56,12 +56,11 @@ constexpr uint8_t nrOfButtons = sizeof(button) / sizeof(button[0]);
|
|||||||
#include "../IRremoteESP8266/IRtext.h"
|
#include "../IRremoteESP8266/IRtext.h"
|
||||||
#include "../IRremoteESP8266/IRutils.h"
|
#include "../IRremoteESP8266/IRutils.h"
|
||||||
uint8_t irVolRepeat = 0;
|
uint8_t irVolRepeat = 0;
|
||||||
const uint16_t kCaptureBufferSize = 1024;
|
//const uint16_t kCaptureBufferSize = 1024;
|
||||||
const uint8_t kTimeout = IR_TIMEOUT;
|
|
||||||
const uint16_t kMinUnknownSize = 12;
|
const uint16_t kMinUnknownSize = 12;
|
||||||
#define LEGACY_TIMING_INFO false
|
#define LEGACY_TIMING_INFO false
|
||||||
|
|
||||||
IRrecv irrecv(IR_PIN, kCaptureBufferSize, kTimeout, true);
|
IRrecv irrecv(IR_PIN, IR_BUFSIZE, IR_TIMEOUT, true);
|
||||||
decode_results irResults;
|
decode_results irResults;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,48 @@
|
|||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
|
#include "netserver.h"
|
||||||
|
#include "timekeeper.h"
|
||||||
|
|
||||||
Display display;
|
Display display;
|
||||||
#ifdef USE_NEXTION
|
#ifdef USE_NEXTION
|
||||||
Nextion nextion;
|
Nextion nextion;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CORE_STACK_SIZE
|
||||||
|
#define CORE_STACK_SIZE 1024*4
|
||||||
|
#endif
|
||||||
|
#ifndef DSP_TASK_PRIORITY
|
||||||
|
#define DSP_TASK_PRIORITY 2
|
||||||
|
#endif
|
||||||
|
#ifndef DSP_TASK_CORE_ID
|
||||||
|
#define DSP_TASK_CORE_ID 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QueueHandle_t displayQueue;
|
||||||
|
|
||||||
|
static void loopDspTask(void * pvParameters){
|
||||||
|
while(true){
|
||||||
|
#ifndef DUMMYDISPLAY
|
||||||
|
if(displayQueue==NULL) break;
|
||||||
|
netserver.loop();
|
||||||
|
if(timekeeper.loop0())
|
||||||
|
display.loop();
|
||||||
|
// will NOT delay here, would use message dequeue timeout instead
|
||||||
|
//vTaskDelay(DSP_TASK_DELAY);
|
||||||
|
#else
|
||||||
|
netserver.loop();
|
||||||
|
timekeeper.loop0();
|
||||||
|
vTaskDelay(10);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
vTaskDelete( NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Display::_createDspTask(){
|
||||||
|
xTaskCreatePinnedToCore(loopDspTask, "DspTask", CORE_STACK_SIZE, NULL, DSP_TASK_PRIORITY, NULL, DSP_TASK_CORE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef DUMMYDISPLAY
|
#ifndef DUMMYDISPLAY
|
||||||
//============================================================================================================================
|
//============================================================================================================================
|
||||||
DspCore dsp;
|
DspCore dsp;
|
||||||
@@ -19,40 +54,27 @@ DspCore dsp;
|
|||||||
Page *pages[] = { new Page(), new Page(), new Page(), new Page() };
|
Page *pages[] = { new Page(), new Page(), new Page(), new Page() };
|
||||||
|
|
||||||
#ifndef DSQ_SEND_DELAY
|
#ifndef DSQ_SEND_DELAY
|
||||||
#define DSQ_SEND_DELAY portMAX_DELAY
|
//#define DSQ_SEND_DELAY portMAX_DELAY
|
||||||
|
#define DSQ_SEND_DELAY pdMS_TO_TICKS(200)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CORE_STACK_SIZE
|
|
||||||
#define CORE_STACK_SIZE 1024*3
|
|
||||||
#endif
|
|
||||||
#ifndef DSP_TASK_DELAY
|
#ifndef DSP_TASK_DELAY
|
||||||
#define DSP_TASK_DELAY pdMS_TO_TICKS(10)
|
#define DSP_TASK_DELAY pdMS_TO_TICKS(20) // cap for 50 fps
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// will use DSP_QUEUE_TICKS as delay interval for display task runner when there are no msgs in a queue to process
|
||||||
|
#define DSP_QUEUE_TICKS DSP_TASK_DELAY
|
||||||
|
|
||||||
#if !((DSP_MODEL==DSP_ST7735 && DTYPE==INITR_BLACKTAB) || DSP_MODEL==DSP_ST7789 || DSP_MODEL==DSP_ST7796 || DSP_MODEL==DSP_ILI9488 || DSP_MODEL==DSP_ILI9486 || DSP_MODEL==DSP_ILI9341 || DSP_MODEL==DSP_ILI9225)
|
#if !((DSP_MODEL==DSP_ST7735 && DTYPE==INITR_BLACKTAB) || DSP_MODEL==DSP_ST7789 || DSP_MODEL==DSP_ST7796 || DSP_MODEL==DSP_ILI9488 || DSP_MODEL==DSP_ILI9486 || DSP_MODEL==DSP_ILI9341 || DSP_MODEL==DSP_ILI9225)
|
||||||
#undef BITRATE_FULL
|
#undef BITRATE_FULL
|
||||||
#define BITRATE_FULL false
|
#define BITRATE_FULL false
|
||||||
#endif
|
#endif
|
||||||
TaskHandle_t DspTask;
|
|
||||||
QueueHandle_t displayQueue;
|
|
||||||
|
|
||||||
void returnPlayer(){
|
void returnPlayer(){
|
||||||
display.putRequest(NEWMODE, PLAYER);
|
display.putRequest(NEWMODE, PLAYER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::_createDspTask(){
|
|
||||||
xTaskCreatePinnedToCore(loopDspTask, "DspTask", CORE_STACK_SIZE, NULL, 4, &DspTask, !xPortGetCoreID());
|
|
||||||
}
|
|
||||||
|
|
||||||
void loopDspTask(void * pvParameters){
|
|
||||||
while(true){
|
|
||||||
if(displayQueue==NULL) break;
|
|
||||||
display.loop();
|
|
||||||
vTaskDelay(DSP_TASK_DELAY);
|
|
||||||
}
|
|
||||||
vTaskDelete( NULL );
|
|
||||||
DspTask=NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::init() {
|
void Display::init() {
|
||||||
Serial.print("##[BOOT]#\tdisplay.init\t");
|
Serial.print("##[BOOT]#\tdisplay.init\t");
|
||||||
#ifdef USE_NEXTION
|
#ifdef USE_NEXTION
|
||||||
@@ -117,7 +139,7 @@ void Display::_buildPager(){
|
|||||||
_volbar = new SliderWidget(volbarConf, config.theme.volbarin, config.theme.background, 254, config.theme.volbarout);
|
_volbar = new SliderWidget(volbarConf, config.theme.volbarin, config.theme.background, 254, config.theme.volbarout);
|
||||||
#endif
|
#endif
|
||||||
#ifndef HIDE_HEAPBAR
|
#ifndef HIDE_HEAPBAR
|
||||||
_heapbar = new SliderWidget(heapbarConf, config.theme.buffer, config.theme.background, psramInit()?300000:1600 * AUDIOBUFFER_MULTIPLIER2);
|
_heapbar = new SliderWidget(heapbarConf, config.theme.buffer, config.theme.background, psramInit()?300000:1600 * config.store.abuff);
|
||||||
#endif
|
#endif
|
||||||
#ifndef HIDE_VOL
|
#ifndef HIDE_VOL
|
||||||
_voltxt = new TextWidget(voltxtConf, 10, false, config.theme.vol, config.theme.background);
|
_voltxt = new TextWidget(voltxtConf, 10, false, config.theme.vol, config.theme.background);
|
||||||
@@ -197,7 +219,7 @@ void Display::_apScreen() {
|
|||||||
TextWidget *appass2 = (TextWidget*) &_boot->addWidget(new TextWidget(apPass2Conf, 30, false, config.theme.clock, config.theme.background));
|
TextWidget *appass2 = (TextWidget*) &_boot->addWidget(new TextWidget(apPass2Conf, 30, false, config.theme.clock, config.theme.background));
|
||||||
appass2->setText(apPassword);
|
appass2->setText(apPassword);
|
||||||
ScrollWidget *bootSett = (ScrollWidget*) &_boot->addWidget(new ScrollWidget("*", apSettConf, config.theme.title2, config.theme.background));
|
ScrollWidget *bootSett = (ScrollWidget*) &_boot->addWidget(new ScrollWidget("*", apSettConf, config.theme.title2, config.theme.background));
|
||||||
bootSett->setText(WiFi.softAPIP().toString().c_str(), apSettFmt);
|
bootSett->setText(config.ipToStr(WiFi.softAPIP()), apSettFmt);
|
||||||
_pager.addPage(_boot);
|
_pager.addPage(_boot);
|
||||||
_pager.setPage(_boot);
|
_pager.setPage(_boot);
|
||||||
#else
|
#else
|
||||||
@@ -234,7 +256,7 @@ void Display::_start() {
|
|||||||
if(_vuwidget) _vuwidget->lock();
|
if(_vuwidget) _vuwidget->lock();
|
||||||
if(_rssi) _setRSSI(WiFi.RSSI());
|
if(_rssi) _setRSSI(WiFi.RSSI());
|
||||||
#ifndef HIDE_IP
|
#ifndef HIDE_IP
|
||||||
if(_volip) _volip->setText(WiFi.localIP().toString().c_str(), iptxtFmt);
|
if(_volip) _volip->setText(config.ipToStr(WiFi.localIP()), iptxtFmt);
|
||||||
#endif
|
#endif
|
||||||
_pager.setPage( pages[PG_PLAYER]);
|
_pager.setPage( pages[PG_PLAYER]);
|
||||||
_volume();
|
_volume();
|
||||||
@@ -254,11 +276,6 @@ void Display::_showDialog(const char *title){
|
|||||||
_meta.setText(title);
|
_meta.setText(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::_setReturnTicker(uint8_t time_s){
|
|
||||||
_returnTicker.detach();
|
|
||||||
_returnTicker.once(time_s, returnPlayer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::_swichMode(displayMode_e newmode) {
|
void Display::_swichMode(displayMode_e newmode) {
|
||||||
#ifdef USE_NEXTION
|
#ifdef USE_NEXTION
|
||||||
//nextion.swichMode(newmode);
|
//nextion.swichMode(newmode);
|
||||||
@@ -276,7 +293,6 @@ void Display::_swichMode(displayMode_e newmode) {
|
|||||||
dsp.clearDsp();
|
dsp.clearDsp();
|
||||||
#endif
|
#endif
|
||||||
numOfNextStation = 0;
|
numOfNextStation = 0;
|
||||||
_returnTicker.detach();
|
|
||||||
#ifdef META_MOVE
|
#ifdef META_MOVE
|
||||||
_meta.moveBack();
|
_meta.moveBack();
|
||||||
#endif
|
#endif
|
||||||
@@ -304,7 +320,7 @@ void Display::_swichMode(displayMode_e newmode) {
|
|||||||
#ifndef HIDE_IP
|
#ifndef HIDE_IP
|
||||||
_showDialog(const_DlgVolume);
|
_showDialog(const_DlgVolume);
|
||||||
#else
|
#else
|
||||||
_showDialog(WiFi.localIP().toString().c_str());
|
_showDialog(config.ipToStr(WiFi.localIP()));
|
||||||
#endif
|
#endif
|
||||||
_nums.setText(config.store.volume, numtxtFmt);
|
_nums.setText(config.store.volume, numtxtFmt);
|
||||||
}
|
}
|
||||||
@@ -329,11 +345,11 @@ void Display::resetQueue(){
|
|||||||
|
|
||||||
void Display::_drawPlaylist() {
|
void Display::_drawPlaylist() {
|
||||||
dsp.drawPlaylist(currentPlItem);
|
dsp.drawPlaylist(currentPlItem);
|
||||||
_setReturnTicker(30);
|
timekeeper.waitAndReturnPlayer(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::_drawNextStationNum(uint16_t num) {
|
void Display::_drawNextStationNum(uint16_t num) {
|
||||||
_setReturnTicker(30);
|
timekeeper.waitAndReturnPlayer(30);
|
||||||
_meta.setText(config.stationByNum(num));
|
_meta.setText(config.stationByNum(num));
|
||||||
_nums.setText(num, "%d");
|
_nums.setText(num, "%d");
|
||||||
}
|
}
|
||||||
@@ -374,9 +390,7 @@ void Display::_layoutChange(bool played){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifndef DSP_QUEUE_TICKS
|
|
||||||
#define DSP_QUEUE_TICKS 0
|
|
||||||
#endif
|
|
||||||
void Display::loop() {
|
void Display::loop() {
|
||||||
if(_bootStep==0) {
|
if(_bootStep==0) {
|
||||||
_pager.begin();
|
_pager.begin();
|
||||||
@@ -429,7 +443,7 @@ void Display::loop() {
|
|||||||
if(_weather) _weather->lock(!config.store.showweather);
|
if(_weather) _weather->lock(!config.store.showweather);
|
||||||
if(!config.store.showweather){
|
if(!config.store.showweather){
|
||||||
#ifndef HIDE_IP
|
#ifndef HIDE_IP
|
||||||
if(_volip) _volip->setText(WiFi.localIP().toString().c_str(), iptxtFmt);
|
if(_volip) _volip->setText(config.ipToStr(WiFi.localIP()), iptxtFmt);
|
||||||
#endif
|
#endif
|
||||||
}else{
|
}else{
|
||||||
if(_weather) _weather->setText(const_getWeather);
|
if(_weather) _weather->setText(const_getWeather);
|
||||||
@@ -463,13 +477,19 @@ void Display::loop() {
|
|||||||
case DSP_START: _start(); break;
|
case DSP_START: _start(); break;
|
||||||
case NEWIP: {
|
case NEWIP: {
|
||||||
#ifndef HIDE_IP
|
#ifndef HIDE_IP
|
||||||
if(_volip) _volip->setText(WiFi.localIP().toString().c_str(), iptxtFmt);
|
if(_volip) _volip->setText(config.ipToStr(WiFi.localIP()), iptxtFmt);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
|
|
||||||
|
// check if there are more messages waiting in the Q, in this case break the loop() and go
|
||||||
|
// for another round to evict next message, do not waste time to redraw the screen, etc...
|
||||||
|
if (uxQueueMessagesWaiting(displayQueue))
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dsp.loop();
|
dsp.loop();
|
||||||
#if I2S_DOUT==255
|
#if I2S_DOUT==255
|
||||||
player.computeVUlevel();
|
player.computeVUlevel();
|
||||||
@@ -561,7 +581,7 @@ void Display::_volume() {
|
|||||||
if(_voltxt) _voltxt->setText(config.store.volume, voltxtFmt);
|
if(_voltxt) _voltxt->setText(config.store.volume, voltxtFmt);
|
||||||
#endif
|
#endif
|
||||||
if(_mode==VOL) {
|
if(_mode==VOL) {
|
||||||
_setReturnTicker(3);
|
timekeeper.waitAndReturnPlayer(3);
|
||||||
_nums.setText(config.store.volume, numtxtFmt);
|
_nums.setText(config.store.volume, numtxtFmt);
|
||||||
}
|
}
|
||||||
/*#ifdef USE_NEXTION
|
/*#ifdef USE_NEXTION
|
||||||
|
|||||||
@@ -3,20 +3,18 @@
|
|||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include <Ticker.h>
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "../displays/dspcore.h"
|
#include "../displays/dspcore.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if NEXTION_RX!=255 && NEXTION_TX!=255
|
#if NEXTION_RX!=255 && NEXTION_TX!=255
|
||||||
#define USE_NEXTION
|
#define USE_NEXTION
|
||||||
#include "../displays/nextion.h"
|
#include "../displays/nextion.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//static void loopDspTask(void * pvParameters);
|
||||||
|
|
||||||
#ifndef DUMMYDISPLAY
|
#ifndef DUMMYDISPLAY
|
||||||
void loopDspTask(void * pvParameters);
|
|
||||||
|
|
||||||
class Display {
|
class Display {
|
||||||
public:
|
public:
|
||||||
@@ -54,7 +52,6 @@ class Display {
|
|||||||
ClockWidget _clock;
|
ClockWidget _clock;
|
||||||
Page *_boot;
|
Page *_boot;
|
||||||
TextWidget *_bootstring, *_volip, *_voltxt, *_rssi, *_bitrate;
|
TextWidget *_bootstring, *_volip, *_voltxt, *_rssi, *_bitrate;
|
||||||
Ticker _returnTicker;
|
|
||||||
uint8_t _bootStep;
|
uint8_t _bootStep;
|
||||||
void _time(bool redraw = false);
|
void _time(bool redraw = false);
|
||||||
void _apScreen();
|
void _apScreen();
|
||||||
@@ -68,7 +65,6 @@ class Display {
|
|||||||
void _showDialog(const char *title);
|
void _showDialog(const char *title);
|
||||||
void _buildPager();
|
void _buildPager();
|
||||||
void _bootScreen();
|
void _bootScreen();
|
||||||
void _setReturnTicker(uint8_t time_s);
|
|
||||||
void _layoutChange(bool played);
|
void _layoutChange(bool played);
|
||||||
void _setRSSI(int rssi);
|
void _setRSSI(int rssi);
|
||||||
};
|
};
|
||||||
@@ -98,6 +94,8 @@ class Display {
|
|||||||
bool deepsleep(){return true;}
|
bool deepsleep(){return true;}
|
||||||
void wakeup(){}
|
void wakeup(){}
|
||||||
void printPLitem(uint8_t pos, const char* item){}
|
void printPLitem(uint8_t pos, const char* item){}
|
||||||
|
private:
|
||||||
|
void _createDspTask();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
AsyncMqttClient mqttClient;
|
AsyncMqttClient mqttClient;
|
||||||
TimerHandle_t mqttReconnectTimer;
|
TimerHandle_t mqttReconnectTimer;
|
||||||
char topic[140], status[BUFLEN*3], vol[5], buf[20];
|
char topic[100], status[BUFLEN+50];
|
||||||
|
|
||||||
void connectToMqtt() {
|
void connectToMqtt() {
|
||||||
mqttClient.connect();
|
mqttClient.connect();
|
||||||
@@ -25,8 +25,10 @@ void mqttInit() {
|
|||||||
connectToMqtt();
|
connectToMqtt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void zeroBuffer(){ memset(topic, 0, sizeof(topic)); memset(status, 0, sizeof(status)); }
|
||||||
|
|
||||||
void onMqttConnect(bool sessionPresent) {
|
void onMqttConnect(bool sessionPresent) {
|
||||||
memset(topic, 0, 140);
|
zeroBuffer();
|
||||||
sprintf(topic, "%s%s", MQTT_ROOT_TOPIC, "command");
|
sprintf(topic, "%s%s", MQTT_ROOT_TOPIC, "command");
|
||||||
mqttClient.subscribe(topic, 2);
|
mqttClient.subscribe(topic, 2);
|
||||||
mqttPublishStatus();
|
mqttPublishStatus();
|
||||||
@@ -36,13 +38,12 @@ void onMqttConnect(bool sessionPresent) {
|
|||||||
|
|
||||||
void mqttPublishStatus() {
|
void mqttPublishStatus() {
|
||||||
if(mqttClient.connected()){
|
if(mqttClient.connected()){
|
||||||
memset(topic, 0, 140);
|
zeroBuffer();
|
||||||
memset(status, 0, BUFLEN*3);
|
|
||||||
sprintf(topic, "%s%s", MQTT_ROOT_TOPIC, "status");
|
sprintf(topic, "%s%s", MQTT_ROOT_TOPIC, "status");
|
||||||
char name[BUFLEN*2];
|
char name[BUFLEN/2];
|
||||||
char title[BUFLEN*2];
|
char title[BUFLEN/2];
|
||||||
config.escapeQuotes(config.station.name, name, sizeof(name));
|
config.escapeQuotes(config.station.name, name, sizeof(name)-10);
|
||||||
config.escapeQuotes(config.station.title, title, sizeof(name));
|
config.escapeQuotes(config.station.title, title, sizeof(title)-10);
|
||||||
sprintf(status, "{\"status\": %d, \"station\": %d, \"name\": \"%s\", \"title\": \"%s\", \"on\": %d}", player.status()==PLAYING?1:0, config.lastStation(), name, title, config.store.dspon);
|
sprintf(status, "{\"status\": %d, \"station\": %d, \"name\": \"%s\", \"title\": \"%s\", \"on\": %d}", player.status()==PLAYING?1:0, config.lastStation(), name, title, config.store.dspon);
|
||||||
mqttClient.publish(topic, 0, true, status);
|
mqttClient.publish(topic, 0, true, status);
|
||||||
}
|
}
|
||||||
@@ -50,17 +51,17 @@ void mqttPublishStatus() {
|
|||||||
|
|
||||||
void mqttPublishPlaylist() {
|
void mqttPublishPlaylist() {
|
||||||
if(mqttClient.connected()){
|
if(mqttClient.connected()){
|
||||||
memset(topic, 0, 140);
|
zeroBuffer();
|
||||||
memset(status, 0, BUFLEN*3);
|
|
||||||
sprintf(topic, "%s%s", MQTT_ROOT_TOPIC, "playlist");
|
sprintf(topic, "%s%s", MQTT_ROOT_TOPIC, "playlist");
|
||||||
sprintf(status, "http://%s%s", WiFi.localIP().toString().c_str(), PLAYLIST_PATH);
|
sprintf(status, "http://%s%s", config.ipToStr(WiFi.localIP()), PLAYLIST_PATH);
|
||||||
mqttClient.publish(topic, 0, true, status);
|
mqttClient.publish(topic, 0, true, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mqttPublishVolume(){
|
void mqttPublishVolume(){
|
||||||
if(mqttClient.connected()){
|
if(mqttClient.connected()){
|
||||||
memset(topic, 0, 140);
|
zeroBuffer();
|
||||||
|
char vol[5];
|
||||||
memset(vol, 0, 5);
|
memset(vol, 0, 5);
|
||||||
sprintf(topic, "%s%s", MQTT_ROOT_TOPIC, "volume");
|
sprintf(topic, "%s%s", MQTT_ROOT_TOPIC, "volume");
|
||||||
sprintf(vol, "%d", config.store.volume);
|
sprintf(vol, "%d", config.store.volume);
|
||||||
@@ -76,33 +77,16 @@ void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
|
|||||||
|
|
||||||
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
|
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
|
||||||
if (len == 0) return;
|
if (len == 0) return;
|
||||||
memset(buf, 0, 20);
|
if(len<20){
|
||||||
strlcpy(buf, payload, len+1);
|
char buf[len+1];
|
||||||
if (strcmp(buf, "prev") == 0) {
|
strncpy(buf, payload, len);
|
||||||
player.prev();
|
buf[len]='\0';
|
||||||
return;
|
if (strcmp(buf, "prev") == 0) { player.sendCommand({PR_PREV, 0}); return; }
|
||||||
}
|
if (strcmp(buf, "next") == 0) { player.sendCommand({PR_NEXT, 0}); return; }
|
||||||
if (strcmp(buf, "next") == 0) {
|
if (strcmp(buf, "toggle") == 0) { player.sendCommand({PR_TOGGLE, 0}); return; }
|
||||||
player.next();
|
if (strcmp(buf, "stop") == 0) { player.sendCommand({PR_STOP, 0}); return; }
|
||||||
return;
|
if (strcmp(buf, "start") == 0 || strcmp(buf, "play") == 0) { player.sendCommand({PR_PLAY, config.lastStation()}); return; }
|
||||||
}
|
if (strcmp(buf, "boot") == 0 || strcmp(buf, "reboot") == 0) { ESP.restart(); return; }
|
||||||
if (strcmp(buf, "toggle") == 0) {
|
|
||||||
player.toggle();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (strcmp(buf, "stop") == 0) {
|
|
||||||
player.sendCommand({PR_STOP, 0});
|
|
||||||
//telnet.info();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (strcmp(buf, "start") == 0 || strcmp(buf, "play") == 0) {
|
|
||||||
player.sendCommand({PR_PLAY, config.lastStation()});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (strcmp(buf, "boot") == 0 || strcmp(buf, "reboot") == 0) {
|
|
||||||
ESP.restart();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (strcmp(buf, "volm") == 0) {
|
if (strcmp(buf, "volm") == 0) {
|
||||||
player.stepVol(false);
|
player.stepVol(false);
|
||||||
return;
|
return;
|
||||||
@@ -115,7 +99,6 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
|
|||||||
uint8_t sst = config.store.smartstart;
|
uint8_t sst = config.store.smartstart;
|
||||||
config.setDspOn(0);
|
config.setDspOn(0);
|
||||||
player.sendCommand({PR_STOP, 0});
|
player.sendCommand({PR_STOP, 0});
|
||||||
//telnet.info();
|
|
||||||
delay(100);
|
delay(100);
|
||||||
config.saveValue(&config.store.smartstart, sst);
|
config.saveValue(&config.store.smartstart, sst);
|
||||||
return;
|
return;
|
||||||
@@ -140,11 +123,18 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
|
|||||||
player.sendCommand({PR_PLAY, (uint16_t)sb});
|
player.sendCommand({PR_PLAY, (uint16_t)sb});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (strstr(buf, "http")==buf){
|
}else{
|
||||||
|
if(len>MQTT_BURL_SIZE) return;
|
||||||
|
strncpy(player.burl, payload, len);
|
||||||
|
player.burl[len]='\0';
|
||||||
|
player.sendCommand({PR_BURL, 0});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*if (strstr(buf, "http")==0){
|
||||||
if(len+1>sizeof(player.burl)) return;
|
if(len+1>sizeof(player.burl)) return;
|
||||||
strlcpy(player.burl, payload, len+1);
|
strlcpy(player.burl, payload, len+1);
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // #ifdef MQTT_ROOT_TOPIC
|
#endif // #ifdef MQTT_ROOT_TOPIC
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
#ifndef mqtt_h
|
#ifndef mqtt_h
|
||||||
#define mqtt_h
|
#define mqtt_h
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#ifdef MQTT_ROOT_TOPIC
|
|
||||||
//#if __has_include("../../mqttoptions.h")
|
|
||||||
//#include "../../mqttoptions.h"
|
|
||||||
#include "../async-mqtt-client/AsyncMqttClient.h"
|
|
||||||
|
|
||||||
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
|
#include "../async-mqtt-client/AsyncMqttClient.h"
|
||||||
|
|
||||||
void mqttInit();
|
void mqttInit();
|
||||||
void connectToMqtt();
|
void connectToMqtt();
|
||||||
@@ -15,6 +13,7 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
|
|||||||
void mqttPublishStatus();
|
void mqttPublishStatus();
|
||||||
void mqttPublishPlaylist();
|
void mqttPublishPlaylist();
|
||||||
void mqttPublishVolume();
|
void mqttPublishVolume();
|
||||||
|
void zeroBuffer();
|
||||||
|
|
||||||
#endif // #ifdef MQTT_ROOT_TOPIC
|
#endif // #ifdef MQTT_ROOT_TOPIC
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "netserver.h"
|
#include "netserver.h"
|
||||||
#include <SPIFFS.h>
|
#include <SPIFFS.h>
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "telnet.h"
|
#include "telnet.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
@@ -10,17 +9,10 @@
|
|||||||
#include "mqtt.h"
|
#include "mqtt.h"
|
||||||
#include "controls.h"
|
#include "controls.h"
|
||||||
#include "commandhandler.h"
|
#include "commandhandler.h"
|
||||||
|
#include "timekeeper.h"
|
||||||
#include <Update.h>
|
#include <Update.h>
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
|
//#include <Ticker.h>
|
||||||
#if USE_OTA
|
|
||||||
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
|
|
||||||
#include <NetworkUdp.h>
|
|
||||||
#else
|
|
||||||
#include <WiFiUdp.h>
|
|
||||||
#endif
|
|
||||||
#include <ArduinoOTA.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_SD
|
#ifdef USE_SD
|
||||||
#include "sdmanager.h"
|
#include "sdmanager.h"
|
||||||
@@ -29,7 +21,7 @@
|
|||||||
#define MIN_MALLOC 24112
|
#define MIN_MALLOC 24112
|
||||||
#endif
|
#endif
|
||||||
#ifndef NSQ_SEND_DELAY
|
#ifndef NSQ_SEND_DELAY
|
||||||
#define NSQ_SEND_DELAY (TickType_t)100 //portMAX_DELAY?
|
#define NSQ_SEND_DELAY pdMS_TO_TICKS(100) //portMAX_DELAY?
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define CORS_DEBUG //Enable CORS policy: 'Access-Control-Allow-Origin' (for testing)
|
//#define CORS_DEBUG //Enable CORS policy: 'Access-Control-Allow-Origin' (for testing)
|
||||||
@@ -46,20 +38,19 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
|
|||||||
|
|
||||||
bool shouldReboot = false;
|
bool shouldReboot = false;
|
||||||
#ifdef MQTT_ROOT_TOPIC
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
Ticker mqttplaylistticker;
|
//Ticker mqttplaylistticker;
|
||||||
bool mqttplaylistblock = false;
|
bool mqttplaylistblock = false;
|
||||||
void mqttplaylistSend() {
|
void mqttplaylistSend() {
|
||||||
mqttplaylistblock = true;
|
mqttplaylistblock = true;
|
||||||
mqttplaylistticker.detach();
|
// mqttplaylistticker.detach();
|
||||||
mqttPublishPlaylist();
|
mqttPublishPlaylist();
|
||||||
mqttplaylistblock = false;
|
mqttplaylistblock = false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char* updateError() {
|
char* updateError() {
|
||||||
static char ret[140] = {0};
|
sprintf(netserver.nsBuf, "Update failed with error (%d)<br /> %s", (int)Update.getError(), Update.errorString());
|
||||||
sprintf(ret, "Update failed with error (%d)<br /> %s", (int)Update.getError(), Update.errorString());
|
return netserver.nsBuf;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetServer::begin(bool quiet) {
|
bool NetServer::begin(bool quiet) {
|
||||||
@@ -67,6 +58,7 @@ bool NetServer::begin(bool quiet) {
|
|||||||
if(!quiet) Serial.print("##[BOOT]#\tnetserver.begin\t");
|
if(!quiet) Serial.print("##[BOOT]#\tnetserver.begin\t");
|
||||||
importRequest = IMDONE;
|
importRequest = IMDONE;
|
||||||
irRecordEnable = false;
|
irRecordEnable = false;
|
||||||
|
playerBufMax = psramInit()?300000:1600 * config.store.abuff;
|
||||||
nsQueue = xQueueCreate( 20, sizeof( nsRequestParams_t ) );
|
nsQueue = xQueueCreate( 20, sizeof( nsRequestParams_t ) );
|
||||||
while(nsQueue==NULL){;}
|
while(nsQueue==NULL){;}
|
||||||
|
|
||||||
@@ -82,43 +74,8 @@ 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
|
|
||||||
if(strlen(config.store.mdnsname)>0)
|
|
||||||
ArduinoOTA.setHostname(config.store.mdnsname);
|
|
||||||
#ifdef OTA_PASS
|
|
||||||
ArduinoOTA.setPassword(OTA_PASS);
|
|
||||||
#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;
|
||||||
}
|
}
|
||||||
@@ -152,6 +109,7 @@ void NetServer::chunkedHtmlPage(const String& contentType, AsyncWebServerRequest
|
|||||||
strlcpy(chunkedPathBuffer, path, sizeof(chunkedPathBuffer)-1);
|
strlcpy(chunkedPathBuffer, path, sizeof(chunkedPathBuffer)-1);
|
||||||
AsyncWebServerResponse *response;
|
AsyncWebServerResponse *response;
|
||||||
response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback);
|
response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback);
|
||||||
|
response->addHeader("Cache-Control","max-age=31536000");
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,13 +139,12 @@ const char *getFormat(BitrateFormat _format) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char wsbuf[BUFLEN * 2];
|
|
||||||
void NetServer::processQueue(){
|
void NetServer::processQueue(){
|
||||||
if(nsQueue==NULL) return;
|
if(nsQueue==NULL) return;
|
||||||
nsRequestParams_t request;
|
nsRequestParams_t request;
|
||||||
if(xQueueReceive(nsQueue, &request, NS_QUEUE_TICKS)){
|
if(xQueueReceive(nsQueue, &request, NS_QUEUE_TICKS)){
|
||||||
memset(wsbuf, 0, BUFLEN * 2);
|
|
||||||
uint8_t clientId = request.clientId;
|
uint8_t clientId = request.clientId;
|
||||||
|
wsBuf[0]='\0';
|
||||||
switch (request.type) {
|
switch (request.type) {
|
||||||
case PLAYLIST: getPlaylist(clientId); break;
|
case PLAYLIST: getPlaylist(clientId); break;
|
||||||
case PLAYLISTSAVED: {
|
case PLAYLISTSAVED: {
|
||||||
@@ -205,36 +162,46 @@ void NetServer::processQueue(){
|
|||||||
}
|
}
|
||||||
case GETACTIVE: {
|
case GETACTIVE: {
|
||||||
bool dbgact = false, nxtn=false;
|
bool dbgact = false, nxtn=false;
|
||||||
String act = F("\"group_wifi\",");
|
//String act = F("\"group_wifi\",");
|
||||||
|
nsBuf[0]='\0';
|
||||||
|
APPEND_GROUP("group_wifi");
|
||||||
if (network.status == CONNECTED) {
|
if (network.status == CONNECTED) {
|
||||||
act += F("\"group_system\",");
|
//act += F("\"group_system\",");
|
||||||
if (BRIGHTNESS_PIN != 255 || DSP_CAN_FLIPPED || DSP_MODEL == DSP_NOKIA5110 || dbgact) act += F("\"group_display\",");
|
APPEND_GROUP("group_system");
|
||||||
|
if (BRIGHTNESS_PIN != 255 || DSP_CAN_FLIPPED || DSP_MODEL == DSP_NOKIA5110 || dbgact) APPEND_GROUP("group_display");
|
||||||
#ifdef USE_NEXTION
|
#ifdef USE_NEXTION
|
||||||
act += F("\"group_nextion\",");
|
APPEND_GROUP("group_nextion");
|
||||||
if (!SHOW_WEATHER || dbgact) act += F("\"group_weather\",");
|
if (!SHOW_WEATHER || dbgact) APPEND_GROUP("group_weather");
|
||||||
nxtn=true;
|
nxtn=true;
|
||||||
#endif
|
#endif
|
||||||
#if defined(LCD_I2C) || defined(DSP_OLED)
|
#if defined(LCD_I2C) || defined(DSP_OLED)
|
||||||
act += F("\"group_oled\",");
|
APPEND_GROUP("group_oled");
|
||||||
#endif
|
#endif
|
||||||
#ifndef HIDE_VU
|
#if !defined(HIDE_VU) && !defined(DUMMYDISPLAY)
|
||||||
act += F("\"group_vu\",");
|
APPEND_GROUP("group_vu");
|
||||||
|
#endif
|
||||||
|
if (BRIGHTNESS_PIN != 255 || nxtn || dbgact) APPEND_GROUP("group_brightness");
|
||||||
|
if (DSP_CAN_FLIPPED || dbgact) APPEND_GROUP("group_tft");
|
||||||
|
if (TS_MODEL != TS_MODEL_UNDEFINED || dbgact) APPEND_GROUP("group_touch");
|
||||||
|
if (DSP_MODEL == DSP_NOKIA5110) APPEND_GROUP("group_nokia");
|
||||||
|
APPEND_GROUP("group_timezone");
|
||||||
|
if (SHOW_WEATHER || dbgact) APPEND_GROUP("group_weather");
|
||||||
|
APPEND_GROUP("group_controls");
|
||||||
|
if (ENC_BTNL != 255 || ENC2_BTNL != 255 || dbgact) APPEND_GROUP("group_encoder");
|
||||||
|
if (IR_PIN != 255 || dbgact) APPEND_GROUP("group_ir");
|
||||||
|
if (!psramInit()) APPEND_GROUP("group_buffer");
|
||||||
|
#if RTCSUPPORTED
|
||||||
|
APPEND_GROUP("group_rtc");
|
||||||
|
#else
|
||||||
|
APPEND_GROUP("group_wortc");
|
||||||
#endif
|
#endif
|
||||||
if (BRIGHTNESS_PIN != 255 || nxtn || dbgact) act += F("\"group_brightness\",");
|
|
||||||
if (DSP_CAN_FLIPPED || dbgact) act += F("\"group_tft\",");
|
|
||||||
if (TS_MODEL != TS_MODEL_UNDEFINED || dbgact) act += F("\"group_touch\",");
|
|
||||||
if (DSP_MODEL == DSP_NOKIA5110) act += F("\"group_nokia\",");
|
|
||||||
act += F("\"group_timezone\",");
|
|
||||||
if (SHOW_WEATHER || dbgact) act += F("\"group_weather\",");
|
|
||||||
act += F("\"group_controls\",");
|
|
||||||
if (ENC_BTNL != 255 || ENC2_BTNL != 255 || dbgact) act += F("\"group_encoder\",");
|
|
||||||
if (IR_PIN != 255 || dbgact) act += F("\"group_ir\",");
|
|
||||||
}
|
}
|
||||||
act = act.substring(0, act.length() - 1);
|
size_t len = strlen(nsBuf);
|
||||||
sprintf (wsbuf, "{\"act\":[%s]}", act.c_str());
|
if (len > 0 && nsBuf[len - 1] == ',') nsBuf[len - 1] = '\0';
|
||||||
|
|
||||||
|
snprintf(wsBuf, sizeof(wsBuf), "{\"act\":[%s]}", nsBuf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//case STARTUP: sprintf (wsbuf, "{\"command\":\"startup\", \"payload\": {\"mode\":\"%s\", \"version\":\"%s\"}}", network.status == CONNECTED ? "player" : "ap", YOVERSION); break;
|
|
||||||
case GETINDEX: {
|
case GETINDEX: {
|
||||||
requestOnChange(STATION, clientId);
|
requestOnChange(STATION, clientId);
|
||||||
requestOnChange(TITLE, clientId);
|
requestOnChange(TITLE, clientId);
|
||||||
@@ -249,15 +216,19 @@ void NetServer::processQueue(){
|
|||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GETSYSTEM: sprintf (wsbuf, "{\"sst\":%d,\"aif\":%d,\"vu\":%d,\"softr\":%d,\"vut\":%d,\"mdns\":\"%s\"}",
|
case GETSYSTEM: sprintf (wsBuf, "{\"sst\":%d,\"aif\":%d,\"vu\":%d,\"softr\":%d,\"vut\":%d,\"mdns\":\"%s\",\"ipaddr\":\"%s\", \"abuff\": %d, \"telnet\": %d, \"watchdog\": %d }",
|
||||||
config.store.smartstart != 2,
|
config.store.smartstart != 2,
|
||||||
config.store.audioinfo,
|
config.store.audioinfo,
|
||||||
config.store.vumeter,
|
config.store.vumeter,
|
||||||
config.store.softapdelay,
|
config.store.softapdelay,
|
||||||
config.vuThreshold,
|
config.vuThreshold,
|
||||||
config.store.mdnsname);
|
config.store.mdnsname,
|
||||||
|
config.ipToStr(WiFi.localIP()),
|
||||||
|
config.store.abuff,
|
||||||
|
config.store.telnet,
|
||||||
|
config.store.watchdog);
|
||||||
break;
|
break;
|
||||||
case GETSCREEN: sprintf (wsbuf, "{\"flip\":%d,\"inv\":%d,\"nump\":%d,\"tsf\":%d,\"tsd\":%d,\"dspon\":%d,\"br\":%d,\"con\":%d,\"scre\":%d,\"scrt\":%d,\"scrb\":%d,\"scrpe\":%d,\"scrpt\":%d,\"scrpb\":%d}",
|
case GETSCREEN: sprintf (wsBuf, "{\"flip\":%d,\"inv\":%d,\"nump\":%d,\"tsf\":%d,\"tsd\":%d,\"dspon\":%d,\"br\":%d,\"con\":%d,\"scre\":%d,\"scrt\":%d,\"scrb\":%d,\"scrpe\":%d,\"scrpt\":%d,\"scrpb\":%d}",
|
||||||
config.store.flipscreen,
|
config.store.flipscreen,
|
||||||
config.store.invertdisplay,
|
config.store.invertdisplay,
|
||||||
config.store.numplaylist,
|
config.store.numplaylist,
|
||||||
@@ -273,52 +244,55 @@ void NetServer::processQueue(){
|
|||||||
config.store.screensaverPlayingTimeout,
|
config.store.screensaverPlayingTimeout,
|
||||||
config.store.screensaverPlayingBlank);
|
config.store.screensaverPlayingBlank);
|
||||||
break;
|
break;
|
||||||
case GETTIMEZONE: sprintf (wsbuf, "{\"tzh\":%d,\"tzm\":%d,\"sntp1\":\"%s\",\"sntp2\":\"%s\"}",
|
case GETTIMEZONE: sprintf (wsBuf, "{\"tzh\":%d,\"tzm\":%d,\"sntp1\":\"%s\",\"sntp2\":\"%s\", \"timeint\":%d,\"timeintrtc\":%d}",
|
||||||
config.store.tzHour,
|
config.store.tzHour,
|
||||||
config.store.tzMin,
|
config.store.tzMin,
|
||||||
config.store.sntp1,
|
config.store.sntp1,
|
||||||
config.store.sntp2);
|
config.store.sntp2,
|
||||||
|
config.store.timeSyncInterval,
|
||||||
|
config.store.timeSyncIntervalRTC);
|
||||||
break;
|
break;
|
||||||
case GETWEATHER: sprintf (wsbuf, "{\"wen\":%d,\"wlat\":\"%s\",\"wlon\":\"%s\",\"wkey\":\"%s\"}",
|
case GETWEATHER: sprintf (wsBuf, "{\"wen\":%d,\"wlat\":\"%s\",\"wlon\":\"%s\",\"wkey\":\"%s\",\"wint\":%d}",
|
||||||
config.store.showweather,
|
config.store.showweather,
|
||||||
config.store.weatherlat,
|
config.store.weatherlat,
|
||||||
config.store.weatherlon,
|
config.store.weatherlon,
|
||||||
config.store.weatherkey);
|
config.store.weatherkey,
|
||||||
|
config.store.weatherSyncInterval);
|
||||||
break;
|
break;
|
||||||
case GETCONTROLS: sprintf (wsbuf, "{\"vols\":%d,\"enca\":%d,\"irtl\":%d,\"skipup\":%d}",
|
case GETCONTROLS: sprintf (wsBuf, "{\"vols\":%d,\"enca\":%d,\"irtl\":%d,\"skipup\":%d}",
|
||||||
config.store.volsteps,
|
config.store.volsteps,
|
||||||
config.store.encacc,
|
config.store.encacc,
|
||||||
config.store.irtlp,
|
config.store.irtlp,
|
||||||
config.store.skipPlaylistUpDown);
|
config.store.skipPlaylistUpDown);
|
||||||
break;
|
break;
|
||||||
case DSPON: sprintf (wsbuf, "{\"dspontrue\":%d}", 1); break;
|
case DSPON: sprintf (wsBuf, "{\"dspontrue\":%d}", 1); break;
|
||||||
case STATION: requestOnChange(STATIONNAME, clientId); requestOnChange(ITEM, clientId); break;
|
case STATION: requestOnChange(STATIONNAME, clientId); requestOnChange(ITEM, clientId); break;
|
||||||
case STATIONNAME: sprintf (wsbuf, "{\"payload\":[{\"id\":\"nameset\", \"value\": \"%s\"}]}", config.station.name); break;
|
case STATIONNAME: sprintf (wsBuf, "{\"payload\":[{\"id\":\"nameset\", \"value\": \"%s\"}]}", config.station.name); break;
|
||||||
case ITEM: sprintf (wsbuf, "{\"current\": %d}", config.lastStation()); break;
|
case ITEM: sprintf (wsBuf, "{\"current\": %d}", config.lastStation()); break;
|
||||||
case TITLE: sprintf (wsbuf, "{\"payload\":[{\"id\":\"meta\", \"value\": \"%s\"}]}", config.station.title); telnet.printf("##CLI.META#: %s\n> ", config.station.title); break;
|
case TITLE: sprintf (wsBuf, "{\"payload\":[{\"id\":\"meta\", \"value\": \"%s\"}]}", config.station.title); telnet.printf("##CLI.META#: %s\n> ", config.station.title); break;
|
||||||
case VOLUME: sprintf (wsbuf, "{\"payload\":[{\"id\":\"volume\", \"value\": %d}]}", config.store.volume); telnet.printf("##CLI.VOL#: %d\n", config.store.volume); break;
|
case VOLUME: sprintf (wsBuf, "{\"payload\":[{\"id\":\"volume\", \"value\": %d}]}", config.store.volume); telnet.printf("##CLI.VOL#: %d\n", config.store.volume); break;
|
||||||
case NRSSI: sprintf (wsbuf, "{\"payload\":[{\"id\":\"rssi\", \"value\": %d}]}", rssi); /*rssi = 255;*/ break;
|
case NRSSI: sprintf (wsBuf, "{\"payload\":[{\"id\":\"rssi\", \"value\": %d}, {\"id\":\"heap\", \"value\": %d}]}", rssi, (player.isRunning() && config.store.audioinfo)?(int)(100*player.inBufferFilled()/playerBufMax):0); /*rssi = 255;*/ break;
|
||||||
case SDPOS: sprintf (wsbuf, "{\"sdpos\": %d,\"sdend\": %d,\"sdtpos\": %d,\"sdtend\": %d}",
|
case SDPOS: sprintf (wsBuf, "{\"sdpos\": %lu,\"sdend\": %lu,\"sdtpos\": %lu,\"sdtend\": %lu}",
|
||||||
player.getFilePos(),
|
player.getFilePos(),
|
||||||
player.getFileSize(),
|
player.getFileSize(),
|
||||||
player.getAudioCurrentTime(),
|
player.getAudioCurrentTime(),
|
||||||
player.getAudioFileDuration());
|
player.getAudioFileDuration());
|
||||||
break;
|
break;
|
||||||
case SDLEN: sprintf (wsbuf, "{\"sdmin\": %d,\"sdmax\": %d}", player.sd_min, player.sd_max); break;
|
case SDLEN: sprintf (wsBuf, "{\"sdmin\": %lu,\"sdmax\": %lu}", player.sd_min, player.sd_max); break;
|
||||||
case SDSNUFFLE: sprintf (wsbuf, "{\"snuffle\": %d}", config.store.sdsnuffle); break;
|
case SDSNUFFLE: sprintf (wsBuf, "{\"snuffle\": %d}", config.store.sdsnuffle); break;
|
||||||
case BITRATE: sprintf (wsbuf, "{\"payload\":[{\"id\":\"bitrate\", \"value\": %d}, {\"id\":\"fmt\", \"value\": \"%s\"}]}", config.station.bitrate, getFormat(config.configFmt)); break;
|
case BITRATE: sprintf (wsBuf, "{\"payload\":[{\"id\":\"bitrate\", \"value\": %d}, {\"id\":\"fmt\", \"value\": \"%s\"}]}", config.station.bitrate, getFormat(config.configFmt)); break;
|
||||||
case MODE: sprintf (wsbuf, "{\"payload\":[{\"id\":\"playerwrap\", \"value\": \"%s\"}]}", player.status() == PLAYING ? "playing" : "stopped"); telnet.info(); break;
|
case MODE: sprintf (wsBuf, "{\"payload\":[{\"id\":\"playerwrap\", \"value\": \"%s\"}]}", player.status() == PLAYING ? "playing" : "stopped"); telnet.info(); break;
|
||||||
case EQUALIZER: sprintf (wsbuf, "{\"payload\":[{\"id\":\"bass\", \"value\": %d}, {\"id\": \"middle\", \"value\": %d}, {\"id\": \"trebble\", \"value\": %d}]}", config.store.bass, config.store.middle, config.store.trebble); break;
|
case EQUALIZER: sprintf (wsBuf, "{\"payload\":[{\"id\":\"bass\", \"value\": %d}, {\"id\": \"middle\", \"value\": %d}, {\"id\": \"trebble\", \"value\": %d}]}", config.store.bass, config.store.middle, config.store.trebble); break;
|
||||||
case BALANCE: sprintf (wsbuf, "{\"payload\":[{\"id\": \"balance\", \"value\": %d}]}", config.store.balance); break;
|
case BALANCE: sprintf (wsBuf, "{\"payload\":[{\"id\": \"balance\", \"value\": %d}]}", config.store.balance); break;
|
||||||
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(config.newConfigMode); return; break;
|
case CHANGEMODE: config.changeMode(config.newConfigMode); return; break;
|
||||||
#endif
|
#endif
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
if (strlen(wsbuf) > 0) {
|
if (strlen(wsBuf) > 0) {
|
||||||
if (clientId == 0) { websocket.textAll(wsbuf); }else{ websocket.text(clientId, wsbuf); }
|
if (clientId == 0) { websocket.textAll(wsBuf); }else{ websocket.text(clientId, wsBuf); }
|
||||||
#ifdef MQTT_ROOT_TOPIC
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
if (clientId == 0 && (request.type == STATION || request.type == ITEM || request.type == TITLE || request.type == MODE)) mqttPublishStatus();
|
if (clientId == 0 && (request.type == STATION || request.type == ITEM || request.type == TITLE || request.type == MODE)) mqttPublishStatus();
|
||||||
if (clientId == 0 && request.type == VOLUME) mqttPublishVolume();
|
if (clientId == 0 && request.type == VOLUME) mqttPublishVolume();
|
||||||
@@ -341,22 +315,19 @@ void NetServer::loop() {
|
|||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
processQueue();
|
processQueue();
|
||||||
#if USE_OTA
|
|
||||||
ArduinoOTA.handle();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IR_PIN!=255
|
#if IR_PIN!=255
|
||||||
void NetServer::irToWs(const char* protocol, uint64_t irvalue) {
|
void NetServer::irToWs(const char* protocol, uint64_t irvalue) {
|
||||||
char buf[BUFLEN] = { 0 };
|
wsBuf[0]='\0';
|
||||||
sprintf (buf, "{\"ircode\": %llu, \"protocol\": \"%s\"}", irvalue, protocol);
|
sprintf (wsBuf, "{\"ircode\": %llu, \"protocol\": \"%s\"}", irvalue, protocol);
|
||||||
websocket.textAll(buf);
|
websocket.textAll(wsBuf);
|
||||||
}
|
}
|
||||||
void NetServer::irValsToWs() {
|
void NetServer::irValsToWs() {
|
||||||
if (!irRecordEnable) return;
|
if (!irRecordEnable) return;
|
||||||
char buf[BUFLEN] = { 0 };
|
wsBuf[0]='\0';
|
||||||
sprintf (buf, "{\"irvals\": [%llu, %llu, %llu]}", config.ircodes.irVals[config.irindex][0], config.ircodes.irVals[config.irindex][1], config.ircodes.irVals[config.irindex][2]);
|
sprintf (wsBuf, "{\"irvals\": [%llu, %llu, %llu]}", config.ircodes.irVals[config.irindex][0], config.ircodes.irVals[config.irindex][1], config.ircodes.irVals[config.irindex][2]);
|
||||||
websocket.textAll(buf);
|
websocket.textAll(wsBuf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -364,32 +335,36 @@ 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 comnd[65], val[65];
|
if (config.parseWsCommand((const char*)data, _wscmd, _wsval, 65)) {
|
||||||
if (config.parseWsCommand((const char*)data, comnd, val, 65)) {
|
if (strcmp(_wscmd, "ping") == 0) {
|
||||||
if (strcmp(comnd, "trebble") == 0) {
|
websocket.text(clientId, "{\"pong\": 1}");
|
||||||
int8_t valb = atoi(val);
|
return;
|
||||||
|
}
|
||||||
|
if (strcmp(_wscmd, "trebble") == 0) {
|
||||||
|
int8_t valb = atoi(_wsval);
|
||||||
config.setTone(config.store.bass, config.store.middle, valb);
|
config.setTone(config.store.bass, config.store.middle, valb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (strcmp(comnd, "middle") == 0) {
|
if (strcmp(_wscmd, "middle") == 0) {
|
||||||
int8_t valb = atoi(val);
|
int8_t valb = atoi(_wsval);
|
||||||
config.setTone(config.store.bass, valb, config.store.trebble);
|
config.setTone(config.store.bass, valb, config.store.trebble);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (strcmp(comnd, "bass") == 0) {
|
if (strcmp(_wscmd, "bass") == 0) {
|
||||||
int8_t valb = atoi(val);
|
int8_t valb = atoi(_wsval);
|
||||||
config.setTone(valb, config.store.middle, config.store.trebble);
|
config.setTone(valb, config.store.middle, config.store.trebble);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (strcmp(comnd, "submitplaylistdone") == 0) {
|
if (strcmp(_wscmd, "submitplaylistdone") == 0) {
|
||||||
#ifdef MQTT_ROOT_TOPIC
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
mqttplaylistticker.attach(5, mqttplaylistSend);
|
//mqttplaylistticker.attach(5, mqttplaylistSend);
|
||||||
|
timekeeper.waitAndDo(5, mqttplaylistSend);
|
||||||
#endif
|
#endif
|
||||||
if (player.isRunning()) player.sendCommand({PR_PLAY, -config.lastStation()});
|
if (player.isRunning()) player.sendCommand({PR_PLAY, -config.lastStation()});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cmd.exec(comnd, val, clientId)){
|
if(cmd.exec(_wscmd, _wsval, clientId)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -397,9 +372,8 @@ void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t client
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NetServer::getPlaylist(uint8_t clientId) {
|
void NetServer::getPlaylist(uint8_t clientId) {
|
||||||
char buf[160] = {0};
|
sprintf(nsBuf, "{\"file\": \"http://%s%s\"}", config.ipToStr(WiFi.localIP()), PLAYLIST_PATH);
|
||||||
sprintf(buf, "{\"file\": \"http://%s%s\"}", WiFi.localIP().toString().c_str(), PLAYLIST_PATH);
|
if (clientId == 0) { websocket.textAll(nsBuf); } else { websocket.text(clientId, nsBuf); }
|
||||||
if (clientId == 0) { websocket.textAll(buf); } else { websocket.text(clientId, buf); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int NetServer::_readPlaylistLine(File &file, char * line, size_t size){
|
int NetServer::_readPlaylistLine(File &file, char * line, size_t size){
|
||||||
@@ -413,27 +387,28 @@ int NetServer::_readPlaylistLine(File &file, char * line, size_t size){
|
|||||||
|
|
||||||
bool NetServer::importPlaylist() {
|
bool NetServer::importPlaylist() {
|
||||||
if(config.getMode()==PM_SDCARD) return false;
|
if(config.getMode()==PM_SDCARD) return false;
|
||||||
|
//player.sendCommand({PR_STOP, 0});
|
||||||
File tempfile = SPIFFS.open(TMP_PATH, "r");
|
File tempfile = SPIFFS.open(TMP_PATH, "r");
|
||||||
if (!tempfile) {
|
if (!tempfile) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
char sName[BUFLEN], sUrl[BUFLEN], linePl[BUFLEN*3];;
|
char linePl[BUFLEN*3];
|
||||||
int sOvol;
|
int sOvol;
|
||||||
_readPlaylistLine(tempfile, linePl, sizeof(linePl)-1);
|
_readPlaylistLine(tempfile, linePl, sizeof(linePl)-1);
|
||||||
if (config.parseCSV(linePl, sName, sUrl, sOvol)) {
|
if (config.parseCSV(linePl, nsBuf, nsBuf2, sOvol)) {
|
||||||
tempfile.close();
|
tempfile.close();
|
||||||
SPIFFS.rename(TMP_PATH, PLAYLIST_PATH);
|
SPIFFS.rename(TMP_PATH, PLAYLIST_PATH);
|
||||||
requestOnChange(PLAYLISTSAVED, 0);
|
requestOnChange(PLAYLISTSAVED, 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (config.parseJSON(linePl, sName, sUrl, sOvol)) {
|
if (config.parseJSON(linePl, nsBuf, nsBuf2, sOvol)) {
|
||||||
File playlistfile = SPIFFS.open(PLAYLIST_PATH, "w");
|
File playlistfile = SPIFFS.open(PLAYLIST_PATH, "w");
|
||||||
snprintf(linePl, sizeof(linePl)-1, "%s\t%s\t%d", sName, sUrl, 0);
|
snprintf(linePl, sizeof(linePl)-1, "%s\t%s\t%d", nsBuf, nsBuf2, 0);
|
||||||
playlistfile.println(linePl);
|
playlistfile.println(linePl);
|
||||||
while (tempfile.available()) {
|
while (tempfile.available()) {
|
||||||
_readPlaylistLine(tempfile, linePl, sizeof(linePl)-1);
|
_readPlaylistLine(tempfile, linePl, sizeof(linePl)-1);
|
||||||
if (config.parseJSON(linePl, sName, sUrl, sOvol)) {
|
if (config.parseJSON(linePl, nsBuf, nsBuf2, sOvol)) {
|
||||||
snprintf(linePl, sizeof(linePl)-1, "%s\t%s\t%d", sName, sUrl, 0);
|
snprintf(linePl, sizeof(linePl)-1, "%s\t%s\t%d", nsBuf, nsBuf2, 0);
|
||||||
playlistfile.println(linePl);
|
playlistfile.println(linePl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -461,11 +436,12 @@ void NetServer::resetQueue(){
|
|||||||
if(nsQueue!=NULL) xQueueReset(nsQueue);
|
if(nsQueue!=NULL) xQueueReset(nsQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
static int freeSpace = 0;
|
||||||
if(request->url()=="/upload"){
|
if(request->url()=="/upload"){
|
||||||
if (!index) {
|
if (!index) {
|
||||||
if(filename!="tempwifi.csv"){
|
if(filename!="tempwifi.csv"){
|
||||||
|
//player.sendCommand({PR_STOP, 0});
|
||||||
if(SPIFFS.exists(PLAYLIST_PATH)) SPIFFS.remove(PLAYLIST_PATH);
|
if(SPIFFS.exists(PLAYLIST_PATH)) SPIFFS.remove(PLAYLIST_PATH);
|
||||||
if(SPIFFS.exists(INDEX_PATH)) SPIFFS.remove(INDEX_PATH);
|
if(SPIFFS.exists(INDEX_PATH)) SPIFFS.remove(INDEX_PATH);
|
||||||
if(SPIFFS.exists(PLAYLIST_SD_PATH)) SPIFFS.remove(PLAYLIST_SD_PATH);
|
if(SPIFFS.exists(PLAYLIST_SD_PATH)) SPIFFS.remove(PLAYLIST_SD_PATH);
|
||||||
@@ -473,6 +449,8 @@ void handleUpload(AsyncWebServerRequest *request, String filename, size_t index,
|
|||||||
}
|
}
|
||||||
freeSpace = (float)SPIFFS.totalBytes()/100*68-SPIFFS.usedBytes();
|
freeSpace = (float)SPIFFS.totalBytes()/100*68-SPIFFS.usedBytes();
|
||||||
request->_tempFile = SPIFFS.open(TMP_PATH , "w");
|
request->_tempFile = SPIFFS.open(TMP_PATH , "w");
|
||||||
|
}else{
|
||||||
|
|
||||||
}
|
}
|
||||||
if (len) {
|
if (len) {
|
||||||
if(freeSpace>index+len){
|
if(freeSpace>index+len){
|
||||||
@@ -481,6 +459,7 @@ void handleUpload(AsyncWebServerRequest *request, String filename, size_t index,
|
|||||||
}
|
}
|
||||||
if (final) {
|
if (final) {
|
||||||
request->_tempFile.close();
|
request->_tempFile.close();
|
||||||
|
freeSpace = 0;
|
||||||
}
|
}
|
||||||
}else if(request->url()=="/update"){
|
}else if(request->url()=="/update"){
|
||||||
if (!index) {
|
if (!index) {
|
||||||
@@ -510,6 +489,7 @@ void handleUpload(AsyncWebServerRequest *request, String filename, size_t index,
|
|||||||
}else{ // "/webboard"
|
}else{ // "/webboard"
|
||||||
DBGVB("File: %s, size:%u bytes, index: %u, final: %s\n", filename.c_str(), len, index, final?"true":"false");
|
DBGVB("File: %s, size:%u bytes, index: %u, final: %s\n", filename.c_str(), len, index, final?"true":"false");
|
||||||
if (!index) {
|
if (!index) {
|
||||||
|
player.sendCommand({PR_STOP, 0});
|
||||||
String spath = "/www/";
|
String spath = "/www/";
|
||||||
if(filename=="playlist.csv" || filename=="wifi.csv") spath = "/data/";
|
if(filename=="playlist.csv" || filename=="wifi.csv") spath = "/data/";
|
||||||
request->_tempFile = SPIFFS.open(spath + filename , "w");
|
request->_tempFile = SPIFFS.open(spath + filename , "w");
|
||||||
@@ -526,8 +506,8 @@ void handleUpload(AsyncWebServerRequest *request, String filename, size_t index,
|
|||||||
|
|
||||||
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) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case WS_EVT_CONNECT: /*netserver.requestOnChange(STARTUP, client->id()); */if (config.store.audioinfo) Serial.printf("[WEBSOCKET] client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str()); break;
|
case WS_EVT_CONNECT: /*netserver.requestOnChange(STARTUP, client->id()); */if (config.store.audioinfo) Serial.printf("[WEBSOCKET] client #%lu connected from %s\n", client->id(), config.ipToStr(client->remoteIP())); break;
|
||||||
case WS_EVT_DISCONNECT: if (config.store.audioinfo) Serial.printf("[WEBSOCKET] client #%u disconnected\n", client->id()); break;
|
case WS_EVT_DISCONNECT: if (config.store.audioinfo) Serial.printf("[WEBSOCKET] client #%lu disconnected\n", client->id()); break;
|
||||||
case WS_EVT_DATA: netserver.onWsMessage(arg, data, len, client->id()); break;
|
case WS_EVT_DATA: netserver.onWsMessage(arg, data, len, client->id()); break;
|
||||||
case WS_EVT_PONG:
|
case WS_EVT_PONG:
|
||||||
case WS_EVT_ERROR:
|
case WS_EVT_ERROR:
|
||||||
@@ -548,7 +528,7 @@ void handleNotFound(AsyncWebServerRequest * request) {
|
|||||||
if(request->url()=="/emergency") { request->send_P(200, "text/html", emergency_form); return; }
|
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_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__, config.ipToStr(request->client()->remoteIP()), request->url().c_str());
|
||||||
if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 ||
|
if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 ||
|
||||||
strcmp(request->url().c_str(), SSIDS_PATH) == 0 ||
|
strcmp(request->url().c_str(), SSIDS_PATH) == 0 ||
|
||||||
strcmp(request->url().c_str(), INDEX_PATH) == 0 ||
|
strcmp(request->url().c_str(), INDEX_PATH) == 0 ||
|
||||||
@@ -595,13 +575,15 @@ void handleNotFound(AsyncWebServerRequest * request) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (request->url() == "/variables.js") {
|
if (request->url() == "/variables.js") {
|
||||||
char varjsbuf[BUFLEN];
|
sprintf (netserver.nsBuf, "var yoVersion='%s';\nvar formAction='%s';\nvar playMode='%s';\n", YOVERSION, (network.status == CONNECTED && !config.emptyFS)?"webboard":"", (network.status == CONNECTED)?"player":"ap");
|
||||||
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", netserver.nsBuf);
|
||||||
request->send(200, "text/html", varjsbuf);
|
|
||||||
return;
|
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);
|
||||||
|
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", index_html);
|
||||||
|
response->addHeader("Cache-Control","max-age=31536000");
|
||||||
|
request->send(response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (request->method() == HTTP_GET && request->url() == "/webboard") {
|
if (request->method() == HTTP_GET && request->url() == "/webboard") {
|
||||||
@@ -618,11 +600,10 @@ void handleIndex(AsyncWebServerRequest * request) {
|
|||||||
if(request->url()=="/" && request->method() == HTTP_GET ) { request->send_P(200, "text/html", emptyfs_html); return; }
|
if(request->url()=="/" && request->method() == HTTP_GET ) { request->send_P(200, "text/html", emptyfs_html); return; }
|
||||||
if(request->url()=="/" && request->method() == HTTP_POST) {
|
if(request->url()=="/" && request->method() == HTTP_POST) {
|
||||||
if(request->arg("ssid")!="" && request->arg("pass")!=""){
|
if(request->arg("ssid")!="" && request->arg("pass")!=""){
|
||||||
char buf[BUFLEN];
|
netserver.nsBuf[0]='\0';
|
||||||
memset(buf, 0, BUFLEN);
|
snprintf(netserver.nsBuf, sizeof(netserver.nsBuf), "%s\t%s", request->arg("ssid").c_str(), request->arg("pass").c_str());
|
||||||
snprintf(buf, BUFLEN, "%s\t%s", request->arg("ssid").c_str(), request->arg("pass").c_str());
|
|
||||||
request->redirect("/");
|
request->redirect("/");
|
||||||
config.saveWifiFromNextion(buf);
|
config.saveWifiFromNextion(netserver.nsBuf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
request->redirect("/");
|
request->redirect("/");
|
||||||
@@ -641,7 +622,12 @@ void handleIndex(AsyncWebServerRequest * request) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (strcmp(request->url().c_str(), "/") == 0 && request->params() == 0) {
|
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");
|
if(network.status == CONNECTED) {
|
||||||
|
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", index_html);
|
||||||
|
response->addHeader("Cache-Control","max-age=31536000");
|
||||||
|
request->send(response);
|
||||||
|
//request->send_P(200, "text/html", index_html);
|
||||||
|
} else request->redirect("/settings.html");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(network.status == CONNECTED){
|
if(network.status == CONNECTED){
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#ifndef netserver_h
|
#ifndef netserver_h
|
||||||
#define netserver_h
|
#define netserver_h
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
#include "config.h"
|
||||||
#include "../AsyncWebServer/ESPAsyncWebServer.h"
|
#include "../AsyncWebServer/ESPAsyncWebServer.h"
|
||||||
|
|
||||||
|
#define APPEND_GROUP(name) strcat(nsBuf, "\"" name "\",")
|
||||||
|
|
||||||
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 };
|
||||||
const char emptyfs_html[] PROGMEM = R"(
|
const char emptyfs_html[] PROGMEM = R"(
|
||||||
@@ -74,6 +76,7 @@ const char index_html[] PROGMEM = R"(
|
|||||||
<div id="content" class="hidden progmem">
|
<div id="content" class="hidden progmem">
|
||||||
</div><!--content-->
|
</div><!--content-->
|
||||||
<div id="progress"><span id="loader"></span></div>
|
<div id="progress"><span id="loader"></span></div>
|
||||||
|
<div id="heap"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
)";
|
)";
|
||||||
@@ -96,6 +99,7 @@ class NetServer {
|
|||||||
import_e importRequest;
|
import_e importRequest;
|
||||||
bool resumePlay;
|
bool resumePlay;
|
||||||
char chunkedPathBuffer[40];
|
char chunkedPathBuffer[40];
|
||||||
|
char nsBuf[BUFLEN], nsBuf2[BUFLEN];
|
||||||
public:
|
public:
|
||||||
NetServer() {};
|
NetServer() {};
|
||||||
bool begin(bool quiet=false);
|
bool begin(bool quiet=false);
|
||||||
@@ -114,7 +118,10 @@ class NetServer {
|
|||||||
private:
|
private:
|
||||||
requestType_e request;
|
requestType_e request;
|
||||||
QueueHandle_t nsQueue;
|
QueueHandle_t nsQueue;
|
||||||
|
char _wscmd[65], _wsval[65];
|
||||||
|
char wsBuf[BUFLEN*2];
|
||||||
int rssi;
|
int rssi;
|
||||||
|
uint32_t playerBufMax;
|
||||||
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);
|
||||||
|
|||||||
@@ -6,98 +6,17 @@
|
|||||||
#include "netserver.h"
|
#include "netserver.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "mqtt.h"
|
#include "mqtt.h"
|
||||||
|
#include "timekeeper.h"
|
||||||
|
|
||||||
#ifndef WIFI_ATTEMPTS
|
#ifndef WIFI_ATTEMPTS
|
||||||
#define WIFI_ATTEMPTS 16
|
#define WIFI_ATTEMPTS 16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SEARCH_WIFI_CORE_ID
|
||||||
|
#define SEARCH_WIFI_CORE_ID 0
|
||||||
|
#endif
|
||||||
MyNetwork network;
|
MyNetwork network;
|
||||||
|
|
||||||
TaskHandle_t syncTaskHandle;
|
|
||||||
//TaskHandle_t reconnectTaskHandle;
|
|
||||||
|
|
||||||
bool getWeather(char *wstr);
|
|
||||||
void doSync(void * pvParameters);
|
|
||||||
|
|
||||||
void ticks() {
|
|
||||||
if(!display.ready()) return; //waiting for SD is ready
|
|
||||||
pm.on_ticker();
|
|
||||||
static const uint16_t weatherSyncInterval=1800;
|
|
||||||
//static const uint16_t weatherSyncIntervalFail=10;
|
|
||||||
#if RTCSUPPORTED
|
|
||||||
static const uint32_t timeSyncInterval=86400;
|
|
||||||
static uint32_t timeSyncTicks = 0;
|
|
||||||
#else
|
|
||||||
static const uint16_t timeSyncInterval=3600;
|
|
||||||
static uint16_t timeSyncTicks = 0;
|
|
||||||
#endif
|
|
||||||
static uint16_t weatherSyncTicks = 0;
|
|
||||||
static bool divrssi;
|
|
||||||
timeSyncTicks++;
|
|
||||||
weatherSyncTicks++;
|
|
||||||
divrssi = !divrssi;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifndef DSP_LCD
|
|
||||||
if(config.store.screensaverEnabled && display.mode()==PLAYER && !player.isRunning()){
|
|
||||||
config.screensaverTicks++;
|
|
||||||
if(config.screensaverTicks > config.store.screensaverTimeout+SCREENSAVERSTARTUPDELAY){
|
|
||||||
if(config.store.screensaverBlank){
|
|
||||||
display.putRequest(NEWMODE, SCREENBLANK);
|
|
||||||
}else{
|
|
||||||
display.putRequest(NEWMODE, SCREENSAVER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(config.store.screensaverPlayingEnabled && display.mode()==PLAYER && player.isRunning()){
|
|
||||||
config.screensaverPlayingTicks++;
|
|
||||||
if(config.screensaverPlayingTicks > config.store.screensaverPlayingTimeout*60+SCREENSAVERSTARTUPDELAY){
|
|
||||||
if(config.store.screensaverPlayingBlank){
|
|
||||||
display.putRequest(NEWMODE, SCREENBLANK);
|
|
||||||
}else{
|
|
||||||
display.putRequest(NEWMODE, SCREENSAVER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if RTCSUPPORTED
|
|
||||||
if(config.isRTCFound()){
|
|
||||||
rtc.getTime(&network.timeinfo);
|
|
||||||
mktime(&network.timeinfo);
|
|
||||||
display.putRequest(CLOCK);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if(network.timeinfo.tm_year>100 || network.status == SDREADY) {
|
|
||||||
network.timeinfo.tm_sec++;
|
|
||||||
mktime(&network.timeinfo);
|
|
||||||
display.putRequest(CLOCK);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(player.isRunning() && config.getMode()==PM_SDCARD) netserver.requestOnChange(SDPOS, 0);
|
|
||||||
if(divrssi) {
|
|
||||||
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
|
|
||||||
player.sendCommand({PR_VUTONUS, 0});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyNetwork::WiFiReconnected(WiFiEvent_t event, WiFiEventInfo_t info){
|
void MyNetwork::WiFiReconnected(WiFiEvent_t event, WiFiEventInfo_t info){
|
||||||
network.beginReconnect = false;
|
network.beginReconnect = false;
|
||||||
player.lockOutput = false;
|
player.lockOutput = false;
|
||||||
@@ -152,6 +71,8 @@ bool MyNetwork::wifiBegin(bool silent){
|
|||||||
Serial.print("##[BOOT]#\t");
|
Serial.print("##[BOOT]#\t");
|
||||||
display.putRequest(BOOTSTRING, ls);
|
display.putRequest(BOOTSTRING, ls);
|
||||||
}
|
}
|
||||||
|
WiFi.disconnect(true, true); //disconnect & erase internal credentials https://github.com/e2002/yoradio/pull/164/commits/89d8b4450dde99cd7930b84bb14d81dab920b879
|
||||||
|
delay(100);
|
||||||
WiFi.begin(config.ssids[ls].ssid, config.ssids[ls].password);
|
WiFi.begin(config.ssids[ls].ssid, config.ssids[ls].password);
|
||||||
while (WiFi.status() != WL_CONNECTED) {
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
if(!silent) Serial.print(".");
|
if(!silent) Serial.print(".");
|
||||||
@@ -180,7 +101,7 @@ bool MyNetwork::wifiBegin(bool silent){
|
|||||||
void searchWiFi(void * pvParameters){
|
void searchWiFi(void * pvParameters){
|
||||||
if(!network.wifiBegin(true)){
|
if(!network.wifiBegin(true)){
|
||||||
delay(10000);
|
delay(10000);
|
||||||
xTaskCreatePinnedToCore(searchWiFi, "searchWiFi", 1024 * 4, NULL, 0, NULL, 0);
|
xTaskCreatePinnedToCore(searchWiFi, "searchWiFi", 1024 * 4, NULL, 0, NULL, SEARCH_WIFI_CORE_ID);
|
||||||
}else{
|
}else{
|
||||||
network.status = CONNECTED;
|
network.status = CONNECTED;
|
||||||
netserver.begin(true);
|
netserver.begin(true);
|
||||||
@@ -196,8 +117,6 @@ void searchWiFi(void * pvParameters){
|
|||||||
void MyNetwork::begin() {
|
void MyNetwork::begin() {
|
||||||
BOOTLOG("network.begin");
|
BOOTLOG("network.begin");
|
||||||
config.initNetwork();
|
config.initNetwork();
|
||||||
ctimer.detach();
|
|
||||||
forceTimeSync = forceWeather = true;
|
|
||||||
if (config.ssidsCount == 0 || DBGAP) {
|
if (config.ssidsCount == 0 || DBGAP) {
|
||||||
raiseSoftAP();
|
raiseSoftAP();
|
||||||
return;
|
return;
|
||||||
@@ -213,7 +132,7 @@ void MyNetwork::begin() {
|
|||||||
setWifiParams();
|
setWifiParams();
|
||||||
}else{
|
}else{
|
||||||
status = SDREADY;
|
status = SDREADY;
|
||||||
xTaskCreatePinnedToCore(searchWiFi, "searchWiFi", 1024 * 4, NULL, 0, NULL, 0);
|
xTaskCreatePinnedToCore(searchWiFi, "searchWiFi", 1024 * 4, NULL, 0, NULL, SEARCH_WIFI_CORE_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println("##[BOOT]#\tdone");
|
Serial.println("##[BOOT]#\tdone");
|
||||||
@@ -226,7 +145,6 @@ void MyNetwork::begin() {
|
|||||||
display.putRequest(CLOCK);
|
display.putRequest(CLOCK);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ctimer.attach(1, ticks);
|
|
||||||
if (network_on_connect) network_on_connect();
|
if (network_on_connect) network_on_connect();
|
||||||
pm.on_connect();
|
pm.on_connect();
|
||||||
}
|
}
|
||||||
@@ -236,16 +154,11 @@ void MyNetwork::setWifiParams(){
|
|||||||
WiFi.onEvent(WiFiReconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
|
WiFi.onEvent(WiFiReconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
|
||||||
WiFi.onEvent(WiFiLostConnection, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
|
WiFi.onEvent(WiFiLostConnection, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
|
||||||
weatherBuf=NULL;
|
weatherBuf=NULL;
|
||||||
trueWeather = false;
|
|
||||||
#if (DSP_MODEL!=DSP_DUMMY || defined(USE_NEXTION)) && !defined(HIDE_WEATHER)
|
#if (DSP_MODEL!=DSP_DUMMY || defined(USE_NEXTION)) && !defined(HIDE_WEATHER)
|
||||||
weatherBuf = (char *) malloc(sizeof(char) * WEATHER_STRING_L);
|
weatherBuf = (char *) malloc(sizeof(char) * WEATHER_STRING_L);
|
||||||
memset(weatherBuf, 0, WEATHER_STRING_L);
|
memset(weatherBuf, 0, WEATHER_STRING_L);
|
||||||
#endif
|
#endif
|
||||||
if(strlen(config.store.sntp1)>0 && strlen(config.store.sntp2)>0){
|
//config.setTimeConf(); //??
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyNetwork::requestTimeSync(bool withTelnetOutput, uint8_t clientId) {
|
void MyNetwork::requestTimeSync(bool withTelnetOutput, uint8_t clientId) {
|
||||||
@@ -275,209 +188,9 @@ void MyNetwork::raiseSoftAP() {
|
|||||||
BOOTLOG("************************************************");
|
BOOTLOG("************************************************");
|
||||||
status = SOFT_AP;
|
status = SOFT_AP;
|
||||||
if(config.store.softapdelay>0)
|
if(config.store.softapdelay>0)
|
||||||
rtimer.once(config.store.softapdelay*60, rebootTime);
|
timekeeper.waitAndDo(config.store.softapdelay*60, rebootTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyNetwork::requestWeatherSync(){
|
void MyNetwork::requestWeatherSync(){
|
||||||
display.putRequest(NEWWEATHER);
|
display.putRequest(NEWWEATHER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void doSync( void * pvParameters ) {
|
|
||||||
static uint8_t tsFailCnt = 0;
|
|
||||||
//static uint8_t wsFailCnt = 0;
|
|
||||||
if(network.forceTimeSync){
|
|
||||||
network.forceTimeSync = false;
|
|
||||||
if(getLocalTime(&network.timeinfo)){
|
|
||||||
tsFailCnt = 0;
|
|
||||||
network.forceTimeSync = false;
|
|
||||||
mktime(&network.timeinfo);
|
|
||||||
display.putRequest(CLOCK);
|
|
||||||
network.requestTimeSync(true);
|
|
||||||
#if RTCSUPPORTED
|
|
||||||
if (config.isRTCFound()) rtc.setTime(&network.timeinfo);
|
|
||||||
#endif
|
|
||||||
}else{
|
|
||||||
if(tsFailCnt<4){
|
|
||||||
network.forceTimeSync = true;
|
|
||||||
tsFailCnt++;
|
|
||||||
}else{
|
|
||||||
network.forceTimeSync = false;
|
|
||||||
tsFailCnt=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(network.weatherBuf && (strlen(config.store.weatherkey)!=0 && config.store.showweather) && network.forceWeather){
|
|
||||||
network.forceWeather = false;
|
|
||||||
network.trueWeather=getWeather(network.weatherBuf);
|
|
||||||
}
|
|
||||||
vTaskDelete( NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getWeather(char *wstr) {
|
|
||||||
#if (DSP_MODEL!=DSP_DUMMY || defined(USE_NEXTION)) && !defined(HIDE_WEATHER)
|
|
||||||
WiFiClient client;
|
|
||||||
const char* host = "api.openweathermap.org";
|
|
||||||
|
|
||||||
if (!client.connect(host, 80)) {
|
|
||||||
Serial.println("##WEATHER###: connection failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
char httpget[250] = {0};
|
|
||||||
sprintf(httpget, "GET /data/2.5/weather?lat=%s&lon=%s&units=%s&lang=%s&appid=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", config.store.weatherlat, config.store.weatherlon, weatherUnits, weatherLang, config.store.weatherkey, host);
|
|
||||||
client.print(httpget);
|
|
||||||
unsigned long timeout = millis();
|
|
||||||
while (client.available() == 0) {
|
|
||||||
if (millis() - timeout > 2000UL) {
|
|
||||||
Serial.println("##WEATHER###: 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("##WEATHER###: client read timeout !");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (strstr(line.c_str(), "\"temp\"") == NULL) {
|
|
||||||
Serial.println("##WEATHER###: weather not found !");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
char *tmpe;
|
|
||||||
char *tmps;
|
|
||||||
char *tmpc;
|
|
||||||
const char* cursor = line.c_str();
|
|
||||||
char desc[120], temp[20], hum[20], press[20], icon[5];
|
|
||||||
|
|
||||||
tmps = strstr(cursor, "\"description\":\"");
|
|
||||||
if (tmps == NULL) { Serial.println("##WEATHER###: description not found !"); return false;}
|
|
||||||
tmps += 15;
|
|
||||||
tmpe = strstr(tmps, "\",\"");
|
|
||||||
if (tmpe == NULL) { Serial.println("##WEATHER###: description not found !"); return false;}
|
|
||||||
strlcpy(desc, tmps, tmpe - tmps + 1);
|
|
||||||
cursor = tmpe + 2;
|
|
||||||
|
|
||||||
// "ясно","icon":"01d"}],
|
|
||||||
tmps = strstr(cursor, "\"icon\":\"");
|
|
||||||
if (tmps == NULL) { Serial.println("##WEATHER###: icon not found !"); return false;}
|
|
||||||
tmps += 8;
|
|
||||||
tmpe = strstr(tmps, "\"}");
|
|
||||||
if (tmpe == NULL) { Serial.println("##WEATHER###: icon not found !"); return false;}
|
|
||||||
strlcpy(icon, tmps, tmpe - tmps + 1);
|
|
||||||
cursor = tmpe + 2;
|
|
||||||
|
|
||||||
tmps = strstr(cursor, "\"temp\":");
|
|
||||||
if (tmps == NULL) { Serial.println("##WEATHER###: temp not found !"); return false;}
|
|
||||||
tmps += 7;
|
|
||||||
tmpe = strstr(tmps, ",\"");
|
|
||||||
if (tmpe == NULL) { Serial.println("##WEATHER###: temp not found !"); return false;}
|
|
||||||
strlcpy(temp, tmps, tmpe - tmps + 1);
|
|
||||||
cursor = tmpe + 1;
|
|
||||||
float tempf = atof(temp);
|
|
||||||
|
|
||||||
tmps = strstr(cursor, "\"feels_like\":");
|
|
||||||
if (tmps == NULL) { Serial.println("##WEATHER###: feels_like not found !"); return false;}
|
|
||||||
tmps += 13;
|
|
||||||
tmpe = strstr(tmps, ",\"");
|
|
||||||
if (tmpe == NULL) { Serial.println("##WEATHER###: feels_like not found !"); return false;}
|
|
||||||
strlcpy(temp, tmps, tmpe - tmps + 1);
|
|
||||||
cursor = tmpe + 2;
|
|
||||||
float tempfl = atof(temp); (void)tempfl;
|
|
||||||
|
|
||||||
tmps = strstr(cursor, "\"pressure\":");
|
|
||||||
if (tmps == NULL) { Serial.println("##WEATHER###: pressure not found !"); return false;}
|
|
||||||
tmps += 11;
|
|
||||||
tmpe = strstr(tmps, ",\"");
|
|
||||||
if (tmpe == NULL) { Serial.println("##WEATHER###: 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("##WEATHER###: humidity not found !"); return false;}
|
|
||||||
tmps += 10;
|
|
||||||
tmpe = strstr(tmps, ",\"");
|
|
||||||
tmpc = strstr(tmps, "}");
|
|
||||||
if (tmpe == NULL) { Serial.println("##WEATHER###: humidity not found !"); return false;}
|
|
||||||
strlcpy(hum, tmps, tmpe - tmps + (tmpc>tmpe?1:0));
|
|
||||||
|
|
||||||
tmps = strstr(cursor, "\"grnd_level\":");
|
|
||||||
bool grnd_level_pr = (tmps != NULL);
|
|
||||||
if(grnd_level_pr){
|
|
||||||
tmps += 13;
|
|
||||||
tmpe = strstr(tmps, ",\"");
|
|
||||||
if (tmpe == NULL) { Serial.println("##WEATHER###: grnd_level not found !"); return false;}
|
|
||||||
strlcpy(press, tmps, tmpe - tmps + 1);
|
|
||||||
cursor = tmpe + 2;
|
|
||||||
pressi = (float)atoi(press) / 1.333;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmps = strstr(cursor, "\"speed\":");
|
|
||||||
if (tmps == NULL) { Serial.println("##WEATHER###: wind speed not found !"); return false;}
|
|
||||||
tmps += 8;
|
|
||||||
tmpe = strstr(tmps, ",\"");
|
|
||||||
if (tmpe == NULL) { Serial.println("##WEATHER###: wind speed not found !"); return false;}
|
|
||||||
strlcpy(temp, tmps, tmpe - tmps + 1);
|
|
||||||
cursor = tmpe + 1;
|
|
||||||
float wind_speed = atof(temp); (void)wind_speed;
|
|
||||||
|
|
||||||
tmps = strstr(cursor, "\"deg\":");
|
|
||||||
if (tmps == NULL) { Serial.println("##WEATHER###: wind deg not found !"); return false;}
|
|
||||||
tmps += 6;
|
|
||||||
tmpe = strstr(tmps, ",\"");
|
|
||||||
if (tmpe == NULL) { Serial.println("##WEATHER###: wind deg not found !"); return false;}
|
|
||||||
strlcpy(temp, tmps, tmpe - tmps + 1);
|
|
||||||
cursor = tmpe + 1;
|
|
||||||
int wind_deg = atof(temp)/22.5;
|
|
||||||
if(wind_deg<0) wind_deg = 16+wind_deg;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_NEXTION
|
|
||||||
nextion.putcmdf("press_txt.txt=\"%dmm\"", pressi);
|
|
||||||
nextion.putcmdf("hum_txt.txt=\"%d%%\"", atoi(hum));
|
|
||||||
char cmd[30];
|
|
||||||
snprintf(cmd, sizeof(cmd)-1,"temp_txt.txt=\"%.1f\"", tempf);
|
|
||||||
nextion.putcmd(cmd);
|
|
||||||
int iconofset;
|
|
||||||
if(strstr(icon,"01")!=NULL) iconofset = 0;
|
|
||||||
else if(strstr(icon,"02")!=NULL) iconofset = 1;
|
|
||||||
else if(strstr(icon,"03")!=NULL) iconofset = 2;
|
|
||||||
else if(strstr(icon,"04")!=NULL) iconofset = 3;
|
|
||||||
else if(strstr(icon,"09")!=NULL) iconofset = 4;
|
|
||||||
else if(strstr(icon,"10")!=NULL) iconofset = 5;
|
|
||||||
else if(strstr(icon,"11")!=NULL) iconofset = 6;
|
|
||||||
else if(strstr(icon,"13")!=NULL) iconofset = 7;
|
|
||||||
else if(strstr(icon,"50")!=NULL) iconofset = 8;
|
|
||||||
else iconofset = 9;
|
|
||||||
nextion.putcmd("cond_img.pic", 50+iconofset);
|
|
||||||
nextion.weatherVisible(1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Serial.printf("##WEATHER###: description: %s, temp:%.1f C, pressure:%dmmHg, humidity:%s%%\n", desc, tempf, pressi, hum);
|
|
||||||
#ifdef WEATHER_FMT_SHORT
|
|
||||||
sprintf(wstr, weatherFmt, tempf, pressi, hum);
|
|
||||||
#else
|
|
||||||
#if EXT_WEATHER
|
|
||||||
sprintf(wstr, weatherFmt, desc, tempf, tempfl, pressi, hum, wind_speed, wind[wind_deg]);
|
|
||||||
#else
|
|
||||||
sprintf(wstr, weatherFmt, desc, tempf, pressi, hum);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
network.requestWeatherSync();
|
|
||||||
return true;
|
|
||||||
#endif // if (DSP_MODEL!=DSP_DUMMY || defined(USE_NEXTION)) && !defined(HIDE_WEATHER)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#ifndef network_h
|
#ifndef network_h
|
||||||
#define network_h
|
#define network_h
|
||||||
#include <Ticker.h>
|
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
#include "WiFi.h"
|
#include "WiFi.h"
|
||||||
#include "rtcsupport.h"
|
#include "rtcsupport.h"
|
||||||
@@ -17,12 +16,10 @@ class MyNetwork {
|
|||||||
public:
|
public:
|
||||||
n_Status_e status;
|
n_Status_e status;
|
||||||
struct tm timeinfo;
|
struct tm timeinfo;
|
||||||
bool firstRun, forceTimeSync, forceWeather;
|
|
||||||
bool lostPlaying = false, beginReconnect = false;
|
bool lostPlaying = false, beginReconnect = false;
|
||||||
//uint8_t tsFailCnt, wsFailCnt;
|
//uint8_t tsFailCnt, wsFailCnt;
|
||||||
Ticker ctimer;
|
|
||||||
char *weatherBuf;
|
char *weatherBuf;
|
||||||
bool trueWeather;
|
//bool trueWeather;
|
||||||
public:
|
public:
|
||||||
MyNetwork() {};
|
MyNetwork() {};
|
||||||
void begin();
|
void begin();
|
||||||
@@ -31,7 +28,6 @@ class MyNetwork {
|
|||||||
void setWifiParams();
|
void setWifiParams();
|
||||||
bool wifiBegin(bool silent=false);
|
bool wifiBegin(bool silent=false);
|
||||||
private:
|
private:
|
||||||
Ticker rtimer;
|
|
||||||
void raiseSoftAP();
|
void raiseSoftAP();
|
||||||
static void WiFiLostConnection(WiFiEvent_t event, WiFiEventInfo_t info);
|
static void WiFiLostConnection(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||||
static void WiFiReconnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
static void WiFiReconnected(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef options_h
|
#ifndef options_h
|
||||||
#define options_h
|
#define options_h
|
||||||
|
|
||||||
#define YOVERSION "0.9.533"
|
#define YOVERSION "0.9.550"
|
||||||
|
|
||||||
/*******************************************************
|
/*******************************************************
|
||||||
DO NOT EDIT THIS FILE.
|
DO NOT EDIT THIS FILE.
|
||||||
@@ -361,6 +361,9 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
|
|||||||
#ifndef IR_TIMEOUT
|
#ifndef IR_TIMEOUT
|
||||||
#define IR_TIMEOUT 80 // kTimeout, see IRremoteESP8266 documentation
|
#define IR_TIMEOUT 80 // kTimeout, see IRremoteESP8266 documentation
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef IR_BUFSIZE
|
||||||
|
#define IR_BUFSIZE 128
|
||||||
|
#endif
|
||||||
|
|
||||||
/* THEMES */
|
/* THEMES */
|
||||||
/* color name R G B */
|
/* color name R G B */
|
||||||
@@ -488,10 +491,26 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
|
|||||||
#ifndef USE_OTA
|
#ifndef USE_OTA
|
||||||
#define USE_OTA false
|
#define USE_OTA false
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef WATCHDOG_INTERVAL
|
||||||
|
#define WATCHDOG_INTERVAL 3 //sec.
|
||||||
|
#endif
|
||||||
//#define OTA_PASS "myotapassword12345"
|
//#define OTA_PASS "myotapassword12345"
|
||||||
//#define HTTP_USER "user"
|
//#define HTTP_USER "user"
|
||||||
//#define HTTP_PASS "password"
|
//#define HTTP_PASS "password"
|
||||||
|
#ifndef WATCHDOG_TASK_SIZE
|
||||||
|
#define WATCHDOG_TASK_SIZE 1024*6
|
||||||
|
#endif
|
||||||
|
#ifndef WATCHDOG_TASK_PRIORITY
|
||||||
|
#define WATCHDOG_TASK_PRIORITY 3
|
||||||
|
#endif
|
||||||
|
#ifndef WATCHDOG_TASK_CORE_ID
|
||||||
|
#define WATCHDOG_TASK_CORE_ID 1
|
||||||
|
#endif
|
||||||
|
#ifndef CONNECTION_TIMEOUT
|
||||||
|
#define CONNECTION_TIMEOUT 5700
|
||||||
|
#endif
|
||||||
|
#ifndef CONNECTION_TIMEOUT_SSL
|
||||||
|
#define CONNECTION_TIMEOUT_SSL 5700
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "sdmanager.h"
|
#include "sdmanager.h"
|
||||||
#include "netserver.h"
|
#include "netserver.h"
|
||||||
|
#include "timekeeper.h"
|
||||||
|
|
||||||
Player player;
|
Player player;
|
||||||
QueueHandle_t playerQueue;
|
QueueHandle_t playerQueue;
|
||||||
@@ -35,10 +36,10 @@ void Player::init() {
|
|||||||
Serial.print("##[BOOT]#\tplayer.init\t");
|
Serial.print("##[BOOT]#\tplayer.init\t");
|
||||||
playerQueue=NULL;
|
playerQueue=NULL;
|
||||||
_resumeFilePos = 0;
|
_resumeFilePos = 0;
|
||||||
|
_hasError=false;
|
||||||
playerQueue = xQueueCreate( 5, sizeof( playerRequestParams_t ) );
|
playerQueue = xQueueCreate( 5, sizeof( playerRequestParams_t ) );
|
||||||
setOutputPins(false);
|
setOutputPins(false);
|
||||||
delay(50);
|
delay(50);
|
||||||
memset(_plError, 0, PLERR_LN);
|
|
||||||
#ifdef MQTT_ROOT_TOPIC
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
memset(burl, 0, MQTT_BURL_SIZE);
|
memset(burl, 0, MQTT_BURL_SIZE);
|
||||||
#endif
|
#endif
|
||||||
@@ -56,14 +57,13 @@ void Player::init() {
|
|||||||
setTone(config.store.bass, config.store.middle, config.store.trebble);
|
setTone(config.store.bass, config.store.middle, config.store.trebble);
|
||||||
setVolume(0);
|
setVolume(0);
|
||||||
_status = STOPPED;
|
_status = STOPPED;
|
||||||
//setOutputPins(false);
|
|
||||||
_volTimer=false;
|
_volTimer=false;
|
||||||
//randomSeed(analogRead(0));
|
//randomSeed(analogRead(0));
|
||||||
#if PLAYER_FORCE_MONO
|
#if PLAYER_FORCE_MONO
|
||||||
forceMono(true);
|
forceMono(true);
|
||||||
#endif
|
#endif
|
||||||
_loadVol(config.store.volume);
|
_loadVol(config.store.volume);
|
||||||
setConnectionTimeout(1700, 3700);
|
setConnectionTimeout(CONNECTION_TIMEOUT, CONNECTION_TIMEOUT_SSL);
|
||||||
Serial.println("done");
|
Serial.println("done");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,16 +78,18 @@ void Player::resetQueue(){
|
|||||||
|
|
||||||
void Player::stopInfo() {
|
void Player::stopInfo() {
|
||||||
config.setSmartStart(0);
|
config.setSmartStart(0);
|
||||||
//telnet.info();
|
|
||||||
netserver.requestOnChange(MODE, 0);
|
netserver.requestOnChange(MODE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::setError(const char *e){
|
void Player::setError(){
|
||||||
strlcpy(_plError, e, PLERR_LN);
|
_hasError=true;
|
||||||
if(hasError()) {
|
config.setTitle(config.tmpBuf);
|
||||||
config.setTitle(_plError);
|
telnet.printf("##ERROR#:\t%s\n", config.tmpBuf);
|
||||||
telnet.printf("##ERROR#:\t%s\n", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::setError(const char *e){
|
||||||
|
strlcpy(config.tmpBuf, e, sizeof(config.tmpBuf));
|
||||||
|
setError();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::_stop(bool alreadyStopped){
|
void Player::_stop(bool alreadyStopped){
|
||||||
@@ -95,17 +97,19 @@ void Player::_stop(bool alreadyStopped){
|
|||||||
if(config.getMode()==PM_SDCARD && !alreadyStopped) config.sdResumePos = player.getFilePos();
|
if(config.getMode()==PM_SDCARD && !alreadyStopped) config.sdResumePos = player.getFilePos();
|
||||||
_status = STOPPED;
|
_status = STOPPED;
|
||||||
setOutputPins(false);
|
setOutputPins(false);
|
||||||
if(!hasError()) config.setTitle((display.mode()==LOST || display.mode()==UPDATING)?"":const_PlStopped);
|
if(!_hasError) config.setTitle((display.mode()==LOST || display.mode()==UPDATING)?"":const_PlStopped);
|
||||||
config.station.bitrate = 0;
|
config.station.bitrate = 0;
|
||||||
config.setBitrateFormat(BF_UNCNOWN);
|
config.setBitrateFormat(BF_UNCNOWN);
|
||||||
#ifdef USE_NEXTION
|
#ifdef USE_NEXTION
|
||||||
nextion.bitrate(config.station.bitrate);
|
nextion.bitrate(config.station.bitrate);
|
||||||
#endif
|
#endif
|
||||||
|
setDefaults();
|
||||||
|
if(!alreadyStopped) stopSong();
|
||||||
netserver.requestOnChange(BITRATE, 0);
|
netserver.requestOnChange(BITRATE, 0);
|
||||||
display.putRequest(DBITRATE);
|
display.putRequest(DBITRATE);
|
||||||
display.putRequest(PSTOP);
|
display.putRequest(PSTOP);
|
||||||
setDefaults();
|
//setDefaults();
|
||||||
if(!alreadyStopped) stopSong();
|
//if(!alreadyStopped) stopSong();
|
||||||
if(!lockOutput) stopInfo();
|
if(!lockOutput) stopInfo();
|
||||||
if (player_on_stop_play) player_on_stop_play();
|
if (player_on_stop_play) player_on_stop_play();
|
||||||
pm.on_stop_play();
|
pm.on_stop_play();
|
||||||
@@ -119,6 +123,12 @@ void Player::initHeaders(const char *file) {
|
|||||||
//netserver.requestOnChange(SDPOS, 0);
|
//netserver.requestOnChange(SDPOS, 0);
|
||||||
setDefaults();
|
setDefaults();
|
||||||
}
|
}
|
||||||
|
void resetPlayer(){
|
||||||
|
if(!config.store.watchdog) return;
|
||||||
|
player.resetQueue();
|
||||||
|
player.sendCommand({PR_STOP, 0});
|
||||||
|
player.loop();
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef PL_QUEUE_TICKS
|
#ifndef PL_QUEUE_TICKS
|
||||||
#define PL_QUEUE_TICKS 0
|
#define PL_QUEUE_TICKS 0
|
||||||
@@ -141,6 +151,10 @@ void Player::loop() {
|
|||||||
pm.on_station_change();
|
pm.on_station_change();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PR_TOGGLE: {
|
||||||
|
toggle();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case PR_VOL: {
|
case PR_VOL: {
|
||||||
config.setVolume(requestP.payload);
|
config.setVolume(requestP.payload);
|
||||||
Audio::setVolume(volToI2S(requestP.payload));
|
Audio::setVolume(volToI2S(requestP.payload));
|
||||||
@@ -157,8 +171,19 @@ void Player::loop() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
case PR_VUTONUS:
|
case PR_VUTONUS: {
|
||||||
if(config.vuThreshold>10) config.vuThreshold -=10;
|
if(config.vuThreshold>10) config.vuThreshold -=10;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PR_BURL: {
|
||||||
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
|
if(strlen(burl)>0){
|
||||||
|
browseUrl();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,11 +195,12 @@ void Player::loop() {
|
|||||||
_volTimer=false;
|
_volTimer=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
#ifdef MQTT_ROOT_TOPIC
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
if(strlen(burl)>0){
|
if(strlen(burl)>0){
|
||||||
browseUrl();
|
browseUrl();
|
||||||
}
|
}
|
||||||
#endif
|
#endif*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::setOutputPins(bool isPlaying) {
|
void Player::setOutputPins(bool isPlaying) {
|
||||||
@@ -185,32 +211,15 @@ void Player::setOutputPins(bool isPlaying) {
|
|||||||
|
|
||||||
void Player::_play(uint16_t stationId) {
|
void Player::_play(uint16_t stationId) {
|
||||||
log_i("%s called, stationId=%d", __func__, stationId);
|
log_i("%s called, stationId=%d", __func__, stationId);
|
||||||
setError("");
|
_hasError=false;
|
||||||
setDefaults();
|
setDefaults();
|
||||||
remoteStationName = false;
|
_status = STOPPED;
|
||||||
config.setDspOn(1);
|
|
||||||
config.vuThreshold = 0;
|
|
||||||
//display.putRequest(PSTOP);
|
|
||||||
config.screensaverTicks=SCREENSAVERSTARTUPDELAY;
|
|
||||||
config.screensaverPlayingTicks=SCREENSAVERSTARTUPDELAY;
|
|
||||||
if(config.getMode()!=PM_SDCARD) {
|
|
||||||
display.putRequest(PSTOP);
|
|
||||||
}
|
|
||||||
setOutputPins(false);
|
setOutputPins(false);
|
||||||
//config.setTitle(config.getMode()==PM_WEB?const_PlConnect:"");
|
remoteStationName = false;
|
||||||
if(!config.loadStation(stationId)) return;
|
|
||||||
config.setTitle(config.getMode()==PM_WEB?const_PlConnect:"[next track]");
|
|
||||||
config.station.bitrate=0;
|
|
||||||
config.setBitrateFormat(BF_UNCNOWN);
|
|
||||||
|
|
||||||
|
if(!config.prepareForPlaying(stationId)) return;
|
||||||
_loadVol(config.store.volume);
|
_loadVol(config.store.volume);
|
||||||
display.putRequest(DBITRATE);
|
|
||||||
display.putRequest(NEWSTATION);
|
|
||||||
netserver.requestOnChange(STATION, 0);
|
|
||||||
netserver.loop();
|
|
||||||
netserver.loop();
|
|
||||||
if(config.store.smartstart!=2)
|
|
||||||
config.setSmartStart(0);
|
|
||||||
bool isConnected = false;
|
bool isConnected = false;
|
||||||
if(config.getMode()==PM_SDCARD && SDC_CS!=255){
|
if(config.getMode()==PM_SDCARD && SDC_CS!=255){
|
||||||
isConnected=connecttoFS(sdman,config.station.url,config.sdResumePos==0?_resumeFilePos:config.sdResumePos-player.sd_min);
|
isConnected=connecttoFS(sdman,config.station.url,config.sdResumePos==0?_resumeFilePos:config.sdResumePos-player.sd_min);
|
||||||
@@ -219,36 +228,25 @@ void Player::_play(uint16_t stationId) {
|
|||||||
}
|
}
|
||||||
if(config.getMode()==PM_WEB) isConnected=connecttohost(config.station.url);
|
if(config.getMode()==PM_WEB) isConnected=connecttohost(config.station.url);
|
||||||
if(isConnected){
|
if(isConnected){
|
||||||
//if (config.store.play_mode==PM_WEB?connecttohost(config.station.url):connecttoFS(SD,config.station.url,config.sdResumePos==0?_resumeFilePos:config.sdResumePos-player.sd_min)) {
|
|
||||||
_status = PLAYING;
|
_status = PLAYING;
|
||||||
if(config.getMode()==PM_SDCARD) {
|
config.configPostPlaying(stationId);
|
||||||
config.sdResumePos = 0;
|
|
||||||
config.saveValue(&config.store.lastSdStation, stationId);
|
|
||||||
}
|
|
||||||
//config.setTitle("");
|
|
||||||
if(config.store.smartstart!=2)
|
|
||||||
config.setSmartStart(1);
|
|
||||||
netserver.requestOnChange(MODE, 0);
|
|
||||||
setOutputPins(true);
|
setOutputPins(true);
|
||||||
display.putRequest(NEWMODE, PLAYER);
|
|
||||||
display.putRequest(PSTART);
|
|
||||||
if (player_on_start_play) player_on_start_play();
|
if (player_on_start_play) player_on_start_play();
|
||||||
pm.on_start_play();
|
pm.on_start_play();
|
||||||
}else{
|
}else{
|
||||||
telnet.printf("##ERROR#:\tError connecting to %s\n", config.station.url);
|
telnet.printf("##ERROR#:\tError connecting to %.128s\n", config.station.url);
|
||||||
SET_PLAY_ERROR("Error connecting to %s", config.station.url);
|
snprintf(config.tmpBuf, sizeof(config.tmpBuf), "Error connecting to %.128s", config.station.url); setError();
|
||||||
_stop(true);
|
_stop(true);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MQTT_ROOT_TOPIC
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
void Player::browseUrl(){
|
void Player::browseUrl(){
|
||||||
setError("");
|
_hasError=false;
|
||||||
remoteStationName = true;
|
remoteStationName = true;
|
||||||
config.setDspOn(1);
|
config.setDspOn(1);
|
||||||
resumeAfterUrl = _status==PLAYING;
|
resumeAfterUrl = _status==PLAYING;
|
||||||
display.putRequest(PSTOP);
|
display.putRequest(PSTOP);
|
||||||
// setDefaults();
|
|
||||||
setOutputPins(false);
|
setOutputPins(false);
|
||||||
config.setTitle(const_PlConnect);
|
config.setTitle(const_PlConnect);
|
||||||
if (connecttohost(burl)){
|
if (connecttohost(burl)){
|
||||||
@@ -260,16 +258,15 @@ void Player::browseUrl(){
|
|||||||
if (player_on_start_play) player_on_start_play();
|
if (player_on_start_play) player_on_start_play();
|
||||||
pm.on_start_play();
|
pm.on_start_play();
|
||||||
}else{
|
}else{
|
||||||
telnet.printf("##ERROR#:\tError connecting to %s\n", burl);
|
telnet.printf("##ERROR#:\tError connecting to %.128s\n", burl);
|
||||||
SET_PLAY_ERROR("Error connecting to %s", burl);
|
snprintf(config.tmpBuf, sizeof(config.tmpBuf), "Error connecting to %.128s", burl); setError();
|
||||||
_stop(true);
|
_stop(true);
|
||||||
}
|
}
|
||||||
memset(burl, 0, MQTT_BURL_SIZE);
|
//memset(burl, 0, MQTT_BURL_SIZE);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Player::prev() {
|
void Player::prev() {
|
||||||
|
|
||||||
uint16_t lastStation = config.lastStation();
|
uint16_t lastStation = config.lastStation();
|
||||||
if(config.getMode()==PM_WEB || !config.store.sdsnuffle){
|
if(config.getMode()==PM_WEB || !config.store.sdsnuffle){
|
||||||
if (lastStation == 1) config.lastStation(config.playlistLength()); else config.lastStation(lastStation-1);
|
if (lastStation == 1) config.lastStation(config.playlistLength()); else config.lastStation(lastStation-1);
|
||||||
|
|||||||
@@ -13,13 +13,14 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PLQ_SEND_DELAY
|
#ifndef PLQ_SEND_DELAY
|
||||||
#define PLQ_SEND_DELAY portMAX_DELAY
|
//#define PLQ_SEND_DELAY portMAX_DELAY
|
||||||
|
#define PLQ_SEND_DELAY pdMS_TO_TICKS(1000)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PLERR_LN 64
|
//#define PLERR_LN 64
|
||||||
#define SET_PLAY_ERROR(...) {char buff[512 + 64]; sprintf(buff,__VA_ARGS__); setError(buff);}
|
//#define SET_PLAY_ERROR(...) {char buff[512 + 64]; sprintf(buff,__VA_ARGS__); setError(buff);}
|
||||||
|
|
||||||
enum playerRequestType_e : uint8_t { PR_PLAY = 1, PR_STOP = 2, PR_PREV = 3, PR_NEXT = 4, PR_VOL = 5, PR_CHECKSD = 6, PR_VUTONUS = 7 };
|
enum playerRequestType_e : uint8_t { PR_PLAY = 1, PR_STOP = 2, PR_PREV = 3, PR_NEXT = 4, PR_VOL = 5, PR_CHECKSD = 6, PR_VUTONUS = 7, PR_BURL = 8, PR_TOGGLE = 9 };
|
||||||
struct playerRequestParams_t
|
struct playerRequestParams_t
|
||||||
{
|
{
|
||||||
playerRequestType_e type;
|
playerRequestType_e type;
|
||||||
@@ -34,11 +35,12 @@ class Player: public Audio {
|
|||||||
bool _volTimer; /* delayed volume save */
|
bool _volTimer; /* delayed volume save */
|
||||||
uint32_t _resumeFilePos;
|
uint32_t _resumeFilePos;
|
||||||
plStatus_e _status;
|
plStatus_e _status;
|
||||||
char _plError[PLERR_LN];
|
//char _plError[PLERR_LN];
|
||||||
private:
|
private:
|
||||||
void _stop(bool alreadyStopped = false);
|
void _stop(bool alreadyStopped = false);
|
||||||
void _play(uint16_t stationId);
|
void _play(uint16_t stationId);
|
||||||
void _loadVol(uint8_t volume);
|
void _loadVol(uint8_t volume);
|
||||||
|
bool _hasError;
|
||||||
public:
|
public:
|
||||||
bool lockOutput = true;
|
bool lockOutput = true;
|
||||||
bool resumeAfterUrl = false;
|
bool resumeAfterUrl = false;
|
||||||
@@ -51,8 +53,9 @@ class Player: public Audio {
|
|||||||
void init();
|
void init();
|
||||||
void loop();
|
void loop();
|
||||||
void initHeaders(const char *file);
|
void initHeaders(const char *file);
|
||||||
|
void setError();
|
||||||
void setError(const char *e);
|
void setError(const char *e);
|
||||||
bool hasError() { return strlen(_plError)>0; }
|
//bool hasError() { return strlen(_plError)>0; }
|
||||||
void sendCommand(playerRequestParams_t request);
|
void sendCommand(playerRequestParams_t request);
|
||||||
void resetQueue();
|
void resetQueue();
|
||||||
#ifdef MQTT_ROOT_TOPIC
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
|
|||||||
@@ -45,10 +45,11 @@ bool SDManager::cardPresent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SDManager::_checkNoMedia(const char* path){
|
bool SDManager::_checkNoMedia(const char* path){
|
||||||
char nomedia[BUFLEN]= {0};
|
if (path[strlen(path) - 1] == '/')
|
||||||
strlcat(nomedia, path, BUFLEN);
|
snprintf(config.tmpBuf, sizeof(config.tmpBuf), "%s%s", path, ".nomedia");
|
||||||
strlcat(nomedia, "/.nomedia", BUFLEN);
|
else
|
||||||
bool nm = exists(nomedia);
|
snprintf(config.tmpBuf, sizeof(config.tmpBuf), "%s/%s", path, ".nomedia");
|
||||||
|
bool nm = exists(config.tmpBuf);
|
||||||
return nm;
|
return nm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,12 @@
|
|||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "telnet.h"
|
#include "telnet.h"
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
|
|
||||||
Telnet telnet;
|
Telnet telnet;
|
||||||
|
|
||||||
bool Telnet::_isIPSet(IPAddress ip) {
|
bool Telnet::_isIPSet(IPAddress ip) {
|
||||||
return ip.toString() == "0.0.0.0";
|
return strcmp(config.ipToStr(ip), "0.0.0.0") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Telnet::begin(bool quiet) {
|
bool Telnet::begin(bool quiet) {
|
||||||
@@ -21,12 +22,11 @@ bool Telnet::begin(bool quiet) {
|
|||||||
}
|
}
|
||||||
if(!quiet) Serial.print("##[BOOT]#\ttelnet.begin\t");
|
if(!quiet) Serial.print("##[BOOT]#\ttelnet.begin\t");
|
||||||
if (WiFi.status() == WL_CONNECTED || _isIPSet(WiFi.softAPIP())) {
|
if (WiFi.status() == WL_CONNECTED || _isIPSet(WiFi.softAPIP())) {
|
||||||
server.begin();
|
toggle();
|
||||||
server.setNoDelay(true);
|
|
||||||
if(!quiet){
|
if(!quiet){
|
||||||
Serial.println("done");
|
Serial.println("done");
|
||||||
Serial.println("##[BOOT]#");
|
Serial.println("##[BOOT]#");
|
||||||
BOOTLOG("Ready! Go to http:/%s/ to configure", WiFi.localIP().toString().c_str());
|
BOOTLOG("Ready! Go to http:/%s/ to configure", config.ipToStr(WiFi.localIP()));
|
||||||
BOOTLOG("------------------------------------------------");
|
BOOTLOG("------------------------------------------------");
|
||||||
Serial.println("##[BOOT]#");
|
Serial.println("##[BOOT]#");
|
||||||
}
|
}
|
||||||
@@ -36,10 +36,19 @@ bool Telnet::begin(bool quiet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Telnet::start() {
|
||||||
|
server.begin();
|
||||||
|
server.setNoDelay(true);
|
||||||
|
}
|
||||||
|
|
||||||
void Telnet::stop() {
|
void Telnet::stop() {
|
||||||
server.stop();
|
server.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Telnet::toggle() {
|
||||||
|
if(config.store.telnet) { start(); }else{ stop(); }
|
||||||
|
}
|
||||||
|
|
||||||
void Telnet::emptyClientStream(WiFiClient client) {
|
void Telnet::emptyClientStream(WiFiClient client) {
|
||||||
client.flush();
|
client.flush();
|
||||||
delay(50);
|
delay(50);
|
||||||
@@ -72,6 +81,7 @@ void Telnet::loop() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
|
if(config.store.telnet)
|
||||||
if (WiFi.status() == WL_CONNECTED) {
|
if (WiFi.status() == WL_CONNECTED) {
|
||||||
if (server.hasClient()) {
|
if (server.hasClient()) {
|
||||||
for (i = 0; i < MAX_TLN_CLIENTS; i++) {
|
for (i = 0; i < MAX_TLN_CLIENTS; i++) {
|
||||||
@@ -81,7 +91,7 @@ void Telnet::loop() {
|
|||||||
}
|
}
|
||||||
clients[i] = server.available();
|
clients[i] = server.available();
|
||||||
if (!clients[i]) Serial.println("available broken");
|
if (!clients[i]) Serial.println("available broken");
|
||||||
on_connect(clients[i].remoteIP().toString().c_str(), i);
|
on_connect(config.ipToStr(clients[i].remoteIP()), i);
|
||||||
clients[i].setNoDelay(true);
|
clients[i].setNoDelay(true);
|
||||||
emptyClientStream(clients[i]);
|
emptyClientStream(clients[i]);
|
||||||
break;
|
break;
|
||||||
@@ -125,35 +135,33 @@ void Telnet::print(uint8_t id, const char *buf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Telnet::printf(const char *format, ...) {
|
void Telnet::printf(const char *format, ...) {
|
||||||
char buf[MAX_PRINTF_LEN];
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start (args, format );
|
va_start (args, format );
|
||||||
vsnprintf(buf, MAX_PRINTF_LEN, format, args);
|
vsnprintf(cmBuf, sizeof(cmBuf), format, args);
|
||||||
va_end (args);
|
va_end (args);
|
||||||
for (int id = 0; id < MAX_TLN_CLIENTS; id++) {
|
for (int id = 0; id < MAX_TLN_CLIENTS; id++) {
|
||||||
if (clients[id] && clients[id].connected()) {
|
if (clients[id] && clients[id].connected()) {
|
||||||
clients[id].print(buf);
|
clients[id].print(cmBuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (strcmp(buf, "> ") == 0) return;
|
if (strcmp(cmBuf, "> ") == 0) return;
|
||||||
//if(strstr(buf,"\n> ")==NULL) Serial.print(buf);
|
//if(strstr(buf,"\n> ")==NULL) Serial.print(buf);
|
||||||
char *nl = strstr(buf, "\n> ");
|
char *nl = strstr(cmBuf, "\n> ");
|
||||||
if (nl != NULL) { buf[nl-buf+1] = '\0'; }
|
if (nl != NULL) { cmBuf[nl-cmBuf+1] = '\0'; }
|
||||||
Serial.print(buf);
|
Serial.print(cmBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Telnet::printf(uint8_t id, const char *format, ...) {
|
void Telnet::printf(uint8_t id, const char *format, ...) {
|
||||||
char buf[MAX_PRINTF_LEN];
|
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
va_start(argptr, format);
|
va_start(argptr, format);
|
||||||
vsnprintf(buf, MAX_PRINTF_LEN, format, argptr);
|
vsnprintf(cmBuf, sizeof(cmBuf), format, argptr);
|
||||||
va_end(argptr);
|
va_end(argptr);
|
||||||
if(id>MAX_TLN_CLIENTS){
|
if(id>MAX_TLN_CLIENTS){
|
||||||
Serial.print(buf);
|
Serial.print(cmBuf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (clients[id] && clients[id].connected()) {
|
if (clients[id] && clients[id].connected()) {
|
||||||
clients[id].print(buf);
|
clients[id].print(cmBuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,9 +172,8 @@ void Telnet::on_connect(const char* str, uint8_t clientId) {
|
|||||||
|
|
||||||
void Telnet::info() {
|
void Telnet::info() {
|
||||||
telnet.printf("##CLI.INFO#\n");
|
telnet.printf("##CLI.INFO#\n");
|
||||||
char timeStringBuff[50];
|
strftime(config.tmpBuf, sizeof(config.tmpBuf), "%Y-%m-%dT%H:%M:%S+03:00", &network.timeinfo);
|
||||||
strftime(timeStringBuff, sizeof(timeStringBuff), "%Y-%m-%dT%H:%M:%S+03:00", &network.timeinfo);
|
telnet.printf("##SYS.DATE#: %s\n", config.tmpBuf); //TODO timezone offset
|
||||||
telnet.printf("##SYS.DATE#: %s\n", timeStringBuff); //TODO timezone offset
|
|
||||||
telnet.printf("##CLI.NAMESET#: %d %s\n", config.lastStation(), config.station.name);
|
telnet.printf("##CLI.NAMESET#: %d %s\n", config.lastStation(), config.station.name);
|
||||||
if (player.status() == PLAYING) {
|
if (player.status() == PLAYING) {
|
||||||
telnet.printf("##CLI.META#: %s\n", config.station.title);
|
telnet.printf("##CLI.META#: %s\n", config.station.title);
|
||||||
@@ -180,6 +187,16 @@ void Telnet::info() {
|
|||||||
telnet.printf("> ");
|
telnet.printf("> ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Telnet::printHeapFragmentationInfo(uint8_t id){
|
||||||
|
size_t freeHeap = heap_caps_get_free_size(MALLOC_CAP_DEFAULT);
|
||||||
|
size_t largestBlock = heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT);
|
||||||
|
float fragmentation = 100.0 * (1.0 - ((float)largestBlock / (float)freeHeap));
|
||||||
|
printf(id, "\n*************************************\n");
|
||||||
|
printf(id, "* Free heap: %u bytes\n", freeHeap);
|
||||||
|
printf(id, "* Largest free block: %u bytes\n", largestBlock);
|
||||||
|
printf(id, "* Fragmentation: %.2f%%\n", fragmentation);
|
||||||
|
printf(id, "*************************************\n\n");
|
||||||
|
}
|
||||||
void Telnet::on_input(const char* str, uint8_t clientId) {
|
void Telnet::on_input(const char* str, uint8_t clientId) {
|
||||||
if (strlen(str) == 0) return;
|
if (strlen(str) == 0) return;
|
||||||
if(network.status == CONNECTED){
|
if(network.status == CONNECTED){
|
||||||
@@ -253,12 +270,11 @@ void Telnet::on_input(const char* str, uint8_t clientId) {
|
|||||||
if (!file || file.isDirectory()) {
|
if (!file || file.isDirectory()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char sName[BUFLEN], sUrl[BUFLEN];
|
|
||||||
int sOvol;
|
int sOvol;
|
||||||
uint8_t c = 1;
|
uint8_t c = 1;
|
||||||
while (file.available()) {
|
while (file.available()) {
|
||||||
if (config.parseCSV(file.readStringUntil('\n').c_str(), sName, sUrl, sOvol)) {
|
if (config.parseCSV(file.readStringUntil('\n').c_str(), config.tmpBuf, config.tmpBuf2, sOvol)) {
|
||||||
printf(clientId, "#CLI.LISTNUM#: %*d: %s, %s\n", 3, c, sName, sUrl);
|
printf(clientId, "#CLI.LISTNUM#: %*d: %s, %s\n", 3, c, config.tmpBuf, config.tmpBuf2);
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -268,12 +284,11 @@ void Telnet::on_input(const char* str, uint8_t clientId) {
|
|||||||
}
|
}
|
||||||
if (strcmp(str, "cli.info") == 0 || strcmp(str, "info") == 0) {
|
if (strcmp(str, "cli.info") == 0 || strcmp(str, "info") == 0) {
|
||||||
printf(clientId, "##CLI.INFO#\n");
|
printf(clientId, "##CLI.INFO#\n");
|
||||||
char timeStringBuff[50];
|
strftime(config.tmpBuf, sizeof(config.tmpBuf), "%Y-%m-%dT%H:%M:%S", &network.timeinfo);
|
||||||
strftime(timeStringBuff, sizeof(timeStringBuff), "%Y-%m-%dT%H:%M:%S", &network.timeinfo);
|
|
||||||
if (config.store.tzHour < 0) {
|
if (config.store.tzHour < 0) {
|
||||||
printf(clientId, "##SYS.DATE#: %s%03d:%02d\n", timeStringBuff, config.store.tzHour, config.store.tzMin);
|
printf(clientId, "##SYS.DATE#: %s%03d:%02d\n", config.tmpBuf, config.store.tzHour, config.store.tzMin);
|
||||||
} else {
|
} else {
|
||||||
printf(clientId, "##SYS.DATE#: %s+%02d:%02d\n", timeStringBuff, config.store.tzHour, config.store.tzMin);
|
printf(clientId, "##SYS.DATE#: %s+%02d:%02d\n", config.tmpBuf, config.store.tzHour, config.store.tzMin);
|
||||||
}
|
}
|
||||||
printf(clientId, "##CLI.NAMESET#: %d %s\n", config.lastStation(), config.station.name);
|
printf(clientId, "##CLI.NAMESET#: %d %s\n", config.lastStation(), config.station.name);
|
||||||
if (player.status() == PLAYING) {
|
if (player.status() == PLAYING) {
|
||||||
@@ -406,11 +421,10 @@ void Telnet::on_input(const char* str, uint8_t clientId) {
|
|||||||
printf(clientId, "#WIFI.CON#\n");
|
printf(clientId, "#WIFI.CON#\n");
|
||||||
File file = SPIFFS.open(SSIDS_PATH, "r");
|
File file = SPIFFS.open(SSIDS_PATH, "r");
|
||||||
if (file && !file.isDirectory()) {
|
if (file && !file.isDirectory()) {
|
||||||
char sSid[BUFLEN], sPas[BUFLEN];
|
|
||||||
uint8_t c = 1;
|
uint8_t c = 1;
|
||||||
while (file.available()) {
|
while (file.available()) {
|
||||||
if (config.parseSsid(file.readStringUntil('\n').c_str(), sSid, sPas)) {
|
if (config.parseSsid(file.readStringUntil('\n').c_str(), config.tmpBuf, config.tmpBuf2)) {
|
||||||
printf(clientId, "%d: %s, %s\n", c, sSid, sPas);
|
printf(clientId, "%d: %s, %s\n", c, config.tmpBuf, config.tmpBuf2);
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -422,11 +436,10 @@ void Telnet::on_input(const char* str, uint8_t clientId) {
|
|||||||
printf(clientId, "#WIFI.STATION#\n");
|
printf(clientId, "#WIFI.STATION#\n");
|
||||||
File file = SPIFFS.open(SSIDS_PATH, "r");
|
File file = SPIFFS.open(SSIDS_PATH, "r");
|
||||||
if (file && !file.isDirectory()) {
|
if (file && !file.isDirectory()) {
|
||||||
char sSid[BUFLEN], sPas[BUFLEN];
|
|
||||||
uint8_t c = 1;
|
uint8_t c = 1;
|
||||||
while (file.available()) {
|
while (file.available()) {
|
||||||
if (config.parseSsid(file.readStringUntil('\n').c_str(), sSid, sPas)) {
|
if (config.parseSsid(file.readStringUntil('\n').c_str(), config.tmpBuf, config.tmpBuf2)) {
|
||||||
if(c==config.store.lastSSID) printf(clientId, "%d: %s, %s\n", c, sSid, sPas);
|
if(c==config.store.lastSSID) printf(clientId, "%d: %s, %s\n", c, config.tmpBuf, config.tmpBuf2);
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -434,23 +447,21 @@ void Telnet::on_input(const char* str, uint8_t clientId) {
|
|||||||
printf(clientId, "##WIFI.STATION#\n> ");
|
printf(clientId, "##WIFI.STATION#\n> ");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char newssid[30], newpass[40];
|
if (sscanf(str, "wifi.con(\"%[^\"]\",\"%[^\"]\")", config.tmpBuf, config.tmpBuf2) == 2 || sscanf(str, "wifi.con(%[^,],%[^)])", config.tmpBuf, config.tmpBuf2) == 2 || sscanf(str, "wifi.con(%[^ ] %[^)])", config.tmpBuf, config.tmpBuf2) == 2 || sscanf(str, "wifi %[^ ] %s", config.tmpBuf, config.tmpBuf2) == 2) {
|
||||||
if (sscanf(str, "wifi.con(\"%[^\"]\",\"%[^\"]\")", newssid, newpass) == 2 || sscanf(str, "wifi.con(%[^,],%[^)])", newssid, newpass) == 2 || sscanf(str, "wifi.con(%[^ ] %[^)])", newssid, newpass) == 2 || sscanf(str, "wifi %[^ ] %s", newssid, newpass) == 2) {
|
snprintf(cmBuf, sizeof(cmBuf), "New SSID: \"%s\" with PASS: \"%s\" for next boot\n> ", config.tmpBuf, config.tmpBuf2);
|
||||||
char buf[BUFLEN];
|
printf(clientId, cmBuf);
|
||||||
snprintf(buf, BUFLEN, "New SSID: \"%s\" with PASS: \"%s\" for next boot\n> ", newssid, newpass);
|
|
||||||
printf(clientId, buf);
|
|
||||||
printf(clientId, "...REBOOTING...\n> ");
|
printf(clientId, "...REBOOTING...\n> ");
|
||||||
memset(buf, 0, BUFLEN);
|
memset(cmBuf, 0, sizeof(cmBuf));
|
||||||
snprintf(buf, BUFLEN, "%s\t%s", newssid, newpass);
|
snprintf(cmBuf, sizeof(cmBuf), "%s\t%s", config.tmpBuf, config.tmpBuf2);
|
||||||
config.saveWifiFromNextion(buf);
|
config.saveWifiFromNextion(cmBuf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (strcmp(str, "wifi.status") == 0 || strcmp(str, "status") == 0) {
|
if (strcmp(str, "wifi.status") == 0 || strcmp(str, "status") == 0) {
|
||||||
printf(clientId, "#WIFI.STATUS#\nStatus:\t\t%d\nMode:\t\t%s\nIP:\t\t%s\nMask:\t\t%s\nGateway:\t%s\nRSSI:\t\t%d dBm\n##WIFI.STATUS#\n> ",
|
printf(clientId, "#WIFI.STATUS#\nStatus:\t\t%d\nMode:\t\t%s\nIP:\t\t%s\nMask:\t\t%s\nGateway:\t%s\nRSSI:\t\t%d dBm\n##WIFI.STATUS#\n> ",
|
||||||
WiFi.status(), WiFi.getMode()==WIFI_STA?"WIFI_STA":"WIFI_AP",
|
WiFi.status(), WiFi.getMode()==WIFI_STA?"WIFI_STA":"WIFI_AP",
|
||||||
WiFi.getMode()==WIFI_STA?WiFi.localIP().toString():WiFi.softAPIP().toString(),
|
WiFi.getMode()==WIFI_STA?config.ipToStr(WiFi.localIP()):config.ipToStr(WiFi.softAPIP()),
|
||||||
WiFi.getMode()==WIFI_STA?WiFi.subnetMask().toString():"255.255.255.0",
|
WiFi.getMode()==WIFI_STA?config.ipToStr(WiFi.subnetMask()):"255.255.255.0",
|
||||||
WiFi.getMode()==WIFI_STA?WiFi.gatewayIP().toString():WiFi.softAPIP().toString(),
|
WiFi.getMode()==WIFI_STA?config.ipToStr(WiFi.gatewayIP()):config.ipToStr(WiFi.softAPIP()),
|
||||||
WiFi.RSSI()
|
WiFi.RSSI()
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -460,12 +471,14 @@ void Telnet::on_input(const char* str, uint8_t clientId) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (strcmp(str, "sys.heap") == 0 || strcmp(str, "heap") == 0) {
|
if (strcmp(str, "sys.heap") == 0 || strcmp(str, "heap") == 0) {
|
||||||
printf(clientId, "Free heap:\t%d bytes\n> ", xPortGetFreeHeapSize());
|
//printf(clientId, "Free heap:\t%d bytes\n> ", xPortGetFreeHeapSize());
|
||||||
|
printHeapFragmentationInfo(clientId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (strcmp(str, "sys.config") == 0 || strcmp(str, "config") == 0) {
|
if (strcmp(str, "sys.config") == 0 || strcmp(str, "config") == 0) {
|
||||||
config.bootInfo();
|
config.bootInfo();
|
||||||
printf(clientId, "Free heap:\t%d bytes\n> ", xPortGetFreeHeapSize());
|
//printf(clientId, "Free heap:\t%d bytes\n> ", xPortGetFreeHeapSize());
|
||||||
|
printHeapFragmentationInfo(clientId);
|
||||||
return;
|
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) {
|
||||||
|
|||||||
@@ -4,14 +4,15 @@
|
|||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
|
||||||
#define MAX_TLN_CLIENTS 5
|
#define MAX_TLN_CLIENTS 5
|
||||||
#define MAX_PRINTF_LEN BUFLEN+50
|
|
||||||
|
|
||||||
class Telnet {
|
class Telnet {
|
||||||
public:
|
public:
|
||||||
Telnet() {};
|
Telnet() {};
|
||||||
bool begin(bool quiet=false);
|
bool begin(bool quiet=false);
|
||||||
void loop();
|
void loop();
|
||||||
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
void toggle();
|
||||||
void print(uint8_t id, const char *buf);
|
void print(uint8_t id, const char *buf);
|
||||||
void print(const char *buf);
|
void print(const char *buf);
|
||||||
void printf(uint8_t id, const char *format, ...);
|
void printf(uint8_t id, const char *format, ...);
|
||||||
@@ -25,8 +26,10 @@ class Telnet {
|
|||||||
void on_connect(const char* str, uint8_t clientId);
|
void on_connect(const char* str, uint8_t clientId);
|
||||||
void on_input(const char* str, uint8_t clientId);
|
void on_input(const char* str, uint8_t clientId);
|
||||||
private:
|
private:
|
||||||
|
char cmBuf[220];
|
||||||
bool _isIPSet(IPAddress ip);
|
bool _isIPSet(IPAddress ip);
|
||||||
void handleSerial();
|
void handleSerial();
|
||||||
|
void printHeapFragmentationInfo(uint8_t id);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Telnet telnet;
|
extern Telnet telnet;
|
||||||
|
|||||||
386
yoRadio/src/core/timekeeper.cpp
Normal file
386
yoRadio/src/core/timekeeper.cpp
Normal file
@@ -0,0 +1,386 @@
|
|||||||
|
#include "timekeeper.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "network.h"
|
||||||
|
#include "display.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "netserver.h"
|
||||||
|
#include "rtcsupport.h"
|
||||||
|
|
||||||
|
#if RTCSUPPORTED
|
||||||
|
//#define TIME_SYNC_INTERVAL 24*60*60*1000
|
||||||
|
#define TIME_SYNC_INTERVAL config.store.timeSyncIntervalRTC*60*60*1000
|
||||||
|
#else
|
||||||
|
#define TIME_SYNC_INTERVAL config.store.timeSyncInterval*60*1000
|
||||||
|
#endif
|
||||||
|
#define WEATHER_SYNC_INTERVAL config.store.weatherSyncInterval*60*1000
|
||||||
|
|
||||||
|
#define SYNC_STACK_SIZE 1024 * 4
|
||||||
|
#define SYNC_TASK_CORE 0
|
||||||
|
#define SYNC_TASK_PRIORITY 1
|
||||||
|
|
||||||
|
TimeKeeper timekeeper;
|
||||||
|
|
||||||
|
void _syncTask(void *pvParameters) {
|
||||||
|
if (timekeeper.forceWeather && timekeeper.forceTimeSync) {
|
||||||
|
timekeeper.weatherTask();
|
||||||
|
timekeeper.timeTask();
|
||||||
|
}
|
||||||
|
else if (timekeeper.forceWeather) {
|
||||||
|
timekeeper.weatherTask();
|
||||||
|
}
|
||||||
|
else if (timekeeper.forceTimeSync) {
|
||||||
|
timekeeper.timeTask();
|
||||||
|
}
|
||||||
|
timekeeper.busy = false;
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TimeKeeper::loop0(){ // core0 (display)
|
||||||
|
uint32_t currentTime = millis();
|
||||||
|
static uint32_t _last1s = 0;
|
||||||
|
static uint32_t _last2s = 0;
|
||||||
|
static uint32_t _last5s = 0;
|
||||||
|
if (currentTime - _last1s >= 1000) { // 1sec
|
||||||
|
_last1s = currentTime;
|
||||||
|
#ifndef DUMMYDISPLAY
|
||||||
|
#ifndef UPCLOCK_CORE1
|
||||||
|
_upClock();
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (currentTime - _last2s >= 2000) { // 2sec
|
||||||
|
_last2s = currentTime;
|
||||||
|
_upRSSI();
|
||||||
|
}
|
||||||
|
if (currentTime - _last5s >= 5000) { // 2sec
|
||||||
|
_last5s = currentTime;
|
||||||
|
//HEAP_INFO();
|
||||||
|
}
|
||||||
|
#ifdef DUMMYDISPLAY
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
static uint32_t lastWeatherTime = 0;
|
||||||
|
if (currentTime - lastWeatherTime >= WEATHER_SYNC_INTERVAL) {
|
||||||
|
lastWeatherTime = currentTime;
|
||||||
|
forceWeather = true;
|
||||||
|
}
|
||||||
|
static uint32_t lastTimeTime = 0;
|
||||||
|
if (currentTime - lastTimeTime >= TIME_SYNC_INTERVAL) {
|
||||||
|
lastTimeTime = currentTime;
|
||||||
|
forceTimeSync = true;
|
||||||
|
}
|
||||||
|
if (!busy && (forceWeather || forceTimeSync) && network.status == CONNECTED) {
|
||||||
|
busy = true;
|
||||||
|
//config.setTimeConf();
|
||||||
|
xTaskCreatePinnedToCore(
|
||||||
|
_syncTask,
|
||||||
|
"syncTask",
|
||||||
|
SYNC_STACK_SIZE,
|
||||||
|
NULL, // Params
|
||||||
|
SYNC_TASK_PRIORITY,
|
||||||
|
NULL, // Descriptor
|
||||||
|
SYNC_TASK_CORE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true; // just in case
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TimeKeeper::loop1(){ // core1 (player)
|
||||||
|
uint32_t currentTime = millis();
|
||||||
|
static uint32_t _last1s = 0;
|
||||||
|
static uint32_t _last2s = 0;
|
||||||
|
if (currentTime - _last1s >= 1000) { // 1sec
|
||||||
|
pm.on_ticker();
|
||||||
|
_last1s = currentTime;
|
||||||
|
#ifndef DUMMYDISPLAY
|
||||||
|
#ifdef UPCLOCK_CORE1
|
||||||
|
_upClock();
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
_upScreensaver();
|
||||||
|
_upSDPos();
|
||||||
|
_returnPlayer();
|
||||||
|
_doAfterWait();
|
||||||
|
}
|
||||||
|
if (currentTime - _last2s >= 2000) { // 2sec
|
||||||
|
_last2s = currentTime;
|
||||||
|
}
|
||||||
|
return true; // just in case
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeKeeper::waitAndReturnPlayer(uint8_t time_s){
|
||||||
|
_returnPlayerTime = millis()+time_s*1000;
|
||||||
|
}
|
||||||
|
void TimeKeeper::_returnPlayer(){
|
||||||
|
if(_returnPlayerTime>0 && millis()>=_returnPlayerTime){
|
||||||
|
_returnPlayerTime = 0;
|
||||||
|
display.putRequest(NEWMODE, PLAYER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeKeeper::waitAndDo(uint8_t time_s, void (*callback)()){
|
||||||
|
_doAfterTime = millis()+time_s*1000;
|
||||||
|
_aftercallback = callback;
|
||||||
|
}
|
||||||
|
void TimeKeeper::_doAfterWait(){
|
||||||
|
if(_doAfterTime>0 && millis()>=_doAfterTime){
|
||||||
|
_doAfterTime = 0;
|
||||||
|
_aftercallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeKeeper::_upClock(){
|
||||||
|
#if RTCSUPPORTED
|
||||||
|
if(config.isRTCFound()){
|
||||||
|
rtc.getTime(&network.timeinfo);
|
||||||
|
mktime(&network.timeinfo);
|
||||||
|
if(display.ready()) display.putRequest(CLOCK);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if(network.timeinfo.tm_year>100 || network.status == SDREADY) {
|
||||||
|
network.timeinfo.tm_sec++;
|
||||||
|
mktime(&network.timeinfo);
|
||||||
|
if(display.ready()) display.putRequest(CLOCK);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeKeeper::_upScreensaver(){
|
||||||
|
#ifndef DSP_LCD
|
||||||
|
if(!display.ready()) return;
|
||||||
|
if(config.store.screensaverEnabled && display.mode()==PLAYER && !player.isRunning()){
|
||||||
|
config.screensaverTicks++;
|
||||||
|
if(config.screensaverTicks > config.store.screensaverTimeout+SCREENSAVERSTARTUPDELAY){
|
||||||
|
if(config.store.screensaverBlank){
|
||||||
|
display.putRequest(NEWMODE, SCREENBLANK);
|
||||||
|
}else{
|
||||||
|
display.putRequest(NEWMODE, SCREENSAVER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(config.store.screensaverPlayingEnabled && display.mode()==PLAYER && player.isRunning()){
|
||||||
|
config.screensaverPlayingTicks++;
|
||||||
|
if(config.screensaverPlayingTicks > config.store.screensaverPlayingTimeout*60+SCREENSAVERSTARTUPDELAY){
|
||||||
|
if(config.store.screensaverPlayingBlank){
|
||||||
|
display.putRequest(NEWMODE, SCREENBLANK);
|
||||||
|
}else{
|
||||||
|
display.putRequest(NEWMODE, SCREENSAVER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeKeeper::_upRSSI(){
|
||||||
|
if(network.status == CONNECTED){
|
||||||
|
netserver.setRSSI(WiFi.RSSI());
|
||||||
|
netserver.requestOnChange(NRSSI, 0);
|
||||||
|
if(display.ready()) display.putRequest(DSPRSSI, netserver.getRSSI());
|
||||||
|
}
|
||||||
|
#ifdef USE_SD
|
||||||
|
if(display.mode()!=SDCHANGE) player.sendCommand({PR_CHECKSD, 0});
|
||||||
|
#endif
|
||||||
|
player.sendCommand({PR_VUTONUS, 0});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeKeeper::_upSDPos(){
|
||||||
|
if(player.isRunning() && config.getMode()==PM_SDCARD) netserver.requestOnChange(SDPOS, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeKeeper::timeTask(){
|
||||||
|
static uint8_t tsFailCnt = 0;
|
||||||
|
if(getLocalTime(&network.timeinfo)){
|
||||||
|
tsFailCnt = 0;
|
||||||
|
forceTimeSync = false;
|
||||||
|
mktime(&network.timeinfo);
|
||||||
|
display.putRequest(CLOCK);
|
||||||
|
network.requestTimeSync(true);
|
||||||
|
#if RTCSUPPORTED
|
||||||
|
if (config.isRTCFound()) rtc.setTime(&network.timeinfo);
|
||||||
|
#endif
|
||||||
|
}else{
|
||||||
|
if(tsFailCnt<4){
|
||||||
|
forceTimeSync = true;
|
||||||
|
tsFailCnt++;
|
||||||
|
}else{
|
||||||
|
forceTimeSync = false;
|
||||||
|
tsFailCnt=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void TimeKeeper::weatherTask(){
|
||||||
|
if(!network.weatherBuf || strlen(config.store.weatherkey)==0 || !config.store.showweather) return;
|
||||||
|
forceWeather = false;
|
||||||
|
_getWeather(network.weatherBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _getWeather(char *wstr) {
|
||||||
|
#if (DSP_MODEL!=DSP_DUMMY || defined(USE_NEXTION)) && !defined(HIDE_WEATHER)
|
||||||
|
|
||||||
|
WiFiClient client;
|
||||||
|
const char* host = "api.openweathermap.org";
|
||||||
|
if (!client.connect(host, 80)) {
|
||||||
|
Serial.println("##WEATHER###: connection failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char httpget[250] = {0};
|
||||||
|
sprintf(httpget, "GET /data/2.5/weather?lat=%s&lon=%s&units=%s&lang=%s&appid=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", config.store.weatherlat, config.store.weatherlon, weatherUnits, weatherLang, config.store.weatherkey, host);
|
||||||
|
client.print(httpget);
|
||||||
|
unsigned long timeout = millis();
|
||||||
|
while (client.available() == 0) {
|
||||||
|
if (millis() - timeout > 2000UL) {
|
||||||
|
Serial.println("##WEATHER###: 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("##WEATHER###: client read timeout !");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (strstr(line.c_str(), "\"temp\"") == NULL) {
|
||||||
|
Serial.println("##WEATHER###: weather not found !");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char *tmpe;
|
||||||
|
char *tmps;
|
||||||
|
char *tmpc;
|
||||||
|
const char* cursor = line.c_str();
|
||||||
|
char desc[120], temp[20], hum[20], press[20], icon[5];
|
||||||
|
|
||||||
|
tmps = strstr(cursor, "\"description\":\"");
|
||||||
|
if (tmps == NULL) { Serial.println("##WEATHER###: description not found !"); return false;}
|
||||||
|
tmps += 15;
|
||||||
|
tmpe = strstr(tmps, "\",\"");
|
||||||
|
if (tmpe == NULL) { Serial.println("##WEATHER###: description not found !"); return false;}
|
||||||
|
strlcpy(desc, tmps, tmpe - tmps + 1);
|
||||||
|
cursor = tmpe + 2;
|
||||||
|
|
||||||
|
// "ясно","icon":"01d"}],
|
||||||
|
tmps = strstr(cursor, "\"icon\":\"");
|
||||||
|
if (tmps == NULL) { Serial.println("##WEATHER###: icon not found !"); return false;}
|
||||||
|
tmps += 8;
|
||||||
|
tmpe = strstr(tmps, "\"}");
|
||||||
|
if (tmpe == NULL) { Serial.println("##WEATHER###: icon not found !"); return false;}
|
||||||
|
strlcpy(icon, tmps, tmpe - tmps + 1);
|
||||||
|
cursor = tmpe + 2;
|
||||||
|
|
||||||
|
tmps = strstr(cursor, "\"temp\":");
|
||||||
|
if (tmps == NULL) { Serial.println("##WEATHER###: temp not found !"); return false;}
|
||||||
|
tmps += 7;
|
||||||
|
tmpe = strstr(tmps, ",\"");
|
||||||
|
if (tmpe == NULL) { Serial.println("##WEATHER###: temp not found !"); return false;}
|
||||||
|
strlcpy(temp, tmps, tmpe - tmps + 1);
|
||||||
|
cursor = tmpe + 1;
|
||||||
|
float tempf = atof(temp);
|
||||||
|
|
||||||
|
tmps = strstr(cursor, "\"feels_like\":");
|
||||||
|
if (tmps == NULL) { Serial.println("##WEATHER###: feels_like not found !"); return false;}
|
||||||
|
tmps += 13;
|
||||||
|
tmpe = strstr(tmps, ",\"");
|
||||||
|
if (tmpe == NULL) { Serial.println("##WEATHER###: feels_like not found !"); return false;}
|
||||||
|
strlcpy(temp, tmps, tmpe - tmps + 1);
|
||||||
|
cursor = tmpe + 2;
|
||||||
|
float tempfl = atof(temp); (void)tempfl;
|
||||||
|
|
||||||
|
tmps = strstr(cursor, "\"pressure\":");
|
||||||
|
if (tmps == NULL) { Serial.println("##WEATHER###: pressure not found !"); return false;}
|
||||||
|
tmps += 11;
|
||||||
|
tmpe = strstr(tmps, ",\"");
|
||||||
|
if (tmpe == NULL) { Serial.println("##WEATHER###: 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("##WEATHER###: humidity not found !"); return false;}
|
||||||
|
tmps += 10;
|
||||||
|
tmpe = strstr(tmps, ",\"");
|
||||||
|
tmpc = strstr(tmps, "}");
|
||||||
|
if (tmpe == NULL) { Serial.println("##WEATHER###: humidity not found !"); return false;}
|
||||||
|
strlcpy(hum, tmps, tmpe - tmps + (tmpc>tmpe?1:0));
|
||||||
|
|
||||||
|
tmps = strstr(cursor, "\"grnd_level\":");
|
||||||
|
bool grnd_level_pr = (tmps != NULL);
|
||||||
|
if(grnd_level_pr){
|
||||||
|
tmps += 13;
|
||||||
|
tmpe = strstr(tmps, ",\"");
|
||||||
|
if (tmpe == NULL) { Serial.println("##WEATHER###: grnd_level not found !"); return false;}
|
||||||
|
strlcpy(press, tmps, tmpe - tmps + 1);
|
||||||
|
cursor = tmpe + 2;
|
||||||
|
pressi = (float)atoi(press) / 1.333;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmps = strstr(cursor, "\"speed\":");
|
||||||
|
if (tmps == NULL) { Serial.println("##WEATHER###: wind speed not found !"); return false;}
|
||||||
|
tmps += 8;
|
||||||
|
tmpe = strstr(tmps, ",\"");
|
||||||
|
if (tmpe == NULL) { Serial.println("##WEATHER###: wind speed not found !"); return false;}
|
||||||
|
strlcpy(temp, tmps, tmpe - tmps + 1);
|
||||||
|
cursor = tmpe + 1;
|
||||||
|
float wind_speed = atof(temp); (void)wind_speed;
|
||||||
|
|
||||||
|
tmps = strstr(cursor, "\"deg\":");
|
||||||
|
if (tmps == NULL) { Serial.println("##WEATHER###: wind deg not found !"); return false;}
|
||||||
|
tmps += 6;
|
||||||
|
tmpe = strstr(tmps, ",\"");
|
||||||
|
if (tmpe == NULL) { Serial.println("##WEATHER###: wind deg not found !"); return false;}
|
||||||
|
strlcpy(temp, tmps, tmpe - tmps + 1);
|
||||||
|
cursor = tmpe + 1;
|
||||||
|
int wind_deg = atof(temp)/22.5;
|
||||||
|
if(wind_deg<0) wind_deg = 16+wind_deg;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_NEXTION
|
||||||
|
nextion.putcmdf("press_txt.txt=\"%dmm\"", pressi);
|
||||||
|
nextion.putcmdf("hum_txt.txt=\"%d%%\"", atoi(hum));
|
||||||
|
char cmd[30];
|
||||||
|
snprintf(cmd, sizeof(cmd)-1,"temp_txt.txt=\"%.1f\"", tempf);
|
||||||
|
nextion.putcmd(cmd);
|
||||||
|
int iconofset;
|
||||||
|
if(strstr(icon,"01")!=NULL) iconofset = 0;
|
||||||
|
else if(strstr(icon,"02")!=NULL) iconofset = 1;
|
||||||
|
else if(strstr(icon,"03")!=NULL) iconofset = 2;
|
||||||
|
else if(strstr(icon,"04")!=NULL) iconofset = 3;
|
||||||
|
else if(strstr(icon,"09")!=NULL) iconofset = 4;
|
||||||
|
else if(strstr(icon,"10")!=NULL) iconofset = 5;
|
||||||
|
else if(strstr(icon,"11")!=NULL) iconofset = 6;
|
||||||
|
else if(strstr(icon,"13")!=NULL) iconofset = 7;
|
||||||
|
else if(strstr(icon,"50")!=NULL) iconofset = 8;
|
||||||
|
else iconofset = 9;
|
||||||
|
nextion.putcmd("cond_img.pic", 50+iconofset);
|
||||||
|
nextion.weatherVisible(1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Serial.printf("##WEATHER###: description: %s, temp:%.1f C, pressure:%dmmHg, humidity:%s%%\n", desc, tempf, pressi, hum);
|
||||||
|
#ifdef WEATHER_FMT_SHORT
|
||||||
|
sprintf(wstr, weatherFmt, tempf, pressi, hum);
|
||||||
|
#else
|
||||||
|
#if EXT_WEATHER
|
||||||
|
sprintf(wstr, weatherFmt, desc, tempf, tempfl, pressi, hum, wind_speed, wind[wind_deg]);
|
||||||
|
#else
|
||||||
|
sprintf(wstr, weatherFmt, desc, tempf, pressi, hum);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
display.putRequest(NEWWEATHER);
|
||||||
|
return true;
|
||||||
|
#endif // if (DSP_MODEL!=DSP_DUMMY || defined(USE_NEXTION)) && !defined(HIDE_WEATHER)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************
|
||||||
42
yoRadio/src/core/timekeeper.h
Normal file
42
yoRadio/src/core/timekeeper.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#ifndef timekeeper_h
|
||||||
|
#define timekeeper_h
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
void _syncTask(void * pvParameters);
|
||||||
|
bool _getWeather(char *wstr);
|
||||||
|
|
||||||
|
class TimeKeeper {
|
||||||
|
public:
|
||||||
|
volatile bool forceWeather;
|
||||||
|
volatile bool forceTimeSync;
|
||||||
|
volatile bool busy;
|
||||||
|
public:
|
||||||
|
TimeKeeper() {
|
||||||
|
busy = false;
|
||||||
|
forceWeather = true;
|
||||||
|
forceTimeSync = true;
|
||||||
|
_returnPlayerTime = _doAfterTime = 0;
|
||||||
|
}
|
||||||
|
bool loop0();
|
||||||
|
bool loop1();
|
||||||
|
void timeTask();
|
||||||
|
void weatherTask();
|
||||||
|
void waitAndReturnPlayer(uint8_t time_s);
|
||||||
|
void waitAndDo(uint8_t time_s, void (*callback)());
|
||||||
|
private:
|
||||||
|
uint32_t _returnPlayerTime, _doAfterTime;
|
||||||
|
void (*_aftercallback)();
|
||||||
|
void (*_watchdogcallback)();
|
||||||
|
void _upRSSI();
|
||||||
|
void _upSDPos();
|
||||||
|
void _upClock();
|
||||||
|
void _upScreensaver();
|
||||||
|
void _returnPlayer();
|
||||||
|
void _doAfterWait();
|
||||||
|
void _doWatchDog();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
extern TimeKeeper timekeeper;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -13,7 +13,7 @@ void Pager::loop(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
Page& Pager::addPage(Page* page, bool setNow){
|
Page& Pager::addPage(Page* page, bool setNow){
|
||||||
_pages.add(page);
|
_pages.push_back(page);
|
||||||
if(setNow) setPage(page);
|
if(setNow) setPage(page);
|
||||||
return *page;
|
return *page;
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,15 @@ Page& Pager::addPage(Page* page, bool setNow){
|
|||||||
bool Pager::removePage(Page* page){
|
bool Pager::removePage(Page* page){
|
||||||
page->setActive(false);
|
page->setActive(false);
|
||||||
dsp.clearDsp();
|
dsp.clearDsp();
|
||||||
return _pages.remove(page);
|
auto i = std::find_if(_pages.begin(), _pages.end(), [&page](const Page* pn){ return page == pn; });
|
||||||
|
if (i != _pages.end()){
|
||||||
|
delete (*i);
|
||||||
|
(*i) = nullptr;
|
||||||
|
_pages.erase(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
//return _pages.remove(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pager::setPage(Page* page, bool black){
|
void Pager::setPage(Page* page, bool black){
|
||||||
@@ -33,12 +41,13 @@ void Pager::setPage(Page* page, bool black){
|
|||||||
|
|
||||||
/*******************************************************/
|
/*******************************************************/
|
||||||
|
|
||||||
Page::Page() : _widgets(LinkedList<Widget * >([](Widget * wd) { delete wd;})), _pages(LinkedList<Page*>([](Page* pg){ delete pg; })) {
|
//Page::Page() : _widgets(LinkedList<Widget * >([](Widget * wd) { delete wd;})), _pages(LinkedList<Page*>([](Page* pg){ delete pg; })) {
|
||||||
_active = false;
|
// _active = false;
|
||||||
}
|
//}
|
||||||
|
|
||||||
Page::~Page() {
|
Page::~Page() {
|
||||||
for (const auto& w : _widgets) removeWidget(w);
|
for (const auto& w : _widgets) removeWidget(w);
|
||||||
|
// what about deleting _pages ???
|
||||||
}
|
}
|
||||||
|
|
||||||
void Page::loop() {
|
void Page::loop() {
|
||||||
@@ -46,23 +55,40 @@ void Page::loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget& Page::addWidget(Widget* widget) {
|
Widget& Page::addWidget(Widget* widget) {
|
||||||
_widgets.add(widget);
|
_widgets.push_back(widget);
|
||||||
widget->setActive(_active, _active);
|
widget->setActive(_active, _active);
|
||||||
return *widget;
|
return *widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Page::removeWidget(Widget* widget){
|
bool Page::removeWidget(Widget* widget){
|
||||||
widget->setActive(false, _active);
|
widget->setActive(false, _active);
|
||||||
return _widgets.remove(widget);
|
auto i = std::find_if(_widgets.begin(), _widgets.end(), [&widget](const Widget* wn){ return widget == wn; });
|
||||||
|
if (i != _widgets.end()){
|
||||||
|
delete (*i);
|
||||||
|
(*i) = nullptr;
|
||||||
|
_widgets.erase(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//return _widgets.remove(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
Page& Page::addPage(Page* page){
|
Page& Page::addPage(Page* page){
|
||||||
_pages.add(page);
|
_pages.push_back(page);
|
||||||
return *page;
|
return *page;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Page::removePage(Page* page){
|
bool Page::removePage(Page* page){
|
||||||
return _pages.remove(page);
|
auto i = std::find_if(_pages.begin(), _pages.end(), [&page](const Page* pn){ return page == pn; });
|
||||||
|
if (i != _pages.end()){
|
||||||
|
delete (*i);
|
||||||
|
(*i) = nullptr;
|
||||||
|
_pages.erase(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
// return _pages.remove(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Page::setActive(bool act) {
|
void Page::setActive(bool act) {
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
#ifndef pages_h
|
#ifndef pages_h
|
||||||
#define pages_h
|
#define pages_h
|
||||||
|
|
||||||
#include "Arduino.h"
|
#include <list>
|
||||||
#include "../../AsyncWebServer/StringArray.h"
|
|
||||||
|
|
||||||
class Page {
|
class Page {
|
||||||
protected:
|
protected:
|
||||||
LinkedList<Widget*> _widgets;
|
std::list<Widget*> _widgets;
|
||||||
LinkedList<Page*> _pages;
|
std::list<Page*> _pages;
|
||||||
bool _active;
|
bool _active;
|
||||||
public:
|
public:
|
||||||
Page();
|
//Page();
|
||||||
~Page();
|
~Page();
|
||||||
void loop();
|
void loop();
|
||||||
Widget& addWidget(Widget* widget);
|
Widget& addWidget(Widget* widget);
|
||||||
@@ -23,14 +23,14 @@ class Page {
|
|||||||
|
|
||||||
class Pager{
|
class Pager{
|
||||||
public:
|
public:
|
||||||
Pager() : _pages(LinkedList<Page*>([](Page* pg){ delete pg; })) {}
|
//Pager() : _pages(std::list<Page*>([](Page* pg){ delete pg; })) {}
|
||||||
void begin();
|
void begin();
|
||||||
void loop();
|
void loop();
|
||||||
Page& addPage(Page* page, bool setNow = false);
|
Page& addPage(Page* page, bool setNow = false);
|
||||||
bool removePage(Page* page);
|
bool removePage(Page* page);
|
||||||
void setPage(Page* page, bool black=false);
|
void setPage(Page* page, bool black=false);
|
||||||
private:
|
private:
|
||||||
LinkedList<Page*> _pages;
|
std::list<Page*> _pages;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ class TextWidget: public Widget {
|
|||||||
TextWidget() {}
|
TextWidget() {}
|
||||||
TextWidget(WidgetConfig wconf, uint16_t buffsize, bool uppercase, uint16_t fgcolor, uint16_t bgcolor) { init(wconf, buffsize, uppercase, fgcolor, bgcolor); }
|
TextWidget(WidgetConfig wconf, uint16_t buffsize, bool uppercase, uint16_t fgcolor, uint16_t bgcolor) { init(wconf, buffsize, uppercase, fgcolor, bgcolor); }
|
||||||
~TextWidget();
|
~TextWidget();
|
||||||
|
using Widget::init;
|
||||||
void init(WidgetConfig wconf, uint16_t buffsize, bool uppercase, uint16_t fgcolor, uint16_t bgcolor);
|
void init(WidgetConfig wconf, uint16_t buffsize, bool uppercase, uint16_t fgcolor, uint16_t bgcolor);
|
||||||
void setText(const char* txt);
|
void setText(const char* txt);
|
||||||
void setText(int val, const char *format);
|
void setText(int val, const char *format);
|
||||||
@@ -139,6 +140,7 @@ class FillWidget: public Widget {
|
|||||||
public:
|
public:
|
||||||
FillWidget() {}
|
FillWidget() {}
|
||||||
FillWidget(FillConfig conf, uint16_t bgcolor) { init(conf, bgcolor); }
|
FillWidget(FillConfig conf, uint16_t bgcolor) { init(conf, bgcolor); }
|
||||||
|
using Widget::init;
|
||||||
void init(FillConfig conf, uint16_t bgcolor);
|
void init(FillConfig conf, uint16_t bgcolor);
|
||||||
void setHeight(uint16_t newHeight);
|
void setHeight(uint16_t newHeight);
|
||||||
protected:
|
protected:
|
||||||
@@ -151,6 +153,7 @@ class ScrollWidget: public TextWidget {
|
|||||||
ScrollWidget(){}
|
ScrollWidget(){}
|
||||||
ScrollWidget(const char* separator, ScrollConfig conf, uint16_t fgcolor, uint16_t bgcolor);
|
ScrollWidget(const char* separator, ScrollConfig conf, uint16_t fgcolor, uint16_t bgcolor);
|
||||||
~ScrollWidget();
|
~ScrollWidget();
|
||||||
|
using Widget::init;
|
||||||
void init(const char* separator, ScrollConfig conf, uint16_t fgcolor, uint16_t bgcolor);
|
void init(const char* separator, ScrollConfig conf, uint16_t fgcolor, uint16_t bgcolor);
|
||||||
void loop();
|
void loop();
|
||||||
void setText(const char* txt);
|
void setText(const char* txt);
|
||||||
@@ -182,6 +185,7 @@ class SliderWidget: public Widget {
|
|||||||
SliderWidget(FillConfig conf, uint16_t fgcolor, uint16_t bgcolor, uint32_t maxval, uint16_t oucolor=0){
|
SliderWidget(FillConfig conf, uint16_t fgcolor, uint16_t bgcolor, uint32_t maxval, uint16_t oucolor=0){
|
||||||
init(conf, fgcolor, bgcolor, maxval, oucolor);
|
init(conf, fgcolor, bgcolor, maxval, oucolor);
|
||||||
}
|
}
|
||||||
|
using Widget::init;
|
||||||
void init(FillConfig conf, uint16_t fgcolor, uint16_t bgcolor, uint32_t maxval, uint16_t oucolor=0);
|
void init(FillConfig conf, uint16_t fgcolor, uint16_t bgcolor, uint32_t maxval, uint16_t oucolor=0);
|
||||||
void setValue(uint32_t val);
|
void setValue(uint32_t val);
|
||||||
protected:
|
protected:
|
||||||
@@ -199,6 +203,7 @@ class VuWidget: public Widget {
|
|||||||
VuWidget() {}
|
VuWidget() {}
|
||||||
VuWidget(WidgetConfig wconf, VUBandsConfig bands, uint16_t vumaxcolor, uint16_t vumincolor, uint16_t bgcolor) { init(wconf, bands, vumaxcolor, vumincolor, bgcolor); }
|
VuWidget(WidgetConfig wconf, VUBandsConfig bands, uint16_t vumaxcolor, uint16_t vumincolor, uint16_t bgcolor) { init(wconf, bands, vumaxcolor, vumincolor, bgcolor); }
|
||||||
~VuWidget();
|
~VuWidget();
|
||||||
|
using Widget::init;
|
||||||
void init(WidgetConfig wconf, VUBandsConfig bands, uint16_t vumaxcolor, uint16_t vumincolor, uint16_t bgcolor);
|
void init(WidgetConfig wconf, VUBandsConfig bands, uint16_t vumaxcolor, uint16_t vumincolor, uint16_t bgcolor);
|
||||||
void loop();
|
void loop();
|
||||||
protected:
|
protected:
|
||||||
@@ -213,6 +218,7 @@ class VuWidget: public Widget {
|
|||||||
|
|
||||||
class NumWidget: public TextWidget {
|
class NumWidget: public TextWidget {
|
||||||
public:
|
public:
|
||||||
|
using Widget::init;
|
||||||
void init(WidgetConfig wconf, uint16_t buffsize, bool uppercase, uint16_t fgcolor, uint16_t bgcolor);
|
void init(WidgetConfig wconf, uint16_t buffsize, bool uppercase, uint16_t fgcolor, uint16_t bgcolor);
|
||||||
void setText(const char* txt);
|
void setText(const char* txt);
|
||||||
void setText(int val, const char *format);
|
void setText(int val, const char *format);
|
||||||
@@ -227,6 +233,7 @@ class ProgressWidget: public TextWidget {
|
|||||||
ProgressWidget(WidgetConfig conf, ProgressConfig pconf, uint16_t fgcolor, uint16_t bgcolor) {
|
ProgressWidget(WidgetConfig conf, ProgressConfig pconf, uint16_t fgcolor, uint16_t bgcolor) {
|
||||||
init(conf, pconf, fgcolor, bgcolor);
|
init(conf, pconf, fgcolor, bgcolor);
|
||||||
}
|
}
|
||||||
|
using Widget::init;
|
||||||
void init(WidgetConfig conf, ProgressConfig pconf, uint16_t fgcolor, uint16_t bgcolor){
|
void init(WidgetConfig conf, ProgressConfig pconf, uint16_t fgcolor, uint16_t bgcolor){
|
||||||
TextWidget::init(conf, pconf.width, false, fgcolor, bgcolor);
|
TextWidget::init(conf, pconf.width, false, fgcolor, bgcolor);
|
||||||
_speed = pconf.speed; _width = pconf.width; _barwidth = pconf.barwidth;
|
_speed = pconf.speed; _width = pconf.width; _barwidth = pconf.barwidth;
|
||||||
@@ -254,6 +261,7 @@ class BitrateWidget: public Widget {
|
|||||||
BitrateWidget() {}
|
BitrateWidget() {}
|
||||||
BitrateWidget(BitrateConfig bconf, uint16_t fgcolor, uint16_t bgcolor) { init(bconf, fgcolor, bgcolor); }
|
BitrateWidget(BitrateConfig bconf, uint16_t fgcolor, uint16_t bgcolor) { init(bconf, fgcolor, bgcolor); }
|
||||||
~BitrateWidget(){}
|
~BitrateWidget(){}
|
||||||
|
using Widget::init;
|
||||||
void init(BitrateConfig bconf, uint16_t fgcolor, uint16_t bgcolor);
|
void init(BitrateConfig bconf, uint16_t fgcolor, uint16_t bgcolor);
|
||||||
void setBitrate(uint16_t bitrate);
|
void setBitrate(uint16_t bitrate);
|
||||||
void setFormat(BitrateFormat format);
|
void setFormat(BitrateFormat format);
|
||||||
|
|||||||
@@ -9,6 +9,16 @@
|
|||||||
#include "core/controls.h"
|
#include "core/controls.h"
|
||||||
#include "core/mqtt.h"
|
#include "core/mqtt.h"
|
||||||
#include "core/optionschecker.h"
|
#include "core/optionschecker.h"
|
||||||
|
#include "core/timekeeper.h"
|
||||||
|
|
||||||
|
#if USE_OTA
|
||||||
|
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
|
||||||
|
#include <NetworkUdp.h>
|
||||||
|
#else
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
#endif
|
||||||
|
#include <ArduinoOTA.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if DSP_HSPI || TS_HSPI || VS_HSPI
|
#if DSP_HSPI || TS_HSPI || VS_HSPI
|
||||||
SPIClass SPI2(HOOPSENb);
|
SPIClass SPI2(HOOPSENb);
|
||||||
@@ -16,6 +26,44 @@ SPIClass SPI2(HOOPSENb);
|
|||||||
|
|
||||||
extern __attribute__((weak)) void yoradio_on_setup();
|
extern __attribute__((weak)) void yoradio_on_setup();
|
||||||
|
|
||||||
|
#if USE_OTA
|
||||||
|
void setupOTA(){
|
||||||
|
if(strlen(config.store.mdnsname)>0)
|
||||||
|
ArduinoOTA.setHostname(config.store.mdnsname);
|
||||||
|
#ifdef OTA_PASS
|
||||||
|
ArduinoOTA.setPassword(OTA_PASS);
|
||||||
|
#endif
|
||||||
|
ArduinoOTA
|
||||||
|
.onStart([]() {
|
||||||
|
player.sendCommand({PR_STOP, 0});
|
||||||
|
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");
|
||||||
|
ESP.restart();
|
||||||
|
})
|
||||||
|
.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
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
if(REAL_LEDBUILTIN!=255) pinMode(REAL_LEDBUILTIN, OUTPUT);
|
if(REAL_LEDBUILTIN!=255) pinMode(REAL_LEDBUILTIN, OUTPUT);
|
||||||
@@ -45,23 +93,29 @@ void setup() {
|
|||||||
#ifdef MQTT_ROOT_TOPIC
|
#ifdef MQTT_ROOT_TOPIC
|
||||||
mqttInit();
|
mqttInit();
|
||||||
#endif
|
#endif
|
||||||
|
#if USE_OTA
|
||||||
|
setupOTA();
|
||||||
|
#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) {
|
if (config.store.smartstart == 1) {
|
||||||
delay(99);
|
delay(250);
|
||||||
player.sendCommand({PR_PLAY, config.lastStation()});
|
player.sendCommand({PR_PLAY, config.lastStation()});
|
||||||
}
|
}
|
||||||
pm.on_end_setup();
|
pm.on_end_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
timekeeper.loop1();
|
||||||
telnet.loop();
|
telnet.loop();
|
||||||
if (network.status == CONNECTED || network.status==SDREADY) {
|
if (network.status == CONNECTED || network.status==SDREADY) {
|
||||||
player.loop();
|
player.loop();
|
||||||
//loopControls();
|
#if USE_OTA
|
||||||
|
ArduinoOTA.handle();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
loopControls();
|
loopControls();
|
||||||
netserver.loop();
|
//netserver.loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "core/audiohandlers.h"
|
#include "core/audiohandlers.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user