This commit is contained in:
e2002
2022-08-15 14:19:39 +03:00
parent 19fede3bdf
commit 442d970fd9
52 changed files with 1363 additions and 359 deletions

View File

@@ -8,6 +8,7 @@
- [Software dependencies](#dependencies) - [Software dependencies](#dependencies)
- [Hardware setup](#hardware-setup) - [Hardware setup](#hardware-setup)
- [Quick start](#quick-start) - [Quick start](#quick-start)
- [Detailed start](https://github.com/e2002/yoradio/wiki/How-to-flash)
- [Update](#update) - [Update](#update)
- [Update over web-interface](#update-over-web-interface) - [Update over web-interface](#update-over-web-interface)
- [Controls](Controls.md) - [Controls](Controls.md)
@@ -63,17 +64,19 @@ https://www.aliexpress.com/item/33009687492.html
--- ---
## Connection tables ## Connection tables
| SPI Display | ESP-32 | options.h | ##### SPI Displays
| Display | ESP-32 | myoptions.h |
| ------ | ------ | ------ | | ------ | ------ | ------ |
| GND | GND | - | | GND | GND | - |
| VCC | +5v | - | | VCC | +5v | - |
| SCL | 18 | - | | SCL | 18 | - |
| SDA | 23 | - | | SDA | 23 | - |
| CSL | 5* | TFT_CS | | CSL | 5* | TFT_CS |
| RSTL | 15* | TFT_RST | | RST | 15* | TFT_RST |
| DCL | 4* | TFT_DC | | DCL | 4* | TFT_DC |
| NOKIA5110 | ESP-32 | options.h | ##### Nokia 5110
| NOKIA5110 | ESP-32 | myoptions.h |
| ------ | ------ | ------ | | ------ | ------ | ------ |
| RST | 15* | TFT_RST | | RST | 15* | TFT_RST |
| CE | 5* | TFT_CS | | CE | 5* | TFT_CS |
@@ -83,14 +86,16 @@ https://www.aliexpress.com/item/33009687492.html
| VCC | +3v3 | - | | VCC | +3v3 | - |
| GND | GND | - | | GND | GND | - |
| I2C Display | ESP-32 | options.h | ##### I2C Displays
| Display | ESP-32 | myoptions.h |
| ------ | ------ | ------ | | ------ | ------ | ------ |
| GND | GND | - | | GND | GND | - |
| VCC | +5v | - | | VCC | +5v | - |
| SDA | 13* | I2C_SDA | | SDA | 21* | I2C_SDA |
| SCL | 14* | I2C_SCL | | SCL | 22* | I2C_SCL |
| LCD 1602 | ESP-32 | options.h | ##### LCD Displays (1602, 2004)
| Display | ESP-32 | myoptions.h |
| ------ | ------ | ------ | | ------ | ------ | ------ |
| GND | GND | - | | GND | GND | - |
| VCC | +5v | - | | VCC | +5v | - |
@@ -101,7 +106,8 @@ https://www.aliexpress.com/item/33009687492.html
| D6 | any* | LCD_D6 | | D6 | any* | LCD_D6 |
| D7 | any* | LCD_D7 | | D7 | any* | LCD_D7 |
| Touchscreen | ESP-32 | options.h | ##### Touchscreen
| Touchscreen | ESP-32 | myoptions.h |
| ------ | ------ | ------ | | ------ | ------ | ------ |
| GND | GND | - | | GND | GND | - |
| VCC | +3.3v | - | | VCC | +3.3v | - |
@@ -111,7 +117,8 @@ https://www.aliexpress.com/item/33009687492.html
| IRQ | N/C | - | | IRQ | N/C | - |
| CS | any* | TS_CS | | CS | any* | TS_CS |
| I2S DAC | ESP-32 | options.h | ##### I2S DAC
| I2S DAC | ESP-32 | myoptions.h |
| ------ | ------ | ------ | | ------ | ------ | ------ |
| GND | GND | - | | GND | GND | - |
| VIN | +5v | - | | VIN | +5v | - |
@@ -119,7 +126,8 @@ https://www.aliexpress.com/item/33009687492.html
| BCLK | 26* | I2S_BCLK | | BCLK | 26* | I2S_BCLK |
| LRC(WSEL) | 25* | I2S_LRC | | LRC(WSEL) | 25* | I2S_LRC |
| VS1053 | ESP-32 | options.h | ##### VS1053
| VS1053 | ESP-32 | myoptions.h |
| ------ | ------ | ------ | | ------ | ------ | ------ |
| XDCS | 25* | VS1053_DCS | | XDCS | 25* | VS1053_DCS |
| XCS | 27* | VS1053_CS | | XCS | 27* | VS1053_CS |
@@ -132,10 +140,19 @@ https://www.aliexpress.com/item/33009687492.html
| DGND | GND | - | | DGND | GND | - |
_\#\# Important! You must choose between I2S DAC and VS1053 by disabling the second module in the settings (see below)_ _\#\# Important! You must choose between I2S DAC and VS1053 by disabling the second module in the settings (see below)_
##### Nextion Displays
| Display | ESP-32 | myoptions.h |
| ------ | ------ | ------ |
| GND | GND | - |
| VCC | +5v | - |
| TX | 14* | NEXTION_RX |
| RX | 15* | NEXTION_TX |
| Buttons, Encoder, LED, IR, Joystick | ESP-32 | options.h | ##### Controls
| Buttons, Encoder, LED, IR, Joystick | ESP-32 | myoptions.h |
| ------ | ------ | ------ | | ------ | ------ | ------ |
| GND | GND | - | | GND | GND | - |
| 5v | 3v3 | - |
| PIN | any* | ENC_BTNx, BTN_xxx, LED_BUILTIN, IR_PIN | | PIN | any* | ENC_BTNx, BTN_xxx, LED_BUILTIN, IR_PIN |
_\* Any free pin, configured in myoptions.h_ \ _\* Any free pin, configured in myoptions.h_ \
@@ -150,7 +167,9 @@ _\** GPIO 16 and 17 are used by PSRAM on the WROVER modules._
\* _if you need MQTT support_ \* _if you need MQTT support_
#### Tool: #### Tool:
[ESP32 Filesystem Uploader](https://randomnerdtutorials.com/install-esp32-filesystem-uploader-arduino-ide/) [ESP32 Filesystem Uploader](https://randomnerdtutorials.com/install-esp32-filesystem-uploader-arduino-ide/) \
**See [wiki](https://github.com/e2002/yoradio/wiki/How-to-flash#preparing) for details**
--- ---
## Hardware setup ## Hardware setup
@@ -206,6 +225,8 @@ _\*this step can be skipped if you add WiFiSSID WiFiPassword pairs to the [yoRad
**Localization:** **Localization:**
Если Adafruit_GFX ещё не русифицирована, русифицировать её, заменив файл Arduino/libraries/Adafruit_GFX_Library/glcdfont.c файлом [yoRadio/fonts/glcdfont.c](yoRadio/fonts/glcdfont.c) Если Adafruit_GFX ещё не русифицирована, русифицировать её, заменив файл Arduino/libraries/Adafruit_GFX_Library/glcdfont.c файлом [yoRadio/fonts/glcdfont.c](yoRadio/fonts/glcdfont.c)
**See [wiki](https://github.com/e2002/yoradio/wiki/How-to-flash#build--flash) for details**
--- ---
## Update ## Update
1. Backup your settings: \ 1. Backup your settings: \
@@ -291,11 +312,22 @@ download _http://\<yoradioip\>/data/playlist.csv_ and _http://\<yoradioip\>/data
--- ---
## Plugins ## Plugins
At the moment, you can display additional information on the display by writing a few additional functions. There is no documentation yet, you will have to deal with the example, which is in file [exsamples/plugins/displayhandlers.ino](exsamples/plugins/displayhandlers.ino).\ At the moment, you can display additional information on the display by writing a few additional functions. There is no documentation yet, you will have to deal with the examples, which is in directory [exsamples/plugins/](https://github.com/e2002/yoradio/tree/main/exsamples/plugins).\
Work is in progress... Work is in progress...
--- ---
## Version history ## Version history
#### v0.7.330
**!!! a [full update](#update-over-web-interface) with Sketch data upload is required. After updating please press CTRL+F5 in browser !!!** \
**Please backup playlist.csv and wifi.csv before updating.**
- added the ability to configure parameters through the [web interface](images/settings.png)
- new parameter BRIGHTNESS_PIN - pin for adjusting the brightness of the display. Details in [exsamples/myoptions.h](exsamples/myoptions.h#L105)
- the weather plugin is integrated into the code, the settings are made through the web interface
_**PS:** Due to the change in the storage location of settings in the ESP memory, settings such as:_ \
**smartstart, audioinfo, time zone, IR remote, last volume level, last played station, equalizer** \
_will have to be configured again through the web interface. Please understand and forgive._
#### v0.7.017 #### v0.7.017
- fix initialization of some vs1053b green boards - fix initialization of some vs1053b green boards
- fix VU initialization on vs1053b boards - fix VU initialization on vs1053b boards
@@ -317,7 +349,7 @@ Work is in progress...
#### v0.6.494 #### v0.6.494
- adding VU meter for displays ST7735 160x128, ST7735 128x128, ILI9341 320x240, ST7789 320x240 \ - adding VU meter for displays ST7735 160x128, ST7735 128x128, ILI9341 320x240, ST7789 320x240 \
option ENABLE_VU_METER (see [myoptions.h](exsamples/myoptions.h#L113) for exsample) \ option ENABLE_VU_METER (see [myoptions.h](exsamples/myoptions.h) for exsample) \
**!!! Important !!!** \ **!!! Important !!!** \
if you enable this feathure on the esp32 wroom, due to lack of memory, you must modify the file Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp \ if you enable this feathure on the esp32 wroom, due to lack of memory, you must modify the file Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp \
**replace the line 221** \ **replace the line 221** \
@@ -344,8 +376,8 @@ Work is in progress...
#### v0.6.355 #### v0.6.355
- added support for ST7789 1.3' 240x240 SPI displays \ - added support for ST7789 1.3' 240x240 SPI displays \
_!!! Important !!! This display requires further development when used in conjunction with the VS1053 module. \ _!!! Important !!! This display requires further development when used in conjunction with the VS1053 module._ \
See this link for details https://www.instructables.com/Adding-CS-Pin-to-13-LCD/_ See this link for details https://www.instructables.com/Adding-CS-Pin-to-13-LCD/
#### v0.6.348 #### v0.6.348
- fixed display bugs in the rssibitrate plugin - fixed display bugs in the rssibitrate plugin
@@ -368,7 +400,7 @@ Work is in progress...
- added support for ILI9225 220x176 SPI displays - added support for ILI9225 220x176 SPI displays
- added support for I2S internal DAC, option I2S_INTERNAL (see [myoptions.h](exsamples/myoptions.h#L111) for exsample) \ - added support for I2S internal DAC, option I2S_INTERNAL (see [myoptions.h](exsamples/myoptions.h#L111) for exsample) \
_(this option worked only with esp32 core version==2.0.0)_ _(this option worked only with esp32 core version==2.0.0)_
- new option SOFT_AP_REBOOT_DELAY (see [myoptions.h](exsamples/myoptions.h#L112) for exsample) - new option SOFT_AP_REBOOT_DELAY (see [myoptions.h](exsamples/myoptions.h) for exsample)
- fixed MQTT connection when WiFi reconnected - fixed MQTT connection when WiFi reconnected
- fixed date display for ILI9341 displays - fixed date display for ILI9341 displays
- fixed garbage on volume control with displays ILI9341 - fixed garbage on volume control with displays ILI9341

View File

@@ -13,6 +13,14 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
/* DSP_MODEL. See description/available values in the options.h file */ /* DSP_MODEL. See description/available values in the options.h file */
/* This option is required. Use DSP_DUMMY if no display is connected */ /* This option is required. Use DSP_DUMMY if no display is connected */
#define DSP_MODEL DSP_DUMMY #define DSP_MODEL DSP_DUMMY
/*
* !!! Important !!!
* if you use colored TFT displays with the esp32 wroom, due to lack of memory, you must modify the file Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp
* replace the line 221
* xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
* with
* xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 / 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
*/
/******************************************/ /******************************************/
/* SPI PINS. SCL(SCK, CLK) must be connected to pin 18 /* SPI PINS. SCL(SCK, CLK) must be connected to pin 18
@@ -25,9 +33,6 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
/* NEXTION */ /* NEXTION */
//#define NEXTION_RX 255 /* Nextion RX pin */ //#define NEXTION_RX 255 /* Nextion RX pin */
//#define NEXTION_TX 255 /* Nextion TX pin */ //#define NEXTION_TX 255 /* Nextion TX pin */
//#define NEXTION_WEATHER_LAT "55.7512" /* Nextion latitude for display Weather */
//#define NEXTION_WEATHER_LON "37.6184" /* Nextion longitude for display Weather */
//#define NEXTION_WEATHER_KEY "" /* Openweathermap API key https://openweathermap.org/appid */
/* I2C PINS */ /* I2C PINS */
//#define I2C_SDA 21 /* I2C SDA pin. It is best to connect to pin 21. */ //#define I2C_SDA 21 /* I2C SDA pin. It is best to connect to pin 21. */
@@ -41,11 +46,12 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
/******************************************/ /******************************************/
/* VS1053 PINS. VS1053 SCK must be connected to pin 18 /* VS1053 PINS. VS1053 SCK must be connected to pin 18
VS1053 MISO must be connected to pin 19
VS1053 MOSI must be connected to pin 23 */ VS1053 MOSI must be connected to pin 23 */
//#define VS1053_CS 255 /* Should be set to 255 if the board is not used */ //#define VS1053_CS 255 /* XCS pin. Should be set to 255 if the board is not used */
//#define VS1053_DCS 25 //#define VS1053_DCS 25 /* XDCS pin. */
//#define VS1053_DREQ 26 //#define VS1053_DREQ 26 /* DREQ pin. */
//#define VS1053_RST -1 /* Set to -1 if connected to Esp EN pin */ //#define VS1053_RST -1 /* XRESET pin. Set to -1 if connected to Esp EN pin */
/******************************************/ /******************************************/
/* ENCODER */ /* ENCODER */
@@ -91,41 +97,25 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
DO must be connected to pin 19 DO must be connected to pin 19
IRQ - not connected */ IRQ - not connected */
//#define TS_CS 255 /* Touch screen CS pin //#define TS_CS 255 /* Touch screen CS pin
//#define TS_ROTATE 1 /* Touch screen rotation. 0 - 0, 1 - 90, 2 - 180, 3 - 270 degrees */
//#define TS_DBG false /* Generate debug to Serial output */
/******************************************/ /******************************************/
/* Other settings. */ /* Other settings. */
//#define DTYPE INITR_BLACKTAB /* ST7735 display submodel */ //#define DTYPE INITR_BLACKTAB /* ST7735 display submodel */
/* Could be one of: */ /* Could be one of: */
/* INITR_BLACKTAB 1.8' https://aliexpress.com/item/1005002822797745.html */ /* INITR_BLACKTAB 1.8' https://aliexpress.com/item/1005002822797745.html */
/* (See this note If INITR_BLACKTAB have a noisy line on one side of the screen https://github.com/e2002/yoradio#note-if-initr_blacktab-dsp-have-a-noisy-line-on-one-side-of-the-screen-then-in-adafruit_st7735cpp ) */ /* (See this note If INITR_BLACKTAB have a noisy line on one side of the screen https://github.com/e2002/yoradio#note-if-initr_blacktab-dsp-have-a-noisy-line-on-one-side-of-the-screen-then-in-adafruit_st7735cpp ) */
/* INITR_144GREENTAB // 1.44' https://aliexpress.com/item/1005002822797745.html */ /* INITR_144GREENTAB // 1.44' https://aliexpress.com/item/1005002822797745.html */
/* INITR_MINI160x80 // 0.96' 160x80 ST7735S https://???? */ /* INITR_MINI160x80 // 0.96' 160x80 ST7735S https://???? */
/* INITR_GREENTAB */ /* INITR_GREENTAB */
/* INITR_REDTAB */ /* INITR_REDTAB */
//#define LED_BUILTIN 2 /* LED Pin */ //#define LED_BUILTIN 2 /* LED Pin */
//#define TFT_ROTATE 3 /* Display rotation. 0 - 0, 1 - 90, 2 - 180, 3 - 270 degrees */
//#define TFT_CONTRAST 55 /* Nokia 5110 contrast */
//#define TFT_INVERT true /* Invert the display colors (usually true) */
//#define VOL_STEP 1 /* Volume control step */
//#define VOL_ACCELERATION 200 /* Encoder vol acceleration; 0 or 1 means disabled acceleration */
//#define MUTE_PIN 255 /* MUTE Pin */ //#define MUTE_PIN 255 /* MUTE Pin */
//#define MUTE_VAL HIGH /* Write this to MUTE_PIN when player is stopped */ //#define MUTE_VAL HIGH /* Write this to MUTE_PIN when player is stopped */
//#define PL_WITH_NUMBERS /* show the number of station in the playlist */ //#define BRIGHTNESS_PIN 255 /* Pin for adjusting the brightness of the display (output 0 - 3v3) */
//#define PLAYER_FORCE_MONO false /* mono option on boot - false stereo, true mono */ //#define PLAYER_FORCE_MONO false /* mono option on boot - false stereo, true mono */
//#define SNTP_SERVER "pool.ntp.org", "0.ru.pool.ntp.org" /* custom ntp servers min 1 max 3 comma separated values */
//#define I2S_INTERNAL false /* If true - use esp32 internal DAC */ //#define I2S_INTERNAL false /* If true - use esp32 internal DAC */
//#define SOFT_AP_REBOOT_DELAY 0 /* Delay in milliseconds after which ESP is rebooting if it is in softAP mode (0 - disabled) */ //#define ROTATE_90 false /* Optional 90 degree rotation for square displays */
//#define ENABLE_VU_METER false /* enable? vu meter for some displays */
/*
* !!! Important !!!
* if you enable this feathure on the esp32 wroom, due to lack of memory, you must modify the file Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp
* replace the line 221
* xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
* with
* xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 / 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
*/
/* VU settings. See the default settings for your display in file yoRadio/display_vu.h */ /* VU settings. See the default settings for your display in file yoRadio/display_vu.h */
/************************************************************************************************************************************************************************************/ /************************************************************************************************************************************************************************************/
/* vu left | vu top | band width | band height | band space | num of bands | fade speed | horisontal | Max Bands Color | Min Bands Color */ /* vu left | vu top | band width | band height | band space | num of bands | fade speed | horisontal | Max Bands Color | Min Bands Color */
@@ -136,7 +126,6 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
/* IR control */ /* IR control */
//#define IR_PIN 255 //#define IR_PIN 255
//#define IR_TIMEOUT 80 /* see kTimeout description in IRremoteESP8266 exsample https://github.com/crankyoldgit/IRremoteESP8266/blob/master/examples/IRrecvDumpV2/IRrecvDumpV2.ino */ //#define IR_TIMEOUT 80 /* see kTimeout description in IRremoteESP8266 exsample https://github.com/crankyoldgit/IRremoteESP8266/blob/master/examples/IRrecvDumpV2/IRrecvDumpV2.ino */
//#define IR_TLP 40 /* see kTolerancePercentage description in IRremoteESP8266 exsample https://github.com/crankyoldgit/IRremoteESP8266/blob/master/examples/IRrecvDumpV2/IRrecvDumpV2.ino */
/******************************************/ /******************************************/

BIN
images/settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

View File

@@ -11,13 +11,7 @@ void Config::init() {
irindex=-1; irindex=-1;
#endif #endif
eepromRead(EEPROM_START, store); eepromRead(EEPROM_START, store);
if (store.tz_set != 57) { // update to v0.4.200 if (store.config_set != 4262) setDefaults();
store.tz_set = 57;
store.tzHour = 3;
store.tzMin = 0;
store.timezoneOffset = 0;
}
if (store.config_set != 4256) setDefaults();
//if (!SPIFFS.begin(false, "/spiffs", 30)) { //if (!SPIFFS.begin(false, "/spiffs", 30)) {
if (!SPIFFS.begin(false)) { if (!SPIFFS.begin(false)) {
return; return;
@@ -36,6 +30,10 @@ void Config::init() {
memset(ircodes.irVals, 0, sizeof(ircodes.irVals)); memset(ircodes.irVals, 0, sizeof(ircodes.irVals));
} }
#endif #endif
#if BRIGHTNESS_PIN!=255
pinMode(BRIGHTNESS_PIN, OUTPUT);
setBrightness(false);
#endif
} }
template <class T> int Config::eepromWrite(int ee, const T& value) { template <class T> int Config::eepromWrite(int ee, const T& value) {
@@ -56,7 +54,7 @@ template <class T> int Config::eepromRead(int ee, T& value) {
} }
void Config::setDefaults() { void Config::setDefaults() {
store.config_set = 4256; store.config_set = 4262;
store.volume = 12; store.volume = 12;
store.balance = 0; store.balance = 0;
store.trebble = 0; store.trebble = 0;
@@ -67,10 +65,41 @@ void Config::setDefaults() {
store.lastSSID = 0; store.lastSSID = 0;
store.audioinfo = false; store.audioinfo = false;
store.smartstart = 2; store.smartstart = 2;
store.tz_set = 57;
store.tzHour = 3; store.tzHour = 3;
store.tzMin = 0; store.tzMin = 0;
store.timezoneOffset = 0; store.timezoneOffset = 0;
store.vumeter=false;
store.softapdelay=0;
store.flipscreen=false;
store.invertdisplay=false;
store.numplaylist=false;
store.fliptouch=false;
store.dbgtouch=false;
store.dspon=true;
store.brightness=100;
store.contrast=55;
strlcpy(store.sntp1,"0.ru.pool.ntp.org", 35);
strlcpy(store.sntp2,"1.ru.pool.ntp.org", 35);
store.showweather=false;
strlcpy(store.weatherlat,"55.7512", 10);
strlcpy(store.weatherlon,"37.6184", 10);
strlcpy(store.weatherkey,"", 64);
store.volsteps = 1;
store.encacc = 200;
store.irto = 80;
store.irtlp = 35;
store.btnpullup = true;
store.btnlongpress = 200;
store.btnclickticks = 300;
store.btnpressticks = 500;
store.encpullup = false;
store.enchalf = false;
store.enc2pullup = false;
store.enc2half = false;
store.forcemono = false;
store.i2sinternal = false;
store.rotate90 = false;
} }
void Config::setTimezone(int8_t tzh, int8_t tzm) { void Config::setTimezone(int8_t tzh, int8_t tzm) {
@@ -247,17 +276,17 @@ void Config::fillPlMenu(char plmenu[][40], int from, byte count, bool removeNum)
} }
while (playlist.available()) { while (playlist.available()) {
if (parseCSV(playlist.readStringUntil('\n').c_str(), sName, sUrl, sOvol)) { if (parseCSV(playlist.readStringUntil('\n').c_str(), sName, sUrl, sOvol)) {
#ifdef PL_WITH_NUMBERS if(config.store.numplaylist){
if(removeNum){ if(removeNum){
strlcpy(plmenu[c], sName, 39); strlcpy(plmenu[c], sName, 39);
}else{
char buf[BUFLEN+10];
sprintf(buf, "%d %s", (int)(from+c), sName);
strlcpy(plmenu[c], buf, 39);
}
}else{ }else{
char buf[BUFLEN+10]; strlcpy(plmenu[c], sName, 39);
sprintf(buf, "%d %s", (int)(from+c), sName);
strlcpy(plmenu[c], buf, 39);
} }
#else
strlcpy(plmenu[c], sName, 39);
#endif
c++; c++;
} }
if (c >= count) break; if (c >= count) break;
@@ -344,7 +373,7 @@ bool Config::parseWsCommand(const char* line, char* cmd, char* val, byte cSize)
strlcpy(cmd, line, tmpe - line + 1); strlcpy(cmd, line, tmpe - line + 1);
if (strlen(tmpe + 1) == 0) return false; if (strlen(tmpe + 1) == 0) return false;
memset(val, 0, cSize); memset(val, 0, cSize);
strlcpy(val, tmpe + 1, tmpe + 1 - line + 1); strlcpy(val, tmpe + 1, strlen(line) - strlen(cmd) + 1);
return true; return true;
} }
@@ -391,3 +420,10 @@ bool Config::initNetwork() {
file.close(); file.close();
return true; return true;
} }
void Config::setBrightness(bool dosave){
#if BRIGHTNESS_PIN!=255
analogWrite(BRIGHTNESS_PIN, config.store.dspon?map(store.brightness, 0, 100, 0, 255):0);
if(dosave) save();
#endif
}

View File

@@ -4,8 +4,9 @@
#include "options.h" #include "options.h"
#define EEPROM_SIZE 768 #define EEPROM_SIZE 768
#define EEPROM_START 0 #define EEPROM_START 500
#define EEPROM_START_IR 100 #define EEPROM_START_IR 0
#define EEPROM_START_2 10
#define BUFLEN 140 #define BUFLEN 140
#define PLAYLIST_PATH "/data/playlist.csv" #define PLAYLIST_PATH "/data/playlist.csv"
#define SSIDS_PATH "/data/wifi.csv" #define SSIDS_PATH "/data/wifi.csv"
@@ -14,7 +15,7 @@
struct config_t struct config_t
{ {
unsigned int config_set; //must be 4256 unsigned int config_set; //must be 4262
byte volume; byte volume;
int8_t balance; int8_t balance;
int8_t trebble; int8_t trebble;
@@ -25,10 +26,41 @@ struct config_t
byte lastSSID; byte lastSSID;
bool audioinfo; bool audioinfo;
byte smartstart; byte smartstart;
byte tz_set; // must be 57
int8_t tzHour; int8_t tzHour;
int8_t tzMin; int8_t tzMin;
uint16_t timezoneOffset; uint16_t timezoneOffset;
bool vumeter;
uint8_t softapdelay;
bool flipscreen;
bool invertdisplay;
bool numplaylist;
bool fliptouch;
bool dbgtouch;
bool dspon;
uint8_t brightness;
uint8_t contrast;
char sntp1[35];
char sntp2[35];
bool showweather;
char weatherlat[10];
char weatherlon[10];
char weatherkey[64];
uint8_t volsteps;
uint16_t encacc;
uint8_t irto;
uint8_t irtlp;
bool btnpullup;
uint16_t btnlongpress;
uint16_t btnclickticks;
uint16_t btnpressticks;
bool encpullup;
bool enchalf;
bool enc2pullup;
bool enc2half;
bool forcemono;
bool i2sinternal;
bool rotate90;
}; };
#if IR_PIN!=255 #if IR_PIN!=255
@@ -74,7 +106,7 @@ class Config {
void init(); void init();
byte setVolume(byte val); byte setVolume(byte val);
void saveVolume(); void saveVolume();
void setTone(int8_t bass, int8_t middle, int8_t trebble); void setTone(int8_t bass, int8_t middle, int8_t trebble);
void setBalance(int8_t balance); void setBalance(int8_t balance);
byte setLastStation(byte val); byte setLastStation(byte val);
byte setCountStation(byte val); byte setCountStation(byte val);
@@ -91,10 +123,12 @@ class Config {
void setSmartStart(byte ss); void setSmartStart(byte ss);
void initPlaylist(); void initPlaylist();
void indexPlaylist(); void indexPlaylist();
void fillPlMenu(char plmenu[][40], int from, byte count, bool removeNum=false); void fillPlMenu(char plmenu[][40], int from, byte count, bool removeNum = false);
void setTimezone(int8_t tzh, int8_t tzm); void setTimezone(int8_t tzh, int8_t tzm);
void setTimezoneOffset(uint16_t tzo); void setTimezoneOffset(uint16_t tzo);
uint16_t getTimezoneOffset(); uint16_t getTimezoneOffset();
void setBrightness(bool dosave=false);
private: private:
template <class T> int eepromWrite(int ee, const T& value); template <class T> int eepromWrite(int ee, const T& value);
template <class T> int eepromRead(int ee, T& value); template <class T> int eepromRead(int ee, T& value);

View File

@@ -59,7 +59,6 @@ byte irVolRepeat = 0;
const uint16_t kCaptureBufferSize = 1024; const uint16_t kCaptureBufferSize = 1024;
const uint8_t kTimeout = IR_TIMEOUT; const uint8_t kTimeout = IR_TIMEOUT;
const uint16_t kMinUnknownSize = 12; const uint16_t kMinUnknownSize = 12;
const uint8_t kTolerancePercentage = IR_TLP; //kTolerance; // kTolerance is normally 25%
#define LEGACY_TIMING_INFO false #define LEGACY_TIMING_INFO false
IRrecv irrecv(IR_PIN, kCaptureBufferSize, kTimeout, true); IRrecv irrecv(IR_PIN, kCaptureBufferSize, kTimeout, true);
@@ -85,13 +84,13 @@ void initControls() {
encoder.begin(); encoder.begin();
encoder.setup(readEncoderISR); encoder.setup(readEncoderISR);
encoder.setBoundaries(0, 254, true); encoder.setBoundaries(0, 254, true);
encoder.setAcceleration(VOL_ACCELERATION); encoder.setAcceleration(config.store.encacc);
#endif #endif
#if ENC2_BTNL!=255 #if ENC2_BTNL!=255
encoder2.begin(); encoder2.begin();
encoder2.setup(readEncoder2ISR); encoder2.setup(readEncoder2ISR);
encoder2.setBoundaries(0, 254, true); encoder2.setBoundaries(0, 254, true);
encoder2.setAcceleration(VOL_ACCELERATION); encoder2.setAcceleration(config.store.encacc);
#endif #endif
#if ISPUSHBUTTONS #if ISPUSHBUTTONS
@@ -116,7 +115,7 @@ void initControls() {
#endif #endif
#if TS_CS!=255 #if TS_CS!=255
ts.begin(); ts.begin();
ts.setRotation(TS_ROTATE); ts.setRotation(config.store.fliptouch?3:1);
#endif #endif
#if IR_PIN!=255 #if IR_PIN!=255
pinMode(IR_PIN, INPUT); pinMode(IR_PIN, INPUT);
@@ -124,7 +123,7 @@ void initControls() {
#if DECODE_HASH #if DECODE_HASH
irrecv.setUnknownThreshold(kMinUnknownSize); irrecv.setUnknownThreshold(kMinUnknownSize);
#endif // DECODE_HASH #endif // DECODE_HASH
irrecv.setTolerance(kTolerancePercentage); irrecv.setTolerance(config.store.irtlp);
irrecv.enableIRIn(); irrecv.enableIRIn();
#endif // IR_PIN!=255 #endif // IR_PIN!=255
} }
@@ -411,7 +410,7 @@ void touchLoop() {
int16_t yDelta = map(abs(touchStation - touchY), 0, display.screenheight, 0, TS_STEPS); int16_t yDelta = map(abs(touchStation - touchY), 0, display.screenheight, 0, TS_STEPS);
display.putRequest({NEWMODE, STATIONS}); display.putRequest({NEWMODE, STATIONS});
if (yDelta>1) { if (yDelta>1) {
controlsEvent((touchStation - touchY)>0); controlsEvent((touchStation - touchY)<0);
touchStation = touchY; touchStation = touchY;
} }
} }
@@ -421,7 +420,7 @@ void touchLoop() {
break; break;
} }
} }
if (TS_DBG) { if (config.store.dbgtouch) {
Serial.print(", x = "); Serial.print(", x = ");
Serial.print(p.x); Serial.print(p.x);
Serial.print(", y = "); Serial.print(", y = ");
@@ -609,3 +608,25 @@ void onBtnDoubleClick(int id) {
break; break;
} }
} }
void setIRTolerance(uint8_t tl){
config.store.irtlp=tl;
config.save();
#if IR_PIN!=255
irrecv.setTolerance(config.store.irtlp);
#endif
}
void setEncAcceleration(uint16_t acc){
config.store.encacc=acc;
config.save();
#if ENC_BTNL!=255
encoder.setAcceleration(config.store.encacc);
#endif
#if ENC2_BTNL!=255
encoder2.setAcceleration(config.store.encacc);
#endif
}
void flipTS(){
#if TS_CS!=255
ts.setRotation(config.store.fliptouch?3:1);
#endif
}

View File

@@ -29,6 +29,10 @@ void onBtnLongPressStart(int id);
void onBtnLongPressStop(int id); void onBtnLongPressStop(int id);
tsDirection_e tsDirection(uint16_t x, uint16_t y); tsDirection_e tsDirection(uint16_t x, uint16_t y);
void setIRTolerance(uint8_t tl);
void setEncAcceleration(uint16_t acc);
void flipTS();
extern __attribute__((weak)) void ctrls_on_loop(); extern __attribute__((weak)) void ctrls_on_loop();
#endif #endif

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 761 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -6,33 +6,28 @@
<meta name="apple-mobile-web-app-status-bar-style" content="default"> <meta name="apple-mobile-web-app-status-bar-style" content="default">
<link rel="apple-touch-icon" type="image/png" href="elogo.png"> <link rel="apple-touch-icon" type="image/png" href="elogo.png">
<link rel="icon" type="image/png" href="elogo.png"> <link rel="icon" type="image/png" href="elogo.png">
<link rel="stylesheet" title="base" href="style.css" type="text/css"> <link rel="stylesheet" title="base" href="style.css?%VERSION%" type="text/css">
<title>ёRadio</title> <title>ёRadio - Player</title>
<style> </style> <style> </style>
</head> </head>
<body> <body>
<div class="content"> <div class="content">
<div class="logo"></div> <div class="logo"></div>
<div id="navbar"%APMODE%> <div id="navbar">
<div class="playerbytton navbutton" id="playlistbutton" onclick="showEditor()"></div> <div class="playerbytton navbutton" id="playlistbutton" data-name="playlist"></div>
<div class="playerbytton navbutton" id="settingsbutton" onclick="event.stopPropagation(); showSettings()"></div> <div class="playerbytton navbutton" id="settingsbutton" data-name="settings"></div>
<div id="settingspopup" class="hidden%IRMODE%">
<div class="button" id="settingsbuttonwifi" onclick="showSettingsWifi()">Wi-Fi</div>
<div class="button" id="settingsbuttonir" onclick="location.href='/ir'">IR</div>
<div class="button" id="settingsbuttonupload" onclick="showSettingsUpload()">Update</div>
</div>
</div> </div>
<div class="playerwrap"> <div class="playerwrap">
<div class="player"> <div class="player">
<div id="nameset">&nbsp;</div> <div id="nameset">&nbsp;</div>
<div id="meta">&nbsp;</div> <div id="meta">&nbsp;</div>
<div class="playerbyttonwrap"> <div class="playerbyttonwrap">
<div class="playerbytton" id="prevbutton"></div> <div class="playerbytton" id="prevbutton" data-name="prev"></div>
<div class="stopped" id="playbutton"></div> <div class="playerbytton stopped" id="playbutton" data-name="play"></div>
<div class="playerbytton" id="nextbutton"></div> <div class="playerbytton" id="nextbutton" data-name="next"></div>
<div class="playerbytton" id="volmbutton"></div> <div class="playerbytton" id="volmbutton" data-name="volm"></div>
<div class="playerbytton" id="volpbutton"></div> <div class="playerbytton" id="volpbutton" data-name="volp"></div>
<div class="playerbytton" id="eqbutton" onclick="showEqualizer(true)"></div> <div class="playerbytton" id="eqalbutton" data-name="equalizer"></div>
</div> </div>
<div id="equalizerwrap"> <div id="equalizerwrap">
<div id="equalizerbg" class="hidden"> <div id="equalizerbg" class="hidden">
@@ -40,27 +35,27 @@
<li> <li>
<li> <li>
balance<span class="eqinfo" id="eqbalinfo">0</span> balance<span class="eqinfo" id="eqbalinfo">0</span>
<input type="range" id="eqbal" class="slider" data-slaveid="eqbalinfo" onchange="onRangeBalChange(this)" name="lovpass" min="-16" max="16" value="0"> <input type="range" id="eqbal" class="slider" data-slaveid="eqbalinfo" name="balance" min="-16" max="16" value="0">
</li> </li>
<li> <li>
<li> <li>
treble<span class="eqinfo" id="eqtrebleinfo">0</span> treble<span class="eqinfo" id="eqtrebleinfo">0</span>
<input type="range" id="eqtreble" class="slider" data-slaveid="eqtrebleinfo" onchange="onRangeEqChange(this)" name="lovpass" min="-16" max="16" value="0"> <input type="range" id="eqtreble" class="slider" data-slaveid="eqtrebleinfo" name="treble" min="-16" max="16" value="0">
</li> </li>
<li> <li>
middle<span class="eqinfo" id="eqmiddleinfo">0</span> middle<span class="eqinfo" id="eqmiddleinfo">0</span>
<input type="range" id="eqmiddle" class="slider" data-slaveid="eqmiddleinfo" onchange="onRangeEqChange(this)" name="bandpass" min="-16" max="16" value="0"> <input type="range" id="eqmiddle" class="slider" data-slaveid="eqmiddleinfo" name="middle" min="-16" max="16" value="0">
</li> </li>
<li> <li>
bass<span class="eqinfo" id="eqbassinfo">0</span> bass<span class="eqinfo" id="eqbassinfo">0</span>
<input type="range" id="eqbass" class="slider" data-slaveid="eqbassinfo" onchange="onRangeEqChange(this)" name="highpass" min="-16" max="16" value="0"> <input type="range" id="eqbass" class="slider" data-slaveid="eqbassinfo" name="bass" min="-16" max="16" value="0">
</li> </li>
<li class="formbuttons"> <li class="formbuttons">
<div class="button" id="accept_button" onclick="showEqualizer(false)">Acceptable...</div> <div class="button" id="accept_button" data-name="equalizer">Acceptable...</div>
</li> </li>
</ul> </ul>
</div> </div>
<input type="range" id="volrange" class="slider" name="vol" data-slaveid="volinfo" onchange="onRangeVolChange(this.value)" min="0" max="254" value="0"> <input type="range" id="volrange" class="slider" name="volume" data-slaveid="volinfo" min="0" max="254" value="0">
<div class="infowrap"> <div class="infowrap">
<div class="infoitem">volume: <span id="volinfo">0</span></div> <div class="infoitem">volume: <span id="volinfo">0</span></div>
<div class="infoitem" id="bitinfo">bitrate: 0kBit</div> <div class="infoitem" id="bitinfo">bitrate: 0kBit</div>
@@ -70,46 +65,9 @@
</ul> </ul>
</div><!--equalizerwrap--> </div><!--equalizerwrap-->
</div><!--player--> </div><!--player-->
<div id="settings"%NOTAPMODE%> <div id="pleditorwrap" class="hidden">
<h2>WiFi Settings</h2>
<form autocomplete="off" id="wifiform">
<ul id="credentialwrap">
<li class="credentialitem">
<span>1.</span>
<div class="textinput"><label for="ssid0">SSID</label><input name="ssid" id="ssid0" type="text" value="%SSID%" maxlength="20"/ ></div>
<div class="textinput"><label for"pass0">Password</label><input name="pass" id="pass0" type="text" data-pass="%PASS%" placeholder="**********" value="" maxlength="40" autocomplete="off" readonly="readonly" onfocus="this.removeAttribute('readonly');" /></div>
</li>
<li class="credentialitem">
<span>2.</span>
<div class="textinput"><label for="ssid1">SSID</label><input name="ssid" id="ssid1" type="text" value="%SSID%" maxlength="20" /></div>
<div class="textinput"><label for"pass1">Password</label><input name="pass" id="pass1" type="text" data-pass="%PASS%" placeholder="**********" value="" maxlength="40" autocomplete="off" readonly="readonly" onfocus="this.removeAttribute('readonly');" /></div>
</li>
<li class="credentialitem">
<span>3.</span>
<div class="textinput"><label for="ssid2">SSID</label><input name="ssid" id="ssid2" type="text" value="%SSID%" maxlength="20" /></div>
<div class="textinput"><label for"pass2">Password</label><input name="pass" id="pass2" type="text" data-pass="%PASS%" placeholder="**********" value="" maxlength="40" autocomplete="off" readonly="readonly" onfocus="this.removeAttribute('readonly');" /></div>
</li>
<li class="credentialitem">
<span>4.</span>
<div class="textinput"><label for="ssid3">SSID</label><input name="ssid" id="ssid3" type="text" value="%SSID%" maxlength="20" /></div>
<div class="textinput"><label for"pass3">Password</label><input name="pass" id="pass3" type="text" data-pass="%PASS%" placeholder="**********" value="" maxlength="40" autocomplete="off" readonly="readonly" onfocus="this.removeAttribute('readonly');" /></div>
</li>
<li class="credentialitem">
<span>5.</span>
<div class="textinput"><label for="ssid4">SSID</label><input name="ssid" id="ssid4" type="text" value="%SSID%" maxlength="20" /></div>
<div class="textinput"><label for"pass4">Password</label><input name="pass" id="pass4" type="text" data-pass="%PASS%" placeholder="**********" value="" maxlength="40" autocomplete="off" readonly="readonly" onfocus="this.removeAttribute('readonly');" /></div>
</li>
</ul>
</form>
<div class="formbuttons">
<div class="button" id="wifiexport_button" onclick="doWifiExport()"%APMODE%>Export</div>
<div class="button" id="cancel_button" onclick="doCancel()"%APMODE%>Cancel</div>
<div class="button" id="save_button" onclick="submitWiFi()">Save</div>
</div>
</div><!--settings-->
<div id="pleditorwrap" hidden>
<div id="pleditor"> <div id="pleditor">
<h2>Playlist Editor<span onclick="doCancel()"></span></h2> <h2>Playlist Editor<span onclick="showEditor()"></span></h2>
<div id="pleheader"><span class="space"><input type="checkbox" onclick="selectAll(this)" /></span><span class="plename">Name</span><span class="pleurl">URL</span><span class="pleovol">Ovol</span></div> <div id="pleheader"><span class="space"><input type="checkbox" onclick="selectAll(this)" /></span><span class="plename">Name</span><span class="pleurl">URL</span><span class="pleovol">Ovol</span></div>
<ol id="pleditorcontent"> <ol id="pleditorcontent">
<li class="pleitem"> <li class="pleitem">
@@ -120,19 +78,18 @@
</li> </li>
</ol><!--pleditorcontent--> </ol><!--pleditorcontent-->
<div class="formbuttons"> <div class="formbuttons">
<label for="file-upload" class="button">Import</label><input id="file-upload" type="file" accept=".txt, .csv" onchange="doUpload(this)" hidden/> <label for="file-upload" class="button" data-name="plimport">Import</label><input id="file-upload" type="file" accept=".txt, .csv" onchange="doPlUpload(this)" hidden/>
<div class="button" onclick="doExport()">Export</div> <div class="button" data-name="plexport">Export</div>
<div class="button" onclick="doAdd()">Add</div> <div class="button" data-name="pladd">Add</div>
<div class="button" onclick="doRemove()">Remove</div> <div class="button" data-name="pldel">Remove</div>
<!--<div class="button" onclick="doCancel()">Cancel</div>--> <div class="button" data-name="plsubmit">Save</div>
<div class="button" onclick="submitPlaylist()">Save</div>
</div> </div>
</div><!--pleditor--> </div><!--pleditor-->
</div><!--pleditorwrap--> </div><!--pleditorwrap-->
</div><!--playerwrap--> </div><!--playerwrap-->
<div id="copy">powered by <a target="_blank" href="https://github.com/e2002/yoradio/">ёRadio</a> | v%VERSION%</div> <div id="copy">powered by <a target="_blank" href="https://github.com/e2002/yoradio/">ёRadio</a> | v%VERSION%</div>
</div> </div>
<script src="script.js"></script> <script src="script.js?%VERSION%"></script>
<script src="dragpl.js"></script> <script src="dragpl.js?%VERSION%"></script>
</body> </body>
</html> </html>

View File

@@ -6,9 +6,9 @@
<meta name="apple-mobile-web-app-status-bar-style" content="default"> <meta name="apple-mobile-web-app-status-bar-style" content="default">
<link rel="apple-touch-icon" type="image/png" href="elogo.png"> <link rel="apple-touch-icon" type="image/png" href="elogo.png">
<link rel="icon" type="image/png" href="elogo.png"> <link rel="icon" type="image/png" href="elogo.png">
<link rel="stylesheet" title="base" href="style.css" type="text/css"> <link rel="stylesheet" title="base" href="style.css?%VERSION%" type="text/css">
<link rel="stylesheet" title="base" href="ir.css" type="text/css"> <link rel="stylesheet" title="base" href="ir.css?%VERSION%" type="text/css">
<title>ёRadio IR recorder</title> <title>ёRadio - IR Recorder</title>
<style> </style> <style> </style>
</head> </head>
<body> <body>
@@ -28,7 +28,7 @@
<div id="irform"> <div id="irform">
<div id="irstartrecord"><h3>Welcome to IR Recorder!</h3> <div id="irstartrecord"><h3>Welcome to IR Recorder!</h3>
Press the button on the left<br />to record the code. Press the button on the left<br />to record the code.
<a href="/" class="button" id="done_ir" onclick="doneRecord()">DONE</a> <a href="/" class="button" id="done_ir">DONE</a>
</div> </div>
<div id="irrecord" class="hidden"> <div id="irrecord" class="hidden">
<h3 id="irrecordtitle"></h3> <h3 id="irrecordtitle"></h3>
@@ -45,5 +45,5 @@
</div><!--playerwrap--> </div><!--playerwrap-->
<div id="copy">powered by <a target="_blank" href="https://github.com/e2002/yoradio/">ёRadio</a> | v%VERSION%</div> <div id="copy">powered by <a target="_blank" href="https://github.com/e2002/yoradio/">ёRadio</a> | v%VERSION%</div>
</div> </div>
<script src="ir.js"></script> <script src="ir.js?%VERSION%"></script>
</body> </body>

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,216 @@
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, minimum-scale=0.25">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<link rel="apple-touch-icon" type="image/png" href="elogo.png">
<link rel="icon" type="image/png" href="elogo.png">
<link rel="stylesheet" title="base" href="style.css?%VERSION%" type="text/css">
<link rel="stylesheet" title="base" href="settings.css?%VERSION%" type="text/css">
<title>ёRadio - Settings</title>
<style> </style>
</head>
<body>
<div class="content">
<h2 class="pagetitle">SёTTINGS</h2>
<div class="navigation group group_system hidden" id="navigation">
<div class="navitem group group_system hidden" data-target="group_system">system</div>
<div class="navitem group group_display group_nextion hidden" data-target="group_display">screen</div>
<div class="navitem group group_controls hidden" data-target="group_controls">controls</div>
<div class="navitem group group_timezone hidden" data-target="group_timezone">timezone</div>
<div class="navitem group group_wifi hidden" data-target="group_wifi">wifi</div>
<div class="navitem group group_weather hidden" data-target="group_weather">weather</div>
</div>
<div class="playerwrap">
<div class="settingsirwrap" id="settingscontent"><a name="system"></a>
<section class="group group_system hidden" id="group_system">
<div class="title"><span>system</span></div><div class="reset" data-name="system"></div>
<div class="flex-row">
<div class="checkbox off nous" id="smartstart">Smart Start</div>
<div class="checkbox off nous" id="audioinfo">Audio info</div>
<div class="checkbox off nous group group_vu hidden" id="vumeter">VU Meter</div>
</div>
<div class="flex-row">
<div class="inputwrap">
<span class="inputtitle">soft ap reboot delay (min)</span>
<span class="inputinfo" id="slsoftapinfo">0</span>
<input type="range" id="slsoftap" class="slider" data-slaveid="slsoftapinfo" name="softap" min="0" max="20" value="0">
</div>
</div>
<div class="flex-row last">
<div class="button apply" data-name="fwupdate" id="fwupdate">Firmware update</div>
</div>
</section><a name="screen"></a>
<section class="group group_display group_nextion hidden" id="group_display">
<div class="title"><span>screen</span></div><div class="reset" data-name="screen"></div>
<div class="flex-row">
<div class="checkbox off nous group group_tft hidden" id="flipscreen">Flip screen</div>
<div class="checkbox off nous group group_tft hidden" id="invertdisplay">Invert screen</div>
<div class="checkbox on nous group group_brightness hidden" id="screenon">Turn on</div>
</div>
<div class="flex-row group group_tft group_nextion hidden">
<div class="checkbox off nous" id="numplaylist">numbered playlist</div>
</div>
<div class="flex-row group group_brightness hidden">
<div class="inputwrap">
<span class="inputtitle">brightness</span>
<span class="inputinfo" id="slbrightnessinfo">0</span>
<input type="range" id="slbrightness" class="slider" data-slaveid="slbrightnessinfo" name="brightness" min="0" max="100" value="100">
</div>
</div>
<div class="flex-row group group_nokia hidden">
<div class="inputwrap">
<span class="inputtitle">contrast</span>
<span class="inputinfo" id="slcontrastinfo">0</span>
<input type="range" id="slcontrast" class="slider" data-slaveid="slcontrastinfo" name="contrast" min="0" max="100" value="55">
</div>
</div>
</section>
<section class="group group_controls hidden" id="group_controls">
<div class="title"><span>Controls</span></div><div class="reset" data-name="controls"></div>
<div class="flex-row">
<div class="inputwrap">
<span class="inputtitle">volume steps</span>
<span class="inputinfo" id="slvolstepsinfo">0</span>
<input type="range" id="slvolsteps" class="slider" data-slaveid="slvolstepsinfo" name="volsteps" min="1" max="10" value="1">
</div>
</div>
<div class="flex-row group group_touch hidden">
<div class="checkbox off nous" id="fliptouch">Flip touch</div>
<div class="checkbox off nous" id="dbgtouch">Debug touch</div>
</div>
<div class="flex-row group group_encoder hidden">
<div class="inputwrap">
<span class="inputtitle">encoder acceleration</span>
<span class="inputinfo" id="slencaccelerationinfo">0</span>
<input type="range" id="slencacceleration" class="slider" data-slaveid="slencaccelerationinfo" name="encacceleration" min="0" max="700" value="200">
</div>
</div>
<div class="flex-row group group_ir hidden">
<div class="inputwrap">
<span class="inputtitle">IR tolerance [<a href="https://crankyoldgit.github.io/IRremoteESP8266/doxygen/html/" target="_blank">docs</a>]</span>
<span class="inputinfo" id="slirtlpinfo">0</span>
<input type="range" id="slirtlp" class="slider" data-slaveid="slirtlpinfo" name="irtlp" min="10" max="80" value="0">
</div>
</div>
<div class="flex-row group group_ir last hidden">
<div class="button apply" data-name="setupir">IR Recorder</div>
</div>
</section><a name="timezone"></a>
<section class="group group_timezone hidden" id="group_timezone">
<div class="title"><span>timezone</span></div><div class="reset" data-name="timezone"></div>
<div class="flex-row">
<div class="inputwrap">
<span class="inputtitle">hours</span>
<input type="number" id="tzhour" class="textinput" name="tzhour" value="" maxlength="3" min="-12" max="14" />
</div>
<div class="inputwrap">
<span class="inputtitle">minutes</span>
<input type="number" id="tzmin" class="textinput" name="tzmin" value="" maxlength="2" min="0" max="45" step="15" />
</div>
</div>
<div class="flex-row">
<div class="inputwrap">
<span class="inputtitle">ntp server #1</span>
<input type="text" id="sntp1" class="textinput" name="sntp1" value="" maxlength="34" />
</div>
<div class="inputwrap">
<span class="inputtitle">ntp server #2</span>
<input type="text" id="sntp2" class="textinput" name="sntp2" value="" maxlength="34" />
</div>
</div>
<div class="flex-row last">
<div class="button apply hlbutton" data-name="applytz" id="applytz">Apply</div>
</div>
</section><a name="wifi"></a>
<section class="group group_wifi hidden" id="group_wifi">
<div class="title"><span>Wi-Fi</span></div>
<div class="flex-row credential">
<div class="inputwrap">
<span class="inputtitle">ssid</span>
<input type="text" id="ssid0" class="textinput" name="ssid" value="" maxlength="20" autocomplete="off" />
</div>
<div class="inputwrap">
<span class="inputtitle">pass</span>
<input type="text" id="pass0" class="textinput" name="pass" value="" placeholder="**********" maxlength="40" autocomplete="off" readonly="readonly" data-pass="" onfocus="this.removeAttribute('readonly');" />
</div>
</div>
<div class="flex-row credential">
<div class="inputwrap">
<span class="inputtitle">ssid</span>
<input type="text" id="ssid1" class="textinput" name="ssid" maxlength="20" autocomplete="off" />
</div>
<div class="inputwrap">
<span class="inputtitle">pass</span>
<input type="text" id="pass1" class="textinput" name="pass" value="" placeholder="**********" maxlength="40" autocomplete="off" readonly="readonly" data-pass="" onfocus="this.removeAttribute('readonly');" />
</div>
</div>
<div class="flex-row credential">
<div class="inputwrap">
<span class="inputtitle">ssid</span>
<input type="text" id="ssid2" class="textinput" name="ssid" value="" maxlength="20" autocomplete="off" />
</div>
<div class="inputwrap">
<span class="inputtitle">pass</span>
<input type="text" id="pass2" class="textinput" name="pass" value="" placeholder="**********" maxlength="40" autocomplete="off" readonly="readonly" data-pass="" onfocus="this.removeAttribute('readonly');" />
</div>
</div>
<div class="flex-row credential">
<div class="inputwrap">
<span class="inputtitle">ssid</span>
<input type="text" id="ssid3" class="textinput" name="ssid" value="" maxlength="20" autocomplete="off" />
</div>
<div class="inputwrap">
<span class="inputtitle">pass</span>
<input type="text" id="pass3" class="textinput" name="pass" value="" placeholder="**********" maxlength="40" autocomplete="off" readonly="readonly" data-pass="" onfocus="this.removeAttribute('readonly');" />
</div>
</div>
<div class="flex-row credential">
<div class="inputwrap">
<span class="inputtitle">ssid</span>
<input type="text" id="ssid4" class="textinput" name="ssid" value="" maxlength="20" autocomplete="off" />
</div>
<div class="inputwrap">
<span class="inputtitle">pass</span>
<input type="text" id="pass4" class="textinput" name="pass" value="" placeholder="**********" maxlength="40" autocomplete="off" readonly="readonly" data-pass="" onfocus="this.removeAttribute('readonly');" />
</div>
</div>
<div class="flex-row last">
<div class="button group group_system hidden" data-name="wifiexport">Export</div>
<div class="button hlbutton" data-name="wifiupload">Save &amp; Reboot</div>
</div>
</section><a name="weather"></a>
<section class="group group_weather hidden" id="group_weather">
<div class="title"><span>Weather</span></div><div class="reset" data-name="weather"></div>
<div class="flex-row center">
<div class="checkbox off nous" id="showweather">show weather</div>
</div>
<div class="flex-row">
<div class="inputwrap">
<span class="inputtitle">latitude</span>
<input type="number" id="weatherlat" class="textinput" name="weatherlat" value="" min="-90" max="90" step="0.0001" />
</div>
<div class="inputwrap">
<span class="inputtitle">longitude</span>
<input type="number" id="weatherlon" class="textinput" name="weatherlon" value="" min="-90" max="90" step="0.0001" />
</div>
</div>
<div class="flex-row">
<div class="inputwrap">
<span class="inputtitle">openweathermap api key [<a href="https://openweathermap.org/appid" target="_blank">link</a>]</span>
<input type="text" id="weatherkey" class="textinput" name="weatherkey" value="" />
</div>
</div>
<div class="flex-row last">
<div class="button apply hlbutton" data-name="applyweather">Apply</div>
</div>
</section><a name="controls"></a>
<div class="hr">&nbsp;</div>
</div>
</div><!--playerwrap-->
<div class="button apply done group group_system hidden" data-name="settingsdone" id="settingsdone">done</div>
<div id="copy">powered by <a target="_blank" href="https://github.com/e2002/yoradio/">ёRadio</a> | v%VERSION%</div>
</div>
<script src="script.js?%VERSION%"></script>
</body>

Binary file not shown.

View File

@@ -6,8 +6,8 @@
<meta name="apple-mobile-web-app-status-bar-style" content="default"> <meta name="apple-mobile-web-app-status-bar-style" content="default">
<link rel="apple-touch-icon" type="image/png" href="elogo.png"> <link rel="apple-touch-icon" type="image/png" href="elogo.png">
<link rel="icon" type="image/png" href="elogo.png"> <link rel="icon" type="image/png" href="elogo.png">
<link rel="stylesheet" title="base" href="style.css" type="text/css"> <link rel="stylesheet" title="base" href="style.css?%VERSION%" type="text/css">
<title>ёRadio-update</title> <title>ёRadio - Update</title>
<style> <style>
</style> </style>
</head> </head>
@@ -33,6 +33,6 @@
</div><!--playerwrap--> </div><!--playerwrap-->
<div id="copy">powered by <a target="_blank" href="https://github.com/e2002/yoradio/">ёRadio</a> | v%VERSION%</div> <div id="copy">powered by <a target="_blank" href="https://github.com/e2002/yoradio/">ёRadio</a> | v%VERSION%</div>
</div> </div>
<script src="script.js"></script> <script src="script.js?%VERSION%"></script>
</body> </body>
</html> </html>

View File

@@ -3,7 +3,7 @@
#include "WiFi.h" #include "WiFi.h"
#include "time.h" #include "time.h"
#include "display.h" #include "display.h"
#if ENABLE_VU_METER #if VU_READY==1
#include "display_vu.h" #include "display_vu.h"
#endif #endif
#include "player.h" #include "player.h"
@@ -73,6 +73,13 @@ void ticks() {
byte currentScrollId = 0; /* one scroll on one time */ byte currentScrollId = 0; /* one scroll on one time */
#if WEATHER_READY==1
bool weatherRequest = false;
TaskHandle_t weatherUpdateTaskHandle;
Ticker weatherTicker;
char weatherText[254] = { 0 };
#endif
void Scroll::init(byte ScrollId, const char *sep, byte tsize, byte top, uint16_t dlay, uint16_t fgcolor, uint16_t bgcolor) { void Scroll::init(byte ScrollId, const char *sep, byte tsize, byte top, uint16_t dlay, uint16_t fgcolor, uint16_t bgcolor) {
textsize = tsize; textsize = tsize;
id = ScrollId; id = ScrollId;
@@ -239,6 +246,15 @@ void Display::init() {
#endif #endif
plCurrent.init(4, " * ", PLCURRENT_SIZE, yStart, STARTTIME_PL, TFT_BG, TFT_LOGO); plCurrent.init(4, " * ", PLCURRENT_SIZE, yStart, STARTTIME_PL, TFT_BG, TFT_LOGO);
plCurrent.lock(); plCurrent.lock();
#if WEATHER_READY==1
if (DSP_MODEL == DSP_ST7735 || (DSP_MODEL == DSP_SSD1327)) {
weatherScroll.init(5, " * ", 1, TFT_LINEHGHT * 4 + 6, 0, ORANGE, TFT_BG);
}else if(DSP_MODEL == DSP_ILI9225){
weatherScroll.init(5, " * ", 1, TFT_LINEHGHT * 6 + 5, 0, ORANGE, TFT_BG);
} else {
weatherScroll.init(5, " * ", 2, TFT_LINEHGHT * 9 + 5, 0, ORANGE, TFT_BG);
}
#endif
if (dsp_on_init) dsp_on_init(); if (dsp_on_init) dsp_on_init();
} }
@@ -476,6 +492,9 @@ void Display::loop() {
switch (mode) { switch (mode) {
case PLAYER: { case PLAYER: {
drawPlayer(); drawPlayer();
#if WEATHER_READY==1
weatherScroll.loop();
#endif
break; break;
} }
case INFO: case INFO:
@@ -500,9 +519,15 @@ void Display::loop() {
} }
dsp.loop(); dsp.loop();
if (dsp_on_loop) dsp_on_loop(&dsp); if (dsp_on_loop) dsp_on_loop(&dsp);
#if ENABLE_VU_METER #if VU_READY==1
drawVU(&dsp); drawVU(&dsp);
#endif #endif
#if WEATHER_READY==1
if (weatherRequest) {
weatherRequest = false;
weatherScroll.setText(dsp.utf8Rus(weatherText, true));
}
#endif
} }
void Display::centerText(const char* text, byte y, uint16_t fg, uint16_t bg) { void Display::centerText(const char* text, byte y, uint16_t fg, uint16_t bg) {
@@ -635,6 +660,19 @@ void Display::volume() {
#endif #endif
//netserver.requestOnChange(VOLUME, 0); //netserver.requestOnChange(VOLUME, 0);
} }
void Display::flip(){
dsp.flip();
}
void Display::invert(){
dsp.invert();
}
#if DSP_MODEL==DSP_NOKIA5110
void Display::setContrast(){
dsp.setContrast(config.store.contrast);
}
#endif // DSP_MODEL==DSP_NOKIA5110
/******************************************************************************************************************/ /******************************************************************************************************************/
#endif // !DUMMYDISPLAY #endif // !DUMMYDISPLAY
@@ -662,3 +700,140 @@ void Display::putRequest(requestParams_t request){
} }
/******************************************************************************************************************/ /******************************************************************************************************************/
#endif // DUMMYDISPLAY #endif // DUMMYDISPLAY
#ifndef DUMMYDISPLAY
#if WEATHER_READY==1
bool getForecast() {
WiFiClient client;
const char* host = "api.openweathermap.org";
if (!client.connect(host, 80)) {
Serial.println("## OPENWEATHERMAP ###: connection failed");
return false;
}
char httpget[250] = {0};
sprintf(httpget, "GET /data/2.5/weather?lat=%s&lon=%s&units=metric&lang=ru&appid=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", config.store.weatherlat, config.store.weatherlon, config.store.weatherkey, host);
client.print(httpget);
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 2000UL) {
Serial.println("## OPENWEATHERMAP ###: client available timeout !");
client.stop();
return false;
}
}
timeout = millis();
String line = "";
if (client.connected()) {
while (client.available())
{
line = client.readStringUntil('\n');
if (strstr(line.c_str(), "\"temp\"") != NULL) {
client.stop();
break;
}
if ((millis() - timeout) > 500)
{
client.stop();
Serial.println("## OPENWEATHERMAP ###: client read timeout !");
return false;
}
}
}
if (strstr(line.c_str(), "\"temp\"") == NULL) {
Serial.println("## OPENWEATHERMAP ###: weather not found !");
return false;
}
char *tmpe;
char *tmps;
const char* cursor = line.c_str();
char desc[120], temp[20], hum[20], press[20], icon[5];
tmps = strstr(cursor, "\"description\":\"");
if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: description not found !"); return false;}
tmps += 15;
tmpe = strstr(tmps, "\",\"");
if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: description not found !"); return false;}
strlcpy(desc, tmps, tmpe - tmps + 1);
cursor = tmpe + 2;
// "ясно","icon":"01d"}],
tmps = strstr(cursor, "\"icon\":\"");
if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: icon not found !"); return false;}
tmps += 8;
tmpe = strstr(tmps, "\"}");
if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: icon not found !"); return false;}
strlcpy(icon, tmps, tmpe - tmps + 1);
cursor = tmpe + 2;
tmps = strstr(cursor, "\"temp\":");
if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: temp not found !"); return false;}
tmps += 7;
tmpe = strstr(tmps, ",\"");
if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: temp not found !"); return false;}
strlcpy(temp, tmps, tmpe - tmps + 1);
cursor = tmpe + 2;
float tempf = atof(temp);
tmps = strstr(cursor, "\"pressure\":");
if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: pressure not found !"); return false;}
tmps += 11;
tmpe = strstr(tmps, ",\"");
if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: pressure not found !"); return false;}
strlcpy(press, tmps, tmpe - tmps + 1);
cursor = tmpe + 2;
int pressi = (float)atoi(press) / 1.333;
tmps = strstr(cursor, "humidity\":");
if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: humidity not found !"); return false;}
tmps += 10;
tmpe = strstr(tmps, ",\"");
if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: humidity not found !"); return false;}
strlcpy(hum, tmps, tmpe - tmps + 1);
Serial.printf("## OPENWEATHERMAP ###: description: %s, temp:%.1f C, pressure:%dmmHg, humidity:%s%%\n", desc, tempf, pressi, hum);
sprintf(weatherText, "%s, %.1f C * давление: %d мм * влажность: %s%%", desc, tempf, pressi, hum);
return true;
}
void Display::getWeather( void * pvParameters ) {
delay(200);
if (getForecast()) {
weatherRequest = true;
weatherTicker.detach();
weatherTicker.attach(WEATHER_REQUEST_INTERVAL, display.updateWeather);
} else {
weatherTicker.detach();
weatherTicker.attach(WEATHER_REQUEST_INTERVAL_FAULTY, display.updateWeather);
}
vTaskDelete( NULL );
}
#endif // WEATHER_READY==1
void Display::updateWeather(){
#if WEATHER_READY==1
if(!config.store.showweather || strlen(config.store.weatherkey)==0) return;
xTaskCreatePinnedToCore(
getWeather, /* Task function. */
"dspGetWeather1", /* name of task. */
1024 * 4, /* Stack size of task */
NULL, /* parameter of the task */
0, /* priority of the task */
&weatherUpdateTaskHandle, /* Task handle to keep track of created task */
0); /* pin task to core CORE_FOR_LOOP_CONTROLS */
#endif // WEATHER_READY==1
}
void Display::showWeather(){
#if WEATHER_READY==1
if(strlen(config.store.weatherkey)!=0 && config.store.showweather) display.updateWeather();
if(!config.store.showweather){
memset(weatherText, 0, sizeof(weatherText));
weatherScroll.setText(weatherText);
}
#endif // WEATHER_READY==1
}
/******************************************************************************************************************/
#endif // !DUMMYDISPLAY

View File

@@ -38,8 +38,20 @@
#elif DSP_MODEL==DSP_ILI9225 #elif DSP_MODEL==DSP_ILI9225
#include "src/displays/displayILI9225.h" #include "src/displays/displayILI9225.h"
#endif #endif
#ifndef VU_READY
#define VU_READY 0
#endif
#ifndef DSP_FLIPPED
#define DSP_FLIPPED 1
#endif
#ifndef WEATHER_READY
#define WEATHER_READY 0
#else
#define WEATHER_REQUEST_INTERVAL 1800 //30min
#define WEATHER_REQUEST_INTERVAL_FAULTY 30
#endif
enum displayMode_e { PLAYER, VOL, STATIONS, NUMBERS, LOST, UPDATING, INFO, SETTINGS, TIMEZONE, WIFI }; enum displayMode_e { PLAYER, VOL, STATIONS, NUMBERS, LOST, UPDATING, INFO, SETTINGS, TIMEZONE, WIFI, CLEAR };
enum displayRequestType_e { NEWMODE, CLOCK, NEWTITLE, RETURNTITLE, NEWSTATION, NEXTSTATION, DRAWPLAYLIST, DRAWVOL }; enum displayRequestType_e { NEWMODE, CLOCK, NEWTITLE, RETURNTITLE, NEWSTATION, NEXTSTATION, DRAWPLAYLIST, DRAWVOL };
struct requestParams_t struct requestParams_t
@@ -111,6 +123,15 @@ class Display {
void bootString(const char* text, byte y); void bootString(const char* text, byte y);
void bootLogo(); void bootLogo();
void putRequest(requestParams_t request); void putRequest(requestParams_t request);
void flip();
void invert();
static void updateWeather();
void showWeather();
#if DSP_MODEL==DSP_NOKIA5110
void setContrast();
#else
void setContrast(){};
#endif // DSP_MODEL==DSP_NOKIA5110
#else #else
void init(); void init();
void loop(){}; void loop(){};
@@ -122,9 +143,18 @@ class Display {
void bootString(const char* text, byte y); void bootString(const char* text, byte y);
void bootLogo(){}; void bootLogo(){};
void putRequest(requestParams_t request); void putRequest(requestParams_t request);
void flip(){};
void invert(){};
void setContrast(){};
static void updateWeather(){};
void showWeather(){};
#endif #endif
#ifndef DUMMYDISPLAY #ifndef DUMMYDISPLAY
private: private:
#if WEATHER_READY==1
Scroll weatherScroll;
static void getWeather( void * pvParameters );
#endif
Ticker timer; Ticker timer;
Scroll meta, title1, title2; Scroll meta, title1, title2;
bool clockRequest; bool clockRequest;

View File

@@ -1,4 +1,3 @@
#if ENABLE_VU_METER
#ifndef display_vu_h #ifndef display_vu_h
#define display_vu_h #define display_vu_h
#include "player.h" #include "player.h"
@@ -21,23 +20,29 @@ enum : uint16_t VU_PARAMS2;
/**********************************************************************************************************************************************************************************/ /**********************************************************************************************************************************************************************************/
/* vu left | vu top | band width | band height | band space | num of bands | fade speed | horisontal | Max Bands Color | Min Bands Color */ /* vu left | vu top | band width | band height | band space | num of bands | fade speed | horisontal | Max Bands Color | Min Bands Color */
/**********************************************************************************************************************************************************************************/ /**********************************************************************************************************************************************************************************/
#if DSP_MODEL==DSP_ST7735 && DTYPE==INITR_BLACKTAB /* ST7735 160x128 */ #if DSP_MODEL==DSP_ST7735 && DTYPE==INITR_BLACKTAB /* ST7735 160x128 */
enum : uint16_t { VU_X = 4, VU_Y = 50, VU_BW = 10, VU_BH = 44, VU_BS = 2, VU_NB = 8, VU_FS = 2, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; enum : uint16_t { VU_X = 4, VU_Y = 50, VU_BW = 10, VU_BH = 44, VU_BS = 2, VU_NB = 8, VU_FS = 2, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY };
#elif DSP_MODEL==DSP_ST7735 && DTYPE==INITR_144GREENTAB /* ST7735 128x128 */ #elif DSP_MODEL==DSP_ST7735 && DTYPE==INITR_144GREENTAB /* ST7735 128x128 */
enum : uint16_t { VU_X = 4, VU_Y = 45, VU_BW = 60, VU_BH = 8, VU_BS = 0, VU_NB = 10, VU_FS = 2, VU_HOR = 1, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = DARK_GRAY }; enum : uint16_t { VU_X = 4, VU_Y = 97, VU_BW = 60, VU_BH = 8, VU_BS = 0, VU_NB = 10, VU_FS = 2, VU_HOR = 1, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = DARK_GRAY };
#define GREENTAB128 #define GREENTAB128
#elif DSP_MODEL==DSP_ILI9341 /* ILI9341 320x240 */ #elif DSP_MODEL==DSP_ILI9341 /* ILI9341 320x240 */
enum : uint16_t { VU_X = 4, VU_Y = 100, VU_BW = 20, VU_BH = 86, VU_BS = 4, VU_NB = 10, VU_FS = 5, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; enum : uint16_t { VU_X = 4, VU_Y = 116, VU_BW = 24, VU_BH = 80, VU_BS = 4, VU_NB = 8, VU_FS = 5, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY };
#elif DSP_MODEL==DSP_ST7789 /* ST7789 320x240 */ #elif DSP_MODEL==DSP_ST7789 /* ST7789 320x240 */
enum : uint16_t { VU_X = 4, VU_Y = 100, VU_BW = 20, VU_BH = 86, VU_BS = 4, VU_NB = 10, VU_FS = 3, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; enum : uint16_t { VU_X = 4, VU_Y = 116, VU_BW = 24, VU_BH = 80, VU_BS = 4, VU_NB = 8, VU_FS = 5, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY };
#elif DSP_MODEL==DSP_ST7789_240 /* ST7789 240x240 */ #elif DSP_MODEL==DSP_ST7789_240 /* ST7789 240x240 */
enum : uint16_t { VU_X = 4, VU_Y = 90, VU_BW = 120, VU_BH = 20, VU_BS = 0, VU_NB = 12, VU_FS = 3, VU_HOR = 1, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; enum : uint16_t { VU_X = 4, VU_Y = 90, VU_BW = 120, VU_BH = 20, VU_BS = 0, VU_NB = 12, VU_FS = 3, VU_HOR = 1, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY };
#elif DSP_MODEL==DSP_ILI9225 /* ILI9225 220x176 */ #elif DSP_MODEL==DSP_ILI9225 /* ILI9225 220x176 */
enum : uint16_t { VU_X = 4, VU_Y = 74, VU_BW = 13, VU_BH = 60, VU_BS = 2, VU_NB = 10, VU_FS = 3, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; enum : uint16_t { VU_X = 4, VU_Y = 80, VU_BW = 13, VU_BH = 56, VU_BS = 2, VU_NB = 8, VU_FS = 3, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY };
#elif (DSP_MODEL==DSP_ST7735 && DTYPE==INITR_MINI160x80) || (DSP_MODEL==DSP_GC9106) /* ST7735 160x80, GC9106 160x80 */ #elif (DSP_MODEL==DSP_ST7735 && DTYPE==INITR_MINI160x80) || (DSP_MODEL==DSP_GC9106) /* ST7735 160x80, GC9106 160x80 */
enum : uint16_t { VU_X = 1, VU_Y = 30, VU_BW = 12, VU_BH = 36, VU_BS = 4, VU_NB = 8, VU_FS = 2, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY }; enum : uint16_t { VU_X = 1, VU_Y = 30, VU_BW = 12, VU_BH = 36, VU_BS = 4, VU_NB = 8, VU_FS = 2, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY };
#else
#error YOUR DISPLAY DOES NOT SUPPORT ENABLE_VU_METER FEATURE YET
#endif #endif
#endif //VU_PARAMS #endif //VU_PARAMS
/**********************************************************************************************************************************************************************************/ /**********************************************************************************************************************************************************************************/
@@ -47,6 +52,7 @@ void drawVU(DspCore *dsp);
GFXcanvas16 gfxc(VU_BW*2+VU_BS,VU_BH); GFXcanvas16 gfxc(VU_BW*2+VU_BS,VU_BH);
void drawVU(DspCore *dsp){ void drawVU(DspCore *dsp){
if(!config.store.vumeter) return;
if(display.mode!=PLAYER && display.mode!=VOL) return; if(display.mode!=PLAYER && display.mode!=VOL) return;
#ifdef GREENTAB128 #ifdef GREENTAB128
if(display.mode==VOL) return; if(display.mode==VOL) return;
@@ -106,4 +112,3 @@ void drawVU(DspCore *dsp){
} }
} }
#endif #endif
#endif

View File

@@ -8,12 +8,15 @@
#include "options.h" #include "options.h"
#include "network.h" #include "network.h"
#include "mqtt.h" #include "mqtt.h"
#include "controls.h"
#include <Update.h> #include <Update.h>
#ifndef MIN_MALLOC #ifndef MIN_MALLOC
#define MIN_MALLOC 24112 #define MIN_MALLOC 24112
#endif #endif
#define CORS_DEBUG
NetServer netserver; NetServer netserver;
AsyncWebServer webserver(80); AsyncWebServer webserver(80);
@@ -25,7 +28,6 @@ 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);
void handleHTTPPost(AsyncWebServerRequest * request); void handleHTTPPost(AsyncWebServerRequest * request);
byte ssidCount;
bool shouldReboot = false; bool shouldReboot = false;
char* updateError(){ char* updateError(){
@@ -34,23 +36,40 @@ char* updateError(){
return ret; return ret;
} }
void NetServer::takeMallocDog(){
int mcb = heap_caps_get_free_size(MALLOC_CAP_8BIT);
int mci = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
(void)mci;
log_i("[yoradio] webserver.on / - MALLOC_CAP_INTERNAL=%d, MALLOC_CAP_8BIT=%d", mci, mcb);
resumePlay = mcb < MIN_MALLOC;
if (resumePlay) {
player.toggle();
while (player.isRunning()) {
vTaskDelay(10);
}
vTaskDelay(50);
}
}
void NetServer::giveMallocDog(){
if (resumePlay) {
resumePlay = false;
vTaskDelay(100);
player.toggle();
}
}
bool NetServer::begin() { bool NetServer::begin() {
importRequest = false; importRequest = false;
irRecordEnable = false; irRecordEnable = false;
webserver.on("/", HTTP_GET, [](AsyncWebServerRequest * request) { webserver.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
ssidCount = 0; netserver.takeMallocDog();
int mcb = heap_caps_get_free_size(MALLOC_CAP_8BIT); if (network.status == CONNECTED) {
int mci = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); request->send(SPIFFS, "/www/index.html", String(), false, processor);
(void)mci; }else{
log_i("[yoradio] webserver.on / - MALLOC_CAP_INTERNAL=%d, MALLOC_CAP_8BIT=%d", mci, mcb); request->send(SPIFFS, "/www/settings.html", String(), false, processor);
netserver.resumePlay = mcb < MIN_MALLOC;
if (netserver.resumePlay) {
player.toggle();
while (player.isRunning()) {
delay(10);
}
} }
request->send(SPIFFS, "/www/index.html", String(), false, processor); netserver.giveMallocDog();
}); });
webserver.serveStatic("/", SPIFFS, "/www/").setCacheControl("max-age=31536000"); webserver.serveStatic("/", SPIFFS, "/www/").setCacheControl("max-age=31536000");
@@ -59,23 +78,37 @@ bool NetServer::begin() {
handleHTTPPost(request); handleHTTPPost(request);
}); });
webserver.on(PLAYLIST_PATH, HTTP_GET, [](AsyncWebServerRequest * request) { webserver.on(PLAYLIST_PATH, HTTP_GET, [](AsyncWebServerRequest * request) {
netserver.takeMallocDog();
request->send(SPIFFS, PLAYLIST_PATH, "application/octet-stream"); request->send(SPIFFS, PLAYLIST_PATH, "application/octet-stream");
netserver.giveMallocDog();
}); });
webserver.on(INDEX_PATH, HTTP_GET, [](AsyncWebServerRequest * request) { webserver.on(INDEX_PATH, HTTP_GET, [](AsyncWebServerRequest * request) {
request->send(SPIFFS, INDEX_PATH, "application/octet-stream"); request->send(SPIFFS, INDEX_PATH, "application/octet-stream");
}); });
webserver.on(SSIDS_PATH, HTTP_GET, [](AsyncWebServerRequest * request) { webserver.on(SSIDS_PATH, HTTP_GET, [](AsyncWebServerRequest * request) {
netserver.takeMallocDog();
request->send(SPIFFS, SSIDS_PATH, "application/octet-stream"); request->send(SPIFFS, SSIDS_PATH, "application/octet-stream");
netserver.giveMallocDog();
}); });
webserver.on("/upload", HTTP_POST, [](AsyncWebServerRequest * request) { webserver.on("/upload", HTTP_POST, [](AsyncWebServerRequest * request) {
//request->send(200); //request->send(200);
}, handleUpload); }, handleUpload);
webserver.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){ webserver.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){
netserver.takeMallocDog();
request->send(SPIFFS, "/www/update.html", String(), false, processor); request->send(SPIFFS, "/www/update.html", String(), false, processor);
netserver.giveMallocDog();
});
webserver.on("/settings", HTTP_GET, [](AsyncWebServerRequest *request){
netserver.takeMallocDog();
request->send(SPIFFS, "/www/settings.html", String(), false, processor);
netserver.giveMallocDog();
}); });
#if IR_PIN!=255 #if IR_PIN!=255
webserver.on("/ir", HTTP_GET, [](AsyncWebServerRequest *request){ webserver.on("/ir", HTTP_GET, [](AsyncWebServerRequest *request){
netserver.takeMallocDog();
request->send(SPIFFS, "/www/ir.html", String(), false, processor); request->send(SPIFFS, "/www/ir.html", String(), false, processor);
netserver.giveMallocDog();
}); });
#endif #endif
webserver.on("/update", HTTP_POST, [](AsyncWebServerRequest *request){ webserver.on("/update", HTTP_POST, [](AsyncWebServerRequest *request){
@@ -109,6 +142,10 @@ bool NetServer::begin() {
} }
} }
}); });
#ifdef CORS_DEBUG
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), F("*"));
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), F("content-type"));
#endif
webserver.begin(); webserver.begin();
websocket.onEvent(onWsEvent); websocket.onEvent(onWsEvent);
webserver.addHandler(&websocket); webserver.addHandler(&websocket);
@@ -136,7 +173,7 @@ void NetServer::loop() {
} }
if (importRequest) { if (importRequest) {
if (importPlaylist()) { if (importPlaylist()) {
requestOnChange(PLAYLIST, 0); //requestOnChange(PLAYLIST, 0);
} }
importRequest = false; importRequest = false;
} }
@@ -157,16 +194,355 @@ void NetServer::irValsToWs(){
websocket.textAll(buf); websocket.textAll(buf);
} }
#endif #endif
void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len) { void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t clientId) {
AwsFrameInfo *info = (AwsFrameInfo*)arg; AwsFrameInfo *info = (AwsFrameInfo*)arg;
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) { if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
data[len] = 0; data[len] = 0;
char cmd[15], val[15]; char cmd[65], val[65];
if (config.parseWsCommand((const char*)data, cmd, val, 15)) { if (config.parseWsCommand((const char*)data, cmd, val, 65)) {
if (strcmp(cmd, "getmode") == 0) {
requestOnChange(GETMODE,clientId);
return;
}
if (strcmp(cmd, "getindex") == 0) {
requestOnChange(GETINDEX,clientId);
return;
}
if (strcmp(cmd, "getsystem") == 0) {
requestOnChange(GETSYSTEM,clientId);
return;
}
if (strcmp(cmd, "getscreen") == 0) {
requestOnChange(GETSCREEN,clientId);
return;
}
if (strcmp(cmd, "gettimezone") == 0) {
requestOnChange(GETTIMEZONE,clientId);
return;
}
if (strcmp(cmd, "getcontrols") == 0) {
requestOnChange(GETCONTROLS,clientId);
return;
}
if (strcmp(cmd, "getweather") == 0) {
requestOnChange(GETWEATHER,clientId);
return;
}
if (strcmp(cmd, "getactive") == 0) {
requestOnChange(GETACTIVE,clientId);
return;
}
if (strcmp(cmd, "smartstart") == 0) {
byte valb=atoi(val);
config.store.smartstart=valb==1?1:2;
if(!player.isRunning() && config.store.smartstart==1) config.store.smartstart=0;
config.save();
return;
}
if (strcmp(cmd, "audioinfo") == 0) {
byte valb=atoi(val);
config.store.audioinfo=valb;
config.save();
display.putRequest({NEWMODE, CLEAR});
display.putRequest({NEWMODE, PLAYER});
return;
}
if (strcmp(cmd, "vumeter") == 0) {
byte valb=atoi(val);
config.store.vumeter=valb;
config.save();
display.putRequest({NEWMODE, CLEAR});
display.putRequest({NEWMODE, PLAYER});
return;
}
if (strcmp(cmd, "softap") == 0) {
byte valb=atoi(val);
config.store.softapdelay=valb;
config.save();
return;
}
if (strcmp(cmd, "invertdisplay") == 0) {
byte valb=atoi(val);
config.store.invertdisplay=valb;
config.save();
display.invert();
return;
}
if (strcmp(cmd, "numplaylist") == 0) {
byte valb=atoi(val);
config.store.numplaylist=valb;
config.save();
display.putRequest({NEWMODE, CLEAR});
display.putRequest({NEWMODE, PLAYER});
return;
}
if (strcmp(cmd, "fliptouch") == 0) {
byte valb=atoi(val);
config.store.fliptouch=valb==1;
config.save();
flipTS();
return;
}
if (strcmp(cmd, "dbgtouch") == 0) {
byte valb=atoi(val);
config.store.dbgtouch=valb==1;
config.save();
return;
}
if (strcmp(cmd, "flipscreen") == 0) {
byte valb=atoi(val);
config.store.flipscreen=valb;
config.save();
display.flip();
display.putRequest({NEWMODE, CLEAR});
display.putRequest({NEWMODE, PLAYER});
return;
}
if (strcmp(cmd, "brightness") == 0) {
byte valb=atoi(val);
config.store.brightness=valb;
//display.setContrast();
config.setBrightness(true);
return;
}
if (strcmp(cmd, "screenon") == 0) {
byte valb=atoi(val);
config.store.dspon=valb==1;
config.setBrightness(true);
return;
}
if (strcmp(cmd, "contrast") == 0) {
byte valb=atoi(val);
config.store.contrast=valb;
config.save();
display.setContrast();
return;
}
if (strcmp(cmd, "tzh") == 0) {
int vali=atoi(val);
config.store.tzHour=vali;
return;
}
if (strcmp(cmd, "tzm") == 0) {
int vali=atoi(val);
config.store.tzMin=vali;
return;
}
if (strcmp(cmd, "sntp2") == 0) {
strlcpy(config.store.sntp2,val, 35);
return;
}
if (strcmp(cmd, "sntp1") == 0) {
strlcpy(config.store.sntp1,val, 35);
bool tzdone=false;
if(strlen(config.store.sntp1)>0 && strlen(config.store.sntp2)>0){
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2);
tzdone=true;
}else if(strlen(config.store.sntp1)>0){
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1);
tzdone=true;
}
if(tzdone){
network.requestTimeSync(true);
config.save();
}
return;
}
if (strcmp(cmd, "volsteps") == 0) {
uint8_t valb=atoi(val);
config.store.volsteps=valb;
config.save();
return;
}
if (strcmp(cmd, "encacceleration") == 0) {
uint16_t valb=atoi(val);
setEncAcceleration(valb);
config.store.encacc=valb;
config.save();
return;
}
if (strcmp(cmd, "irtlp") == 0) {
uint8_t valb=atoi(val);
setIRTolerance(valb);
return;
}
if (strcmp(cmd, "showweather") == 0) {
uint8_t valb=atoi(val);
config.store.showweather=valb==1;
config.save();
display.showWeather();
#ifdef USE_NEXTION
nextion.startWeather();
#endif
display.putRequest({NEWMODE, CLEAR});
display.putRequest({NEWMODE, PLAYER});
return;
}
if (strcmp(cmd, "lat") == 0) {
strlcpy(config.store.weatherlat,val, 10);
return;
}
if (strcmp(cmd, "lon") == 0) {
strlcpy(config.store.weatherlon,val, 10);
return;
}
if (strcmp(cmd, "key") == 0) {
strlcpy(config.store.weatherkey,val, 64);
config.save();
display.showWeather();
#ifdef USE_NEXTION
nextion.startWeather();
#endif
display.putRequest({NEWMODE, CLEAR});
display.putRequest({NEWMODE, PLAYER});
return;
}
if (strcmp(cmd, "reset") == 0) {
if (strcmp(val, "system") == 0) {
config.store.smartstart=2;
config.store.audioinfo=false;
config.store.vumeter=false;
config.store.softapdelay=0;
config.save();
display.putRequest({NEWMODE, CLEAR});
display.putRequest({NEWMODE, PLAYER});
requestOnChange(GETSYSTEM,clientId);
return;
}
if (strcmp(val, "screen") == 0) {
config.store.flipscreen=false;
display.flip();
config.store.invertdisplay=false;
display.invert();
config.store.dspon=true;
config.store.brightness=100;
config.setBrightness(false);
config.store.contrast=55;
display.setContrast();
config.store.numplaylist=false;
config.save();
display.putRequest({NEWMODE, CLEAR});
display.putRequest({NEWMODE, PLAYER});
requestOnChange(GETSCREEN,clientId);
return;
}
if (strcmp(val, "timezone") == 0) {
config.store.tzHour=3;
config.store.tzMin=0;
strlcpy(config.store.sntp1,"pool.ntp.org", 35);
strlcpy(config.store.sntp2,"0.ru.pool.ntp.org", 35);
config.save();
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2);
network.requestTimeSync(true);
requestOnChange(GETTIMEZONE,clientId);
return;
}
if (strcmp(val, "weather") == 0) {
config.store.showweather=0;
strlcpy(config.store.weatherlat,"55.7512", 10);
strlcpy(config.store.weatherlon,"37.6184", 10);
strlcpy(config.store.weatherkey,"", 64);
config.save();
display.showWeather();
#ifdef USE_NEXTION
nextion.startWeather();
#endif
display.putRequest({NEWMODE, CLEAR});
display.putRequest({NEWMODE, PLAYER});
requestOnChange(GETWEATHER,clientId);
return;
}
if (strcmp(val, "controls") == 0) {
config.store.volsteps=1;
config.store.fliptouch=false;
config.store.dbgtouch=false;
setEncAcceleration(200);
setIRTolerance(40);
requestOnChange(GETCONTROLS,clientId);
return;
}
}
if (strcmp(cmd, "volume") == 0) { if (strcmp(cmd, "volume") == 0) {
byte v = atoi(val); byte v = atoi(val);
player.setVol(v, false); player.setVol(v, false);
} }
/* REMOVE FROM POST
* if (request->hasParam("trebble", true)) {
AsyncWebParameter* pt = request->getParam("trebble", true);
AsyncWebParameter* pm = request->getParam("middle", true);
AsyncWebParameter* pb = request->getParam("bass", true);
int t = atoi(pt->value().c_str());
int m = atoi(pm->value().c_str());
int b = atoi(pb->value().c_str());
//setTone(int8_t gainLowPass, int8_t gainBandPass, int8_t gainHighPass)
player.setTone(b, m, t);
config.setTone(b, m, t);
netserver.requestOnChange(EQUALIZER, 0);
request->send(200);
return;
}
if (request->hasParam("ballance", true)) {
AsyncWebParameter* p = request->getParam("ballance", true);
int b = atoi(p->value().c_str());
player.setBalance(b);
config.setBalance(b);
netserver.requestOnChange(BALANCE, 0);
request->send(200);
return;
}
*/
if (strcmp(cmd, "balance") == 0) {
int8_t valb=atoi(val);
player.setBalance(valb);
config.setBalance(valb);
netserver.requestOnChange(BALANCE, 0);
return;
}
if (strcmp(cmd, "treble") == 0) {
int8_t valb=atoi(val);
player.setTone(config.store.bass, config.store.middle, valb);
config.setTone(config.store.bass, config.store.middle, valb);
netserver.requestOnChange(EQUALIZER, 0);
return;
}
if (strcmp(cmd, "middle") == 0) {
int8_t valb=atoi(val);
player.setTone(config.store.bass, valb, config.store.trebble);
config.setTone(config.store.bass, valb, config.store.trebble);
netserver.requestOnChange(EQUALIZER, 0);
return;
}
if (strcmp(cmd, "bass") == 0) {
int8_t valb=atoi(val);
player.setTone(valb, config.store.middle, config.store.trebble);
config.setTone(valb, config.store.middle, config.store.trebble);
netserver.requestOnChange(EQUALIZER, 0);
return;
}
if (strcmp(cmd, "submitplaylist") == 0) {
if(player.isRunning()){
player.toggle();
while (player.isRunning()) {
vTaskDelay(10);
}
vTaskDelay(50);
resumePlay=true;
}
return;
}
if (strcmp(cmd, "submitplaylistdone") == 0) {
if(resumePlay){
vTaskDelay(100);
player.toggle();
resumePlay=false;
}
return;
}
#if IR_PIN!=255 #if IR_PIN!=255
if (strcmp(cmd, "irbtn") == 0) { if (strcmp(cmd, "irbtn") == 0) {
config.irindex=atoi(val); config.irindex=atoi(val);
@@ -264,7 +640,7 @@ bool NetServer::importPlaylist() {
} }
void NetServer::requestOnChange(requestType_e request, uint8_t clientId) { void NetServer::requestOnChange(requestType_e request, uint8_t clientId) {
char buf[BUFLEN + 50] = { 0 }; char buf[BUFLEN * 2] = { 0 };
switch (request) { switch (request) {
case PLAYLIST: { case PLAYLIST: {
getPlaylist(clientId); getPlaylist(clientId);
@@ -279,6 +655,90 @@ void NetServer::requestOnChange(requestType_e request, uint8_t clientId) {
#endif #endif
break; break;
} }
case GETACTIVE: {
bool dbgact = false;
String act="\"group_wifi\",";
if (network.status == CONNECTED) {
act+="\"group_system\",";
if(BRIGHTNESS_PIN!=255 || DSP_FLIPPED==1 || DSP_MODEL==DSP_NOKIA5110 || dbgact){
act+="\"group_display\",";
}
#ifdef USE_NEXTION
act+="\"group_nextion\",";
if (WEATHER_READY==0 || dbgact){
act+="\"group_weather\",";
}
#endif
if(VU_READY==1 || dbgact){
act+="\"group_vu\",";
}
if(BRIGHTNESS_PIN!=255 || dbgact){
act+="\"group_brightness\",";
}
if(DSP_FLIPPED==1 || dbgact){
act+="\"group_tft\",";
}
if(TS_CS!=255 || dbgact){
act+="\"group_touch\",";
}
if(DSP_MODEL==DSP_NOKIA5110){
act+="\"group_nokia\",";
}
if(DSP_MODEL!=DSP_DUMMY || dbgact){
act+="\"group_timezone\",";
}
if (WEATHER_READY==1 || dbgact){
act+="\"group_weather\",";
}
act+="\"group_controls\",";
if(ENC_BTNL!=255 || ENC2_BTNL!=255 || dbgact){
act+="\"group_encoder\",";
}
if(IR_PIN!=255 || dbgact){
act+="\"group_ir\",";
}
}
act = act.substring(0, act.length()-1);
sprintf (buf, "{\"act\":[%s]}", act.c_str());
break;
}
case GETMODE: {
sprintf (buf, "{\"pmode\":\"%s\"}", network.status == CONNECTED?"player":"ap");
break;
}
case GETINDEX: {
requestOnChange(STATION, clientId);
requestOnChange(TITLE, clientId);
requestOnChange(VOLUME, clientId);
requestOnChange(EQUALIZER, clientId);
requestOnChange(BALANCE, clientId);
requestOnChange(BITRATE, clientId);
requestOnChange(MODE, clientId);
//playlistrequest = clientId; /* Cleanup this */
return;
break;
}
case GETSYSTEM: {
sprintf (buf, "{\"sst\":%d,\"aif\":%d,\"vu\":%d,\"softr\":%d}", config.store.smartstart!=2, config.store.audioinfo, config.store.vumeter, config.store.softapdelay);
break;
}
case GETSCREEN: {
sprintf (buf, "{\"flip\":%d,\"inv\":%d,\"nump\":%d,\"tsf\":%d,\"tsd\":%d,\"dspon\":%d,\"br\":%d,\"con\":%d}", config.store.flipscreen, config.store.invertdisplay, config.store.numplaylist, config.store.fliptouch, config.store.dbgtouch, config.store.dspon, config.store.brightness, config.store.contrast);
break;
}
case GETTIMEZONE: {
sprintf (buf, "{\"tzh\":%d,\"tzm\":%d,\"sntp1\":\"%s\",\"sntp2\":\"%s\"}", config.store.tzHour, config.store.tzMin, config.store.sntp1, config.store.sntp2);
break;
}
case GETWEATHER: {
sprintf (buf, "{\"wen\":%d,\"wlat\":\"%s\",\"wlon\":\"%s\",\"wkey\":\"%s\"}", config.store.showweather, config.store.weatherlat, config.store.weatherlon, config.store.weatherkey);
break;
}
case GETCONTROLS: {
sprintf (buf, "{\"vols\":%d,\"enca\":%d,\"irtl\":%d}", config.store.volsteps, config.store.encacc, config.store.irtlp);
break;
}
case STATION: { case STATION: {
sprintf (buf, "{\"nameset\": \"%s\"}", config.station.name); sprintf (buf, "{\"nameset\": \"%s\"}", config.station.name);
requestOnChange(ITEM, clientId); requestOnChange(ITEM, clientId);
@@ -343,22 +803,6 @@ String processor(const String& var) { // %Templates%
if (var == "VERSION") { if (var == "VERSION") {
return VERSION; return VERSION;
} }
if (var == "SSID") {
ssidCount++;
return String(config.ssids[ssidCount - 1].ssid);
}
if (var == "PASS") {
return String(config.ssids[ssidCount - 1].password);
}
if (var == "APMODE") {
return network.status == CONNECTED ? "" : " style=\"display: none!important\"";
}
if (var == "NOTAPMODE") {
return network.status == CONNECTED ? " hidden" : "";
}
if (var == "IRMODE") {
return IR_PIN == 255 ? "" : " ir";
}
return String(); return String();
} }
@@ -381,22 +825,21 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp
switch (type) { switch (type) {
case WS_EVT_CONNECT: case WS_EVT_CONNECT:
if(config.store.audioinfo) Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str()); if(config.store.audioinfo) Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
/*netserver.requestOnChange(STATION, client->id());
netserver.requestOnChange(STATION, client->id());
netserver.requestOnChange(TITLE, client->id()); netserver.requestOnChange(TITLE, client->id());
netserver.requestOnChange(VOLUME, client->id()); netserver.requestOnChange(VOLUME, client->id());
netserver.requestOnChange(EQUALIZER, client->id()); netserver.requestOnChange(EQUALIZER, client->id());
netserver.requestOnChange(BALANCE, client->id()); netserver.requestOnChange(BALANCE, client->id());
netserver.requestOnChange(BITRATE, client->id()); netserver.requestOnChange(BITRATE, client->id());
netserver.requestOnChange(MODE, client->id()); netserver.requestOnChange(MODE, client->id());
netserver.playlistrequest = client->id(); netserver.playlistrequest = client->id();*/
break; break;
case WS_EVT_DISCONNECT: case WS_EVT_DISCONNECT:
if(config.store.audioinfo) Serial.printf("WebSocket client #%u disconnected\n", client->id()); if(config.store.audioinfo) Serial.printf("WebSocket client #%u disconnected\n", client->id());
break; break;
case WS_EVT_DATA: case WS_EVT_DATA:
netserver.onWsMessage(arg, data, len); netserver.onWsMessage(arg, data, len, client->id());
break; break;
case WS_EVT_PONG: case WS_EVT_PONG:
case WS_EVT_ERROR: case WS_EVT_ERROR:

View File

@@ -5,7 +5,7 @@
#include "ESPAsyncWebServer.h" #include "ESPAsyncWebServer.h"
#include "AsyncUDP.h" #include "AsyncUDP.h"
enum requestType_e { PLAYLIST, STATION, ITEM, TITLE, VOLUME, NRSSI, BITRATE, MODE, EQUALIZER, BALANCE, PLAYLISTSAVED }; enum requestType_e { PLAYLIST, STATION, ITEM, TITLE, VOLUME, NRSSI, BITRATE, MODE, EQUALIZER, BALANCE, PLAYLISTSAVED, GETMODE, GETINDEX, GETACTIVE, GETSYSTEM, GETSCREEN, GETTIMEZONE, GETWEATHER, GETCONTROLS };
class NetServer { class NetServer {
public: public:
@@ -18,8 +18,10 @@ class NetServer {
void loop(); void loop();
void requestOnChange(requestType_e request, uint8_t clientId); void requestOnChange(requestType_e request, uint8_t clientId);
void setRSSI(int val); void setRSSI(int val);
void onWsMessage(void *arg, uint8_t *data, size_t len); void onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t clientId);
bool savePlaylist(const char* post); bool savePlaylist(const char* post);
void takeMallocDog();
void giveMallocDog();
#if IR_PIN!=255 #if IR_PIN!=255
bool irRecordEnable; bool irRecordEnable;
void irToWs(const char* protocol, uint64_t irvalue); void irToWs(const char* protocol, uint64_t irvalue);

View File

@@ -62,13 +62,19 @@ void Network::begin() {
digitalWrite(LED_BUILTIN, LOW); digitalWrite(LED_BUILTIN, LOW);
status = CONNECTED; status = CONNECTED;
WiFi.setSleep(false); WiFi.setSleep(false);
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), SNTP_SERVER); //configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), SNTP_SERVER);
//getLocalTime(&timeinfo); if(strlen(config.store.sntp1)>0 && strlen(config.store.sntp2)>0){
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2);
}else if(strlen(config.store.sntp1)>0){
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1);
}
////getLocalTime(&timeinfo);
stimer.once_ms(200,getFirstTime); stimer.once_ms(200,getFirstTime);
ntimer.attach_ms(TSYNC_DELAY, syncTime); ntimer.attach_ms(TSYNC_DELAY, syncTime);
#ifdef USE_NEXTION #ifdef USE_NEXTION
nextion.startWeather(); nextion.startWeather();
#endif #endif
display.updateWeather();
if (network_on_connect) network_on_connect(); if (network_on_connect) network_on_connect();
} }
@@ -91,7 +97,6 @@ void Network::raiseSoftAP() {
WiFi.softAP(apSsid, apPassword); WiFi.softAP(apSsid, apPassword);
Serial.printf("\n\nRunning in AP mode.\nConnect to AP %s with password %s for settings.\n\n", apSsid, apPassword); Serial.printf("\n\nRunning in AP mode.\nConnect to AP %s with password %s for settings.\n\n", apSsid, apPassword);
status = SOFT_AP; status = SOFT_AP;
#if SOFT_AP_REBOOT_DELAY>0 if(config.store.softapdelay>0)
rtimer.attach_ms(SOFT_AP_REBOOT_DELAY, rebootTime); rtimer.attach_ms(config.store.softapdelay*1000*60, rebootTime);
#endif
} }

View File

@@ -1,7 +1,7 @@
#ifndef options_h #ifndef options_h
#define options_h #define options_h
#define VERSION "0.7.017" #define VERSION "0.7.330"
/******************************************************* /*******************************************************
DO NOT EDIT THIS FILE. DO NOT EDIT THIS FILE.
@@ -64,22 +64,13 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#ifndef NEXTION_TX #ifndef NEXTION_TX
#define NEXTION_TX 255 #define NEXTION_TX 255
#endif #endif
#ifndef NEXTION_WEATHER_LAT
#define NEXTION_WEATHER_LAT "55.7512"
#endif
#ifndef NEXTION_WEATHER_LON
#define NEXTION_WEATHER_LON "37.6184"
#endif
#ifndef NEXTION_WEATHER_KEY
#define NEXTION_WEATHER_KEY ""
#endif
/* OLED I2C DISPLAY */ /* OLED I2C DISPLAY */
#ifndef I2C_SDA #ifndef I2C_SDA
#define I2C_SDA 13 #define I2C_SDA 21
#endif #endif
#ifndef I2C_SCL #ifndef I2C_SCL
#define I2C_SCL 14 #define I2C_SCL 22
#endif #endif
#ifndef I2C_RST #ifndef I2C_RST
#define I2C_RST -1 #define I2C_RST -1
@@ -176,12 +167,6 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#ifndef TS_CS #ifndef TS_CS
#define TS_CS 255 #define TS_CS 255
#endif #endif
#ifndef TS_ROTATE
#define TS_ROTATE 1
#endif
#ifndef TS_DBG
#define TS_DBG false
#endif
/* LCD DISPLAY */ /* LCD DISPLAY */
#ifndef LCD_RS #ifndef LCD_RS
@@ -209,49 +194,23 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#endif #endif
/* Other settings. You can overwrite them in the myoptions.h file */ /* Other settings. You can overwrite them in the myoptions.h file */
#ifndef TFT_ROTATE
#define TFT_ROTATE 3 // display rotation. 0 - 0, 1 - 90, 2 - 180, 3 - 270 degrees
#endif
#ifndef TFT_CONTRAST
#define TFT_CONTRAST 55 // Nokia 5110 contrast
#endif
#ifndef TFT_INVERT
#define TFT_INVERT true // invert the display colors (usually true)
#endif
#ifndef VOL_STEP
#define VOL_STEP 1 // Encoder vol step
#endif
#ifndef VOL_ACCELERATION
#define VOL_ACCELERATION 200 // Encoder vol acceleration; 0 or 1 means disabled acceleration
#endif
#ifndef MUTE_PIN #ifndef MUTE_PIN
#define MUTE_PIN 255 // MUTE Pin #define MUTE_PIN 255 // MUTE Pin
#endif #endif
#ifndef MUTE_VAL #ifndef MUTE_VAL
#define MUTE_VAL HIGH // Write this to MUTE_PIN when player is stopped #define MUTE_VAL HIGH // Write this to MUTE_PIN when player is stopped
#endif #endif
#ifndef BRIGHTNESS_PIN
#define BRIGHTNESS_PIN 255 // BRIGHTNESS Pin
#endif
#ifndef PLAYER_FORCE_MONO #ifndef PLAYER_FORCE_MONO
#define PLAYER_FORCE_MONO false // mono option - false stereo, true mono #define PLAYER_FORCE_MONO false // mono option - false stereo, true mono
#endif #endif
#ifndef SNTP_SERVER
#define SNTP_SERVER "pool.ntp.org", "0.ru.pool.ntp.org" // custom ntp servers min 1 max 3 comma separated values
#endif
#ifndef I2S_INTERNAL #ifndef I2S_INTERNAL
#define I2S_INTERNAL false // If true - use esp32 internal DAC #define I2S_INTERNAL false // If true - use esp32 internal DAC
#endif #endif
#ifndef SOFT_AP_REBOOT_DELAY #ifndef ROTATE_90
#define SOFT_AP_REBOOT_DELAY 0 // Delay in ms after which ESP is rebooting if it is in softAP mode (0 - disabled) #define ROTATE_90 false // Optional 90 degree rotation for square displays
#endif
#ifndef ENABLE_VU_METER
#define ENABLE_VU_METER false // enable? vu meter for some displays
/*
* !!! Important !!!
* if you enable this feathure on the esp32 wroom, due to lack of memory, you must modify the file Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp
* replace the line 221
* xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
* with
* xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 / 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
*/
#endif #endif
/* /*
*** ST7735 display submodel *** *** ST7735 display submodel ***
@@ -273,8 +232,5 @@ INITR_REDTAB
#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_TLP
#define IR_TLP 40 // kTolerancePercentage, see IRremoteESP8266 documentation
#endif
#endif #endif

View File

@@ -156,14 +156,14 @@ void Player::toggle() {
void Player::stepVol(bool up) { void Player::stepVol(bool up) {
if (up) { if (up) {
if (config.store.volume <= 254 - VOL_STEP) { if (config.store.volume <= 254 - config.store.volsteps) {
setVol(config.store.volume + VOL_STEP, false); setVol(config.store.volume + config.store.volsteps, false);
}else{ }else{
setVol(254, false); setVol(254, false);
} }
} else { } else {
if (config.store.volume >= VOL_STEP) { if (config.store.volume >= config.store.volsteps) {
setVol(config.store.volume - VOL_STEP, false); setVol(config.store.volume - config.store.volsteps, false);
}else{ }else{
setVol(0, false); setVol(0, false);
} }

View File

@@ -545,7 +545,7 @@ void TFT_22_ILI9225::clear() {
} }
void TFT_22_ILI9225::invert(boolean flag) { void TFT_22_ILI9225::invertDisplay(boolean flag) {
startWrite(); startWrite();
_writeCommand16(flag ? ILI9225C_INVON : ILI9225C_INVOFF); _writeCommand16(flag ? ILI9225C_INVON : ILI9225C_INVOFF);
//_writeCommand(0x00, flag ? ILI9225C_INVON : ILI9225C_INVOFF); //_writeCommand(0x00, flag ? ILI9225C_INVON : ILI9225C_INVOFF);

View File

@@ -186,7 +186,7 @@ class TFT_22_ILI9225 {
/// Invert screen /// Invert screen
/// @param flag true to invert, false for normal screen /// @param flag true to invert, false for normal screen
void invert(boolean flag); void invertDisplay(boolean flag);
/// Switch backlight on or off /// Switch backlight on or off
/// @param flag true=on, false=off /// @param flag true=on, false=off

View File

@@ -1569,7 +1569,6 @@ void Audio::setDefaults(){
* \n The VU meter takes about 0.2MHz of processing power with 48 kHz samplerate. * \n The VU meter takes about 0.2MHz of processing power with 48 kHz samplerate.
*/ */
void Audio::setVUmeter() { void Audio::setVUmeter() {
// if(!ENABLE_VU_METER) return;
uint16_t MP3Status = read_register(SCI_STATUS); uint16_t MP3Status = read_register(SCI_STATUS);
if(MP3Status==0) { if(MP3Status==0) {
Serial.println("VS1053 Error: Unable to write SCI_STATUS"); Serial.println("VS1053 Error: Unable to write SCI_STATUS");
@@ -1593,7 +1592,6 @@ void Audio::setVUmeter() {
* \warning This feature is only available with patches that support VU meter. * \warning This feature is only available with patches that support VU meter.
*/ */
void Audio::getVUlevel() { void Audio::getVUlevel() {
// if(!ENABLE_VU_METER) return;
if(!_vuInitalized) return; if(!_vuInitalized) return;
int16_t reg = read_register(SCI_AICTRL3); int16_t reg = read_register(SCI_AICTRL3);
uint8_t rl = map((uint8_t)reg, 85, 92, 0, 255); uint8_t rl = map((uint8_t)reg, 85, 92, 0, 255);

View File

@@ -15,6 +15,8 @@
#define SCROLLTIME 60 #define SCROLLTIME 60
#endif #endif
#define DSP_FLIPPED 0
class DspCore { class DspCore {
public: public:
DspCore(); DspCore();

View File

@@ -12,11 +12,7 @@
#define DEF_SPI_FREQ 24000000 /* set it to 0 for system default */ #define DEF_SPI_FREQ 24000000 /* set it to 0 for system default */
#endif #endif
#if ENABLE_VU_METER
#define CLOCK_DELTA 16 #define CLOCK_DELTA 16
#else
#define CLOCK_DELTA 0
#endif
#define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY) #define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY)
#define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl) #define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl)
@@ -120,12 +116,9 @@ void DspCore::apScreen() {
void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) {
begin(DEF_SPI_FREQ); begin(DEF_SPI_FREQ);
cp437(true); cp437(true);
invertDisplay(!TFT_INVERT); invert();
fillScreen(TFT_BG); fillScreen(TFT_BG);
byte tftRotate = TFT_ROTATE; flip();
if(tftRotate>1) tftRotate=3;
if(tftRotate==0) tftRotate=1;
setRotation(tftRotate);
setTextWrap(false); setTextWrap(false);
screenwidth = width(); screenwidth = width();
screenheight = height(); screenheight = height();
@@ -239,15 +232,16 @@ void DspCore::printClock(struct tm timeinfo, bool dots, bool redraw){
char timeBuf[50] = { 0 }; char timeBuf[50] = { 0 };
char tmpBuf[4] = { 0 }; char tmpBuf[4] = { 0 };
uint16_t ncwidth, ncheight; uint16_t ncwidth, ncheight;
uint16_t clockdelta=config.store.vumeter?CLOCK_DELTA:0;
strftime(timeBuf, sizeof(timeBuf), "%H %M", &timeinfo); strftime(timeBuf, sizeof(timeBuf), "%H %M", &timeinfo);
setTextSize(1); setTextSize(1);
setFont(&DS_DIGI28pt7b); setFont(&DS_DIGI28pt7b);
if(strstr(oldTimeBuf, timeBuf)==NULL || redraw){ if(strstr(oldTimeBuf, timeBuf)==NULL || redraw){
getTextBounds(oldTimeBuf, 0, 0, &x, &y, &wot, &hot); getTextBounds(oldTimeBuf, 0, 0, &x, &y, &wot, &hot);
setCursor((swidth - wot) / 2 - 4 + CLOCK_DELTA, clockY+28+6); setCursor((swidth - wot) / 2 - 4 + clockdelta, clockY+28+6);
setTextColor(TFT_BG); setTextColor(TFT_BG);
print(oldTimeBuf); print(oldTimeBuf);
dot = (swidth - wot) / 2 - 4 + CLOCK_DELTA; dot = (swidth - wot) / 2 - 4 + clockdelta;
/* dots */ /* dots */
strlcpy(tmpBuf, oldTimeBuf, 3); strlcpy(tmpBuf, oldTimeBuf, 3);
getTextBounds(tmpBuf, 0, 0, &x, &y, &ncwidth, &ncheight); getTextBounds(tmpBuf, 0, 0, &x, &y, &ncwidth, &ncheight);
@@ -260,8 +254,8 @@ void DspCore::printClock(struct tm timeinfo, bool dots, bool redraw){
setTextSize(1); setTextSize(1);
getTextBounds(timeBuf, 0, 0, &x, &y, &ncwidth, &ncheight); getTextBounds(timeBuf, 0, 0, &x, &y, &ncwidth, &ncheight);
setTextColor(TFT_LOGO); setTextColor(TFT_LOGO);
setCursor((swidth - ncwidth) / 2 - 4 + CLOCK_DELTA, clockY+28+6); setCursor((swidth - ncwidth) / 2 - 4 + clockdelta, clockY+28+6);
dot = (swidth - ncwidth) / 2 - 4 + CLOCK_DELTA; dot = (swidth - ncwidth) / 2 - 4 + clockdelta;
setTextSize(1); setTextSize(1);
print(timeBuf); print(timeBuf);
/* dots */ /* dots */
@@ -384,5 +378,11 @@ void DspCore::printText(const char* txt) {
void DspCore::loop(bool force) { void DspCore::loop(bool force) {
} }
void DspCore::flip(){
setRotation(config.store.flipscreen?1:3);
}
void DspCore::invert(){
invertDisplay(config.store.invertdisplay);
}
#endif #endif

View File

@@ -7,6 +7,8 @@
#include "../Adafruit_GC9106Ex/Adafruit_GC9106Ex.h" #include "../Adafruit_GC9106Ex/Adafruit_GC9106Ex.h"
#include "fonts/DS_DIGI28pt7b.h" #include "fonts/DS_DIGI28pt7b.h"
#define VU_READY 1
#define TFT_LINEHGHT 10 #define TFT_LINEHGHT 10
#define TFT_FRAMEWDT 0 #define TFT_FRAMEWDT 0
@@ -58,6 +60,8 @@ class DspCore: public Adafruit_GC9106Ex {
void loop(bool force=false); void loop(bool force=false);
virtual void startWrite(void); virtual void startWrite(void);
virtual void endWrite(void); virtual void endWrite(void);
void flip();
void invert();
/*virtual void sendCommand(uint8_t commandByte, uint8_t *dataBytes, /*virtual void sendCommand(uint8_t commandByte, uint8_t *dataBytes,
uint8_t numDataBytes); uint8_t numDataBytes);
virtual void sendCommand(uint8_t commandByte, const uint8_t *dataBytes = NULL, virtual void sendCommand(uint8_t commandByte, const uint8_t *dataBytes = NULL,

View File

@@ -190,10 +190,10 @@ void DspCore::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) {
//hspi.begin(); //hspi.begin();
begin(); begin();
invert(TFT_INVERT); invert();
setBackgroundColor(TFT_BG); setBackgroundColor(TFT_BG);
clear(); clear();
setOrientation(TFT_ROTATE); flip();
setTextSize(1); setTextSize(1);
screenwidth = maxX(); screenwidth = maxX();
screenheight = maxY(); screenheight = maxY();
@@ -449,5 +449,10 @@ void DspCore::drawRGBBitmap(int16_t x, int16_t y, const uint16_t *bitmap, int16_
drawBitmap(x, y, bitmap, w, h); drawBitmap(x, y, bitmap, w, h);
GIVE_MUTEX(); GIVE_MUTEX();
} }
void DspCore::flip(){
setOrientation(config.store.flipscreen?3:1);
}
void DspCore::invert(){
invertDisplay(config.store.invertdisplay);
}
#endif #endif

View File

@@ -5,6 +5,9 @@
#include "../ILI9225Fix/TFT_22_ILI9225Fix.h" #include "../ILI9225Fix/TFT_22_ILI9225Fix.h"
#include "fonts/DS_DIGI28pt7b.h" #include "fonts/DS_DIGI28pt7b.h"
#define VU_READY 1
#define WEATHER_READY 1
#define TFT_LINEHGHT 10 #define TFT_LINEHGHT 10
#define TFT_FRAMEWDT 4 #define TFT_FRAMEWDT 4
#define META_SIZE 2 #define META_SIZE 2
@@ -73,6 +76,8 @@ class DspCore: public TFT_22_ILI9225 {
int16_t width(void) { return (int16_t)maxX(); } int16_t width(void) { return (int16_t)maxX(); }
int16_t height(void) { return (int16_t)maxY(); } int16_t height(void) { return (int16_t)maxY(); }
void drawRGBBitmap(int16_t x, int16_t y, const uint16_t *bitmap, int16_t w, int16_t h); void drawRGBBitmap(int16_t x, int16_t y, const uint16_t *bitmap, int16_t w, int16_t h);
void flip();
void invert();
private: private:
uint16_t swidth, sheight; uint16_t swidth, sheight;
uint16_t bgcolor, fgcolor; uint16_t bgcolor, fgcolor;

View File

@@ -113,10 +113,10 @@ void DspCore::apScreen() {
void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) {
begin(); /* SPI_DEFAULT_FREQ 40000000 */ begin(); /* SPI_DEFAULT_FREQ 40000000 */
invertDisplay(TFT_INVERT); invert();
cp437(true); cp437(true);
fillScreen(TFT_BG); fillScreen(TFT_BG);
setRotation(TFT_ROTATE); flip();
setTextWrap(false); setTextWrap(false);
setTextSize(1); setTextSize(1);
screenwidth = width(); screenwidth = width();
@@ -385,5 +385,11 @@ void DspCore::printText(const char* txt) {
void DspCore::loop(bool force) { void DspCore::loop(bool force) {
} }
void DspCore::flip(){
setRotation(config.store.flipscreen?1:3);
}
void DspCore::invert(){
invertDisplay(config.store.invertdisplay);
}
#endif #endif

View File

@@ -7,6 +7,9 @@
// https://tchapi.github.io/Adafruit-GFX-Font-Customiser/ // https://tchapi.github.io/Adafruit-GFX-Font-Customiser/
#include "fonts/DS_DIGI42pt7b.h" #include "fonts/DS_DIGI42pt7b.h"
#define VU_READY 1
#define WEATHER_READY 1
#define TFT_LINEHGHT 10 #define TFT_LINEHGHT 10
#define TFT_FRAMEWDT 8 #define TFT_FRAMEWDT 8
#define META_SIZE 3 #define META_SIZE 3
@@ -58,6 +61,8 @@ class DspCore: public Adafruit_ILI9341 {
void loop(bool force=false); void loop(bool force=false);
virtual void startWrite(void); virtual void startWrite(void);
virtual void endWrite(void); virtual void endWrite(void);
void flip();
void invert();
private: private:
uint16_t swidth, sheight; uint16_t swidth, sheight;
char oldTimeBuf[20]; char oldTimeBuf[20];

View File

@@ -3,6 +3,8 @@
#include "Arduino.h" #include "Arduino.h"
#define DSP_FLIPPED 0
#if DSP_MODEL==DSP_2004 || DSP_MODEL==DSP_2004I2C #if DSP_MODEL==DSP_2004 || DSP_MODEL==DSP_2004I2C
#define LCD_2004 #define LCD_2004
#endif #endif
@@ -89,6 +91,8 @@ class DspCore: public LiquidCrystal {
void ip(const char* str); void ip(const char* str);
void drawPlaylist(uint16_t currentItem, char* currentItemText); void drawPlaylist(uint16_t currentItem, char* currentItemText);
void loop(bool force=false); void loop(bool force=false);
void flip(){};
void invert(){};
private: private:
uint16_t swidth, sheight, xOffset, yOffset; uint16_t swidth, sheight, xOffset, yOffset;
int16_t nextX; int16_t nextX;

View File

@@ -134,13 +134,11 @@ void DspCore::data(uint8_t c) {
void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) {
begin(); begin();
setContrast(TFT_CONTRAST); setContrast(config.store.contrast);
cp437(true); cp437(true);
invert();
fillScreen(TFT_BG); fillScreen(TFT_BG);
byte tftRotate = TFT_ROTATE; flip();
if(tftRotate>2) tftRotate=2;
if(tftRotate==1) tftRotate=0;
setRotation(tftRotate);
setTextWrap(false); setTextWrap(false);
screenwidth = width(); screenwidth = width();
screenheight = height(); screenheight = height();
@@ -339,5 +337,11 @@ boolean DspCore::checkdelay(int m, unsigned long &tstamp) {
return false; return false;
} }
} }
void DspCore::flip(){
setRotation(config.store.flipscreen?2:0);
}
void DspCore::invert(){
invertDisplay(config.store.invertdisplay);
}
#endif #endif

View File

@@ -58,6 +58,8 @@ class DspCore: public Adafruit_PCD8544 {
void loop(bool force=false); void loop(bool force=false);
virtual void command(uint8_t c); virtual void command(uint8_t c);
virtual void data(uint8_t c); virtual void data(uint8_t c);
void flip();
void invert();
private: private:
uint16_t swidth, sheight; uint16_t swidth, sheight;
unsigned long loopdelay; unsigned long loopdelay;

View File

@@ -142,12 +142,8 @@ void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) {
} }
cp437(true); cp437(true);
fillScreen(TFT_BG); fillScreen(TFT_BG);
byte tftRotate = TFT_ROTATE; flip();
#if DSP_MODEL==DSP_SH1107 invert();
if(tftRotate>=2) tftRotate=3;
if(tftRotate==0) tftRotate=1;
#endif
setRotation(tftRotate);
setTextWrap(false); setTextWrap(false);
screenwidth = width(); screenwidth = width();
screenheight = height(); screenheight = height();
@@ -348,5 +344,16 @@ boolean DspCore::checkdelay(int m, unsigned long &tstamp) {
return false; return false;
} }
} }
void DspCore::flip(){
#if DSP_MODEL==DSP_SH1107
setRotation(config.store.flipscreen?3:1);
#endif
#if DSP_MODEL==DSP_SH1106
setRotation(config.store.flipscreen?2:0);
#endif
}
void DspCore::invert(){
invertDisplay(config.store.invertdisplay);
}
#endif #endif

View File

@@ -57,6 +57,8 @@ class DspCore: public Adafruit_SH1107 {
void ip(const char* str); void ip(const char* str);
void drawPlaylist(uint16_t currentItem, char* currentItemText); void drawPlaylist(uint16_t currentItem, char* currentItemText);
void loop(bool force=false); void loop(bool force=false);
void flip();
void invert();
private: private:
uint16_t swidth, sheight; uint16_t swidth, sheight;
unsigned long loopdelay; unsigned long loopdelay;

View File

@@ -144,7 +144,8 @@ void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) {
} }
cp437(true); cp437(true);
fillScreen(TFT_BG); fillScreen(TFT_BG);
setRotation(TFT_ROTATE); flip();
invert();
setTextWrap(false); setTextWrap(false);
screenwidth = width(); screenwidth = width();
screenheight = height(); screenheight = height();
@@ -332,5 +333,11 @@ boolean DspCore::checkdelay(int m, unsigned long &tstamp) {
return false; return false;
} }
} }
void DspCore::flip(){
setRotation(config.store.flipscreen?2:0);
}
void DspCore::invert(){
invertDisplay(config.store.invertdisplay);
}
#endif #endif

View File

@@ -5,6 +5,8 @@
#include <Adafruit_GFX.h> #include <Adafruit_GFX.h>
#include <Adafruit_SSD1305.h> #include <Adafruit_SSD1305.h>
#define WEATHER_READY 0
#define TFT_LINEHGHT 8 #define TFT_LINEHGHT 8
#define TFT_FRAMEWDT 0 #define TFT_FRAMEWDT 0
@@ -51,6 +53,8 @@ class DspCore: public Adafruit_SSD1305 {
void ip(const char* str); void ip(const char* str);
void drawPlaylist(uint16_t currentItem, char* currentItemText); void drawPlaylist(uint16_t currentItem, char* currentItemText);
void loop(bool force=false); void loop(bool force=false);
void flip();
void invert();
private: private:
uint16_t swidth, sheight; uint16_t swidth, sheight;
unsigned long loopdelay; unsigned long loopdelay;

View File

@@ -141,10 +141,8 @@ void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) {
} }
cp437(true); cp437(true);
fillScreen(TFT_BG); fillScreen(TFT_BG);
byte tftRotate = TFT_ROTATE; flip();
if(tftRotate>2) tftRotate=2; invert();
if(tftRotate==1) tftRotate=0;
setRotation(tftRotate);
setTextWrap(false); setTextWrap(false);
screenwidth = width(); screenwidth = width();
screenheight = height(); screenheight = height();
@@ -355,5 +353,11 @@ boolean DspCore::checkdelay(int m, unsigned long &tstamp) {
return false; return false;
} }
} }
void DspCore::flip(){
setRotation(config.store.flipscreen?2:0);
}
void DspCore::invert(){
invertDisplay(config.store.invertdisplay);
}
#endif #endif

View File

@@ -71,6 +71,8 @@ class DspCore: public Adafruit_SSD1306 {
void ip(const char* str); void ip(const char* str);
void drawPlaylist(uint16_t currentItem, char* currentItemText); void drawPlaylist(uint16_t currentItem, char* currentItemText);
void loop(bool force=false); void loop(bool force=false);
void flip();
void invert();
private: private:
uint16_t swidth, sheight; uint16_t swidth, sheight;
unsigned long loopdelay; unsigned long loopdelay;

View File

@@ -123,7 +123,8 @@ void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) {
} }
cp437(true); cp437(true);
fillScreen(TFT_BG); fillScreen(TFT_BG);
setRotation(TFT_ROTATE); flip();
invert();
setTextWrap(false); setTextWrap(false);
screenwidth = width(); screenwidth = width();
screenheight = height(); screenheight = height();
@@ -401,5 +402,15 @@ boolean DspCore::checkdelay(int m, unsigned long &tstamp) {
return false; return false;
} }
} }
void DspCore::flip(){
if(ROTATE_90){
setRotation(config.store.flipscreen?3:1);
}else{
setRotation(config.store.flipscreen?2:0);
}
}
void DspCore::invert(){
invertDisplay(config.store.invertdisplay);
}
#endif #endif

View File

@@ -6,6 +6,8 @@
#include <Adafruit_SSD1327.h> #include <Adafruit_SSD1327.h>
#include "fonts/DS_DIGI28pt7b.h" #include "fonts/DS_DIGI28pt7b.h"
#define WEATHER_READY 1
#define TFT_LINEHGHT 10 #define TFT_LINEHGHT 10
#define TFT_FRAMEWDT 4 #define TFT_FRAMEWDT 4
@@ -13,26 +15,9 @@
#define PLMITEMLENGHT 40 #define PLMITEMLENGHT 40
#define PLMITEMHEIGHT 22 #define PLMITEMHEIGHT 22
#define TITLE_TOP2 TFT_FRAMEWDT + 3 * TFT_LINEHGHT #define TITLE_TOP2 TFT_FRAMEWDT + 3 * TFT_LINEHGHT
/*
#ifdef DSP_FPS
#if DSP_FPS!=0
#define SCROLLDELTA (DSP_FPS>30)?3:(80/DSP_FPS)
#define SCROLLTIME (DSP_FPS>30)?34:(1000/DSP_FPS)
#else
#define SCROLLDELTA 4
#define SCROLLTIME 83
#define LOOP_DELAY 83
#endif
#else
#define SCROLLDELTA 4
#define SCROLLTIME 83
#define LOOP_DELAY 40
#endif
*/
#if !defined(SCROLLDELTA) || !defined(SCROLLTIME) #if !defined(SCROLLDELTA) || !defined(SCROLLTIME)
/*#define SCROLLDELTA 5
#define SCROLLTIME 83
#define LOOP_DELAY 100*/
#define SCROLLDELTA 2 #define SCROLLDELTA 2
#define SCROLLTIME 30 #define SCROLLTIME 30
#define LOOP_DELAY 33 #define LOOP_DELAY 33
@@ -70,6 +55,8 @@ class DspCore: public Adafruit_SSD1327 {
void ip(const char* str); void ip(const char* str);
void drawPlaylist(uint16_t currentItem, char* currentItemText); void drawPlaylist(uint16_t currentItem, char* currentItemText);
void loop(bool force=false); void loop(bool force=false);
void flip();
void invert();
private: private:
uint16_t swidth, sheight; uint16_t swidth, sheight;
int16_t x, y; int16_t x, y;

View File

@@ -13,11 +13,9 @@
#include "../../network.h" #include "../../network.h"
#ifndef DEF_SPI_FREQ #ifndef DEF_SPI_FREQ
#define DEF_SPI_FREQ 40000000UL /* set it to 0 for system default */ #define DEF_SPI_FREQ 26000000UL /* set it to 0 for system default */
#endif #endif
#if ENABLE_VU_METER
#if DTYPE==INITR_BLACKTAB #if DTYPE==INITR_BLACKTAB
#define CLOCK_DELTA 12 #define CLOCK_DELTA 12
#elif DTYPE==INITR_MINI160x80 #elif DTYPE==INITR_MINI160x80
@@ -26,10 +24,6 @@
#define CLOCK_DELTA 0 #define CLOCK_DELTA 0
#endif #endif
#else // !ENABLE_VU_METER
#define CLOCK_DELTA 0
#endif
#define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY) #define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY)
#define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl) #define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl)
@@ -133,9 +127,9 @@ void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) {
initR(DTYPE); initR(DTYPE);
if(DEF_SPI_FREQ > 0) setSPISpeed(DEF_SPI_FREQ); if(DEF_SPI_FREQ > 0) setSPISpeed(DEF_SPI_FREQ);
cp437(true); cp437(true);
invertDisplay((DTYPE==INITR_MINI160x80)?TFT_INVERT:!TFT_INVERT); invert();
fillScreen(TFT_BG); fillScreen(TFT_BG);
setRotation(TFT_ROTATE); flip();
setTextWrap(false); setTextWrap(false);
screenwidth = width(); screenwidth = width();
screenheight = height(); screenheight = height();
@@ -270,15 +264,16 @@ void DspCore::printClock(struct tm timeinfo, bool dots, bool redraw){
char timeBuf[50] = { 0 }; char timeBuf[50] = { 0 };
char tmpBuf[4] = { 0 }; char tmpBuf[4] = { 0 };
uint16_t ncwidth, ncheight; uint16_t ncwidth, ncheight;
uint16_t clockdelta=config.store.vumeter?CLOCK_DELTA:0;
strftime(timeBuf, sizeof(timeBuf), "%H %M", &timeinfo); strftime(timeBuf, sizeof(timeBuf), "%H %M", &timeinfo);
setTextSize(1); setTextSize(1);
setFont(&DS_DIGI28pt7b); setFont(&DS_DIGI28pt7b);
if(strstr(oldTimeBuf, timeBuf)==NULL || redraw){ if(strstr(oldTimeBuf, timeBuf)==NULL || redraw){
getTextBounds(oldTimeBuf, 0, 0, &x, &y, &wot, &hot); getTextBounds(oldTimeBuf, 0, 0, &x, &y, &wot, &hot);
setCursor((swidth - wot) / 2 - 4 + CLOCK_DELTA, clockY+28+6); setCursor((swidth - wot) / 2 - 4 + clockdelta, clockY+28+6);
setTextColor(TFT_BG); setTextColor(TFT_BG);
print(oldTimeBuf); print(oldTimeBuf);
dot = (swidth - wot) / 2 - 4 + CLOCK_DELTA; dot = (swidth - wot) / 2 - 4 + clockdelta;
/* dots */ /* dots */
strlcpy(tmpBuf, oldTimeBuf, 3); strlcpy(tmpBuf, oldTimeBuf, 3);
getTextBounds(tmpBuf, 0, 0, &x, &y, &ncwidth, &ncheight); getTextBounds(tmpBuf, 0, 0, &x, &y, &ncwidth, &ncheight);
@@ -291,8 +286,8 @@ void DspCore::printClock(struct tm timeinfo, bool dots, bool redraw){
setTextSize(1); setTextSize(1);
getTextBounds(timeBuf, 0, 0, &x, &y, &ncwidth, &ncheight); getTextBounds(timeBuf, 0, 0, &x, &y, &ncwidth, &ncheight);
setTextColor(TFT_LOGO); setTextColor(TFT_LOGO);
setCursor((swidth - ncwidth) / 2 - 4 + CLOCK_DELTA, clockY+28+6); setCursor((swidth - ncwidth) / 2 - 4 + clockdelta, clockY+28+6);
dot = (swidth - ncwidth) / 2 - 4 + CLOCK_DELTA; dot = (swidth - ncwidth) / 2 - 4 + clockdelta;
setTextSize(1); setTextSize(1);
print(timeBuf); print(timeBuf);
/* dots */ /* dots */
@@ -406,5 +401,15 @@ void DspCore::printText(const char* txt) {
void DspCore::loop(bool force) { void DspCore::loop(bool force) {
} }
void DspCore::flip(){
if(ROTATE_90){
setRotation(config.store.flipscreen?2:0);
}else{
setRotation(config.store.flipscreen?3:1);
}
}
void DspCore::invert(){
invertDisplay((DTYPE==INITR_MINI160x80)?!config.store.invertdisplay:config.store.invertdisplay);
}
#endif #endif

View File

@@ -6,6 +6,9 @@
#include <Adafruit_ST7735.h> #include <Adafruit_ST7735.h>
#include "fonts/DS_DIGI28pt7b.h" #include "fonts/DS_DIGI28pt7b.h"
#define VU_READY 1
#define WEATHER_READY 1
#define TFT_LINEHGHT 10 #define TFT_LINEHGHT 10
#if DTYPE==INITR_MINI160x80 #if DTYPE==INITR_MINI160x80
#define TFT_FRAMEWDT 0 #define TFT_FRAMEWDT 0
@@ -69,6 +72,8 @@ class DspCore: public Adafruit_ST7735 {
void loop(bool force=false); void loop(bool force=false);
virtual void startWrite(void); virtual void startWrite(void);
virtual void endWrite(void); virtual void endWrite(void);
void flip();
void invert();
private: private:
uint16_t swidth, sheight; uint16_t swidth, sheight;
char oldTimeBuf[20]; char oldTimeBuf[20];

View File

@@ -117,10 +117,10 @@ void DspCore::apScreen() {
void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) { void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) {
init(240,(DSP_MODEL==DSP_ST7789)?320:240); init(240,(DSP_MODEL==DSP_ST7789)?320:240);
if(DEF_SPI_FREQ > 0) setSPISpeed(DEF_SPI_FREQ); if(DEF_SPI_FREQ > 0) setSPISpeed(DEF_SPI_FREQ);
invertDisplay(TFT_INVERT); invert();
cp437(true); cp437(true);
fillScreen(TFT_BG); fillScreen(TFT_BG);
setRotation(TFT_ROTATE); flip();
setTextWrap(false); setTextWrap(false);
setTextSize(1); setTextSize(1);
screenwidth = width(); screenwidth = width();
@@ -382,5 +382,20 @@ void DspCore::printText(const char* txt) {
void DspCore::loop(bool force) { void DspCore::loop(bool force) {
} }
void DspCore::flip(){
#if DSP_MODEL==DSP_ST7789
setRotation(config.store.flipscreen?3:1);
#endif
#if DSP_MODEL==DSP_ST7789_240
if(ROTATE_90){
setRotation(config.store.flipscreen?3:1);
}else{
setRotation(config.store.flipscreen?2:0);
}
#endif
}
void DspCore::invert(){
invertDisplay(config.store.invertdisplay);
}
#endif #endif

View File

@@ -7,6 +7,9 @@
// https://tchapi.github.io/Adafruit-GFX-Font-Customiser/ // https://tchapi.github.io/Adafruit-GFX-Font-Customiser/
#include "fonts/DS_DIGI42pt7b.h" #include "fonts/DS_DIGI42pt7b.h"
#define VU_READY 1
#define WEATHER_READY 1
#define TFT_LINEHGHT 10 #define TFT_LINEHGHT 10
#define TFT_FRAMEWDT 8 #define TFT_FRAMEWDT 8
#define META_SIZE 3 #define META_SIZE 3
@@ -58,6 +61,8 @@ class DspCore: public Adafruit_ST7789 {
void loop(bool force=false); void loop(bool force=false);
virtual void startWrite(void); virtual void startWrite(void);
virtual void endWrite(void); virtual void endWrite(void);
void flip();
void invert();
private: private:
uint16_t swidth, sheight; uint16_t swidth, sheight;
char oldTimeBuf[20]; char oldTimeBuf[20];

View File

@@ -320,12 +320,22 @@ void Nextion::loop() {
} }
if (sscanf(rxbuf, "tzhour=%d", &scanDigit) == 1){ if (sscanf(rxbuf, "tzhour=%d", &scanDigit) == 1){
config.setTimezone((int8_t)scanDigit, config.store.tzMin); config.setTimezone((int8_t)scanDigit, config.store.tzMin);
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), SNTP_SERVER); //configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), SNTP_SERVER);
if(strlen(config.store.sntp1)>0 && strlen(config.store.sntp2)>0){
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2);
}else if(strlen(config.store.sntp1)>0){
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1);
}
network.requestTimeSync(true); network.requestTimeSync(true);
} }
if (sscanf(rxbuf, "tzmin=%d", &scanDigit) == 1){ if (sscanf(rxbuf, "tzmin=%d", &scanDigit) == 1){
config.setTimezone(config.store.tzHour, (int8_t)scanDigit); config.setTimezone(config.store.tzHour, (int8_t)scanDigit);
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), SNTP_SERVER); //configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), SNTP_SERVER);
if(strlen(config.store.sntp1)>0 && strlen(config.store.sntp2)>0){
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1, config.store.sntp2);
}else if(strlen(config.store.sntp1)>0){
configTime(config.store.tzHour * 3600 + config.store.tzMin * 60, config.getTimezoneOffset(), config.store.sntp1);
}
network.requestTimeSync(true); network.requestTimeSync(true);
} }
if (sscanf(rxbuf, "audioinfo=%d", &scanDigit) == 1){ if (sscanf(rxbuf, "audioinfo=%d", &scanDigit) == 1){
@@ -558,7 +568,7 @@ bool Nextion::getForecast(){
return false; return false;
} }
char httpget[250] = {0}; char httpget[250] = {0};
sprintf(httpget, "GET /data/2.5/weather?lat=%s&lon=%s&units=metric&lang=ru&appid=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", NEXTION_WEATHER_LAT, NEXTION_WEATHER_LON, NEXTION_WEATHER_KEY, host); sprintf(httpget, "GET /data/2.5/weather?lat=%s&lon=%s&units=metric&lang=ru&appid=%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", config.store.weatherlat, config.store.weatherlon, config.store.weatherkey, host);
client.print(httpget); client.print(httpget);
unsigned long timeout = millis(); unsigned long timeout = millis();
while (client.available() == 0) { while (client.available() == 0) {
@@ -684,6 +694,10 @@ void Nextion::getWeather(void * pvParameters){
} }
void Nextion::updateWeather() { void Nextion::updateWeather() {
if(strlen(config.store.weatherkey)==0 || !config.store.showweather) {
nextion.weatherVisible(0);
return;
}
xTaskCreatePinnedToCore( xTaskCreatePinnedToCore(
nextion.getWeather, /* Task function. */ nextion.getWeather, /* Task function. */
"nextiongetWeather", /* name of task. */ "nextiongetWeather", /* name of task. */
@@ -691,15 +705,11 @@ void Nextion::updateWeather() {
NULL, /* parameter of the task */ NULL, /* parameter of the task */
0, /* priority of the task */ 0, /* priority of the task */
&nextion.weatherUpdateTaskHandle, /* Task handle to keep track of created task */ &nextion.weatherUpdateTaskHandle, /* Task handle to keep track of created task */
0); /* pin task to core CORE_FOR_LOOP_CONTROLS */ 0); /* pin task to core 0 */
} }
void Nextion::startWeather(){ void Nextion::startWeather(){
if(strlen(NEXTION_WEATHER_KEY)==0) { updateWeather();
Serial.println("## OPENWEATHERMAP ###: ERROR: NEXTION_WEATHER_KEY not configured");
return;
}
updateWeather(); /* pin task to core CORE_FOR_LOOP_CONTROLS */
} }
/* /*