Browse Source

fix wakeup issue, once wifi was lost during night the communication didn't start in the morning

reenabled FlashStringHelper because of lacking RAM
complete rewrite of monochrome display class, thx to @dAjaY85 -> displays are now configurable in setup
pull/635/head
lumapu 2 years ago
parent
commit
2b3f252bbf
  1. 2
      .github/workflows/compile_development.yml
  2. 2
      .github/workflows/compile_release.yml
  3. 5
      src/CHANGES.md
  4. 20
      src/app.cpp
  5. 14
      src/app.h
  6. 2
      src/config/config.h
  7. 62
      src/config/settings.h
  8. 2
      src/defines.h
  9. 16
      src/hm/hmInverter.h
  10. 112
      src/platformio.ini
  11. 411
      src/plugins/MonochromeDisplay/MonochromeDisplay.h
  12. 2
      src/utils/dbg.h
  13. 13
      src/web/RestApi.h
  14. 151
      src/web/html/setup.html
  15. 11
      src/web/web.h
  16. 25
      src/wifi/ahoywifi.cpp
  17. 4
      src/wifi/ahoywifi.h

2
.github/workflows/compile_development.yml

@ -47,7 +47,7 @@ jobs:
run: python convert.py run: python convert.py
- name: Run PlatformIO - name: Run PlatformIO
run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp8266-sh1106 --environment esp32-wroom32-release --environment esp32-wroom32-nokia5110 --environment esp32-wroom32-ssd1306 --environment esp32-wroom32-sh1106 run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release
- name: Rename Binary files - name: Rename Binary files
id: rename-binary-files id: rename-binary-files

2
.github/workflows/compile_release.yml

@ -51,7 +51,7 @@ jobs:
run: python convert.py run: python convert.py
- name: Run PlatformIO - name: Run PlatformIO
run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp8266-sh1106 --environment esp32-wroom32-release --environment esp32-wroom32-nokia5110 --environment esp32-wroom32-ssd1306 --environment esp32-wroom32-sh1106 run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release
- name: Rename Binary files - name: Rename Binary files
id: rename-binary-files id: rename-binary-files

5
src/CHANGES.md

@ -2,6 +2,11 @@
(starting from release version `0.5.66`) (starting from release version `0.5.66`)
## 0.5.75
* fix wakeup issue, once wifi was lost during night the communication didn't start in the morning
* reenabled FlashStringHelper because of lacking RAM
* complete rewrite of monochrome display class, thx to @dAjaY85 -> displays are now configurable in setup
## 0.5.74 ## 0.5.74
* improved payload handling (retransmit all fragments on CRC error) * improved payload handling (retransmit all fragments on CRC error)
* improved `isAvailable`, checkes all record structs, inverter becomes available more early because version is check first * improved `isAvailable`, checkes all record structs, inverter becomes available more early because version is check first

20
src/app.cpp

@ -64,9 +64,8 @@ void app::setup() {
mApi.setup(this, mSys, mWeb.getWebSrvPtr(), mConfig); mApi.setup(this, mSys, mWeb.getWebSrvPtr(), mConfig);
// Plugins // Plugins
#if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) if(mConfig->plugin.display.type != 0)
mMonoDisplay.setup(&mConfig->plugin.display, mSys, &mTimestamp); mMonoDisplay.setup(&mConfig->plugin.display, mSys, &mTimestamp, 0xff, mVersion);
#endif
mPubSerial.setup(mConfig, mSys, &mTimestamp); mPubSerial.setup(mConfig, mSys, &mTimestamp);
@ -133,6 +132,7 @@ void app::onWifi(bool gotIp) {
mInnerLoopCb = std::bind(&app::loopStandard, this); mInnerLoopCb = std::bind(&app::loopStandard, this);
mSendTickerId = every(std::bind(&app::tickSend, this), mConfig->nrf.sendInterval, "tSend"); mSendTickerId = every(std::bind(&app::tickSend, this), mConfig->nrf.sendInterval, "tSend");
mMqttReconnect = true; mMqttReconnect = true;
mSunrise = 0; // needs to be set to 0, to reinstall sunrise and ivComm tickers!
once(std::bind(&app::tickNtpUpdate, this), 2, "ntp2"); once(std::bind(&app::tickNtpUpdate, this), 2, "ntp2");
} }
else { else {
@ -146,27 +146,27 @@ void app::regularTickers(void) {
DPRINTLN(DBG_DEBUG, F("regularTickers")); DPRINTLN(DBG_DEBUG, F("regularTickers"));
everySec(std::bind(&WebType::tickSecond, &mWeb), "webSc"); everySec(std::bind(&WebType::tickSecond, &mWeb), "webSc");
// Plugins // Plugins
#if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) if(mConfig->plugin.display.type != 0)
everySec(std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay), "disp"); everySec(std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay), "disp");
#endif
every(std::bind(&PubSerialType::tick, &mPubSerial), mConfig->serial.interval, "uart"); every(std::bind(&PubSerialType::tick, &mPubSerial), mConfig->serial.interval, "uart");
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void app::tickNtpUpdate(void) { void app::tickNtpUpdate(void) {
uint32_t nxtTrig = 5; // default: check again in 5 sec uint32_t nxtTrig = 5; // default: check again in 5 sec
if (mWifi.getNtpTime(&nxtTrig)) { if (mWifi.getNtpTime()) {
if (mMqttReconnect && mMqttEnabled) { if (mMqttReconnect && mMqttEnabled) {
mMqtt.connect(); mMqtt.connect();
everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt), "mqttS"); everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt), "mqttS");
everyMin(std::bind(&PubMqttType::tickerMinute, &mMqtt), "mqttM"); everyMin(std::bind(&PubMqttType::tickerMinute, &mMqtt), "mqttM");
uint32_t nxtTrig = mTimestamp - ((mTimestamp - 1) % 86400) + 86400; // next midnight if(mConfig->mqtt.rstYieldMidNight) {
if(mConfig->mqtt.rstYieldMidNight) uint32_t midTrig = mTimestamp - ((mTimestamp - 1) % 86400) + 86400; // next midnight
onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "midNi"); onceAt(std::bind(&app::tickMidnight, this), midTrig, "midNi");
}
mMqttReconnect = false; mMqttReconnect = false;
} }
nxtTrig = 43200; nxtTrig = 43200; // check again in 12h
if((mSunrise == 0) && (mConfig->sun.lat) && (mConfig->sun.lon)) { if((mSunrise == 0) && (mConfig->sun.lat) && (mConfig->sun.lon)) {
mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600;

14
src/app.h

@ -46,10 +46,8 @@ typedef PubMqtt<HmSystemType> PubMqttType;
typedef PubSerial<HmSystemType> PubSerialType; typedef PubSerial<HmSystemType> PubSerialType;
// PLUGINS // PLUGINS
#if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106) #include "plugins/MonochromeDisplay/MonochromeDisplay.h"
#include "plugins/MonochromeDisplay/MonochromeDisplay.h" typedef MonochromeDisplay<HmSystemType> MonoDisplayType;
typedef MonochromeDisplay<HmSystemType> MonoDisplayType;
#endif
class app : public IApp, public ah::Scheduler { class app : public IApp, public ah::Scheduler {
@ -180,10 +178,8 @@ class app : public IApp, public ah::Scheduler {
void setTimestamp(uint32_t newTime) { void setTimestamp(uint32_t newTime) {
DPRINTLN(DBG_DEBUG, F("setTimestamp: ") + String(newTime)); DPRINTLN(DBG_DEBUG, F("setTimestamp: ") + String(newTime));
if(0 == newTime) { if(0 == newTime)
uint32_t tmp; mWifi.getNtpTime();
mWifi.getNtpTime(&tmp);
}
else else
Scheduler::setTimestamp(newTime); Scheduler::setTimestamp(newTime);
} }
@ -269,9 +265,7 @@ class app : public IApp, public ah::Scheduler {
uint32_t mSunrise, mSunset; uint32_t mSunrise, mSunset;
// plugins // plugins
#if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106)
MonoDisplayType mMonoDisplay; MonoDisplayType mMonoDisplay;
#endif
}; };
#endif /*__APP_H__*/ #endif /*__APP_H__*/

2
src/config/config.h

@ -52,8 +52,6 @@
#define DEF_CE_PIN 2 #define DEF_CE_PIN 2
#define DEF_IRQ_PIN 0 #define DEF_IRQ_PIN 0
#endif #endif
#define DEF_LED0_PIN 255 // off
#define DEF_LED1_PIN 255 // off
// default NRF24 power, possible values (0 - 3) // default NRF24 power, possible values (0 - 3)
#define DEF_AMPLIFIERPOWER 1 #define DEF_AMPLIFIERPOWER 1

62
src/config/settings.h

@ -17,6 +17,7 @@
* More info: * More info:
* https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout * https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout
* */ * */
#define DEF_PIN_OFF 255
#define PROT_MASK_INDEX 0x0001 #define PROT_MASK_INDEX 0x0001
@ -117,10 +118,15 @@ typedef struct {
} cfgInst_t; } cfgInst_t;
typedef struct { typedef struct {
uint8_t type;
bool pwrSaveAtIvOffline; bool pwrSaveAtIvOffline;
uint32_t wakeUp; bool logoEn;
uint32_t sleepAt; bool pxShift;
uint16_t wakeUp;
uint16_t sleepAt;
uint8_t contrast; uint8_t contrast;
uint8_t pin0;
uint8_t pin1;
} display_t; } display_t;
typedef struct { typedef struct {
@ -216,14 +222,15 @@ class settings {
DeserializationError err = deserializeJson(root, fp); DeserializationError err = deserializeJson(root, fp);
if(!err && (root.size() > 0)) { if(!err && (root.size() > 0)) {
mCfg.valid = true; mCfg.valid = true;
jsonWifi(root["wifi"]); jsonWifi(root[F("wifi")]);
jsonNrf(root["nrf"]); jsonNrf(root[F("nrf")]);
jsonNtp(root["ntp"]); jsonNtp(root[F("ntp")]);
jsonSun(root["sun"]); jsonSun(root[F("sun")]);
jsonSerial(root["serial"]); jsonSerial(root[F("serial")]);
jsonMqtt(root["mqtt"]); jsonMqtt(root[F("mqtt")]);
jsonLed(root["led"]); jsonLed(root[F("led")]);
jsonInst(root["inst"]); jsonPlugin(root[F("plugin")]);
jsonInst(root[F("inst")]);
success = true; success = true;
} }
else { else {
@ -252,6 +259,7 @@ class settings {
jsonSerial(root.createNestedObject(F("serial")), true); jsonSerial(root.createNestedObject(F("serial")), true);
jsonMqtt(root.createNestedObject(F("mqtt")), true); jsonMqtt(root.createNestedObject(F("mqtt")), true);
jsonLed(root.createNestedObject(F("led")), true); jsonLed(root.createNestedObject(F("led")), true);
jsonPlugin(root.createNestedObject(F("plugin")), true);
jsonInst(root.createNestedObject(F("inst")), true); jsonInst(root.createNestedObject(F("inst")), true);
if(0 == serializeJson(root, fp)) { if(0 == serializeJson(root, fp)) {
@ -323,13 +331,17 @@ class settings {
mCfg.mqtt.rstValsNotAvail = false; mCfg.mqtt.rstValsNotAvail = false;
mCfg.mqtt.rstValsCommStop = false; mCfg.mqtt.rstValsCommStop = false;
mCfg.led.led0 = DEF_LED0_PIN; mCfg.led.led0 = DEF_PIN_OFF;
mCfg.led.led1 = DEF_LED1_PIN; mCfg.led.led1 = DEF_PIN_OFF;
memset(&mCfg.inst, 0, sizeof(cfgInst_t)); memset(&mCfg.inst, 0, sizeof(cfgInst_t));
mCfg.plugin.display.pwrSaveAtIvOffline = false; mCfg.plugin.display.pwrSaveAtIvOffline = false;
mCfg.plugin.display.contrast = 60; mCfg.plugin.display.contrast = 60;
mCfg.plugin.display.logoEn = true;
mCfg.plugin.display.pxShift = true;
mCfg.plugin.display.pin0 = DEF_PIN_OFF; // SCL
mCfg.plugin.display.pin1 = DEF_PIN_OFF; // SDA
} }
void jsonWifi(JsonObject obj, bool set = false) { void jsonWifi(JsonObject obj, bool set = false) {
@ -452,6 +464,32 @@ class settings {
} }
} }
void jsonPlugin(JsonObject obj, bool set = false) {
if(set) {
JsonObject disp = obj.createNestedObject("disp");
disp[F("type")] = mCfg.plugin.display.type;
disp[F("pwrSafe")] = (bool)mCfg.plugin.display.pwrSaveAtIvOffline;
disp[F("logo")] = (bool)mCfg.plugin.display.logoEn;
disp[F("pxShift")] = (bool)mCfg.plugin.display.pxShift;
disp[F("wake")] = mCfg.plugin.display.wakeUp;
disp[F("sleep")] = mCfg.plugin.display.sleepAt;
disp[F("contrast")] = mCfg.plugin.display.contrast;
disp[F("pin0")] = mCfg.plugin.display.pin0;
disp[F("pin1")] = mCfg.plugin.display.pin1;
} else {
JsonObject disp = obj["disp"];
mCfg.plugin.display.type = disp[F("type")];
mCfg.plugin.display.pwrSaveAtIvOffline = (bool) disp[F("pwrSafe")];
mCfg.plugin.display.logoEn = (bool) disp[F("logo")];
mCfg.plugin.display.pxShift = (bool) disp[F("pxShift")];
mCfg.plugin.display.wakeUp = disp[F("wake")];
mCfg.plugin.display.sleepAt = disp[F("sleep")];
mCfg.plugin.display.contrast = disp[F("contrast")];
mCfg.plugin.display.pin0 = disp[F("pin0")];
mCfg.plugin.display.pin1 = disp[F("pin1")];
}
}
void jsonInst(JsonObject obj, bool set = false) { void jsonInst(JsonObject obj, bool set = false) {
if(set) if(set)
obj[F("en")] = (bool)mCfg.inst.enabled; obj[F("en")] = (bool)mCfg.inst.enabled;

2
src/defines.h

@ -13,7 +13,7 @@
//------------------------------------- //-------------------------------------
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 5 #define VERSION_MINOR 5
#define VERSION_PATCH 74 #define VERSION_PATCH 75
//------------------------------------- //-------------------------------------
typedef struct { typedef struct {

16
src/hm/hmInverter.h

@ -315,6 +315,22 @@ class Inverter {
return true; return true;
} }
REC_TYP getChannelFieldValue(uint8_t channel, uint8_t fieldId, record_t<> *rec) {
uint8_t pos = 0;
if(NULL != rec) {
for(; pos < rec->length; pos++) {
if((rec->assign[pos].ch == channel) && (rec->assign[pos].fieldId == fieldId))
break;
}
if(pos >= rec->length)
return 0;
return rec->record[pos];
}
else
return 0;
}
REC_TYP getValue(uint8_t pos, record_t<> *rec) { REC_TYP getValue(uint8_t pos, record_t<> *rec) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getValue")); DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getValue"));
if(NULL == rec) if(NULL == rec)

112
src/platformio.ini

@ -38,6 +38,8 @@ lib_deps =
paulstoffregen/Time paulstoffregen/Time
https://github.com/bertmelis/espMqttClient#v1.3.3 https://github.com/bertmelis/espMqttClient#v1.3.3
bblanchon/ArduinoJson bblanchon/ArduinoJson
https://github.com/JChristensen/Timezone
olikraus/U8g2
;esp8266/DNSServer ;esp8266/DNSServer
;esp8266/EEPROM ;esp8266/EEPROM
;esp8266/ESP8266WiFi ;esp8266/ESP8266WiFi
@ -89,60 +91,6 @@ monitor_filters =
time ; Add timestamp with milliseconds for each new line time ; Add timestamp with milliseconds for each new line
log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory
[env:esp8266-nokia5110]
platform = espressif8266
board = esp12e
board_build.f_cpu = 80000000L
build_flags = -D RELEASE -DU8X8_NO_HW_I2C -DENA_NOKIA
monitor_filters =
;default ; Remove typical terminal control codes from input
time ; Add timestamp with milliseconds for each new line
;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory
lib_deps =
https://github.com/yubox-node-org/ESPAsyncWebServer
nrf24/RF24
paulstoffregen/Time
https://github.com/bertmelis/espMqttClient#v1.3.3
bblanchon/ArduinoJson
https://github.com/JChristensen/Timezone
olikraus/U8g2
[env:esp8266-ssd1306]
platform = espressif8266
board = esp12e
board_build.f_cpu = 80000000L
build_flags = -D RELEASE -DENA_SSD1306
monitor_filters =
;default ; Remove typical terminal control codes from input
time ; Add timestamp with milliseconds for each new line
;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory
lib_deps =
https://github.com/yubox-node-org/ESPAsyncWebServer
nrf24/RF24
paulstoffregen/Time
https://github.com/bertmelis/espMqttClient#v1.3.3
bblanchon/ArduinoJson
https://github.com/JChristensen/Timezone
olikraus/U8g2
[env:esp8266-sh1106]
platform = espressif8266
board = esp12e
board_build.f_cpu = 80000000L
build_flags = -D RELEASE -DENA_SH1106
monitor_filters =
;default ; Remove typical terminal control codes from input
time ; Add timestamp with milliseconds for each new line
;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory
lib_deps =
https://github.com/yubox-node-org/ESPAsyncWebServer
nrf24/RF24
paulstoffregen/Time
https://github.com/bertmelis/espMqttClient#v1.3.3
bblanchon/ArduinoJson
https://github.com/JChristensen/Timezone
olikraus/U8g2
[env:esp32-wroom32-release] [env:esp32-wroom32-release]
platform = espressif32 platform = espressif32
board = lolin_d32 board = lolin_d32
@ -163,59 +111,3 @@ monitor_filters =
;default ; Remove typical terminal control codes from input ;default ; Remove typical terminal control codes from input
time ; Add timestamp with milliseconds for each new line time ; Add timestamp with milliseconds for each new line
log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory
[env:esp32-wroom32-nokia5110]
platform = espressif32
board = lolin_d32
build_flags = -D RELEASE -std=gnu++14 -DU8X8_NO_HW_I2C -DENA_NOKIA
build_unflags = -std=gnu++11
monitor_filters =
;default ; Remove typical terminal control codes from input
time ; Add timestamp with milliseconds for each new line
;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory
lib_deps =
https://github.com/yubox-node-org/ESPAsyncWebServer
nrf24/RF24
paulstoffregen/Time
https://github.com/bertmelis/espMqttClient#v1.3.3
bblanchon/ArduinoJson
https://github.com/JChristensen/Timezone
olikraus/U8g2
[env:esp32-wroom32-ssd1306]
platform = espressif32
board = lolin_d32
build_flags = -D RELEASE -std=gnu++14 -DENA_SSD1306
build_unflags = -std=gnu++11
monitor_filters =
;default ; Remove typical terminal control codes from input
time ; Add timestamp with milliseconds for each new line
;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory
lib_deps =
https://github.com/yubox-node-org/ESPAsyncWebServer
nrf24/RF24
paulstoffregen/Time
https://github.com/bertmelis/espMqttClient#v1.3.3
bblanchon/ArduinoJson
https://github.com/ThingPulse/esp8266-oled-ssd1306.git
https://github.com/JChristensen/Timezone
olikraus/U8g2
[env:esp32-wroom32-sh1106]
platform = espressif32
board = lolin_d32
build_flags = -D RELEASE -std=gnu++14 -DENA_SH1106
build_unflags = -std=gnu++11
monitor_filters =
;default ; Remove typical terminal control codes from input
time ; Add timestamp with milliseconds for each new line
;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory
lib_deps =
https://github.com/yubox-node-org/ESPAsyncWebServer
nrf24/RF24
paulstoffregen/Time
https://github.com/bertmelis/espMqttClient#v1.3.3
bblanchon/ArduinoJson
https://github.com/ThingPulse/esp8266-oled-ssd1306.git
https://github.com/JChristensen/Timezone
olikraus/U8g2

411
src/plugins/MonochromeDisplay/MonochromeDisplay.h

@ -1,46 +1,41 @@
#ifndef __MONOCHROME_DISPLAY__ #ifndef __MONOCHROME_DISPLAY__
#define __MONOCHROME_DISPLAY__ #define __MONOCHROME_DISPLAY__
/* esp8266 : SCL = 5, SDA = 4 */
/* ewsp32 : SCL = 22, SDA = 21 */
#if defined(ENA_NOKIA) || defined(ENA_SSD1306) || defined(ENA_SH1106)
#include <U8g2lib.h> #include <U8g2lib.h>
#ifdef ENA_NOKIA
#define DISP_PROGMEM U8X8_PROGMEM
#else // ENA_SSD1306 || ENA_SH1106
#define DISP_PROGMEM PROGMEM
#endif
#include <Timezone.h> #include <Timezone.h>
#include "../../utils/helper.h" #include "../../utils/helper.h"
#include "../../hm/hmSystem.h" #include "../../hm/hmSystem.h"
#define DISP_DEFAULT_TIMEOUT 60 // in seconds
static uint8_t bmp_logo[] PROGMEM = { static uint8_t bmp_logo[] PROGMEM = {
B00000000,B00000000, // ................ B00000000, B00000000, // ................
B11101100,B00110111, // ..##.######.##.. B11101100, B00110111, // ..##.######.##..
B11101100,B00110111, // ..##.######.##.. B11101100, B00110111, // ..##.######.##..
B11100000,B00000111, // .....######..... B11100000, B00000111, // .....######.....
B11010000,B00001011, // ....#.####.#.... B11010000, B00001011, // ....#.####.#....
B10011000,B00011001, // ...##..##..##... B10011000, B00011001, // ...##..##..##...
B10000000,B00000001, // .......##....... B10000000, B00000001, // .......##.......
B00000000,B00000000, // ................ B00000000, B00000000, // ................
B01111000,B00011110, // ...####..####... B01111000, B00011110, // ...####..####...
B11111100,B00111111, // ..############.. B11111100, B00111111, // ..############..
B01111100,B00111110, // ..#####..#####.. B01111100, B00111110, // ..#####..#####..
B00000000,B00000000, // ................ B00000000, B00000000, // ................
B11111100,B00111111, // ..############.. B11111100, B00111111, // ..############..
B11111110,B01111111, // .##############. B11111110, B01111111, // .##############.
B01111110,B01111110, // .######..######. B01111110, B01111110, // .######..######.
B00000000,B00000000 // ................ B00000000, B00000000 // ................
}; };
static uint8_t bmp_arrow[] DISP_PROGMEM = { static uint8_t bmp_arrow[] PROGMEM = {
B00000000, B00011100, B00011100, B00001110, B00001110, B11111110, B01111111, B00000000, B00011100, B00011100, B00001110, B00001110, B11111110, B01111111,
B01110000, B01110000, B00110000, B00111000, B00011000, B01111111, B00111111, B01110000, B01110000, B00110000, B00111000, B00011000, B01111111, B00111111,
B00011110, B00001110, B00000110, B00000000, B00000000, B00000000, B00000000}; B00011110, B00001110, B00000110, B00000000, B00000000, B00000000, B00000000
};
static TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; // Central European Summer Time static TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; // Central European Summer Time
static TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; // Central European Standard Tim static TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; // Central European Standard Tim
@ -48,31 +43,41 @@ static TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; // Central Eu
template<class HMSYSTEM> template<class HMSYSTEM>
class MonochromeDisplay { class MonochromeDisplay {
public: public:
#ifdef ENA_NOKIA uint8_t dispContrast = 60;
MonochromeDisplay() : mDisplay(U8G2_R0, 5, 4, 16), mCE(CEST, CET) {
mNewPayload = false; MonochromeDisplay() : mCE(CEST, CET) {}
mExtra = 0;
}
#else // ENA_SSD1306 || ENA_SH1106
MonochromeDisplay() : mDisplay(U8G2_R0, SCL, SDA, U8X8_PIN_NONE), mCE(CEST, CET) {
mNewPayload = false;
mExtra = 0;
}
#endif
void setup(display_t *cfg, HMSYSTEM *sys, uint32_t *utcTs) { void setup(display_t *cfg, HMSYSTEM *sys, uint32_t *utcTs, uint8_t disp_reset, const char *version) {
mCfg = cfg; mCfg = cfg;
mSys = sys; mSys = sys;
mUtcTs = utcTs; mUtcTs = utcTs;
memset( mToday, 0, sizeof(float)*MAX_NUM_INVERTERS ); mNewPayload = false;
memset( mTotal, 0, sizeof(float)*MAX_NUM_INVERTERS ); mLoopCnt = 0;
mLastHour = 25;
mDisplay.begin(); mTimeout = DISP_DEFAULT_TIMEOUT; // power off timeout (after inverters go offline)
ShowInfoText("booting..."); if(mCfg->type) {
switch(mCfg->type) {
case 1:
mDisplay = new U8G2_PCD8544_84X48_F_4W_HW_SPI(U8G2_R0, mCfg->pin0, mCfg->pin1, disp_reset);
break;
case 2:
mDisplay = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(U8G2_R0, disp_reset, mCfg->pin0, mCfg->pin1);
break;
case 3:
mDisplay = new U8G2_SH1106_128X64_NONAME_F_HW_I2C(U8G2_R0, disp_reset, mCfg->pin0, mCfg->pin1);
break;
} }
mDisplay->begin();
void loop(void) { mIsLarge = ((mDisplay->getWidth() > 120) && (mDisplay->getHeight() > 60));
calcLineHeights();
mDisplay->clearBuffer();
mDisplay->setContrast(mCfg->contrast);
printText("Ahoy!", 0, 35);
printText(version, 3, 46);
mDisplay->sendBuffer();
}
} }
void payloadEventListener(uint8_t cmd) { void payloadEventListener(uint8_t cmd) {
@ -80,244 +85,136 @@ class MonochromeDisplay {
} }
void tickerSecond() { void tickerSecond() {
static int cnt=1; if(mCfg->pwrSaveAtIvOffline) {
if(mNewPayload || !(cnt % 10)) { if(mTimeout != 0)
cnt=1; mTimeout--;
}
if(mNewPayload || ((++mLoopCnt % 10) == 0)) {
mNewPayload = false; mNewPayload = false;
mLoopCnt = 0;
DataScreen(); DataScreen();
} }
else
cnt++;
} }
private: private:
void ShowInfoText(const char *txt) { void DataScreen() {
/* u8g2_font_open_iconic_embedded_2x_t 'D' + 'G' + 'J' */ if (mCfg->type == 0)
mDisplay.clear(); return;
mDisplay.firstPage(); if(*mUtcTs == 0)
do { return;
const char *e;
const char *p = txt; float totalPower = 0;
int y=10; float totalYieldDay = 0;
mDisplay.setFont(u8g2_font_5x8_tr); float totalYieldTotal = 0;
while(1) {
for(e=p+1; (*e && (*e != '\n')); e++); bool isprod = false;
size_t len=e-p;
mDisplay.setCursor(2,y); Inverter<> *iv;
String res=((String)p).substring(0,len); record_t<> *rec;
mDisplay.print(res); for (uint8_t i = 0; i < mSys->getNumInverters(); i++) {
if ( !*e ) iv = mSys->getInverterByPos(i);
break; rec = iv->getRecordStruct(RealTimeRunData_Debug);
p=e+1; if (iv == NULL)
y+=12; continue;
if (iv->isProducing(*mUtcTs))
isprod = true;
totalPower += iv->getChannelFieldValue(CH0, FLD_PAC, rec);
totalYieldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec);
totalYieldTotal += iv->getChannelFieldValue(CH0, FLD_YT, rec);
}
mDisplay->clearBuffer();
// Logos
// pxMovement +x (0 - 6 px)
uint8_t ex = (_mExtra % 7);
if (isprod) {
mDisplay->drawXBMP(5 + ex, 1, 8, 17, bmp_arrow);
if (mCfg->logoEn)
mDisplay->drawXBMP(mDisplay->getWidth() - 24 + ex, 2, 16, 16, bmp_logo);
}
if ((totalPower > 0) && isprod) {
mTimeout = DISP_DEFAULT_TIMEOUT;
mDisplay->setPowerSave(false);
mDisplay->setContrast(mCfg->contrast);
if (totalPower > 999)
snprintf(_fmtText, sizeof(_fmtText), "%2.1f kW", (totalPower / 1000));
else
snprintf(_fmtText, sizeof(_fmtText), "%3.0f W", totalPower);
printText(_fmtText, 0, 20);
} else {
printText("offline", 0, 25);
if(mCfg->pwrSaveAtIvOffline) {
if(mTimeout == 0)
mDisplay->setPowerSave(true);
} }
mDisplay.sendBuffer();
} while( mDisplay.nextPage() );
} }
void DataScreen(void) { snprintf(_fmtText, sizeof(_fmtText), "today: %4.0f Wh", totalYieldDay);
String timeStr = ah::getDateTimeStr(mCE.toLocal(*mUtcTs)).substring(2, 16); printText(_fmtText, 1);
int hr = timeStr.substring(9,2).toInt();
snprintf(_fmtText, sizeof(_fmtText), "total: %.1f kWh", totalYieldTotal);
printText(_fmtText, 2);
IPAddress ip = WiFi.localIP(); IPAddress ip = WiFi.localIP();
float totalYield = 0.0, totalYieldToday = 0.0, totalActual = 0.0; if (!(_mExtra % 10) && (ip)) {
char fmtText[32]; printText(ip.toString().c_str(), 3);
int ucnt=0, num_inv=0;
unsigned int pow_i[ MAX_NUM_INVERTERS ];
memset( pow_i, 0, sizeof(unsigned int)* MAX_NUM_INVERTERS );
if ( hr < mLastHour ) // next day ? reset today-values
memset( mToday, 0, sizeof(float)*MAX_NUM_INVERTERS );
mLastHour = hr;
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
Inverter<> *iv = mSys->getInverterByPos(id);
if (NULL != iv) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
uint8_t pos;
uint8_t list[] = {FLD_PAC, FLD_YT, FLD_YD};
for (uint8_t fld = 0; fld < 3; fld++) {
pos = iv->getPosByChFld(CH0, list[fld],rec);
int isprod = iv->isProducing(*mUtcTs);
if(fld == 1)
{
if ( isprod )
mTotal[num_inv] = iv->getValue(pos,rec);
totalYield += mTotal[num_inv];
}
if(fld == 2)
{
if ( isprod )
mToday[num_inv] = iv->getValue(pos,rec);
totalYieldToday += mToday[num_inv];
}
if((fld == 0) && isprod )
{
pow_i[num_inv] = iv->getValue(pos,rec);
totalActual += iv->getValue(pos,rec);
ucnt++;
}
}
num_inv++;
}
}
/* u8g2_font_open_iconic_embedded_2x_t 'D' + 'G' + 'J' */
mDisplay.clear();
mDisplay.firstPage();
do {
#ifdef ENA_NOKIA
if(ucnt) {
//=====> Actual Production
mDisplay.drawXBMP(10,1,8,17,bmp_arrow);
mDisplay.setFont(u8g2_font_logisoso16_tr);
mDisplay.setCursor(25,17);
if (totalActual>999){
sprintf(fmtText,"%2.1f",(totalActual/1000));
mDisplay.print(String(fmtText)+F(" kW"));
} else { } else {
sprintf(fmtText,"%3.0f",totalActual); // Get current time
mDisplay.print(String(fmtText)+F(" W")); if(mIsLarge)
} printText(ah::getDateTimeStr(mCE.toLocal(*mUtcTs)).c_str(), 3);
//<=======================
}
else
{
//=====> Offline
mDisplay.setFont(u8g2_font_logisoso16_tr );
mDisplay.setCursor(10,17);
mDisplay.print(String(F("offline")));
//<=======================
}
mDisplay.drawHLine(2,20,78);
mDisplay.setFont(u8g2_font_5x8_tr);
mDisplay.setCursor(5,29);
if (( num_inv < 2 ) || !(mExtra%2))
{
sprintf(fmtText,"%4.0f",totalYieldToday);
mDisplay.print(F("today ")+String(fmtText)+F(" Wh"));
mDisplay.setCursor(5,37);
sprintf(fmtText,"%.1f",totalYield);
mDisplay.print(F("total ")+String(fmtText)+F(" kWh"));
}
else
{
int id1=(mExtra/2)%(num_inv-1);
if( pow_i[id1] )
mDisplay.print(F("#")+String(id1+1)+F(" ")+String(pow_i[id1])+F(" W"));
else
mDisplay.print(F("#")+String(id1+1)+F(" -----"));
mDisplay.setCursor(5,37);
if( pow_i[id1+1] )
mDisplay.print(F("#")+String(id1+2)+F(" ")+String(pow_i[id1+1])+F(" W"));
else else
mDisplay.print(F("#")+String(id1+2)+F(" -----")); printText(ah::getTimeStr(mCE.toLocal(*mUtcTs)).c_str(), 3);
} }
if ( !(mExtra%10) && ip ) { mDisplay->sendBuffer();
mDisplay.setCursor(5,47);
mDisplay.print(ip.toString()); _mExtra++;
}
else {
mDisplay.setCursor(5,47);
mDisplay.print(timeStr);
}
#else // ENA_SSD1306
mDisplay.setContrast(mCfg->contrast);
// pxZittern in +x (0 - 8 px)
int ex = 2*( mExtra % 5 );
mDisplay.drawXBM(100+ex,2,16,16,bmp_logo);
mDisplay.setFont(u8g2_font_ncenB08_tr);
if(ucnt) {
//=====> Actual Production
mDisplay.setPowerSave(false);
displaySleep=false;
mDisplay.setFont(u8g2_font_logisoso18_tr);
mDisplay.drawXBM(10+ex,2,8,17,bmp_arrow);
mDisplay.setCursor(25+ex,20);
if (totalActual>999){
sprintf(fmtText,"%2.1f",(totalActual/1000));
mDisplay.print(String(fmtText)+F(" kW"));
} else {
sprintf(fmtText,"%3.0f",totalActual);
mDisplay.print(String(fmtText)+F(" W"));
} }
//<=======================
void calcLineHeights() {
uint8_t yOff = 0;
for(uint8_t i = 0; i < 4; i++) {
setFont(i);
yOff += (mDisplay->getMaxCharHeight() + 1);
mLineOffsets[i] = yOff;
} }
else
{
//=====> Offline
if(!displaySleep) {
displaySleepTimer = millis();
displaySleep=true;
} }
mDisplay.setFont(u8g2_font_logisoso18_tr);
mDisplay.setCursor(10+ex,20); inline void setFont(uint8_t line) {
mDisplay.print(String(F("offline"))); switch (line) {
if(mCfg->pwrSaveAtIvOffline) { case 0: mDisplay->setFont((mIsLarge) ? u8g2_font_ncenB14_tr : u8g2_font_lubBI14_tr); break;
if ((millis() - displaySleepTimer) > displaySleepDelay) case 3: mDisplay->setFont(u8g2_font_5x8_tr); break;
mDisplay.setPowerSave(true); default: mDisplay->setFont((mIsLarge) ? u8g2_font_ncenB10_tr : u8g2_font_5x8_tr); break;
} }
//<=======================
} }
mDisplay.drawLine(2+ex, 23, 123, 23);
mDisplay.setFont(u8g2_font_ncenB10_tr); void printText(const char* text, uint8_t line, uint8_t dispX = 5) {
mDisplay.setCursor(2+ex,36); if(!mIsLarge)
if (( num_inv < 2 ) || !(mExtra%2)) dispX = 5;
{ setFont(line);
//=====> Today & Total Production if(mCfg->pxShift)
sprintf(fmtText,"%5.0f",totalYieldToday); dispX += (_mExtra % 7); // add pixel movement
mDisplay.print(F("today: ")+String(fmtText)+F(" Wh")); mDisplay->drawStr(dispX, mLineOffsets[line], text);
mDisplay.setCursor(2+ex,50);
sprintf(fmtText,"%.1f",totalYield);
mDisplay.print(F("total: ")+String(fmtText)+F(" kWh"));
//<=======================
} else {
int id1=(mExtra/2)%(num_inv-1);
if( pow_i[id1] )
mDisplay.print(F("#")+String(id1+1)+F(" ")+String(pow_i[id1])+F(" W"));
else
mDisplay.print(F("#")+String(id1+1)+F(" -----"));
mDisplay.setCursor(5+ex,50);
if( pow_i[id1+1] )
mDisplay.print(F("#")+String(id1+2)+F(" ")+String(pow_i[id1+1])+F(" W"));
else
mDisplay.print(F("#")+String(id1+2)+F(" -----"));
}
mDisplay.setFont(u8g2_font_5x8_tr);
mDisplay.setCursor(5+ex,63);
if ( !(mExtra%10) && ip )
mDisplay.print(ip.toString());
else
mDisplay.print(timeStr);
#endif
mDisplay.sendBuffer();
} while( mDisplay.nextPage() );
delay(200);
mExtra++;
} }
// private member variables // private member variables
#ifdef ENA_NOKIA U8G2* mDisplay;
U8G2_PCD8544_84X48_1_4W_HW_SPI mDisplay;
#elif defined(ENA_SSD1306) uint8_t _mExtra;
U8G2_SSD1306_128X64_NONAME_F_HW_I2C mDisplay; uint16_t mTimeout; // interval at which to power save (milliseconds)
#elif defined(ENA_SH1106) char _fmtText[32];
U8G2_SH1106_128X64_NONAME_F_HW_I2C mDisplay;
#endif
int mExtra;
bool mNewPayload; bool mNewPayload;
float mTotal[ MAX_NUM_INVERTERS ]; bool mIsLarge;
float mToday[ MAX_NUM_INVERTERS ]; uint8_t mLoopCnt;
uint32_t *mUtcTs; uint32_t *mUtcTs;
int mLastHour; uint8_t mLineOffsets[5];
display_t *mCfg; display_t *mCfg;
HMSYSTEM *mSys; HMSYSTEM *mSys;
Timezone mCE; Timezone mCE;
bool displaySleep;
uint32_t displaySleepTimer;
const uint32_t displaySleepDelay= 60000;
}; };
#endif
#endif /*__MONOCHROME_DISPLAY__*/ #endif /*__MONOCHROME_DISPLAY__*/

2
src/utils/dbg.h

@ -5,7 +5,7 @@
#ifndef __DBG_H__ #ifndef __DBG_H__
#define __DBG_H__ #define __DBG_H__
#if defined(F) //defined(ESP32) && #if defined(F) && defined(ESP32)
#undef F #undef F
#define F(sl) (sl) #define F(sl) (sl)
#endif #endif

13
src/web/RestApi.h

@ -14,7 +14,7 @@
#include "../appInterface.h" #include "../appInterface.h"
#if defined(F) //defined(ESP32) && #if defined(F) && defined(ESP32)
#undef F #undef F
#define F(sl) (sl) #define F(sl) (sl)
#endif #endif
@ -354,6 +354,16 @@ class RestApi {
ah::ip2Char(mConfig->sys.ip.gateway, buf); obj[F("gateway")] = String(buf); ah::ip2Char(mConfig->sys.ip.gateway, buf); obj[F("gateway")] = String(buf);
} }
void getDisplay(JsonObject obj) {
obj[F("disp_type")] = (uint8_t)mConfig->plugin.display.type;
obj[F("disp_pwr")] = (bool)mConfig->plugin.display.pwrSaveAtIvOffline;
obj[F("logo_en")] = (bool)mConfig->plugin.display.logoEn;
obj[F("px_shift")] = (bool)mConfig->plugin.display.pxShift;
obj[F("contrast")] = (uint8_t)mConfig->plugin.display.contrast;
obj[F("pinDisp0")] = mConfig->plugin.display.pin0;
obj[F("pinDisp1")] = mConfig->plugin.display.pin1;
}
void getMenu(JsonObject obj) { void getMenu(JsonObject obj) {
uint8_t i = 0; uint8_t i = 0;
uint16_t mask = (mApp->getProtection()) ? mConfig->sys.protectionMask : 0; uint16_t mask = (mApp->getProtection()) ? mConfig->sys.protectionMask : 0;
@ -461,6 +471,7 @@ class RestApi {
getRadio(obj.createNestedObject(F("radio"))); getRadio(obj.createNestedObject(F("radio")));
getSerial(obj.createNestedObject(F("serial"))); getSerial(obj.createNestedObject(F("serial")));
getStaticIp(obj.createNestedObject(F("static_ip"))); getStaticIp(obj.createNestedObject(F("static_ip")));
getDisplay(obj.createNestedObject(F("display")));
} }
void getNetworks(JsonObject obj) { void getNetworks(JsonObject obj) {

151
src/web/html/setup.html

@ -165,7 +165,7 @@
<div class="s_content"> <div class="s_content">
<fieldset> <fieldset>
<legend class="des">System Config</legend> <legend class="des">System Config</legend>
<p class="des">Pinout (Wemos)</p> <p class="des">Pinout</p>
<div id="pinout"></div> <div id="pinout"></div>
<p class="des">Radio (NRF24L01+)</p> <p class="des">Radio (NRF24L01+)</p>
@ -181,6 +181,25 @@
</fieldset> </fieldset>
</div> </div>
<button type="button" class="s_collapsible">Display Config</button>
<div class="s_content">
<fieldset>
<legend class="des">Display Config</legend>
<div id="dispType"></div>
<label for="logoEn">Show Logo</label>
<input type="checkbox" class="cb" name="logoEn"/><br/>
<label for="dispPwr">Turn off while inverters are offline</label>
<input type="checkbox" class="cb" name="dispPwr"/><br/>
<label for="dispPxSh">Enable pixel shifting</label>
<input type="checkbox" class="cb" name="dispPxSh"/><br/>
<label for="dispCont">Contrast</label>
<select name="dispCont" id="contrast"></select>
<p class="des">Pinout</p>
<div id="dispPins"></div>
</fieldset>
</div>
<div class="mt-3"> <div class="mt-3">
<label for="reboot">Reboot device after successful save</label> <label for="reboot">Reboot device after successful save</label>
<input type="checkbox" class="cb" name="reboot" checked /> <input type="checkbox" class="cb" name="reboot" checked />
@ -221,6 +240,56 @@
var highestId = 0; var highestId = 0;
var maxInv = 0; var maxInv = 0;
var esp8266pins = [
[255, "off / default"],
[0, "D3 (GPIO0)"],
[1, "TX (GPIO1)"],
[2, "D4 (GPIO2)"],
[3, "RX (GPIO3)"],
[4, "D2 (GPIO4, SDA)"],
[5, "D1 (GPIO5, SCL)"],
[6, "GPIO6"],
[7, "GPIO7"],
[8, "GPIO8"],
[9, "GPIO9"],
[10, "GPIO10"],
[11, "GPIO11"],
[12, "D6 (GPIO12)"],
[13, "D7 (GPIO13)"],
[14, "D5 (GPIO14)"],
[15, "D8 (GPIO15)"],
[16, "D0 (GPIO16 - no IRQ!)"]
];
var esp32pins = [
[255, "off / default"],
[0, "GPIO0"],
[1, "TX (GPIO1)"],
[2, "GPIO2 (LED)"],
[3, "RX (GPIO3)"],
[4, "GPIO4"],
[5, "GPIO5"],
[12, "GPIO12"],
[13, "GPIO13"],
[14, "GPIO14"],
[15, "GPIO15"],
[16, "GPIO16"],
[17, "GPIO17"],
[18, "GPIO18"],
[19, "GPIO19"],
[21, "GPIO21 (SDA)"],
[22, "GPIO22 (SCL)"],
[23, "GPIO23"],
[25, "GPIO25"],
[26, "GPIO26"],
[27, "GPIO27"],
[32, "GPIO32"],
[33, "GPIO33"],
[34, "GPIO34"],
[35, "GPIO35"],
[36, "VP (GPIO36)"],
[39, "VN (GPIO39)"]
];
const re = /11[2,4,6]1.*/; const re = /11[2,4,6]1.*/;
document.getElementById("btnAdd").addEventListener("click", function() { document.getElementById("btnAdd").addEventListener("click", function() {
@ -443,59 +512,7 @@
pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['led0', 'pinLed0'], ['led1', 'pinLed1']]; pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['led0', 'pinLed0'], ['led1', 'pinLed1']];
for(p of pins) { for(p of pins) {
e.appendChild(lbl(p[1], p[0].toUpperCase())); e.appendChild(lbl(p[1], p[0].toUpperCase()));
if("ESP8266" == type) { e.appendChild(sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[0]]));
e.appendChild(sel(p[1], [
[255, "off / default"],
[0, "D3 (GPIO0)"],
[1, "TX (GPIO1)"],
[2, "D4 (GPIO2)"],
[3, "RX (GPIO3)"],
[4, "D2 (GPIO4)"],
[5, "D1 (GPIO5)"],
[6, "GPIO6"],
[7, "GPIO7"],
[8, "GPIO8"],
[9, "GPIO9"],
[10, "GPIO10"],
[11, "GPIO11"],
[12, "D6 (GPIO12)"],
[13, "D7 (GPIO13)"],
[14, "D5 (GPIO14)"],
[15, "D8 (GPIO15)"],
[16, "D0 (GPIO16 - no IRQ!)"]
], obj[p[0]]));
}
else {
e.appendChild(sel(p[1], [
[255, "off / default"],
[0, "GPIO0"],
[1, "TX (GPIO1)"],
[2, "GPIO2 (LED)"],
[3, "RX (GPIO3)"],
[4, "GPIO4"],
[5, "GPIO5"],
[12, "GPIO12"],
[13, "GPIO13"],
[14, "GPIO14"],
[15, "GPIO15"],
[16, "GPIO16"],
[17, "GPIO17"],
[18, "GPIO18"],
[19, "GPIO19"],
[21, "GPIO21"],
[22, "GPIO22"],
[23, "GPIO23"],
[25, "GPIO25"],
[26, "GPIO26"],
[27, "GPIO27"],
[32, "GPIO32"],
[33, "GPIO33"],
[34, "GPIO34"],
[35, "GPIO35"],
[36, "VP (GPIO36)"],
[39, "VN (GPIO39)"]
], obj[p[0]]));
}
} }
} }
@ -516,6 +533,29 @@
document.getElementsByName("serIntvl")[0].value = obj["interval"]; document.getElementsByName("serIntvl")[0].value = obj["interval"];
} }
function parseDisplay(obj, type) {
for(var i of [["logoEn", "logo_en"], ["dispPwr", "disp_pwr"], ["dispPxSh", "px_shift"]])
document.getElementsByName(i[0])[0].checked = obj[i[1]];
var e = document.getElementById("dispPins");
pins = [['SCL / CS', 'pinDisp0'], ['SDA / DC', 'pinDisp1']];
for(p of pins) {
e.appendChild(lbl(p[1], p[0].toUpperCase()));
e.appendChild(sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[1]]));
}
var opts = [[0, "None"], [1, "Nokia5110"], [2, "SSD1306 0.96\""], [3, "SH1106 1.3\""]];
document.getElementById("dispType").append(
lbl("dispType", "Type"),
sel("dispType", opts, obj["disp_type"])
);
e = document.getElementById("contrast");
for(var i = 30; i < 101; i += 2) {
e.appendChild(opt(i, i, (i == obj["contrast"])));
}
}
function parse(root) { function parse(root) {
if(null != root) { if(null != root) {
parseMenu(root["menu"]); parseMenu(root["menu"]);
@ -529,6 +569,7 @@
parsePinout(root["pinout"], root["system"]["esp_type"]); parsePinout(root["pinout"], root["system"]["esp_type"]);
parseRadio(root["radio"]); parseRadio(root["radio"]);
parseSerial(root["serial"]); parseSerial(root["serial"]);
parseDisplay(root["display"], root["system"]["esp_type"]);
} }
} }
@ -555,7 +596,7 @@
hiddenInput = document.getElementById("disclaimer") hiddenInput = document.getElementById("disclaimer")
hiddenInput.value = sessionStorage.getItem("gDisclaimer"); hiddenInput.value = sessionStorage.getItem("gDisclaimer");
getAjax("/api/setup", parse); getAjax("http://10.20.3.44/api/setup", parse);
</script> </script>
</body> </body>

11
src/web/web.h

@ -562,6 +562,17 @@ class Web {
// Needed to log TX buffers to serial console // Needed to log TX buffers to serial console
mSys->Radio.mSerialDebug = mConfig->serial.debug; mSys->Radio.mSerialDebug = mConfig->serial.debug;
} }
// display
mConfig->plugin.display.pwrSaveAtIvOffline = (request->arg("dispPwr") == "on");
mConfig->plugin.display.logoEn = (request->arg("logoEn") == "on");
mConfig->plugin.display.pxShift = (request->arg("dispPxSh") == "on");
mConfig->plugin.display.type = request->arg("dispType").toInt();
mConfig->plugin.display.contrast = request->arg("dispCont").toInt();
mConfig->plugin.display.pin0 = request->arg("pinDisp0").toInt();
mConfig->plugin.display.pin1 = request->arg("pinDisp1").toInt();
mApp->saveSettings(); mApp->saveSettings();
if(request->arg("reboot") == "on") if(request->arg("reboot") == "on")

25
src/wifi/ahoywifi.cpp

@ -11,7 +11,6 @@
// NTP CONFIG // NTP CONFIG
#define NTP_PACKET_SIZE 48 #define NTP_PACKET_SIZE 48
#define NTP_RETRIES 5
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
ahoywifi::ahoywifi() : mApIp(192, 168, 4, 1) {} ahoywifi::ahoywifi() : mApIp(192, 168, 4, 1) {}
@ -26,7 +25,7 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb) {
mStaConn = DISCONNECTED; mStaConn = DISCONNECTED;
mCnt = 0; mCnt = 0;
mScanActive = false; mScanActive = false;
mRetries = NTP_RETRIES; mLastNtpFailed = false;
#if defined(ESP8266) #if defined(ESP8266)
wifiConnectHandler = WiFi.onStationModeConnected(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); wifiConnectHandler = WiFi.onStationModeConnected(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1));
@ -149,26 +148,25 @@ void ahoywifi::setupStation(void) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool ahoywifi::getNtpTime(uint32_t *nxtTrig) { bool ahoywifi::getNtpTime() {
if(0 != mRetries) { if(mLastNtpFailed && (0 != *mUtcTimestamp)) { // time is available, but NTP not maybe it was set by "sync with browser"
DPRINTLN(DBG_INFO, "try to getNtpTime"); mLastNtpFailed = false;
*nxtTrig = 43200; // check again in 12h (if NTP was successful)
mRetries--;
} else if(0 != *mUtcTimestamp) { // time is availabe, but NTP not
*nxtTrig = 5; // check again 5s
mRetries = NTP_RETRIES;
return true; // true is necessary to enable all timers even if NTP was not reachable return true; // true is necessary to enable all timers even if NTP was not reachable
} }
if(GOT_IP != mStaConn) if(GOT_IP != mStaConn) {
mLastNtpFailed = true;
return false; return false;
}
IPAddress timeServer; IPAddress timeServer;
uint8_t buf[NTP_PACKET_SIZE]; uint8_t buf[NTP_PACKET_SIZE];
uint8_t retry = 0; uint8_t retry = 0;
if (WiFi.hostByName(mConfig->ntp.addr, timeServer) != 1) if (WiFi.hostByName(mConfig->ntp.addr, timeServer) != 1) {
mLastNtpFailed = true;
return false; return false;
}
mUdp.begin(mConfig->ntp.port); mUdp.begin(mConfig->ntp.port);
sendNTPpacket(timeServer); sendNTPpacket(timeServer);
@ -193,6 +191,7 @@ bool ahoywifi::getNtpTime(uint32_t *nxtTrig) {
} }
DPRINTLN(DBG_INFO, F("[NTP]: getNtpTime failed")); DPRINTLN(DBG_INFO, F("[NTP]: getNtpTime failed"));
mLastNtpFailed = true;
return false; return false;
} }
@ -275,10 +274,10 @@ void ahoywifi::connectionEvent(WiFiStatus_t status) {
if(mStaConn != CONNECTING) { if(mStaConn != CONNECTING) {
mStaConn = DISCONNECTED; mStaConn = DISCONNECTED;
mCnt = 5; // try to reconnect in 5 sec mCnt = 5; // try to reconnect in 5 sec
mLastNtpFailed = false;
setupWifi(); // reconnect with AP / Station setup setupWifi(); // reconnect with AP / Station setup
mAppWifiCb(false); mAppWifiCb(false);
DPRINTLN(DBG_INFO, "[WiFi] Connection Lost"); DPRINTLN(DBG_INFO, "[WiFi] Connection Lost");
mRetries = NTP_RETRIES;
} }
break; break;

4
src/wifi/ahoywifi.h

@ -25,7 +25,7 @@ class ahoywifi {
void setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb); void setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb);
void tickWifiLoop(void); void tickWifiLoop(void);
bool getNtpTime(uint32_t *nxtTrig); bool getNtpTime();
void scanAvailNetworks(void); void scanAvailNetworks(void);
void getAvailNetworks(JsonObject obj); void getAvailNetworks(JsonObject obj);
@ -68,7 +68,7 @@ class ahoywifi {
uint8_t mLoopCnt; uint8_t mLoopCnt;
bool mScanActive; bool mScanActive;
uint8_t mRetries; bool mLastNtpFailed;
}; };
#endif /*__AHOYWIFI_H__*/ #endif /*__AHOYWIFI_H__*/

Loading…
Cancel
Save