From 03b9af216d0d16748d033617edaa302fca27f17c Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 25 Aug 2022 09:44:50 +0200 Subject: [PATCH 01/38] /setup geht noch nicht --- tools/esp8266/ahoywifi.h | 7 - tools/esp8266/app.cpp | 10 +- tools/esp8266/app.h | 1 + tools/esp8266/defines.h | 2 +- tools/esp8266/favicon.h | 194 -------- tools/esp8266/html/convert.py | 7 +- tools/esp8266/html/h/favicon_ico_gz.h | 100 ++++ tools/esp8266/html/h/index_html.h | 1 + tools/esp8266/html/h/setup_html.h | 3 +- tools/esp8266/html/h/style_css.h | 1 + tools/esp8266/html/h/visualization_html.h | 1 + tools/esp8266/html/setup.html | 50 +- tools/esp8266/platformio.ini | 6 +- tools/esp8266/tmplProc.h | 108 +++++ tools/esp8266/web.cpp | 528 +++++++++++++--------- tools/esp8266/web.h | 59 ++- 16 files changed, 593 insertions(+), 485 deletions(-) delete mode 100644 tools/esp8266/favicon.h create mode 100644 tools/esp8266/html/h/favicon_ico_gz.h create mode 100644 tools/esp8266/tmplProc.h diff --git a/tools/esp8266/ahoywifi.h b/tools/esp8266/ahoywifi.h index 5e79568f..fdd3bff0 100644 --- a/tools/esp8266/ahoywifi.h +++ b/tools/esp8266/ahoywifi.h @@ -7,13 +7,6 @@ #define __AHOYWIFI_H__ #include "dbg.h" -#ifdef ESP8266 - #include - #include -#elif defined(ESP32) - #include - #include -#endif // NTP #include diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 75fe77df..c33bd7f4 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -20,9 +20,10 @@ app::app() { mWifi = new ahoywifi(this, &mSysConfig, &mConfig); resetSystem(); - loadDefaultConfig(); + loadDefaultConfig(); mSys = new HmSystemType(); + mShouldReboot = false; } @@ -64,6 +65,11 @@ void app::loop(void) { } } + if(mShouldReboot) { + DPRINTLN(DBG_INFO, F("Rebooting...")); + ESP.restart(); + } + mSys->Radio.loop(); @@ -946,4 +952,4 @@ void app::resetPayload(Inverter<>* iv) mPayload[iv->id].complete = false; mPayload[iv->id].requested = true; mPayload[iv->id].ts = mTimestamp; -} \ No newline at end of file +} diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index 0e09701a..308f222c 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -142,6 +142,7 @@ class app { } HmSystemType *mSys; + bool mShouldReboot; private: void resetSystem(void); diff --git a/tools/esp8266/defines.h b/tools/esp8266/defines.h index 31b65b77..3fbf8489 100644 --- a/tools/esp8266/defines.h +++ b/tools/esp8266/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 15 +#define VERSION_PATCH 16 //------------------------------------- diff --git a/tools/esp8266/favicon.h b/tools/esp8266/favicon.h deleted file mode 100644 index f0c501cd..00000000 --- a/tools/esp8266/favicon.h +++ /dev/null @@ -1,194 +0,0 @@ -//----------------------------------------------------------------------------- -// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778 -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ -//----------------------------------------------------------------------------- - - -// a) https://www.favicon-generator.org/ -// b) exiftool -all:all= -r -// c) hexlify.py: -// import sys -// f = open (sys.argv[1], 'rb').read() -// for n, c in enumerate(f): -// if n % 16 == 0: print (' "', end = '') -// print (f"\\x{c:02x}", end = '') -// if n % 16 == 15: print ('" \\') -// if n % 16 != 15: print ('"') - -#define FAVICON_PANEL_16 \ - "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52" \ - "\x00\x00\x00\x10\x00\x00\x00\x10\x08\x03\x00\x00\x00\x28\x2d\x0f" \ - "\x53\x00\x00\x00\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61" \ - "\x05\x00\x00\x00\x20\x63\x48\x52\x4d\x00\x00\x7a\x26\x00\x00\x80" \ - "\x84\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00\x75\x30\x00\x00\xea" \ - "\x60\x00\x00\x3a\x98\x00\x00\x17\x70\x9c\xba\x51\x3c\x00\x00\x01" \ - "\x9b\x50\x4c\x54\x45\xfc\xfe\xff\xff\xff\xff\xcb\xcd\xcf\x22\x25" \ - "\x30\x12\x16\x21\x11\x15\x21\x11\x15\x23\x12\x16\x25\x10\x13\x1f" \ - "\x8f\x91\x93\x9b\x9d\xa1\x14\x17\x22\x14\x18\x25\x14\x17\x23\x13" \ - "\x17\x22\x14\x17\x24\x17\x19\x27\x22\x24\x2e\xc1\xc2\xc3\xf8\xfa" \ - "\xfb\x61\x63\x6b\x11\x13\x1f\x15\x19\x24\x17\x19\x24\x18\x1a\x24" \ - "\x18\x1b\x26\x16\x19\x26\x42\x44\x4b\xe7\xe8\xe9\xfd\xff\xff\xfe" \ - "\xff\xff\xe0\xe2\xe4\x33\x36\x3f\x16\x19\x24\x16\x17\x22\x16\x18" \ - "\x22\x17\x18\x23\x11\x12\x1e\x71\x73\x76\xfb\xfc\xfd\xb5\xb7\xba" \ - "\x1a\x1c\x27\x15\x17\x22\x15\x17\x21\x14\x15\x20\x14\x16\x23\x17" \ - "\x1a\x26\x1b\x1c\x25\xaa\xac\xad\x7c\x7f\x85\x11\x13\x1d\x16\x18" \ - "\x24\x17\x19\x25\x18\x1a\x25\x30\x32\x38\xd7\xd9\xd9\xef\xf1\xf2" \ - "\x47\x49\x51\x12\x13\x1e\x17\x19\x22\x16\x17\x23\x10\x11\x1c\x59" \ - "\x5a\x5f\xf4\xf6\xf7\xcc\xce\xd0\x24\x25\x2e\x16\x18\x23\x19\x1a" \ - "\x24\x16\x17\x21\x15\x16\x21\x17\x17\x21\x15\x17\x20\x92\x93\x95" \ - "\x99\x9a\x9e\x16\x16\x20\x17\x19\x23\x1a\x1b\x25\x23\x25\x2c\xc4" \ - "\xc6\xc7\xf8\xfa\xfa\x61\x62\x68\x15\x16\x20\x11\x12\x1d\x44\x45" \ - "\x49\xea\xec\xec\xdf\xe1\xe2\x33\x35\x3b\x15\x16\x1f\x13\x14\x1d" \ - "\x78\x7a\x7c\xfc\xfd\xfe\xb2\xb4\xb7\x1a\x1c\x26\x18\x1b\x25\x1a" \ - "\x1b\x22\x19\x1b\x22\xae\xaf\xb0\x86\x88\x8b\x14\x16\x1e\x19\x1b" \ - "\x25\x17\x19\x21\x17\x19\x20\x12\x13\x1a\x2c\x2d\x32\xcc\xce\xcf" \ - "\xfb\xfe\xff\xd8\xdb\xdb\x72\x74\x76\x25\x26\x2c\x19\x1c\x24\x13" \ - "\x16\x1d\x11\x13\x18\x4c\x4d\x4f\xc1\xc3\xc3\xe2\xe4\xe6\xf6\xf8" \ - "\xf8\xb6\xb9\xb9\x4f\x51\x55\x1b\x1c\x23\x19\x1b\x23\x15\x17\x1f" \ - "\x70\x71\x72\xbb\xbb\xbc\xc3\xc4\xc5\xde\xe0\xe1\xf6\xf8\xf9\xfd" \ - "\xfe\xff\xe3\xe5\xe6\x7e\x81\x82\x21\x22\x27\x1d\x1f\x26\x94\x95" \ - "\x95\xbd\xbd\xbe\xbd\xbe\xbe\xc8\xca\xcb\xe5\xe7\xe9\xfa\xfc\xfd" \ - "\x52\x5f\xd3\xea\x00\x00\x00\x01\x62\x4b\x47\x44\x01\xff\x02\x2d" \ - "\xde\x00\x00\x00\xd2\x49\x44\x41\x54\x18\xd3\x63\x60\x00\x02\x46" \ - "\x26\x66\x16\x16\x56\x36\x76\x0e\x4e\x46\x06\x30\x60\xe4\xe2\xe6" \ - "\xe1\xe5\xe3\x17\x10\x14\x82\x0a\x08\x8b\x88\x8a\x89\x4b\x48\x4a" \ - "\x49\xcb\xc8\x82\xf9\x72\xf2\x0a\xdc\x8a\x4a\xca\x2a\xaa\x6a\xea" \ - "\x50\x1d\x1a\x9a\x5a\xda\x3a\xba\x7a\xfa\x06\x50\x1d\xb2\x86\x46" \ - "\x5a\xbc\xc6\x26\xa6\x66\xe6\x72\x10\xbe\x85\xa5\x95\xb5\x89\xa9" \ - "\x8d\xad\x9d\x3d\xc4\x08\x46\x07\x47\x27\x67\x17\x57\x37\x77\x0f" \ - "\x39\xa8\x11\x9e\x4a\xa6\x36\x5e\xde\x3e\xbe\x7e\x50\x23\xfc\x03" \ - "\x02\x55\x8c\x9d\x55\x82\x82\x43\xa0\x96\x86\x86\x85\x4b\x48\xb8" \ - "\x84\x47\x44\x46\x41\x75\x44\xc7\x78\xc7\xba\x87\xc7\xc5\x27\x40" \ - "\x75\xc8\x25\x26\x25\x7b\xa7\xa4\xa6\xa5\x67\x64\x42\x5d\x91\x95" \ - "\x9d\x93\x92\x9b\x97\x5f\x50\x58\x24\x0c\x55\x52\x5c\x52\x5a\x56" \ - "\x5e\x51\x59\x55\x5d\x53\x0b\x11\xa9\x93\xab\x6f\x68\x6c\x6a\x6e" \ - "\x69\x6d\x6b\xef\x60\x00\x00\x01\x53\x2a\x2a\x63\x34\xcd\xf7\x00" \ - "\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82" - -#define FAVICON_PANEL_32 \ - "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52" \ - "\x00\x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a" \ - "\xf4\x00\x00\x00\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61" \ - "\x05\x00\x00\x00\x20\x63\x48\x52\x4d\x00\x00\x7a\x26\x00\x00\x80" \ - "\x84\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00\x75\x30\x00\x00\xea" \ - "\x60\x00\x00\x3a\x98\x00\x00\x17\x70\x9c\xba\x51\x3c\x00\x00\x00" \ - "\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00" \ - "\x00\x07\x4a\x49\x44\x41\x54\x58\xc3\x9d\x97\xd9\x72\x5d\xc5\x15" \ - "\x86\xbf\xee\xde\xd3\xd9\x67\xd0\x99\x74\x34\x3b\x48\x32\x48\xe0" \ - "\x21\x60\xe1\x32\xd8\x15\x5e\x80\xdc\xf2\x00\xe4\x41\x12\x9e\x21" \ - "\x37\xc9\x43\xa4\x20\x95\xe2\x9a\x82\x0c\x10\x70\x62\x06\x0f\xc2" \ - "\x24\x15\xe2\x59\x96\xce\xbc\xe7\xb1\x73\x21\x93\x32\x20\x4b\xa7" \ - "\xe8\xaa\x7d\xb3\x2f\x7a\x7d\xf5\xff\xfd\xaf\x5e\x2d\xf2\x52\x6b" \ - "\x66\x58\x4a\xc0\x67\xff\xf8\x27\x6f\xbd\xf5\x36\xa3\xf1\x04\xad" \ - "\x0b\x84\x94\x68\xad\xc9\xf3\x1c\xc7\x76\x08\xa3\x04\xdb\xb6\xc8" \ - "\xf3\x12\x0d\xb8\x15\x9b\x28\x8c\x90\x52\xb0\xfe\xdc\x02\xbf\xff" \ - "\xdd\x6f\xb9\x72\xf9\x32\xc5\x53\x15\xe5\x2c\xc5\xbf\x5b\xdf\x7e" \ - "\x7b\x87\x34\x4b\x68\x36\xeb\x38\x8e\x4d\xb3\x59\xc7\xb6\x0d\x3a" \ - "\x9d\x16\xb6\x63\x52\x71\x6c\xea\xb5\x2a\x52\x0a\x6a\xd5\x0a\x96" \ - "\x65\x02\x1a\xc7\x36\xd9\xde\xda\x64\x6b\x6b\x9b\xf2\x07\x7b\x1a" \ - "\xb3\x16\xcf\x8a\x82\x4f\x3f\xbd\x4a\x18\x86\x34\x1a\x73\x68\x24" \ - "\x52\x1a\x08\xa1\xa8\x54\x1c\xa2\x30\xa4\xd9\xac\xd3\x9d\xef\xa0" \ - "\xb5\x66\x65\x65\x91\x30\x8c\x50\x52\xd3\x6a\xd5\xd9\xda\x7a\x81" \ - "\x56\xbb\xcd\x0f\xf5\x9e\x09\x40\x0a\x78\xb4\xf7\x98\x8f\x3f\xfe" \ - "\x8c\xa2\x28\x99\x4c\xa6\x94\x25\xe4\x59\x49\x14\x47\xc4\x51\x4c" \ - "\x92\x24\x54\x9c\x0a\xfd\xfe\x88\x3c\xcb\x89\xc2\x88\x2c\xcb\xd1" \ - "\x5a\x23\x74\xce\xf6\xf6\x36\x4a\xf0\x3d\xf9\x67\x06\x10\xc0\xd7" \ - "\xb7\xbf\xa1\x3f\x18\xb1\xb0\x30\x8f\xef\xfb\x98\xa6\x49\x96\x6b" \ - "\xda\x9d\x39\x6c\x4b\x31\x1c\x8e\xa9\xd5\xaa\x8c\xc7\x1e\xae\xeb" \ - "\x50\x71\xab\x0c\xfa\x63\x4c\x43\xb2\x79\xfa\x39\x2e\xbd\xf6\x1a" \ - "\x47\x1d\xb6\x99\x2d\xb8\x7a\xf5\x73\xee\xde\x79\x80\x6d\x9b\x64" \ - "\x79\x86\x6d\xdb\x64\x59\x86\x28\x73\x22\xa1\xa1\x2c\xb1\x2d\x03" \ - "\xd3\x54\x2c\x2e\xf6\x70\x6c\x87\xb2\x28\xa8\xd5\x1c\xce\x9f\x3b" \ - "\xc3\xda\xda\x29\x4a\xfd\x13\x00\x84\x00\xcf\x0f\xb8\x7e\xfd\x3a" \ - "\xbd\x85\x0e\x8e\x6d\x31\x99\x7a\x58\x96\xc5\x70\x38\x22\x8a\x63" \ - "\xd2\x24\xc5\xb2\x4c\x1e\xde\x7f\x44\x9c\xa4\xa4\x71\x42\x91\xe7" \ - "\x14\x65\x49\x96\xda\xac\xad\xad\xe2\x58\xe6\x8f\xe4\x9f\x09\x40" \ - "\x02\xb7\xbf\xf9\x86\x4f\x3e\xb9\x4a\x92\xc4\x68\x5d\xd2\x68\xd4" \ - "\x71\x9c\x0a\x4a\x49\x1c\xdb\xe2\xe0\x60\xc0\xe2\x52\x0f\x7f\xea" \ - "\xe3\xe4\x19\xae\x5b\xe5\xe0\x60\x88\x10\x8a\x4e\xbb\xc5\xeb\x97" \ - "\x2f\x3f\x73\xff\x99\x2c\xd8\xdd\xbd\xcd\x70\x34\x46\x6b\xcd\x74" \ - "\xea\x63\x99\x16\x79\x9e\x63\x5b\x06\x9e\x80\x2c\xcb\x99\x4e\x7d" \ - "\x92\xa4\xa0\xd9\x6a\xb1\xd0\xeb\x90\x65\x39\x96\x65\xb0\xb3\xf3" \ - "\x73\xce\xbc\x74\xe6\x47\xf1\x9b\x19\x20\x2b\x0a\xbe\xf8\xe2\x3a" \ - "\x95\x4a\x85\xb9\x46\x95\xfe\x60\x48\xb7\xdb\x65\x32\x1a\xa1\x94" \ - "\x62\x3a\x0d\x90\x52\x12\x85\x11\x7e\x90\x50\x14\x05\xfd\xbd\x3d" \ - "\xb2\x3c\xa3\xde\x70\x59\x5b\x5b\x65\xae\x39\xc7\xb3\xda\xdd\xb1" \ - "\x00\x52\xc0\x83\x47\x7b\x7c\xf8\xd1\xdf\x18\x8f\x27\x44\xbe\x07" \ - "\x42\xe1\xfb\x11\x85\x96\x74\xda\x6d\xb4\x50\xb8\xae\x4d\x51\x94" \ - "\x98\x56\x82\xeb\x3a\x0c\xfb\x03\x84\x90\x28\x25\x39\x7f\xfe\x3c" \ - "\x12\x28\x7e\x8a\x02\x02\xd8\xdd\xfd\x9a\xbd\xbd\x7d\x96\x16\x7b" \ - "\x84\xbe\x87\x46\x3e\xe9\x03\x9a\xfb\xf7\xf6\x88\x93\x84\x38\x76" \ - "\x28\x72\xa8\x56\x5d\xe6\xe7\x3b\x14\x79\x86\xd6\x70\xee\xdc\xf3" \ - "\x5c\xba\x74\x89\xe3\x7a\xfd\x89\x16\x5c\xbb\xf6\x25\xfd\x7e\x9f" \ - "\xb9\x46\x0d\x29\x25\xed\x76\x0b\x06\x23\x9a\xed\x16\x9e\x17\x81" \ - "\x00\x43\x29\x02\xcf\x47\x08\xf8\xd7\xed\x7f\x13\xc7\x09\x8d\xb9" \ - "\x3a\xa7\x37\x37\x58\x5e\x59\x39\x32\x7e\x27\x02\x08\x01\x5e\x10" \ - "\x70\xfd\xc6\x4d\x2a\x8e\x4d\x96\x66\x24\x49\x42\x9e\x17\x44\x51" \ - "\x8c\x32\x14\x68\x58\x5d\x5d\x24\x4f\x13\xa4\x94\xd4\xea\xd5\x43" \ - "\xf9\xa5\xa4\x2c\x33\x36\xd6\x9f\xc3\x32\x8c\x23\xe3\x77\x22\x80" \ - "\x7c\x22\xff\xd5\xcf\xae\xd2\xeb\x75\x48\xd3\x0c\xcb\xb2\x48\x93" \ - "\x84\x2c\xcb\x49\xa2\x98\x30\x88\x88\xa3\x94\xb2\x48\x31\x0c\x03" \ - "\x77\xbe\x45\xde\xa8\xe3\xe4\x05\xa7\xd6\x7a\x5c\xbe\x72\xe5\x24" \ - "\x81\x8f\xb7\xe0\xe6\xcd\x5b\x3c\x7c\xf0\x08\x29\x0c\x0a\xad\xe9" \ - "\x74\x5a\x20\x24\xcb\x2b\x8b\xa4\x69\x8a\x65\xd9\x28\x43\x31\x1a" \ - "\x44\x80\xe4\xe1\x83\x3d\x82\x20\xa2\x5a\xaf\xb2\xbd\xf5\x02\xdb" \ - "\x2f\xbe\xf8\xcc\xf8\x9d\x08\x90\xe5\x05\x37\x6f\xdc\xa2\xd1\x68" \ - "\x50\x6f\xcc\xb1\xbf\xdf\x27\x08\x62\xa2\x30\xc4\x77\x2c\xb4\x2e" \ - "\x69\xb7\x9b\x74\xe6\xbb\xa4\x69\x4a\xaf\xd7\x65\xd0\x1f\x20\xa4" \ - "\x40\x88\x92\x53\xa7\x56\xa9\xd7\x6a\xc7\xfa\xff\x4c\x00\x29\xe0" \ - "\xde\xc3\x87\x7c\xf0\xc1\x5f\x08\xc2\x14\x43\x05\x74\x3b\x73\x18" \ - "\x96\xc3\x74\x3c\x01\x34\xa3\xe1\x98\xd1\x70\x42\x7f\x30\xa1\x2c" \ - "\x72\xb2\x34\xc3\xa9\xb8\x28\x43\xd1\xee\x34\xb8\x70\xe1\x02\xe2" \ - "\x44\x03\x9e\x01\x70\x18\xbf\x5d\x06\xc3\x21\x8e\x63\x33\x19\x4f" \ - "\xb0\x2c\x93\x42\x2b\x1a\xcd\x26\xad\xa6\x4b\x51\xe4\xd4\x1b\x75" \ - "\x1e\xef\x1d\x00\x30\x1a\x4d\xf0\xbd\x90\x8a\x6b\xb1\xbe\x73\x96" \ - "\x57\x2f\x5e\x64\x96\x51\xeb\x48\x00\x0d\x7c\x7e\xed\x4b\x26\x93" \ - "\x29\xbd\x5e\x97\x40\x81\x53\xa9\xf0\xf8\xf1\x90\xf1\x68\xcc\xb0" \ - "\xbf\x8f\x69\x2a\x5c\xd7\xa5\x5a\xab\xd2\xed\xb6\xf1\xfd\x10\xdf" \ - "\x0f\x50\x0a\xd6\x7f\x76\x8a\x85\x85\xc5\x13\xe5\x87\x23\x46\xb2" \ - "\xc3\xdb\xcf\xe7\xda\xb5\x6b\x64\x69\x42\x7f\xbf\x4f\x92\xa4\xb8" \ - "\xd5\x0a\xcd\x66\x8d\x85\xc5\x0e\x08\x41\xa9\x05\x77\xff\x7b\x9f" \ - "\xc9\xd8\xc3\x0f\x42\x84\x28\x69\xb6\x1b\x74\xba\x2d\x5e\xd8\xda" \ - "\xc2\x54\xb3\x4d\x7b\xf2\xa8\x1f\xbb\xbb\xbb\xdc\xb8\x79\x8b\xc5" \ - "\xa5\x1e\xae\xeb\xa0\x81\x7b\x77\x1f\xe2\xf9\x01\xe8\x82\x7a\xdd" \ - "\xa5\x3b\xdf\xc2\xb4\x14\x52\x68\xa6\xe3\x31\x7b\x8f\x1e\x13\xf8" \ - "\x01\xed\x76\x8b\x2b\x33\xc4\xef\x58\x0b\xbe\xfa\xea\x16\x77\xee" \ - "\x3c\xc2\x75\x1d\x2c\xd3\xa0\xd9\x6e\xe2\xfb\x11\x59\x96\xb1\xbf" \ - "\xb7\x4f\x9e\x17\x28\x29\x31\x2d\x83\xd5\xce\x12\x42\x1c\xaa\xa1" \ - "\x94\xe2\xf4\xe6\x3a\xa7\x9f\x7f\xfe\xc4\xf8\x3d\x13\x20\xcd\x0b" \ - "\xae\xdf\xb8\x49\xad\xd1\xc0\x50\x8a\xe9\x64\x42\x56\x68\xa4\x54" \ - "\x74\x3b\x4d\x3c\xcf\x27\x89\x13\xc2\x20\x24\x0c\x02\x04\x1a\xcb" \ - "\xb6\x69\x34\x1b\x54\xaa\x15\x4e\x6f\x6e\x50\x75\xdd\x99\xfc\xff" \ - "\x11\x80\x14\x70\xe7\xfe\x3d\x3e\xfa\xf0\xcf\x58\xa6\xa2\x56\xab" \ - "\x61\x59\x26\x69\x9a\x32\x9d\x78\xa0\x0b\x40\xb3\xb4\xbc\x80\xe7" \ - "\x79\x24\x69\x4c\xe0\x07\x8c\xfa\x63\x84\x61\xd0\x68\xb8\x9c\x39" \ - "\x7b\x96\xa2\xd4\x08\x31\x4b\x08\x7f\x00\x20\x80\x7b\xf7\xef\x93" \ - "\xc4\x01\xa1\x37\xc1\x9f\x4e\x59\x5a\x5e\xc2\xb2\x4c\x2c\xcb\x24" \ - "\x8e\x22\xbc\xa9\x47\x59\x14\x08\x43\x31\xbf\xd0\xc5\x75\x1d\xee" \ - "\xfc\xe7\x2e\x52\xc1\xea\xca\x12\x4b\xcb\x2b\x0c\x87\x23\xea\xf5" \ - "\xfa\x93\x77\xc1\xf1\x4b\xfd\xfa\x37\xef\xbc\xf3\x34\x41\xbd\x56" \ - "\x67\x71\xb9\xc7\x78\x32\xe2\xe0\xf1\x3e\x81\x17\xe0\x79\x3e\xdd" \ - "\x6e\x07\xc3\x30\x10\x42\x20\xa4\xc4\x9b\x7a\x68\x01\xba\x28\x91" \ - "\x4a\xd2\x6c\xd6\x79\xe9\xa5\x2d\x76\x76\x76\xc8\x8b\x02\x21\x04" \ - "\xa6\x69\xa0\x94\x3a\x56\x8d\xef\x03\x00\xae\x5b\xe1\xdc\xd9\xb3" \ - "\xbc\xfc\xca\xcb\x38\xae\xcd\x64\x32\x66\xd0\x1f\x10\xf8\x3e\x41" \ - "\x10\xd2\x5b\xe8\x61\x3b\x0e\x49\x92\x52\x16\x05\xde\xd4\x23\x4d" \ - "\x12\x2c\x5b\xf1\xfa\x6b\x97\xd8\xd8\xd8\x20\x4b\x53\xf2\x3c\x07" \ - "\x0e\x21\xbe\x03\x9f\x09\xe0\x50\x09\xc1\x42\xaf\xc7\xc5\x8b\x17" \ - "\x59\xdf\x5c\x47\x8b\x92\xc9\x74\xc2\x68\x30\x22\x89\x53\xa2\x30" \ - "\xa6\x56\xab\xd2\x9d\xef\x12\xf8\x11\x5a\xc3\xf2\x52\x8f\x5f\xbe" \ - "\xf9\x26\x8d\x46\x9d\xa2\x28\xc8\xb2\x9c\x2c\xcf\x0f\x7d\x36\x0c" \ - "\x0c\xc3\x3c\x12\xe2\x68\x00\x0e\xbb\xa1\x65\x59\x9c\xde\xdc\xe4" \ - "\xc2\x2b\xaf\xd0\x6c\xcd\x31\x1a\x8f\x89\xe3\x98\xe9\x68\x8c\x2e" \ - "\x0b\xb4\x06\xa9\x14\xcd\x56\x93\xed\xad\x4d\xde\x78\xe3\x17\x48" \ - "\xa9\x00\x8d\x2e\x4b\x8a\x22\x27\xcf\x0f\x5f\x47\x87\x10\x06\x52" \ - "\x7e\x1f\xe2\xd8\xeb\xf8\xbb\x41\x72\x75\x75\x95\x5f\xbd\xfd\x36" \ - "\xaf\xee\xec\xf0\xa7\xf7\xdf\xe7\xdd\x3f\xfc\x91\x83\xfd\x7d\xa6" \ - "\xe3\x11\x85\x96\xd8\x8e\xc9\xd2\xe2\x02\x8e\xe3\xa0\xff\x3f\x7d" \ - "\x6a\x8a\x3c\x27\x0c\x43\x84\x10\x68\x0d\x5a\x6b\xaa\xd5\x2a\xea" \ - "\xa9\x2e\x39\xd3\x58\xae\x35\x98\x86\xc9\xab\x3b\x3b\xac\x9d\x3a" \ - "\xc5\xc6\xfa\x3a\xef\xbe\xf7\x1e\x7f\xff\xeb\xa7\xe4\x71\x46\x99" \ - "\xe7\xac\xaf\xaf\xa3\x94\xa2\x2c\xf5\x93\x2b\x59\x22\xe5\xe1\xa7" \ - "\x35\x94\x65\x49\x59\x16\x68\x5d\xf2\x74\x03\xfe\x1f\xc2\x60\x72" \ - "\xe2\x6a\x9b\x4e\x8f\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60" \ - "\x82" diff --git a/tools/esp8266/html/convert.py b/tools/esp8266/html/convert.py index 98027b2f..f3156189 100755 --- a/tools/esp8266/html/convert.py +++ b/tools/esp8266/html/convert.py @@ -1,9 +1,8 @@ import re -import sys import os def convert2Header(inFile): - fileType = inFile.split(".")[1] + fileType = inFile.split(".")[1] define = inFile.split(".")[0].upper() define2 = inFile.split(".")[1].upper() inFileVarName = inFile.replace(".", "_") @@ -21,18 +20,22 @@ def convert2Header(inFile): if fileType == "html": data = re.sub(r"\>\s+\<", '><', data) # whitespaces between xml tags data = re.sub(r"(\;|\}|\>|\{)\s+", r'\1', data) # whitespaces inner javascript + length = len(data) # get unescaped length data = re.sub(r"\"", '\\\"', data) # escape quotation marks else: data = re.sub(r"(\;|\}|\:|\{)\s+", r'\1', data) # whitespaces inner css + length = len(data) # get unescaped length f = open(outName, "w") f.write("#ifndef __{}_{}_H__\n".format(define, define2)) f.write("#define __{}_{}_H__\n".format(define, define2)) f.write("const char {}[] PROGMEM = \"{}\";\n".format(inFileVarName, data)) + f.write("const uint32_t {}_len = {};\n".format(inFileVarName, length)) f.write("#endif /*__{}_{}_H__*/\n".format(define, define2)) f.close() convert2Header("index.html") convert2Header("setup.html") convert2Header("visualization.html") +convert2Header("update.html") convert2Header("style.css") diff --git a/tools/esp8266/html/h/favicon_ico_gz.h b/tools/esp8266/html/h/favicon_ico_gz.h new file mode 100644 index 00000000..b978fb85 --- /dev/null +++ b/tools/esp8266/html/h/favicon_ico_gz.h @@ -0,0 +1,100 @@ +#ifndef __FAVICON_ICO_GZ_H__ +#define __FAVICON_ICO_GZ_H__ +#define favicon_ico_gz_len 1533 +const uint8_t favicon_ico_gz[] PROGMEM = {0x1f, 0x8b, 0x08, 0x08, 0xf2, 0xc5, 0xd5, 0x62, 0x04, 0x00, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6f, +0x6e, 0x2e, 0x69, 0x63, 0x6f, 0x00, 0xed, 0x5c, 0x49, 0x68, 0x13, 0x51, 0x18, 0xfe, 0x62, 0xa3, +0x51, 0x28, 0xd6, 0x83, 0x82, 0xa0, 0x98, 0xb8, 0x1c, 0xbc, 0x59, 0x11, 0x5c, 0x50, 0xac, 0x88, +0x8a, 0xb8, 0xdd, 0x3c, 0x89, 0xd0, 0x93, 0x7a, 0x53, 0x51, 0x9b, 0x80, 0x4b, 0x46, 0xad, 0xfb, +0xd2, 0xb4, 0x2e, 0xb8, 0xa3, 0xc6, 0xba, 0xe1, 0x02, 0xae, 0xad, 0x0a, 0x26, 0x3d, 0xe8, 0xc5, +0x83, 0x57, 0x31, 0x2d, 0xc1, 0x8b, 0xb7, 0x92, 0x63, 0x0e, 0xa1, 0xcf, 0xff, 0xcf, 0xbc, 0xc9, +0x32, 0xa4, 0x66, 0xcf, 0x4b, 0xf3, 0xfa, 0xc3, 0xc7, 0x97, 0xcc, 0xcc, 0xcb, 0xf7, 0xbe, 0x6f, +0x26, 0x6f, 0x26, 0xf3, 0x92, 0x00, 0x0e, 0x34, 0x61, 0xda, 0x34, 0x66, 0x0f, 0xf6, 0x38, 0x81, +0xa5, 0x00, 0x3c, 0x1e, 0xf3, 0xf9, 0x53, 0x5a, 0x7e, 0x8f, 0x96, 0xad, 0x59, 0x63, 0x3e, 0x5f, +0xb8, 0x16, 0xd8, 0x30, 0x03, 0x58, 0x48, 0xdb, 0xd0, 0x2a, 0x5a, 0x62, 0x2e, 0x1f, 0xad, 0x06, +0xc3, 0x5d, 0xc6, 0x60, 0x38, 0x20, 0x08, 0x5e, 0xf1, 0x08, 0x77, 0x09, 0x42, 0xf4, 0xe2, 0xd7, +0x67, 0x2f, 0x56, 0xf5, 0x7b, 0x21, 0x18, 0xfc, 0xb8, 0x63, 0x0b, 0x7e, 0x11, 0x84, 0x77, 0x0b, +0xee, 0x2e, 0x9a, 0x03, 0x6f, 0xab, 0x1b, 0x82, 0x31, 0x38, 0x10, 0x38, 0xce, 0xaf, 0x51, 0x72, +0x7b, 0xd2, 0xe6, 0xf6, 0xbf, 0xbf, 0xf6, 0xcc, 0x2e, 0xbd, 0x7d, 0xf2, 0x35, 0x76, 0x88, 0x20, +0xf6, 0x96, 0xde, 0x3e, 0xe0, 0xa5, 0x76, 0xad, 0xd4, 0xfe, 0x64, 0xc9, 0xed, 0xa9, 0xff, 0xd4, +0xd6, 0x4f, 0x68, 0x2f, 0xb9, 0x3d, 0xf5, 0x9f, 0x70, 0xb8, 0xaf, 0x03, 0x4b, 0x4b, 0x6e, 0x4f, +0xfd, 0xe7, 0x7d, 0x4b, 0x6d, 0x4f, 0x96, 0xd3, 0xde, 0x7a, 0x8d, 0x72, 0xda, 0x73, 0x7d, 0xdb, +0x8f, 0x29, 0x45, 0xb5, 0x7f, 0x84, 0x4e, 0xfb, 0x71, 0xda, 0xb1, 0x19, 0x9d, 0x05, 0xb5, 0xef, +0xc5, 0xa5, 0xd1, 0x8e, 0x75, 0xef, 0x56, 0x9c, 0xfa, 0x6f, 0xfb, 0x87, 0x58, 0x86, 0x3c, 0x75, +0x70, 0x13, 0x96, 0xe5, 0x6a, 0x1f, 0x19, 0xe8, 0x6a, 0x47, 0x81, 0xd5, 0xea, 0x41, 0x7b, 0x56, +0xfb, 0x50, 0xe0, 0x72, 0xae, 0xed, 0xbe, 0x1a, 0x98, 0xcc, 0xc8, 0xf9, 0x1a, 0x73, 0x70, 0x9a, +0xda, 0x8f, 0xda, 0xf6, 0xb9, 0x81, 0x49, 0xfd, 0x3e, 0xbc, 0xa5, 0xfd, 0xd7, 0xcf, 0xf9, 0x8f, +0xf6, 0x1a, 0xff, 0xeb, 0xe7, 0x04, 0x42, 0x13, 0xc3, 0x20, 0x84, 0x00, 0x57, 0x14, 0x68, 0x89, +0x01, 0xee, 0x38, 0xb0, 0xfa, 0x08, 0x70, 0x64, 0xb5, 0x39, 0xce, 0x78, 0x08, 0x6b, 0x0a, 0x1f, +0x67, 0x2c, 0x0c, 0xf3, 0x72, 0xf1, 0x18, 0xab, 0xe4, 0x3e, 0x4f, 0x23, 0x88, 0x37, 0xbc, 0xae, +0xcf, 0x07, 0xaf, 0xf9, 0x1e, 0x48, 0x83, 0x97, 0xf1, 0xba, 0x43, 0x5b, 0xf0, 0x86, 0x8f, 0x87, +0x4c, 0xd0, 0xfe, 0x5d, 0xc5, 0xeb, 0x28, 0x97, 0x61, 0x33, 0xdf, 0x34, 0x78, 0x39, 0x8f, 0x55, +0xaa, 0xf4, 0x23, 0x03, 0x81, 0x53, 0x56, 0x1f, 0x54, 0xe8, 0xb3, 0xe6, 0x50, 0x28, 0x70, 0xde, +0xea, 0x83, 0x0a, 0xfd, 0x64, 0x1f, 0xc2, 0x81, 0x93, 0xbc, 0x0d, 0xf1, 0x01, 0x15, 0xfa, 0x49, +0x0c, 0x74, 0x9d, 0xe3, 0xed, 0x94, 0xe9, 0x13, 0x78, 0x1f, 0x24, 0xf5, 0x7b, 0xb1, 0x54, 0x89, +0x3e, 0xef, 0x7f, 0x59, 0x7c, 0xce, 0x53, 0xa5, 0x2f, 0x7a, 0xe0, 0x92, 0x7d, 0x38, 0xad, 0x44, +0x9f, 0xf6, 0x3f, 0x9f, 0xb3, 0x65, 0x1f, 0x3a, 0x95, 0xe8, 0x9b, 0xbe, 0x8f, 0x59, 0x7d, 0x50, +0xa4, 0x9f, 0xea, 0x03, 0xe9, 0xaf, 0x57, 0xa4, 0x9f, 0xea, 0x83, 0x42, 0x7d, 0xbe, 0x7e, 0xd9, +0xcf, 0xeb, 0x3e, 0xf9, 0xd0, 0xae, 0x44, 0x9f, 0xf7, 0xbf, 0x2c, 0x3a, 0x87, 0x9f, 0x56, 0xa9, +0x6f, 0xf5, 0x41, 0xa5, 0xbe, 0xbc, 0x0e, 0x3d, 0xa3, 0x52, 0xdf, 0xea, 0x83, 0x4a, 0x7d, 0xae, +0x0f, 0x87, 0x30, 0x5f, 0xa5, 0x3e, 0x57, 0x0d, 0xf4, 0x8d, 0x7c, 0xfa, 0xa4, 0x67, 0x54, 0x49, +0xff, 0x86, 0x10, 0x74, 0x29, 0x9b, 0xbf, 0x1c, 0xa4, 0xd9, 0x5d, 0x51, 0xfd, 0x20, 0x6e, 0x16, +0xa8, 0x9d, 0xd5, 0x87, 0x8a, 0xe8, 0x17, 0xaf, 0x9d, 0xea, 0x03, 0xe9, 0xf6, 0x94, 0xa9, 0x7f, +0xab, 0x44, 0xed, 0xac, 0x3e, 0x94, 0xa4, 0xff, 0x1c, 0xcd, 0x65, 0x6a, 0xa7, 0xfa, 0x60, 0x6c, +0x47, 0x73, 0xb1, 0xfa, 0xd5, 0xa8, 0x42, 0xf4, 0x23, 0xe1, 0xc0, 0x15, 0x54, 0xa9, 0x16, 0xbb, +0x71, 0xe5, 0x7f, 0xfa, 0x91, 0x50, 0xf7, 0x6d, 0x21, 0x8c, 0x09, 0xa8, 0x5e, 0x39, 0x48, 0xf3, +0x6a, 0x86, 0x7e, 0x59, 0xda, 0xfd, 0x07, 0x31, 0x97, 0x81, 0xe2, 0x2a, 0xdd, 0x87, 0xb4, 0xfe, +0x9d, 0x62, 0xb5, 0xe9, 0xde, 0xcb, 0x1c, 0x3a, 0xef, 0x0c, 0xf5, 0x77, 0xe0, 0xcf, 0x17, 0x1f, +0xe6, 0xa1, 0xb8, 0xe2, 0x3e, 0x5c, 0x23, 0x94, 0xa4, 0xfd, 0xd1, 0x07, 0x0f, 0x5d, 0x03, 0x45, +0xad, 0x73, 0x3f, 0x3f, 0xe6, 0x65, 0x28, 0xae, 0x92, 0x7d, 0x70, 0x4e, 0x9e, 0xe6, 0xe9, 0x24, +0xac, 0x23, 0x2c, 0x20, 0x4c, 0x27, 0x34, 0x13, 0x78, 0xf9, 0x24, 0xc2, 0x44, 0x7e, 0x7c, 0x96, +0xb0, 0x91, 0xb0, 0x90, 0x30, 0xd3, 0x5c, 0xe7, 0x6c, 0x26, 0x4c, 0x25, 0xb4, 0x30, 0x02, 0x84, +0x9f, 0x84, 0x58, 0x1a, 0xee, 0xb8, 0xc7, 0xd9, 0x96, 0xf0, 0x38, 0xfd, 0x23, 0x1e, 0xa7, 0x10, +0x1e, 0x97, 0x10, 0x51, 0x0b, 0x2d, 0x23, 0xfe, 0x98, 0x3b, 0xd1, 0x16, 0x6f, 0x8b, 0xbb, 0x13, +0x0b, 0xe5, 0x3d, 0x0a, 0xa3, 0xf8, 0xfb, 0x14, 0xb9, 0x3e, 0xbb, 0x45, 0xac, 0xed, 0xe5, 0x67, +0x38, 0x2f, 0x8f, 0xa1, 0x79, 0xd1, 0x8b, 0x5d, 0xb6, 0xeb, 0x89, 0x61, 0xce, 0x35, 0x0f, 0x86, +0x6d, 0xf7, 0xc1, 0x76, 0xf1, 0x58, 0x9b, 0x17, 0x9b, 0xe1, 0xb5, 0x8d, 0x09, 0x91, 0xf4, 0xfb, +0x21, 0x8d, 0x02, 0xee, 0x93, 0x68, 0xe7, 0x3f, 0x6f, 0x06, 0x1a, 0xf8, 0xe7, 0x1a, 0x0a, 0x75, +0x9d, 0xd0, 0xcd, 0xff, 0xe0, 0x40, 0xf7, 0xa5, 0xbc, 0x19, 0x34, 0xb2, 0x7f, 0xf3, 0xda, 0xe0, +0xa2, 0x3d, 0x03, 0x9d, 0xfc, 0xe7, 0xca, 0x80, 0xef, 0x5b, 0xea, 0xe4, 0xdf, 0xcc, 0xa0, 0xeb, +0x82, 0x3d, 0x03, 0x9d, 0xfc, 0xe7, 0xca, 0x20, 0x12, 0xee, 0xee, 0xd4, 0xc9, 0x3f, 0x21, 0x35, +0x77, 0x91, 0xce, 0x20, 0xb0, 0x5b, 0x27, 0xff, 0xe9, 0xb9, 0x93, 0x74, 0xe9, 0xe6, 0xdf, 0xca, +0x40, 0x67, 0xff, 0xd6, 0xdc, 0x91, 0xd6, 0xfe, 0x93, 0xe8, 0xf6, 0xdb, 0xfc, 0xb7, 0xe7, 0xf5, +0xde, 0x48, 0xfe, 0x6d, 0xe3, 0xbf, 0x35, 0x7f, 0xa5, 0xb3, 0xff, 0x82, 0x32, 0x68, 0x70, 0xff, +0x32, 0x83, 0x33, 0xba, 0xf9, 0x17, 0x0f, 0x30, 0x2b, 0xeb, 0x79, 0x10, 0x97, 0xb5, 0xf2, 0x4f, +0xe3, 0x3f, 0xc1, 0x6f, 0xcb, 0xe0, 0xac, 0x56, 0xfe, 0xe5, 0xdc, 0xad, 0x3d, 0x03, 0xcd, 0xfc, +0x67, 0x65, 0xc0, 0xf3, 0x0a, 0xf4, 0xbc, 0x5b, 0x33, 0xff, 0x3c, 0x97, 0x74, 0xd4, 0x9e, 0x81, +0x56, 0xfe, 0x73, 0x67, 0xd0, 0xa3, 0x95, 0x7f, 0x13, 0x87, 0x6d, 0x19, 0xcc, 0xd6, 0xcc, 0x3f, +0x1f, 0xf3, 0x47, 0x32, 0xb7, 0xd5, 0xce, 0xbf, 0x3c, 0x0e, 0x34, 0xf7, 0x9f, 0xcc, 0x40, 0x73, +0xff, 0x3c, 0x26, 0x6e, 0xb3, 0xda, 0xc8, 0xef, 0x57, 0x5d, 0xd1, 0xca, 0xbf, 0x6d, 0xfc, 0x17, +0x34, 0x15, 0xd9, 0xe7, 0xc5, 0x55, 0x5d, 0xfd, 0x17, 0x98, 0x41, 0x43, 0xfb, 0xb7, 0x32, 0xa0, +0xef, 0xd8, 0x5d, 0xd3, 0xd5, 0x7f, 0x66, 0x06, 0xba, 0xfa, 0xcf, 0xcc, 0x40, 0x57, 0xff, 0x56, +0x06, 0xe4, 0xf9, 0xba, 0xae, 0xfe, 0x33, 0x33, 0xd0, 0xd5, 0x7f, 0x66, 0x06, 0xba, 0xfa, 0xcf, +0x18, 0x0f, 0x4e, 0xeb, 0xea, 0xdf, 0xaa, 0x71, 0xff, 0xe3, 0xfe, 0x1b, 0xc4, 0xff, 0x4e, 0x94, +0x59, 0x1d, 0x5b, 0xb1, 0x33, 0xaf, 0xf7, 0x7a, 0xf4, 0x1f, 0xc4, 0x13, 0xf1, 0x9c, 0x7e, 0x4e, +0x5a, 0x66, 0x19, 0x06, 0x26, 0x50, 0x06, 0xf7, 0xc7, 0x94, 0xff, 0x0a, 0x79, 0x2f, 0x2a, 0x83, +0xfa, 0xf1, 0xff, 0x54, 0x7c, 0x85, 0x13, 0x15, 0x2e, 0xce, 0x80, 0x7e, 0x83, 0xf2, 0xa0, 0xce, +0xfd, 0x57, 0xc5, 0xbb, 0x55, 0xdb, 0xb7, 0xa3, 0x89, 0x33, 0xa8, 0x53, 0xff, 0xcf, 0xaa, 0xe9, +0x3d, 0x33, 0x03, 0xf2, 0xfb, 0xb0, 0xce, 0xfc, 0xd7, 0xc4, 0xbb, 0x3d, 0x83, 0x3a, 0xf1, 0x5f, +0x53, 0xef, 0x59, 0xef, 0x85, 0xad, 0x08, 0x2a, 0xf6, 0xff, 0x5c, 0x85, 0x77, 0x7b, 0x06, 0x8a, +0xfc, 0x2b, 0xf5, 0x6e, 0xcf, 0xa0, 0xa6, 0xfe, 0x83, 0x58, 0x54, 0xc9, 0xf3, 0x7b, 0xb9, 0xc5, +0x19, 0xd0, 0xff, 0x9c, 0x2c, 0xaa, 0x95, 0xff, 0xb1, 0x50, 0xe3, 0xfe, 0xc7, 0xfd, 0xb7, 0x56, +0xc8, 0xff, 0x50, 0xb8, 0xeb, 0x3e, 0xc6, 0x58, 0xd1, 0x7f, 0xfd, 0xdc, 0x6f, 0xad, 0x8c, 0xff, +0x17, 0x3f, 0x7e, 0xdc, 0x9c, 0x88, 0x31, 0x56, 0xdb, 0xe9, 0x2f, 0x8c, 0xc8, 0x5f, 0x6f, 0x99, +0xfe, 0xc7, 0xa4, 0xf7, 0x62, 0x32, 0x68, 0x54, 0xef, 0xb6, 0x0c, 0x1e, 0x17, 0xe9, 0xff, 0x65, +0x23, 0x78, 0x2f, 0x24, 0x03, 0x95, 0xde, 0x69, 0x1e, 0xf8, 0x14, 0x03, 0x35, 0x28, 0xce, 0x60, +0x91, 0x1b, 0x4f, 0x6c, 0xfe, 0xd5, 0x79, 0xf7, 0xe1, 0x44, 0x6a, 0xce, 0xab, 0x03, 0xe7, 0x51, +0x83, 0xca, 0x91, 0x41, 0xe6, 0x77, 0xfc, 0xdf, 0xfd, 0xfe, 0xd0, 0xe3, 0x42, 0x0d, 0xea, 0x93, +0x17, 0xc7, 0xed, 0xf3, 0xbe, 0x74, 0x1c, 0x9c, 0x43, 0x0d, 0x6a, 0xc9, 0x12, 0x4c, 0x24, 0xdf, +0xaf, 0x6c, 0xfe, 0xdf, 0xab, 0xf4, 0xae, 0x28, 0x83, 0xd7, 0x84, 0xba, 0xf1, 0x6e, 0x81, 0xb7, +0x41, 0x0d, 0xca, 0xca, 0x00, 0xcb, 0x11, 0x75, 0xd1, 0xd7, 0x14, 0x0d, 0xc9, 0x21, 0xc9, 0x51, +0xc9, 0xfb, 0x24, 0x2f, 0x97, 0x3c, 0x5b, 0xf2, 0x54, 0xc9, 0x2e, 0xc9, 0x4d, 0x7d, 0x26, 0x3b, +0xe2, 0x26, 0xc3, 0x62, 0x9f, 0xe4, 0xe5, 0x92, 0x57, 0x49, 0x5e, 0x2d, 0xb9, 0x4d, 0xf2, 0x4a, +0xc3, 0xe4, 0x15, 0x21, 0xb9, 0x7d, 0x54, 0x72, 0xbb, 0xe4, 0x56, 0xc9, 0x33, 0x25, 0x37, 0x4b, +0x76, 0x49, 0x6e, 0x92, 0xec, 0xb0, 0xf4, 0xec, 0x1c, 0x93, 0x1c, 0x97, 0x9c, 0x90, 0x3c, 0x22, +0x59, 0x58, 0x7c, 0x46, 0xf2, 0x77, 0xc9, 0x7f, 0x25, 0x8b, 0x82, 0xd8, 0x41, 0x7f, 0x3b, 0x91, +0xec, 0x8f, 0x10, 0x21, 0x66, 0xfe, 0x67, 0x06, 0xe6, 0x16, 0x21, 0x62, 0xcc, 0x6e, 0x21, 0xe2, +0xcc, 0x6d, 0x42, 0x24, 0x98, 0xfd, 0x42, 0x8c, 0x30, 0x0b, 0x2a, 0xf6, 0xcf, 0x7c, 0x87, 0x72, +0x61, 0x4e, 0xe4, 0x67, 0x3f, 0xf3, 0x08, 0x7d, 0x28, 0x4f, 0x16, 0x1c, 0x26, 0x1b, 0x4d, 0xb4, +0x90, 0x56, 0x85, 0x5c, 0xb4, 0x11, 0x6d, 0x1a, 0x6d, 0x21, 0x55, 0x52, 0x8e, 0x31, 0xf8, 0x31, +0x2f, 0xe3, 0x75, 0xff, 0x00, 0xd3, 0x39, 0x74, 0x2c, 0x6e, 0x57, 0x00, 0x00}; +#endif /*__FAVICON_ICO_GZ_H__*/ diff --git a/tools/esp8266/html/h/index_html.h b/tools/esp8266/html/h/index_html.h index c6f769ce..34098afe 100644 --- a/tools/esp8266/html/h/index_html.h +++ b/tools/esp8266/html/h/index_html.h @@ -1,4 +1,5 @@ #ifndef __INDEX_HTML_H__ #define __INDEX_HTML_H__ const char index_html[] PROGMEM = "Index - {DEVICE}

AHOY - {DEVICE}

Visualization

Setup

Uptime:

Statistics:

Every {TS}seconds the values are updated

This project was started from this discussion. (Mikrocontroller.net)
New updates can be found on Github: https://github.com/grindylow/ahoy

Please report issues using the feature provided by Github

Discuss with us on Discord

Creative Commons - https://creativecommons.org/licenses/by-nc-sa/3.0/de/
Check the licenses which are published on https://github.com/grindylow/ahoyas well

© 2022

Update Firmware

AHOY :: {VERSION}

Reboot

Git SHA: {BUILD}

"; +const uint32_t index_html_len = 2317; #endif /*__INDEX_HTML_H__*/ diff --git a/tools/esp8266/html/h/setup_html.h b/tools/esp8266/html/h/setup_html.h index 5ec006e5..4ffbe94a 100644 --- a/tools/esp8266/html/h/setup_html.h +++ b/tools/esp8266/html/h/setup_html.h @@ -1,4 +1,5 @@ #ifndef __SETUP_HTML_H__ #define __SETUP_HTML_H__ -const char setup_html[] PROGMEM = "Setup - {DEVICE}

Setup

ERASE SETTINGS (not WiFi)
Device Host Name
WiFi

Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information.

Inverter{INVERTERS}

General

NTP Server
MQTT
System Config

Pinout (Wemos)

{PINOUT}

Radio (NRF24L01+)

Serial Console



"; +const char setup_html[] PROGMEM = "Setup - {#DEVICE}

Setup

ERASE SETTINGS (not WiFi)
Device Host Name
WiFi

Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information.

Inverter{#INVERTERS}

General

NTP Server
MQTT
System Config

Pinout (Wemos)

{#PINOUT}

Radio (NRF24L01+)

Serial Console



"; +const uint32_t setup_html_len = 5023; #endif /*__SETUP_HTML_H__*/ diff --git a/tools/esp8266/html/h/style_css.h b/tools/esp8266/html/h/style_css.h index 24f50e79..dcfb045f 100644 --- a/tools/esp8266/html/h/style_css.h +++ b/tools/esp8266/html/h/style_css.h @@ -1,4 +1,5 @@ #ifndef __STYLE_CSS_H__ #define __STYLE_CSS_H__ const char style_css[] PROGMEM = "h1 {margin:0;padding:20pt;font-size:22pt;color:#fff;background-color:#006ec0;display:block;text-transform:uppercase;}html, body {font-family:Arial;margin:0;padding:0;}p {text-align:justify;font-size:13pt;}p.lic, p.lic a {font-size:8pt;color:#999;}.des {margin-top:20px;font-size:13pt;color:#006ec0;}.s_active, .s_collapsible:hover {background-color:#006ec0;}.s_content {display:none;overflow:hidden;}.s_collapsible {background-color:#044e86;color:white;cursor:pointer;padding:18px;width:100%;border:none;text-align:left;outline:none;font-size:15px;margin-bottom:4px;}.subdes {font-size:12pt;color:#006ec0;margin-left:7px;}.subsubdes {font-size:12pt;color:#006ec0;margin:0 0 7px 12px;}.hide {display:none;}a:link, a:visited {text-decoration:none;font-size:13pt;color:#006ec0;}a:hover, a:focus {color:#f00;}a.erase {background-color:#006ec0;color:#fff;padding:7px;display:inline-block;margin-top:30px;}#content {padding:15px 15px 60px 15px;}#footer {position:fixed;bottom:0px;height:45px;background-color:#006ec0;width:100%;border-top:5px solid #fff;}#footer p, #footer a {color:#fff;padding:0 7px 0 7px;font-size:10pt !important;}div.content {background-color:#fff;padding-bottom:65px;overflow:auto;}input, select {padding:7px;font-size:13pt;}input.text, select {width:70%;box-sizing:border-box;margin-bottom:10px;border:1px solid #ccc;}input.sh {max-width:150px !important;margin-right:10px;}input.btn {background-color:#006ec0;color:#fff;border:0px;float:right;margin:10px 0 30px;text-transform:uppercase;}input.cb {margin-bottom:20px;}label {width:20%;display:inline-block;font-size:12pt;padding-right:10px;margin:10px 0px 0px 15px;vertical-align:top;}fieldset {margin-bottom:15px;}.left {float:left;}.right {float:right;}div.ch-iv {width:100%;background-color:#32b004;display:inline-block;margin-bottom:15px;padding-bottom:20px;overflow:auto;}div.ch {width:220px;min-height:350px;background-color:#006ec0;display:inline-block;margin:0 10px 15px 10px;overflow:auto;padding-bottom:20px;}div.ch .value, div.ch .info, div.ch .head, div.ch-iv .value, div.ch-iv .info, div.ch-iv .head {color:#fff;display:block;width:100%;text-align:center;}.subgrp {float:left;width:220px;}div.ch .unit, div.ch-iv .unit {font-size:19px;margin-left:10px;}div.ch .value, div.ch-iv .value {margin-top:20px;font-size:24px;}div.ch .info, div.ch-iv .info {margin-top:3px;font-size:10px;}div.ch .head {background-color:#003c80;padding:10px 0 10px 0;}div.ch-iv .head {background-color:#1c6800;padding:10px 0 10px 0;}div.iv {max-width:960px;margin-bottom:40px;}div.ts {font-size:13px;background-color:#ddd;border-top:7px solid #999;padding:7px;}div.modpwr, div.modname {width:70%;display:inline-block;}#note {margin:50px 10px 10px 10px;padding-top:10px;width:100%;border-top:1px solid #bbb;}@media(max-width:500px) {div.ch .unit, div.ch-iv .unit {font-size:18px;}div.ch {width:170px;min-height:100px }.subgrp {width:180px;}}"; +const uint32_t style_css_len = 2899; #endif /*__STYLE_CSS_H__*/ diff --git a/tools/esp8266/html/h/visualization_html.h b/tools/esp8266/html/h/visualization_html.h index b70bc5b2..1b05b37c 100644 --- a/tools/esp8266/html/h/visualization_html.h +++ b/tools/esp8266/html/h/visualization_html.h @@ -1,4 +1,5 @@ #ifndef __VISUALIZATION_HTML_H__ #define __VISUALIZATION_HTML_H__ const char visualization_html[] PROGMEM = "Index - {DEVICE}

AHOY - {DEVICE}

Every {TS}seconds the values are updated

© 2022

Home

AHOY :: {VERSION}

"; +const uint32_t visualization_html_len = 922; #endif /*__VISUALIZATION_HTML_H__*/ diff --git a/tools/esp8266/html/setup.html b/tools/esp8266/html/setup.html index 98a30680..53404b4c 100644 --- a/tools/esp8266/html/setup.html +++ b/tools/esp8266/html/setup.html @@ -1,7 +1,7 @@ - Setup - {DEVICE} + Setup - {#DEVICE}

AHOY - {DEVICE}

Visualization

Setup

Uptime:

Statistics:

Every {TS}seconds the values are updated

This project was started from this discussion. (Mikrocontroller.net)
New updates can be found on Github: https://github.com/grindylow/ahoy

Please report issues using the feature provided by Github

Discuss with us on Discord

Creative Commons - https://creativecommons.org/licenses/by-nc-sa/3.0/de/
Check the licenses which are published on https://github.com/grindylow/ahoyas well

© 2022

Update Firmware

AHOY :: {VERSION}

Reboot

Git SHA: {BUILD}

"; -const uint32_t index_html_len = 2317; -#endif /*__INDEX_HTML_H__*/ diff --git a/tools/esp8266/html/h/setup_html.h b/tools/esp8266/html/h/setup_html.h deleted file mode 100644 index 990ab73a..00000000 --- a/tools/esp8266/html/h/setup_html.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef __SETUP_HTML_H__ -#define __SETUP_HTML_H__ -const char setup_html[] PROGMEM = "Setup - {#DEVICE}

Setup

ERASE SETTINGS (not WiFi)
Device Host Name
WiFi

Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information.

Inverter{#INVERTERS}

General

NTP Server
MQTT
System Config

Pinout (Wemos)

{#PINOUT}

Radio (NRF24L01+)

Serial Console



"; -const uint32_t setup_html_len = 5019; -#endif /*__SETUP_HTML_H__*/ diff --git a/tools/esp8266/html/h/style_css.h b/tools/esp8266/html/h/style_css.h deleted file mode 100644 index dcfb045f..00000000 --- a/tools/esp8266/html/h/style_css.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef __STYLE_CSS_H__ -#define __STYLE_CSS_H__ -const char style_css[] PROGMEM = "h1 {margin:0;padding:20pt;font-size:22pt;color:#fff;background-color:#006ec0;display:block;text-transform:uppercase;}html, body {font-family:Arial;margin:0;padding:0;}p {text-align:justify;font-size:13pt;}p.lic, p.lic a {font-size:8pt;color:#999;}.des {margin-top:20px;font-size:13pt;color:#006ec0;}.s_active, .s_collapsible:hover {background-color:#006ec0;}.s_content {display:none;overflow:hidden;}.s_collapsible {background-color:#044e86;color:white;cursor:pointer;padding:18px;width:100%;border:none;text-align:left;outline:none;font-size:15px;margin-bottom:4px;}.subdes {font-size:12pt;color:#006ec0;margin-left:7px;}.subsubdes {font-size:12pt;color:#006ec0;margin:0 0 7px 12px;}.hide {display:none;}a:link, a:visited {text-decoration:none;font-size:13pt;color:#006ec0;}a:hover, a:focus {color:#f00;}a.erase {background-color:#006ec0;color:#fff;padding:7px;display:inline-block;margin-top:30px;}#content {padding:15px 15px 60px 15px;}#footer {position:fixed;bottom:0px;height:45px;background-color:#006ec0;width:100%;border-top:5px solid #fff;}#footer p, #footer a {color:#fff;padding:0 7px 0 7px;font-size:10pt !important;}div.content {background-color:#fff;padding-bottom:65px;overflow:auto;}input, select {padding:7px;font-size:13pt;}input.text, select {width:70%;box-sizing:border-box;margin-bottom:10px;border:1px solid #ccc;}input.sh {max-width:150px !important;margin-right:10px;}input.btn {background-color:#006ec0;color:#fff;border:0px;float:right;margin:10px 0 30px;text-transform:uppercase;}input.cb {margin-bottom:20px;}label {width:20%;display:inline-block;font-size:12pt;padding-right:10px;margin:10px 0px 0px 15px;vertical-align:top;}fieldset {margin-bottom:15px;}.left {float:left;}.right {float:right;}div.ch-iv {width:100%;background-color:#32b004;display:inline-block;margin-bottom:15px;padding-bottom:20px;overflow:auto;}div.ch {width:220px;min-height:350px;background-color:#006ec0;display:inline-block;margin:0 10px 15px 10px;overflow:auto;padding-bottom:20px;}div.ch .value, div.ch .info, div.ch .head, div.ch-iv .value, div.ch-iv .info, div.ch-iv .head {color:#fff;display:block;width:100%;text-align:center;}.subgrp {float:left;width:220px;}div.ch .unit, div.ch-iv .unit {font-size:19px;margin-left:10px;}div.ch .value, div.ch-iv .value {margin-top:20px;font-size:24px;}div.ch .info, div.ch-iv .info {margin-top:3px;font-size:10px;}div.ch .head {background-color:#003c80;padding:10px 0 10px 0;}div.ch-iv .head {background-color:#1c6800;padding:10px 0 10px 0;}div.iv {max-width:960px;margin-bottom:40px;}div.ts {font-size:13px;background-color:#ddd;border-top:7px solid #999;padding:7px;}div.modpwr, div.modname {width:70%;display:inline-block;}#note {margin:50px 10px 10px 10px;padding-top:10px;width:100%;border-top:1px solid #bbb;}@media(max-width:500px) {div.ch .unit, div.ch-iv .unit {font-size:18px;}div.ch {width:170px;min-height:100px }.subgrp {width:180px;}}"; -const uint32_t style_css_len = 2899; -#endif /*__STYLE_CSS_H__*/ diff --git a/tools/esp8266/html/h/visualization_html.h b/tools/esp8266/html/h/visualization_html.h deleted file mode 100644 index 1b05b37c..00000000 --- a/tools/esp8266/html/h/visualization_html.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef __VISUALIZATION_HTML_H__ -#define __VISUALIZATION_HTML_H__ -const char visualization_html[] PROGMEM = "Index - {DEVICE}

AHOY - {DEVICE}

Every {TS}seconds the values are updated

© 2022

Home

AHOY :: {VERSION}

"; -const uint32_t visualization_html_len = 922; -#endif /*__VISUALIZATION_HTML_H__*/ diff --git a/tools/esp8266/html/setup.html b/tools/esp8266/html/setup.html index 9d32fedb..309968d0 100644 --- a/tools/esp8266/html/setup.html +++ b/tools/esp8266/html/setup.html @@ -54,11 +54,11 @@
ERASE SETTINGS (not WiFi) -
+
Device Host Name - +
@@ -67,7 +67,7 @@ WiFi

Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information.

- + @@ -77,12 +77,12 @@
Inverter - {#INVERTERS}
+

General

- + - +
@@ -102,15 +102,15 @@
MQTT - + - + - + - + - +
@@ -143,11 +143,11 @@ diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 4ac2b004..6a48d00b 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -41,6 +41,9 @@ web::web(app *main, sysConfig_t *sysCfg, config_t *config, char version[]) { mConfig = config; mVersion = version; mWeb = new AsyncWebServer(80); + //mEvts = new AsyncEventSource("/events"); + + mApi = new api(mWeb, main, sysCfg, config, version); } @@ -48,7 +51,7 @@ web::web(app *main, sysConfig_t *sysCfg, config_t *config, char version[]) { void web::setup(void) { DPRINTLN(DBG_VERBOSE, F("app::setup-begin")); mWeb->begin(); - DPRINTLN(DBG_VERBOSE, F("app::setup-on")); + DPRINTLN(DBG_VERBOSE, F("app::setup-on")); mWeb->on("/", HTTP_ANY, std::bind(&web::showIndex, this, std::placeholders::_1)); mWeb->on("/style.css", HTTP_ANY, std::bind(&web::showCss, this, std::placeholders::_1)); mWeb->on("/favicon.ico", HTTP_ANY, std::bind(&web::showFavicon, this, std::placeholders::_1)); @@ -71,15 +74,31 @@ void web::setup(void) { mWeb->on("/update", HTTP_GET, std::bind(&web::showUpdateForm, this, std::placeholders::_1)); mWeb->on("/update", HTTP_POST, std::bind(&web::showUpdate, this, std::placeholders::_1), std::bind(&web::showUpdate2, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6)); + + //mEvts->onConnect(std::bind(&web::onConnect, this, std::placeholders::_1)); + //mWeb->addHandler(mEvts); + + mApi->setup(); } //----------------------------------------------------------------------------- void web::loop(void) { - + mApi->loop(); } +//----------------------------------------------------------------------------- +/*void web::onConnect(AsyncEventSourceClient *client) { + DPRINTLN(DBG_INFO, "onConnect"); + + if(client->lastId()) + DPRINTLN(DBG_INFO, "Client reconnected! Last message ID that it got is: " + String(client->lastId())); + + client->send("hello!", NULL, millis(), 1000); +}*/ + + //----------------------------------------------------------------------------- void web::showIndex(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("showIndex")); @@ -192,8 +211,11 @@ void web::showFactoryRst(AsyncWebServerRequest *request) { void web::showSetup(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("app::showSetup")); - tmplProc *proc = new tmplProc(request, 11000); - proc->process(setup_html, setup_html_len, std::bind(&web::showSetupCb, this, std::placeholders::_1)); + //tmplProc *proc = new tmplProc(request, 11000); + //proc->process(setup_html, setup_html_len, std::bind(&web::showSetupCb, this, std::placeholders::_1)); + AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), setup_html, setup_html_len); + response->addHeader(F("Content-Encoding"), "gzip"); + request->send(response); } @@ -391,7 +413,6 @@ void web::showLiveData(AsyncWebServerRequest *request) { } } modHtml += ""; - yield(); } modHtml += F("
Last received data requested at: ") + mMain->getDateTimeStr(iv->ts) + F("
"); modHtml += F(""); @@ -563,64 +584,6 @@ String web::showSetupCb(char* key) { if(generic.length() == 0) { if(0 == strncmp(key, "SSID", 4)) return mSysCfg->stationSsid; else if(0 == strncmp(key, "PWD", 3)) return F("{PWD}"); - else if(0 == strncmp(key, "INVERTERS", 9)) { - String inv = ""; - Inverter<> *iv; - for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) { - iv = mMain->mSys->getInverterByPos(i); - - inv += F("

Inverter ") + String(i) + "

"; - inv += F(""); - inv += F("serial.u64, HEX); - inv += F("\"/ maxlength=\"12\">"); - - inv += F(""); - inv += F("name); - inv += F("\"/ maxlength=\"") + String(MAX_NAME_LENGTH) + "\">"; - - inv += F(""); - inv += F("powerLimit[0]); - inv += F("\"/ maxlength=\"") + String(6) + "\">"; - - inv += F(""); - inv += F(""); - - inv += F("
"); - for(uint8_t j = 0; j < 4; j++) { - inv += F("chMaxPwr[j]); - inv += F("\"/ maxlength=\"4\">"); - } - inv += F("

"); - for(uint8_t j = 0; j < 4; j++) { - inv += F("chName[j]); - inv += F("\"/ maxlength=\"") + String(MAX_NAME_LENGTH) + "\">"; - } - inv += F("
"); - } - DPRINTLN(DBG_INFO, inv); - return inv; - } else if(0 == strncmp(key, "PINOUT", 6)) { String pinout = ""; for(uint8_t i = 0; i < 3; i++) { @@ -661,7 +624,6 @@ String web::showSetupCb(char* key) { else if(0 == strncmp(key, "MQTT_USER", 9)) return String(mConfig->mqtt.user); else if(0 == strncmp(key, "MQTT_PWD", 8)) return String(mConfig->mqtt.pwd); else if(0 == strncmp(key, "MQTT_TOPIC", 10)) return String(mConfig->mqtt.topic); - //else if(0 == strncmp(key, "MQTT_INTVL", 10)) return String(mMqttInterval); } return generic; diff --git a/tools/esp8266/web.h b/tools/esp8266/web.h index 43226304..7f7da316 100644 --- a/tools/esp8266/web.h +++ b/tools/esp8266/web.h @@ -10,9 +10,11 @@ #include "ESPAsyncTCP.h" #include "ESPAsyncWebServer.h" #include "app.h" +#include "api.h" #include "tmplProc.h" class app; +class api; class web { public: @@ -22,6 +24,8 @@ class web { void setup(void); void loop(void); + void onConnect(AsyncEventSourceClient *client); + void showIndex(AsyncWebServerRequest *request); void showCss(AsyncWebServerRequest *request); void showFavicon(AsyncWebServerRequest *request); @@ -49,11 +53,13 @@ class web { String showUpdateFormCb(char* key); AsyncWebServer *mWeb; + AsyncEventSource *mEvts; config_t *mConfig; sysConfig_t *mSysCfg; char *mVersion; app *mMain; + api *mApi; }; #endif /*__WEB_H__*/ From b6ac41666549d38b7c20b6e2c3ff5db7df867f0a Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 28 Aug 2022 01:48:53 +0200 Subject: [PATCH 03/38] improved async web setup page --- tools/esp8266/api.cpp | 66 ++++++++++++- tools/esp8266/api.h | 4 + tools/esp8266/app.h | 7 -- tools/esp8266/html/convert.py | 2 +- tools/esp8266/html/setup.html | 175 ++++++++++++++++++++-------------- tools/esp8266/html/style.css | 2 +- tools/esp8266/web.cpp | 77 +-------------- tools/esp8266/web.h | 1 - 8 files changed, 176 insertions(+), 158 deletions(-) diff --git a/tools/esp8266/api.cpp b/tools/esp8266/api.cpp index 59f2817e..8270797f 100644 --- a/tools/esp8266/api.cpp +++ b/tools/esp8266/api.cpp @@ -26,6 +26,10 @@ void api::setup(void) { mSrv->on("/api/system", HTTP_GET, std::bind(&api::onSystem, this, std::placeholders::_1)); mSrv->on("/api/inverter/list", HTTP_GET, std::bind(&api::onInverterList, this, std::placeholders::_1)); mSrv->on("/api/mqtt", HTTP_GET, std::bind(&api::onMqtt, this, std::placeholders::_1)); + mSrv->on("/api/ntp", HTTP_GET, std::bind(&api::onNtp, this, std::placeholders::_1)); + mSrv->on("/api/pinout", HTTP_GET, std::bind(&api::onPinout, this, std::placeholders::_1)); + mSrv->on("/api/radio", HTTP_GET, std::bind(&api::onRadio, this, std::placeholders::_1)); + mSrv->on("/api/serial", HTTP_GET, std::bind(&api::onSerial, this, std::placeholders::_1)); } @@ -72,12 +76,13 @@ void api::onInverterList(AsyncWebServerRequest *request) { obj[F("ch_name")][j] = iv->chName[j]; } - obj[F("power_limit")][F("limit")] = iv->powerLimit[0]; - obj[F("power_limit")][F("limit_option")] = iv->powerLimit[1]; + obj[F("power_limit")] = iv->powerLimit[0]; + obj[F("power_limit_option")] = iv->powerLimit[1]; } } root[F("interval")] = String(mConfig->sendInterval); root[F("retries")] = String(mConfig->maxRetransPerPyld); + root[F("max_num_inverters")] = MAX_NUM_INVERTERS; response->setLength(); request->send(response); @@ -92,9 +97,64 @@ void api::onMqtt(AsyncWebServerRequest *request) { root[F("broker")] = String(mConfig->mqtt.broker); root[F("port")] = String(mConfig->mqtt.port); root[F("user")] = String(mConfig->mqtt.user); - root[F("pwd")] = String(mConfig->mqtt.pwd); // TODO: not that nice! + root[F("pwd")] = (strlen(mConfig->mqtt.pwd) > 0) ? F("{PWD}") : String(""); root[F("topic")] = String(mConfig->mqtt.topic); response->setLength(); request->send(response); } + + +//----------------------------------------------------------------------------- +void api::onNtp(AsyncWebServerRequest *request) { + AsyncJsonResponse* response = new AsyncJsonResponse(); + JsonObject root = response->getRoot(); + + root[F("addr")] = String(mConfig->ntpAddr); + root[F("port")] = String(mConfig->ntpPort); + + response->setLength(); + request->send(response); +} + + +//----------------------------------------------------------------------------- +void api::onPinout(AsyncWebServerRequest *request) { + AsyncJsonResponse* response = new AsyncJsonResponse(); + JsonObject root = response->getRoot(); + + root[F("cs")] = mConfig->pinCs; + root[F("ce")] = mConfig->pinCe; + root[F("irq")] = mConfig->pinIrq; + + response->setLength(); + request->send(response); +} + + +//----------------------------------------------------------------------------- +void api::onRadio(AsyncWebServerRequest *request) { + AsyncJsonResponse* response = new AsyncJsonResponse(); + JsonObject root = response->getRoot(); + + root[F("power_level")] = mConfig->amplifierPower; + + response->setLength(); + request->send(response); +} + + + +//----------------------------------------------------------------------------- +void api::onSerial(AsyncWebServerRequest *request) { + AsyncJsonResponse* response = new AsyncJsonResponse(); + JsonObject root = response->getRoot(); + + // next line cause a chrash but why? + //root[F("interval")] = mConfig->serialInterval; + root[F("show_live_data")] = mConfig->serialShowIv; + root[F("debug")] = mConfig->serialDebug; + + response->setLength(); + request->send(response); +} diff --git a/tools/esp8266/api.h b/tools/esp8266/api.h index 84df8023..03e3a164 100644 --- a/tools/esp8266/api.h +++ b/tools/esp8266/api.h @@ -20,6 +20,10 @@ class api { void onSystem(AsyncWebServerRequest *request); void onInverterList(AsyncWebServerRequest *request); void onMqtt(AsyncWebServerRequest *request); + void onNtp(AsyncWebServerRequest *request); + void onPinout(AsyncWebServerRequest *request); + void onRadio(AsyncWebServerRequest *request); + void onSerial(AsyncWebServerRequest *request); AsyncWebServer *mSrv; app *mApp; diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index 9e66fcd3..a3a33d20 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -36,13 +36,6 @@ typedef HmRadio RadioType; typedef Inverter InverterType; typedef HmSystem HmSystemType; -const char* const wemosPins[] = {"D3 (GPIO0)", "TX (GPIO1)", "D4 (GPIO2)", "RX (GPIO3)", - "D2 (GPIO4)", "D1 (GPIO5)", "GPIO6", "GPIO7", "GPIO8", - "GPIO9", "GPIO10", "GPIO11", "D6 (GPIO12)", "D7 (GPIO13)", - "D5 (GPIO14)", "D8 (GPIO15)", "D0 (GPIO16 - no IRQ!)"}; -const char* const pinNames[] = {"CS", "CE", "IRQ"}; -const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq"}; - typedef struct { uint8_t invId; diff --git a/tools/esp8266/html/convert.py b/tools/esp8266/html/convert.py index d03e3e58..953dafca 100755 --- a/tools/esp8266/html/convert.py +++ b/tools/esp8266/html/convert.py @@ -21,7 +21,7 @@ def convert2Header(inFile, compress): if False == compress: if fileType == "html": data = re.sub(r"\>\s+\<", '><', data) # whitespaces between xml tags - data = re.sub(r"(\;|\}|\>|\{)\s+", r'\1', data) # whitespaces inner javascript + data = re.sub(r"(\s?\;|\}|\>|\{|\=)\s+", r'\1', data) # whitespaces inner javascript length = len(data) # get unescaped length data = re.sub(r"\"", '\\\"', data) # escape quotation marks else: diff --git a/tools/esp8266/html/setup.html b/tools/esp8266/html/setup.html index 309968d0..bf1e3b1c 100644 --- a/tools/esp8266/html/setup.html +++ b/tools/esp8266/html/setup.html @@ -1,7 +1,7 @@ - Setup - {#DEVICE} + Setup diff --git a/tools/esp8266/html/style.css b/tools/esp8266/html/style.css index 8ce9c570..eea5db06 100644 --- a/tools/esp8266/html/style.css +++ b/tools/esp8266/html/style.css @@ -231,7 +231,7 @@ div.ts { padding: 7px; } -div.modpwr, div.modname { +div.ModPwr, div.ModName { width:70%; display: inline-block; } diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 6a48d00b..b4510e9f 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -17,22 +17,7 @@ #include "html/h/visualization_html.h" #include "html/h/update_html.h" - -const uint16_t pwrLimitOptionValues[] { - NoPowerLimit, - AbsolutNonPersistent, - AbsolutPersistent, - RelativNonPersistent, - RelativPersistent -}; - -const char* const pwrLimitOptions[] { - "no power limit", - "absolute in Watt non persistent", - "absolute in Watt persistent", - "relativ in percent non persistent", - "relativ in percent persistent" -}; +const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq"}; //----------------------------------------------------------------------------- web::web(app *main, sysConfig_t *sysCfg, config_t *config, char version[]) { @@ -211,8 +196,6 @@ void web::showFactoryRst(AsyncWebServerRequest *request) { void web::showSetup(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("app::showSetup")); - //tmplProc *proc = new tmplProc(request, 11000); - //proc->process(setup_html, setup_html_len, std::bind(&web::showSetupCb, this, std::placeholders::_1)); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), setup_html, setup_html_len); response->addHeader(F("Content-Encoding"), "gzip"); request->send(response); @@ -306,7 +289,8 @@ void web::showSave(AsyncWebServerRequest *request) { if(request->arg("mqttAddr") != "") { request->arg("mqttAddr").toCharArray(mConfig->mqtt.broker, MQTT_ADDR_LEN); request->arg("mqttUser").toCharArray(mConfig->mqtt.user, MQTT_USER_LEN); - request->arg("mqttPwd").toCharArray(mConfig->mqtt.pwd, MQTT_PWD_LEN); + if(request->arg("mqttPwd") != "{PWD}") + request->arg("mqttPwd").toCharArray(mConfig->mqtt.pwd, MQTT_PWD_LEN); request->arg("mqttTopic").toCharArray(mConfig->mqtt.topic, MQTT_TOPIC_LEN); mConfig->mqtt.port = request->arg("mqttPort").toInt(); } @@ -575,61 +559,6 @@ String web::replaceHtmlGenericKeys(char *key) { } -//----------------------------------------------------------------------------- -String web::showSetupCb(char* key) { - // PWD will be left at the default value (for protection) - // -> the PWD will only be changed if it does not match the placeholder "{PWD}" - - String generic = replaceHtmlGenericKeys(key); - if(generic.length() == 0) { - if(0 == strncmp(key, "SSID", 4)) return mSysCfg->stationSsid; - else if(0 == strncmp(key, "PWD", 3)) return F("{PWD}"); - else if(0 == strncmp(key, "PINOUT", 6)) { - String pinout = ""; - for(uint8_t i = 0; i < 3; i++) { - pinout += F(""); - pinout += F(""); - } - return pinout; - } - else if(0 == strncmp(key, "RF24", 4)) { - String rf24 = ""; - for(uint8_t i = 0; i <= 3; i++) { - rf24 += F(""); - } - return rf24; - } - else if(0 == strncmp(key, "INV_INTVL", 9)) return String(mConfig->sendInterval); - else if(0 == strncmp(key, "INV_RETRIES", 11)) return String(mConfig->maxRetransPerPyld); - else if(0 == strncmp(key, "SER_INTVL", 9)) return String(mConfig->serialInterval); - else if(0 == strncmp(key, "SER_VAL_CB", 10)) return (mConfig->serialShowIv) ? "checked" : ""; - else if(0 == strncmp(key, "SER_DBG_CB", 10)) return (mConfig->serialDebug) ? "checked" : ""; - else if(0 == strncmp(key, "NTP_ADDR", 8)) return String(mConfig->ntpAddr); - else if(0 == strncmp(key, "NTP_PORT", 8)) return String(mConfig->ntpPort); - else if(0 == strncmp(key, "MQTT_ADDR", 9)) return String(mConfig->mqtt.broker); - else if(0 == strncmp(key, "MQTT_PORT", 9)) return String(mConfig->mqtt.port); - else if(0 == strncmp(key, "MQTT_USER", 9)) return String(mConfig->mqtt.user); - else if(0 == strncmp(key, "MQTT_PWD", 8)) return String(mConfig->mqtt.pwd); - else if(0 == strncmp(key, "MQTT_TOPIC", 10)) return String(mConfig->mqtt.topic); - } - - return generic; -} - - //----------------------------------------------------------------------------- String web::showUpdateFormCb(char *key) { String generic = replaceHtmlGenericKeys(key); diff --git a/tools/esp8266/web.h b/tools/esp8266/web.h index 7f7da316..0d8fe760 100644 --- a/tools/esp8266/web.h +++ b/tools/esp8266/web.h @@ -49,7 +49,6 @@ class web { private: String replaceHtmlGenericKeys(char *key); - String showSetupCb(char* key); String showUpdateFormCb(char* key); AsyncWebServer *mWeb; From 08d86587376864e7951d8ffabea13abd43b5d314 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 28 Aug 2022 13:54:34 +0200 Subject: [PATCH 04/38] setup page complete converted to static version --- tools/esp8266/api.cpp | 13 ++++++++----- tools/esp8266/html/setup.html | 10 +++++++++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/tools/esp8266/api.cpp b/tools/esp8266/api.cpp index 8270797f..2cded6ed 100644 --- a/tools/esp8266/api.cpp +++ b/tools/esp8266/api.cpp @@ -44,8 +44,12 @@ void api::onSystem(AsyncWebServerRequest *request) { AsyncJsonResponse* response = new AsyncJsonResponse(); JsonObject root = response->getRoot(); - root[F("ssid")] = mSysCfg->stationSsid; + root[F("ssid")] = mSysCfg->stationSsid; root[F("device_name")] = mSysCfg->deviceName; + root[F("version")] = String(mVersion); + root[F("build")] = String(AUTO_GIT_HASH); + root[F("ts_uptime")] = mApp->getUptime(); + root[F("ts_now")] = mApp->getTimestamp(); response->setLength(); //response->addHeader("Access-Control-Allow-Origin", "*"); @@ -80,8 +84,8 @@ void api::onInverterList(AsyncWebServerRequest *request) { obj[F("power_limit_option")] = iv->powerLimit[1]; } } - root[F("interval")] = String(mConfig->sendInterval); - root[F("retries")] = String(mConfig->maxRetransPerPyld); + root[F("interval")] = String(mConfig->sendInterval); + root[F("retries")] = String(mConfig->maxRetransPerPyld); root[F("max_num_inverters")] = MAX_NUM_INVERTERS; response->setLength(); @@ -150,8 +154,7 @@ void api::onSerial(AsyncWebServerRequest *request) { AsyncJsonResponse* response = new AsyncJsonResponse(); JsonObject root = response->getRoot(); - // next line cause a chrash but why? - //root[F("interval")] = mConfig->serialInterval; + root[F("interval")] = (uint16_t)mConfig->serialInterval; root[F("show_live_data")] = mConfig->serialShowIv; root[F("debug")] = mConfig->serialDebug; diff --git a/tools/esp8266/html/setup.html b/tools/esp8266/html/setup.html index bf1e3b1c..d540e7e6 100644 --- a/tools/esp8266/html/setup.html +++ b/tools/esp8266/html/setup.html @@ -145,7 +145,7 @@ @@ -265,6 +265,7 @@ function parseSys(obj) { for(var i of [["device", "device_name"], ["ssid", "ssid"]]) document.getElementsByName(i[0])[0].value = obj[i[1]]; + document.getElementById("version").innerHTML = "Git SHA: " + obj["build"] + " :: " + obj["version"]; } function parseIv(obj) { @@ -322,12 +323,19 @@ ], obj["power_level"])); } + function parseSerial(obj) { + for(var i of [["serEn", "show_live_data"], ["serDbg", "debug"]]) + document.getElementsByName(i[0])[0].checked = obj[i[1]]; + document.getElementsByName("serIntvl")[0].value = obj["interval"]; + } + getAjax("/api/system", parseSys); getAjax("/api/inverter/list", parseIv); getAjax("/api/mqtt", parseMqtt); getAjax("/api/ntp", parseNtp); getAjax("/api/pinout", parsePinout); getAjax("/api/radio", parseRadio); + getAjax("/api/serial", parseSerial); From 440d386ec0e7ad7a91c0bf558f0f9dbe8c80fc6d Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 28 Aug 2022 22:32:34 +0200 Subject: [PATCH 05/38] * improved api (now webApi) * converted index to static page --- tools/esp8266/app.cpp | 18 ++-- tools/esp8266/app.h | 5 +- tools/esp8266/defines.h | 6 ++ tools/esp8266/html/api.js | 65 ++++++++++++ tools/esp8266/html/convert.py | 37 ++++--- tools/esp8266/html/index.html | 74 ++++++------- tools/esp8266/html/setup.html | 146 +++++++------------------- tools/esp8266/web.cpp | 71 +++++++------ tools/esp8266/web.h | 19 ++-- tools/esp8266/{api.cpp => webApi.cpp} | 53 ++++++---- tools/esp8266/{api.h => webApi.h} | 12 ++- 11 files changed, 266 insertions(+), 240 deletions(-) create mode 100644 tools/esp8266/html/api.js rename tools/esp8266/{api.cpp => webApi.cpp} (70%) rename tools/esp8266/{api.h => webApi.h} (70%) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 2bdb29ec..0685dcb4 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -42,7 +42,7 @@ void app::setup(uint32_t timeout) { #endif mSys->setup(&mConfig); - mWebInst = new web(this, &mSysConfig, &mConfig, mVersion); + mWebInst = new web(this, &mSysConfig, &mConfig, &mStat, mVersion); mWebInst->setup(); } @@ -88,7 +88,7 @@ void app::loop(void) { DPRINT(DBG_INFO, "RX " + String(len) + "B Ch" + String(p->rxCh) + " | "); mSys->Radio.dumpBuf(NULL, p->packet, len); } - mFrameCnt++; + mStat.frmCnt++; if(0 != len) { Inverter<> *iv = mSys->findInverter(&p->packet[1]); @@ -231,7 +231,7 @@ void app::loop(void) { processPayload(false); if(!mPayload[iv->id].complete) { - mRxFailed++; + mStat.rxFail++; iv->setQueuedCmdFinished(); // command failed if(mConfig.serialDebug) { DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); @@ -358,7 +358,7 @@ void app::processPayload(bool retransmit) { DPRINT(DBG_INFO, F("Payload (") + String(offs) + "): "); mSys->Radio.dumpBuf(NULL, payload, offs); } - mRxSuccess++; + mStat.rxSuccess++; iv->getAssignment(); // choose the parser for(uint8_t i = 0; i < iv->listLen; i++) { @@ -498,9 +498,9 @@ void app::cbMqtt(char* topic, byte* payload, unsigned int length) { //----------------------------------------------------------------------------- String app::getStatistics(void) { - String content = F("Receive success: ") + String(mRxSuccess) + "\n"; - content += F("Receive fail: ") + String(mRxFailed) + "\n"; - content += F("Frames received: ") + String(mFrameCnt) + "\n"; + String content = F("Receive success: ") + String(mStat.rxSuccess) + "\n"; + content += F("Receive fail: ") + String(mStat.rxFail) + "\n"; + content += F("Frames received: ") + String(mStat.frmCnt) + "\n"; content += F("Send Cnt: ") + String(mSys->Radio.mSendCnt) + String("\n\n"); Inverter<> *iv; @@ -686,9 +686,7 @@ void app::resetSystem(void) { memset(mPayload, 0, (MAX_NUM_INVERTERS * sizeof(invPayload_t))); - mRxFailed = 0; - mRxSuccess = 0; - mFrameCnt = 0; + memset(&mStat, 0, sizeof(statistics_t)); mLastPacketId = 0x00; } diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index a3a33d20..1fd3b5db 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -48,7 +48,6 @@ typedef struct { bool requested; } invPayload_t; - class ahoywifi; class web; @@ -239,9 +238,7 @@ class app { uint8_t mSendLastIvId; invPayload_t mPayload[MAX_NUM_INVERTERS]; - uint32_t mRxFailed; - uint32_t mRxSuccess; - uint32_t mFrameCnt; + statistics_t mStat; uint8_t mLastPacketId; // timer diff --git a/tools/esp8266/defines.h b/tools/esp8266/defines.h index 210604a5..867b3cb5 100644 --- a/tools/esp8266/defines.h +++ b/tools/esp8266/defines.h @@ -154,6 +154,12 @@ typedef struct { } /*__attribute__((__packed__))*/ config_t; #pragma pack(pop) // restore original alignment from stack +typedef struct { + uint32_t rxFail; + uint32_t rxSuccess; + uint32_t frmCnt; +} statistics_t; + #define CFG_MQTT_LEN MQTT_ADDR_LEN + 2 + MQTT_USER_LEN + MQTT_PWD_LEN +MQTT_TOPIC_LEN #define CFG_SYS_LEN DEVNAME_LEN + SSID_LEN + PWD_LEN + 1 diff --git a/tools/esp8266/html/api.js b/tools/esp8266/html/api.js new file mode 100644 index 00000000..f8b002a9 --- /dev/null +++ b/tools/esp8266/html/api.js @@ -0,0 +1,65 @@ +function toggle(name, hide) { + var elm = document.getElementsByName(name)[0]; + if(hide) { + if(!elm.classList.contains("hide")) + elm.classList.add("hide"); + } + else + elm.classList.remove('hide'); +} + +function getAjax(url, ptr) { + var http = new XMLHttpRequest(); + if(http != null) { + http.open("GET", url, true); + http.onreadystatechange = p; + http.send(null); + } + function p() { + if(http.readyState == 4) + ptr(JSON.parse(http.responseText)); + } +} + +function des(val) { + e = document.createElement('p'); + e.classList.add("subdes"); + e.innerHTML = val; + return e; +} + +function lbl(id, val) { + e = document.createElement('label'); + e.htmlFor = id; + e.innerHTML = val; + return e; +} + +function inp(name, val, max=32, cl=["text"]) { + e = document.createElement('input'); + e.classList.add(...cl); + e.name = name; + e.value = val; + e.maxLength = max; + return e; +} + +function sel(name, opt, selId) { + e = document.createElement('select'); + e.name = name; + for(it of opt) { + o = document.createElement('option'); + o.value = it[0]; + o.innerHTML = it[1]; + if(it[0] == selId) + o.selected = true; + e.appendChild(o); + } + return e; +} + +function div(cl) { + e = document.createElement('div'); + e.classList.add(cl); + return e; +} diff --git a/tools/esp8266/html/convert.py b/tools/esp8266/html/convert.py index 953dafca..333cf61e 100755 --- a/tools/esp8266/html/convert.py +++ b/tools/esp8266/html/convert.py @@ -7,30 +7,36 @@ def convert2Header(inFile, compress): define = inFile.split(".")[0].upper() define2 = inFile.split(".")[1].upper() inFileVarName = inFile.replace(".", "_") + print(inFile + ", compress: " + str(compress)) if os.getcwd()[-4:] != "html": - print("ok") outName = "html/" + "h/" + inFileVarName + ".h" inFile = "html/" + inFile else: outName = "h/" + inFileVarName + ".h" f = open(inFile, "r") - data = f.read().replace('\n', '') + data = f.read() f.close() - if False == compress: - if fileType == "html": + + if fileType == "html": + if False == compress: + data = data.replace('\n', '') data = re.sub(r"\>\s+\<", '><', data) # whitespaces between xml tags - data = re.sub(r"(\s?\;|\}|\>|\{|\=)\s+", r'\1', data) # whitespaces inner javascript - length = len(data) # get unescaped length - data = re.sub(r"\"", '\\\"', data) # escape quotation marks - else: - data = re.sub(r"(\;|\}|\:|\{)\s+", r'\1', data) # whitespaces inner css - length = len(data) # get unescaped length - else: - data = re.sub(r"\>\s+\<", '><', data) # whitespaces between xml tags - data = re.sub(r"(\;|\}|\>|\{)\s+", r'\1', data) # whitespaces inner javascript + data = re.sub(r"(\r\n|\r|\n)(\s+|\s?)", '', data) # whitespaces inner javascript length = len(data) # get unescaped length + if False == compress: + data = re.sub(r"\"", '\\\"', data) # escape quotation marks + elif fileType == "js": + #data = re.sub(r"(\r\n|\r|\n)(\s+|\s?)", '', data) # whitespaces inner javascript + #data = re.sub(r"\s?(\=|\!\=|\{|,)+\s?", r'\1', data) # whitespaces inner javascript + length = len(data) # get unescaped length + if False == compress: + data = re.sub(r"\"", '\\\"', data) # escape quotation marks + else: + data = data.replace('\n', '') + data = re.sub(r"(\;|\}|\:|\{)\s+", r'\1', data) # whitespaces inner css + length = len(data) # get unescaped length # get unescaped length f = open(outName, "w") f.write("#ifndef __{}_{}_H__\n".format(define, define2)) @@ -52,8 +58,9 @@ def convert2Header(inFile, compress): f.write("#endif /*__{}_{}_H__*/\n".format(define, define2)) f.close() -convert2Header("index.html", False) +convert2Header("index.html", True) convert2Header("setup.html", True) convert2Header("visualization.html", False) convert2Header("update.html", False) -convert2Header("style.css", False) +convert2Header("style.css", True) +convert2Header("api.js", True) diff --git a/tools/esp8266/html/index.html b/tools/esp8266/html/index.html index de381281..73e53b34 100644 --- a/tools/esp8266/html/index.html +++ b/tools/esp8266/html/index.html @@ -1,44 +1,13 @@ - Index - {DEVICE} + Index - + -

AHOY - {DEVICE}

+

AHOY

Visualization
@@ -46,7 +15,7 @@ Setup

Uptime:

-

Statistics:

+

Statistics:

Every {TS}seconds the values are updated

@@ -64,9 +33,40 @@ + diff --git a/tools/esp8266/html/setup.html b/tools/esp8266/html/setup.html index d540e7e6..cdc94133 100644 --- a/tools/esp8266/html/setup.html +++ b/tools/esp8266/html/setup.html @@ -4,49 +4,7 @@ Setup - +

Setup

@@ -60,7 +18,7 @@ - +
@@ -141,7 +99,6 @@
- - diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 4da0375d..8dc6a046 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -55,7 +55,7 @@ void web::setup(void) { mWeb->on("/visualization", HTTP_ANY, std::bind(&web::showVisualization, this, std::placeholders::_1)); mWeb->on("/livedata", HTTP_ANY, std::bind(&web::showLiveData, this, std::placeholders::_1)); mWeb->on("/json", HTTP_ANY, std::bind(&web::showJson, this, std::placeholders::_1)); - mWeb->on("/api", HTTP_POST, std::bind(&web::showWebApi, this, std::placeholders::_1)); + mWeb->on("/api1", HTTP_POST, std::bind(&web::showWebApi, this, std::placeholders::_1)); mWeb->on("/update", HTTP_GET, std::bind(&web::showUpdateForm, this, std::placeholders::_1)); @@ -288,7 +288,7 @@ void web::showSave(AsyncWebServerRequest *request) { // mqtt if(request->arg("mqttAddr") != "") { - String addr = mWeb->arg("mqttAddr"); + String addr = request->arg("mqttAddr"); addr.trim(); addr.toCharArray(mConfig->mqtt.broker, MQTT_ADDR_LEN); request->arg("mqttUser").toCharArray(mConfig->mqtt.user, MQTT_USER_LEN); diff --git a/tools/esp8266/webApi.cpp b/tools/esp8266/webApi.cpp index 1f0cae3c..be5e2ff5 100644 --- a/tools/esp8266/webApi.cpp +++ b/tools/esp8266/webApi.cpp @@ -9,7 +9,6 @@ #endif #include "webApi.h" -#include "AsyncJson.h" //----------------------------------------------------------------------------- webApi::webApi(AsyncWebServer *srv, app *app, sysConfig_t *sysCfg, config_t *config, statistics_t *stat, char version[]) { @@ -24,34 +23,32 @@ webApi::webApi(AsyncWebServer *srv, app *app, sysConfig_t *sysCfg, config_t *con //----------------------------------------------------------------------------- void webApi::setup(void) { - mSrv->on("/api/system", HTTP_GET, std::bind(&webApi::onSystem, this, std::placeholders::_1)); - mSrv->on("/api/statistics", HTTP_GET, std::bind(&webApi::onStatistics, this, std::placeholders::_1)); - mSrv->on("/api/inverter/list", HTTP_GET, std::bind(&webApi::onInverterList, this, std::placeholders::_1)); - mSrv->on("/api/mqtt", HTTP_GET, std::bind(&webApi::onMqtt, this, std::placeholders::_1)); - mSrv->on("/api/ntp", HTTP_GET, std::bind(&webApi::onNtp, this, std::placeholders::_1)); - mSrv->on("/api/pinout", HTTP_GET, std::bind(&webApi::onPinout, this, std::placeholders::_1)); - mSrv->on("/api/radio", HTTP_GET, std::bind(&webApi::onRadio, this, std::placeholders::_1)); - mSrv->on("/api/serial", HTTP_GET, std::bind(&webApi::onSerial, this, std::placeholders::_1)); + mSrv->on("/api", HTTP_GET, std::bind(&webApi::onApi, this, std::placeholders::_1)); } //----------------------------------------------------------------------------- void webApi::loop(void) { - } //----------------------------------------------------------------------------- -void webApi::onSystem(AsyncWebServerRequest *request) { - AsyncJsonResponse* response = new AsyncJsonResponse(); +void webApi::onApi(AsyncWebServerRequest *request) { + AsyncJsonResponse* response = new AsyncJsonResponse(false, 2048); JsonObject root = response->getRoot(); - root[F("ssid")] = mSysCfg->stationSsid; - root[F("device_name")] = mSysCfg->deviceName; - root[F("version")] = String(mVersion); - root[F("build")] = String(AUTO_GIT_HASH); - root[F("ts_uptime")] = mApp->getUptime(); - root[F("ts_now")] = mApp->getTimestamp(); + String path = request->url().substring(5); + if(path == "system") getSystem(root); + else if(path == "statistics") getStatistics(root); + else if(path == "inverter/list") getInverterList(root); + else if(path == "mqtt") getMqtt(root); + else if(path == "ntp") getNtp(root); + else if(path == "pinout") getPinout(root); + else if(path == "radio") getRadio(root); + else if(path == "serial") getSerial(root); + else if(path == "setup") getSetup(root); + else + root["info"] = "not found"; //root["url"] = request->url(); response->setLength(); //response->addHeader("Access-Control-Allow-Origin", "*"); @@ -61,25 +58,28 @@ void webApi::onSystem(AsyncWebServerRequest *request) { //----------------------------------------------------------------------------- -void webApi::onStatistics(AsyncWebServerRequest *request) { - AsyncJsonResponse* response = new AsyncJsonResponse(); - JsonObject root = response->getRoot(); +void webApi::getSystem(JsonObject obj) { + obj[F("ssid")] = mSysCfg->stationSsid; + obj[F("device_name")] = mSysCfg->deviceName; + obj[F("version")] = String(mVersion); + obj[F("build")] = String(AUTO_GIT_HASH); + obj[F("ts_uptime")] = mApp->getUptime(); + obj[F("ts_now")] = mApp->getTimestamp(); +} - root[F("rx_success")] = mStat->rxSuccess; - root[F("rx_fail")] = mStat->rxFail; - root[F("frame_cnt")] = mStat->frmCnt; - root[F("tx_cnt")] = mApp->mSys->Radio.mSendCnt; - response->setLength(); - request->send(response); +//----------------------------------------------------------------------------- +void webApi::getStatistics(JsonObject obj) { + obj[F("rx_success")] = mStat->rxSuccess; + obj[F("rx_fail")] = mStat->rxFail; + obj[F("frame_cnt")] = mStat->frmCnt; + obj[F("tx_cnt")] = mApp->mSys->Radio.mSendCnt; } //----------------------------------------------------------------------------- -void webApi::onInverterList(AsyncWebServerRequest *request) { - AsyncJsonResponse* response = new AsyncJsonResponse(); - JsonObject root = response->getRoot(); - JsonArray invArr = root.createNestedArray("inverter"); +void webApi::getInverterList(JsonObject obj) { + JsonArray invArr = obj.createNestedArray("inverter"); Inverter<> *iv; for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) { @@ -101,80 +101,58 @@ void webApi::onInverterList(AsyncWebServerRequest *request) { obj[F("power_limit_option")] = iv->powerLimit[1]; } } - root[F("interval")] = String(mConfig->sendInterval); - root[F("retries")] = String(mConfig->maxRetransPerPyld); - root[F("max_num_inverters")] = MAX_NUM_INVERTERS; - - response->setLength(); - request->send(response); + obj[F("interval")] = String(mConfig->sendInterval); + obj[F("retries")] = String(mConfig->maxRetransPerPyld); + obj[F("max_num_inverters")] = MAX_NUM_INVERTERS; } //----------------------------------------------------------------------------- -void webApi::onMqtt(AsyncWebServerRequest *request) { - AsyncJsonResponse* response = new AsyncJsonResponse(); - JsonObject root = response->getRoot(); - - root[F("broker")] = String(mConfig->mqtt.broker); - root[F("port")] = String(mConfig->mqtt.port); - root[F("user")] = String(mConfig->mqtt.user); - root[F("pwd")] = (strlen(mConfig->mqtt.pwd) > 0) ? F("{PWD}") : String(""); - root[F("topic")] = String(mConfig->mqtt.topic); - - response->setLength(); - request->send(response); +void webApi::getMqtt(JsonObject obj) { + obj[F("broker")] = String(mConfig->mqtt.broker); + obj[F("port")] = String(mConfig->mqtt.port); + obj[F("user")] = String(mConfig->mqtt.user); + obj[F("pwd")] = (strlen(mConfig->mqtt.pwd) > 0) ? F("{PWD}") : String(""); + obj[F("topic")] = String(mConfig->mqtt.topic); } //----------------------------------------------------------------------------- -void webApi::onNtp(AsyncWebServerRequest *request) { - AsyncJsonResponse* response = new AsyncJsonResponse(); - JsonObject root = response->getRoot(); - - root[F("addr")] = String(mConfig->ntpAddr); - root[F("port")] = String(mConfig->ntpPort); - - response->setLength(); - request->send(response); +void webApi::getNtp(JsonObject obj) { + obj[F("addr")] = String(mConfig->ntpAddr); + obj[F("port")] = String(mConfig->ntpPort); } //----------------------------------------------------------------------------- -void webApi::onPinout(AsyncWebServerRequest *request) { - AsyncJsonResponse* response = new AsyncJsonResponse(); - JsonObject root = response->getRoot(); - - root[F("cs")] = mConfig->pinCs; - root[F("ce")] = mConfig->pinCe; - root[F("irq")] = mConfig->pinIrq; - - response->setLength(); - request->send(response); +void webApi::getPinout(JsonObject obj) { + obj[F("cs")] = mConfig->pinCs; + obj[F("ce")] = mConfig->pinCe; + obj[F("irq")] = mConfig->pinIrq; } //----------------------------------------------------------------------------- -void webApi::onRadio(AsyncWebServerRequest *request) { - AsyncJsonResponse* response = new AsyncJsonResponse(); - JsonObject root = response->getRoot(); - - root[F("power_level")] = mConfig->amplifierPower; - - response->setLength(); - request->send(response); +void webApi::getRadio(JsonObject obj) { + obj[F("power_level")] = mConfig->amplifierPower; } - //----------------------------------------------------------------------------- -void webApi::onSerial(AsyncWebServerRequest *request) { - AsyncJsonResponse* response = new AsyncJsonResponse(); - JsonObject root = response->getRoot(); +void webApi::getSerial(JsonObject obj) { + obj[F("interval")] = (uint16_t)mConfig->serialInterval; + obj[F("show_live_data")] = mConfig->serialShowIv; + obj[F("debug")] = mConfig->serialDebug; +} - root[F("interval")] = (uint16_t)mConfig->serialInterval; - root[F("show_live_data")] = mConfig->serialShowIv; - root[F("debug")] = mConfig->serialDebug; - response->setLength(); - request->send(response); +//----------------------------------------------------------------------------- +void webApi::getSetup(JsonObject obj) { + getSystem(obj.createNestedObject("system")); + getInverterList(obj.createNestedObject("inverter")); + getMqtt(obj.createNestedObject("mqtt")); + getNtp(obj.createNestedObject("ntp")); + getPinout(obj.createNestedObject("pinout")); + getRadio(obj.createNestedObject("radio")); + getSerial(obj.createNestedObject("serial")); } diff --git a/tools/esp8266/webApi.h b/tools/esp8266/webApi.h index 9eefd054..afe35ba1 100644 --- a/tools/esp8266/webApi.h +++ b/tools/esp8266/webApi.h @@ -4,6 +4,7 @@ #include "dbg.h" #include "ESPAsyncTCP.h" #include "ESPAsyncWebServer.h" +#include "AsyncJson.h" #include "app.h" @@ -17,14 +18,18 @@ class webApi { void loop(void); private: - void onSystem(AsyncWebServerRequest *request); - void onStatistics(AsyncWebServerRequest *request); - void onInverterList(AsyncWebServerRequest *request); - void onMqtt(AsyncWebServerRequest *request); - void onNtp(AsyncWebServerRequest *request); - void onPinout(AsyncWebServerRequest *request); - void onRadio(AsyncWebServerRequest *request); - void onSerial(AsyncWebServerRequest *request); + void onApi(AsyncWebServerRequest *request); + + void getSystem(JsonObject obj); + void getStatistics(JsonObject obj); + void getInverterList(JsonObject obj); + void getMqtt(JsonObject obj); + void getNtp(JsonObject obj); + void getPinout(JsonObject obj); + void getRadio(JsonObject obj); + void getSerial(JsonObject obj); + + void getSetup(JsonObject obj); AsyncWebServer *mSrv; app *mApp; From 1f6db2ffdbb9f84e9bc38c59286327266eba0a66 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 31 Aug 2022 23:05:56 +0200 Subject: [PATCH 09/38] * improved api * finished index page --- tools/esp8266/app.cpp | 64 +++-------------------------- tools/esp8266/app.h | 7 ++-- tools/esp8266/html/index.html | 63 ++++++++++++++++++++++++----- tools/esp8266/web.cpp | 8 ---- tools/esp8266/web.h | 1 - tools/esp8266/webApi.cpp | 76 ++++++++++++++++++++++++++++++----- tools/esp8266/webApi.h | 2 + 7 files changed, 129 insertions(+), 92 deletions(-) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 643a54a7..84fa4ae6 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -53,13 +53,11 @@ void app::loop(void) { bool apActive = mWifi->loop(); mWebInst->loop(); - if(checkTicker(&mUptimeTicker, mUptimeInterval)) { - if(millis() - mPrevMillis >= 1000) { - mPrevMillis += 1000; - mUptimeSecs++; - if(0 != mTimestamp) - mTimestamp++; - } + if(millis() - mPrevMillis >= 1000) { + mPrevMillis += 1000; + mUptimeSecs++; + if(0 != mTimestamp) + mTimestamp++; } if(checkTicker(&mNtpRefreshTicker, mNtpRefreshInterval)) { @@ -500,56 +498,6 @@ void app::cbMqtt(char* topic, byte* payload, unsigned int length) { } -//----------------------------------------------------------------------------- -String app::getStatistics(void) { - String content = F("Receive success: ") + String(mStat.rxSuccess) + "\n"; - content += F("Receive fail: ") + String(mStat.rxFail) + "\n"; - content += F("Frames received: ") + String(mStat.frmCnt) + "\n"; - content += F("Send Cnt: ") + String(mSys->Radio.mSendCnt) + String("\n\n"); - - Inverter<> *iv; - for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { - iv = mSys->getInverterByPos(i); - content += F("Inverter #") + String(i) + F(": "); - if(NULL != iv) { - bool avail = true; - content += String(iv->name) + F(" (v") + String(iv->fwVersion) +F(")") + F(" is "); - if(!iv->isAvailable(mTimestamp)) { - content += F("not "); - avail = false; - } - content += F("available and is "); - if(!iv->isProducing(mTimestamp)) - content += F("not "); - content += F("producing\n"); - - if(!avail) { - if(iv->getLastTs() > 0) - content += F("-> last successful transmission: ") + getDateTimeStr(iv->getLastTs()) + "\n"; - } - } - else - content += F("n/a\n"); - } - - if(!mSys->Radio.isChipConnected()) - content += F("WARNING! your NRF24 module can't be reached, check the wiring and pinout (setup)\n"); - - if(mShowRebootRequest) - content += F("INFO: reboot your ESP to apply all your configuration changes!\n"); - - if(!mSettingsValid) - content += F("INFO: your settings are invalid, please switch to Setup to correct this.\n"); - - content += F("MQTT: "); - if(!mMqtt.isConnected()) - content += F("not "); - content += F("connected\n"); - - return content; -} - - //----------------------------------------------------------------------------- String app::getJson(void) { DPRINTLN(DBG_VERBOSE, F("app::showJson")); @@ -664,8 +612,6 @@ const char* app::getFieldStateClass(uint8_t fieldId) { //----------------------------------------------------------------------------- void app::resetSystem(void) { mUptimeSecs = 0; - mUptimeTicker = 0xffffffff; - mUptimeInterval = 500; // [ms] mPrevMillis = 0; mNtpRefreshTicker = 0; diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index c3c1030a..2d728be5 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -62,7 +62,6 @@ class app { void cbMqtt(char* topic, byte* payload, unsigned int length); void saveValues(void); void resetPayload(Inverter<>* iv); - String getStatistics(void); String getJson(void); bool getWifiApActive(void); @@ -135,6 +134,10 @@ class app { return false; } + inline bool mqttIsConnected(void) { return mMqtt.isConnected(); } + inline bool getSettingsValid(void) { return mSettingsValid; } + inline bool getRebootRequestState(void) { return mShowRebootRequest; } + HmSystemType *mSys; bool mShouldReboot; @@ -214,8 +217,6 @@ class app { } - uint32_t mUptimeTicker; - uint16_t mUptimeInterval; uint32_t mUptimeSecs; uint32_t mPrevMillis; uint8_t mHeapStatCnt; diff --git a/tools/esp8266/html/index.html b/tools/esp8266/html/index.html index 33a7e3dd..f8a06f6c 100644 --- a/tools/esp8266/html/index.html +++ b/tools/esp8266/html/index.html @@ -15,8 +15,14 @@ Setup

Uptime:

-

Statistics:

-

Every {TS}seconds the values are updated

+

ESP-Time:

+

+ Statistics: +


+                

+                

+            

+

Every seconds the values are updated

This project was started from this discussion. (Mikrocontroller.net)
@@ -35,8 +41,10 @@

Update Firmware

Reboot

+

REST API

diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 8dc6a046..ffd676c7 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -51,7 +51,6 @@ void web::setup(void) { mWeb->on("/setup", HTTP_GET, std::bind(&web::onSetup, this, std::placeholders::_1)); mWeb->on("/save", HTTP_ANY, std::bind(&web::showSave, this, std::placeholders::_1)); - mWeb->on("/cmdstat", HTTP_ANY, std::bind(&web::showStatistics, this, std::placeholders::_1)); mWeb->on("/visualization", HTTP_ANY, std::bind(&web::showVisualization, this, std::placeholders::_1)); mWeb->on("/livedata", HTTP_ANY, std::bind(&web::showLiveData, this, std::placeholders::_1)); mWeb->on("/json", HTTP_ANY, std::bind(&web::showJson, this, std::placeholders::_1)); @@ -319,13 +318,6 @@ void web::showSave(AsyncWebServerRequest *request) { } -//----------------------------------------------------------------------------- -void web::showStatistics(AsyncWebServerRequest *request) { - DPRINTLN(DBG_VERBOSE, F("web::showStatistics")); - request->send(200, F("text/plain"), mMain->getStatistics()); -} - - //----------------------------------------------------------------------------- void web::showVisualization(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("web::showVisualization")); diff --git a/tools/esp8266/web.h b/tools/esp8266/web.h index 84e272b8..652bf677 100644 --- a/tools/esp8266/web.h +++ b/tools/esp8266/web.h @@ -37,7 +37,6 @@ class web { void onSetup(AsyncWebServerRequest *request); void showSave(AsyncWebServerRequest *request); - void showStatistics(AsyncWebServerRequest *request); void showVisualization(AsyncWebServerRequest *request); void showLiveData(AsyncWebServerRequest *request); void showJson(AsyncWebServerRequest *request); diff --git a/tools/esp8266/webApi.cpp b/tools/esp8266/webApi.cpp index be5e2ff5..60d1ed2d 100644 --- a/tools/esp8266/webApi.cpp +++ b/tools/esp8266/webApi.cpp @@ -46,13 +46,14 @@ void webApi::onApi(AsyncWebServerRequest *request) { else if(path == "pinout") getPinout(root); else if(path == "radio") getRadio(root); else if(path == "serial") getSerial(root); + else if(path == "index") getIndex(root); else if(path == "setup") getSetup(root); else - root["info"] = "not found"; //root["url"] = request->url(); + getNotFound(root, F("http://") + request->host() + F("/api/")); response->setLength(); - //response->addHeader("Access-Control-Allow-Origin", "*"); - //response->addHeader("Access-Control-Allow-Headers", "content-type"); + response->addHeader("Access-Control-Allow-Origin", "*"); + response->addHeader("Access-Control-Allow-Headers", "content-type"); request->send(response); } @@ -79,7 +80,7 @@ void webApi::getStatistics(JsonObject obj) { //----------------------------------------------------------------------------- void webApi::getInverterList(JsonObject obj) { - JsonArray invArr = obj.createNestedArray("inverter"); + JsonArray invArr = obj.createNestedArray(F("inverter")); Inverter<> *iv; for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) { @@ -146,13 +147,66 @@ void webApi::getSerial(JsonObject obj) { } +//----------------------------------------------------------------------------- +void webApi::getNotFound(JsonObject obj, String url) { + JsonObject ep = obj.createNestedObject("avail_endpoints"); + ep[F("system")] = url + F("system"); + ep[F("statistics")] = url + F("statistics"); + ep[F("inverter/list")] = url + F("inverter/list"); + ep[F("mqtt")] = url + F("mqtt"); + ep[F("ntp")] = url + F("ntp"); + ep[F("pinout")] = url + F("pinout"); + ep[F("radio")] = url + F("radio"); + ep[F("serial")] = url + F("serial"); + ep[F("index")] = url + F("index"); + ep[F("setup")] = url + F("setup"); +} + + +//----------------------------------------------------------------------------- +void webApi::getIndex(JsonObject obj) { + getSystem(obj.createNestedObject(F("system"))); + getStatistics(obj.createNestedObject(F("statistics"))); + obj["refresh_interval"] = SEND_INTERVAL; + + JsonArray inv = obj.createNestedArray(F("inverter")); + Inverter<> *iv; + for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) { + iv = mApp->mSys->getInverterByPos(i); + if(NULL != iv) { + JsonObject invObj = inv.createNestedObject(); + invObj[F("id")] = i; + invObj[F("name")] = String(iv->name); + invObj[F("version")] = String(iv->fwVersion); + invObj[F("is_avail")] = iv->isAvailable(mApp->getTimestamp()); + invObj[F("is_producing")] = iv->isProducing(mApp->getTimestamp()); + invObj[F("ts_last_success")] = iv->getLastTs(); + } + } + + JsonArray warn = obj.createNestedArray(F("warnings")); + if(!mApp->mSys->Radio.isChipConnected()) + warn.add(F("your NRF24 module can't be reached, check the wiring and pinout")); + if(!mApp->mqttIsConnected()) + warn.add(F("MQTT is not connected")); + + JsonArray info = obj.createNestedArray(F("infos")); + if(mApp->getRebootRequestState()) + info.add(F("reboot your ESP to apply all your configuration changes!")); + if(!mApp->getSettingsValid()) + info.add(F("your settings are invalid")); + if(mApp->mqttIsConnected()) + info.add(F("MQTT is connected")); +} + + //----------------------------------------------------------------------------- void webApi::getSetup(JsonObject obj) { - getSystem(obj.createNestedObject("system")); - getInverterList(obj.createNestedObject("inverter")); - getMqtt(obj.createNestedObject("mqtt")); - getNtp(obj.createNestedObject("ntp")); - getPinout(obj.createNestedObject("pinout")); - getRadio(obj.createNestedObject("radio")); - getSerial(obj.createNestedObject("serial")); + getSystem(obj.createNestedObject(F("system"))); + getInverterList(obj.createNestedObject(F("inverter"))); + getMqtt(obj.createNestedObject(F("mqtt"))); + getNtp(obj.createNestedObject(F("ntp"))); + getPinout(obj.createNestedObject(F("pinout"))); + getRadio(obj.createNestedObject(F("radio"))); + getSerial(obj.createNestedObject(F("serial"))); } diff --git a/tools/esp8266/webApi.h b/tools/esp8266/webApi.h index afe35ba1..1ad91d05 100644 --- a/tools/esp8266/webApi.h +++ b/tools/esp8266/webApi.h @@ -29,6 +29,8 @@ class webApi { void getRadio(JsonObject obj); void getSerial(JsonObject obj); + void getNotFound(JsonObject obj, String url); + void getIndex(JsonObject obj); void getSetup(JsonObject obj); AsyncWebServer *mSrv; From 330d9d5002e3a7e054cc90d9093f354fca63ca2a Mon Sep 17 00:00:00 2001 From: Nico Hess <12140312+Grufbert@users.noreply.github.com> Date: Tue, 6 Sep 2022 08:44:47 +0200 Subject: [PATCH 10/38] use relative not absolute url path --- tools/esp8266/html/setup.html | 10 +++++----- tools/esp8266/web.cpp | 4 ---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/tools/esp8266/html/setup.html b/tools/esp8266/html/setup.html index 5be9e9d7..aecdd6f3 100644 --- a/tools/esp8266/html/setup.html +++ b/tools/esp8266/html/setup.html @@ -54,7 +54,7 @@
ERASE SETTINGS (not WiFi) -
+
Device Host Name @@ -143,11 +143,11 @@
+ + +

Serial Console

+
+ +
+ + + + diff --git a/tools/esp8266/html/setup.html b/tools/esp8266/html/setup.html index e0e6d9a4..6460fae7 100644 --- a/tools/esp8266/html/setup.html +++ b/tools/esp8266/html/setup.html @@ -262,13 +262,15 @@ } function parse(root) { - parseSys(root["system"]); - parseIv(root["inverter"]); - parseMqtt(root["mqtt"]); - parseNtp(root["ntp"]); - parsePinout(root["pinout"]); - parseRadio(root["radio"]); - parseSerial(root["serial"]); + if(null != root) { + parseSys(root["system"]); + parseIv(root["inverter"]); + parseMqtt(root["mqtt"]); + parseNtp(root["ntp"]); + parsePinout(root["pinout"]); + parseRadio(root["radio"]); + parseSerial(root["serial"]); + } } getAjax("/api/setup", parse); diff --git a/tools/esp8266/html/update.html b/tools/esp8266/html/update.html index 4da28459..b7644a21 100644 --- a/tools/esp8266/html/update.html +++ b/tools/esp8266/html/update.html @@ -4,7 +4,7 @@ Update - {#HEAD} +

Update

@@ -13,13 +13,21 @@ Make sure that you have noted all or settings before starting an update. New versions maybe changed their memory layout which remains in default settings.


- {#CONTENT} + + + + diff --git a/tools/esp8266/html/visualization.html b/tools/esp8266/html/visualization.html index ddb48fe7..5eec08cc 100644 --- a/tools/esp8266/html/visualization.html +++ b/tools/esp8266/html/visualization.html @@ -1,43 +1,116 @@ - Index - {DEVICE} + Live - - + -

AHOY - {DEVICE}

+

AHOY

-
-

Every {TS}seconds the values are updated

+
+

Every seconds the values are updated

+ diff --git a/tools/esp8266/include/dbg.h b/tools/esp8266/include/dbg.h index 8eb41f7c..94c05e9a 100644 --- a/tools/esp8266/include/dbg.h +++ b/tools/esp8266/include/dbg.h @@ -10,6 +10,7 @@ #define F(sl) (sl) #endif +#include //----------------------------------------------------------------------------- // available levels #define DBG_ERROR 1 @@ -32,14 +33,22 @@ #define DBGPRINTLN(str) #else #ifdef ARDUINO + #define DBG_CB std::function + extern DBG_CB mCb; + //static DBG_CB mCb; + + inline void registerDebugCb(DBG_CB cb) { + mCb = cb; + } + #ifndef DSERIAL #define DSERIAL Serial #endif - template - inline void DBGPRINT(T str) { DSERIAL.print(str); } - template - inline void DBGPRINTLN(T str) { DBGPRINT(str); DBGPRINT(F("\r\n")); } + //template + inline void DBGPRINT(String str) { DSERIAL.print(str); if(NULL != mCb) mCb(str); } + //template + inline void DBGPRINTLN(String str) { DBGPRINT(str); DBGPRINT(F("\r\n")); } inline void DHEX(uint8_t b) { if( b<0x10 ) DSERIAL.print('0'); DSERIAL.print(b,HEX); @@ -60,6 +69,8 @@ else if( b<0x10000000 ) DSERIAL.print(F("0")); DSERIAL.print(b,HEX); } + + #endif #endif diff --git a/tools/esp8266/tmplProc.h b/tools/esp8266/tmplProc.h deleted file mode 100644 index aa81915c..00000000 --- a/tools/esp8266/tmplProc.h +++ /dev/null @@ -1,108 +0,0 @@ -//----------------------------------------------------------------------------- -// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778 -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ -//----------------------------------------------------------------------------- - -#ifndef __TMPL_PROC__ -#define __TMPL_PROC__ - -// HTML template processor, searches keywords and calls callback -// inspired by: https://github.com/plapointe6/EspHtmlTemplateProcessor - -#include "dbg.h" -#include -#include -#include "ESPAsyncWebServer.h" - -#define MAX_BUFFER_SIZE 256 -#define MAX_KEY_LEN 20 -enum { ST_NONE = 0, ST_BUF, ST_PROC, ST_START, ST_KEY }; - -typedef std::function TmplCb; - -class tmplProc { - public: - tmplProc(AsyncWebServerRequest *request, uint32_t bufStartSize = 1000) { - // Note: don't choose the bufStartSize to small. A too small start - // size will result in fractioned memory and maybe in a zero - // increase -> fail (Arduino - cbuf.cpp) - mRequest = request; - mResponse = request->beginResponseStream("text/html", bufStartSize); - } - - ~tmplProc() {} - - void process(const char* tmpl, const uint32_t tmplLen, TmplCb cb) { - char* buf = new char[MAX_BUFFER_SIZE]; - char* p = buf; - uint32_t len = 0, pos = 0, i = 0; - uint8_t state = ST_BUF; - bool complete = false; - - while (i < tmplLen) { - switch (state) { - default: - DPRINTLN(DBG_DEBUG, F("unknown state")); - break; - case ST_BUF: - if(0 != i) { - buf[pos] = '\0'; - mResponse->print(p); - } - pos = 0; - len = ((tmplLen - i) > MAX_BUFFER_SIZE) ? MAX_BUFFER_SIZE : (tmplLen - i); - if((len + i) == tmplLen) - complete = true; - memcpy_P(buf, &tmpl[i], len); - if(len < MAX_BUFFER_SIZE) - buf[len] = '\0'; - p = buf; - state = ST_PROC; - break; - - case ST_PROC: - if(((pos + MAX_KEY_LEN) >= len) && !complete) - state = ST_BUF; - else if(buf[pos] == '{') - state = ST_START; - break; - - case ST_START: - if(buf[pos] == '#') { - if(pos != 0) - buf[pos-1] = '\0'; - mResponse->print(p); - p = &buf[pos+1]; - state = ST_KEY; - } - else - state = ST_PROC; - break; - - case ST_KEY: - if(buf[pos] == '}') { - buf[pos] = '\0'; - mResponse->print((cb)(p)); - p = &buf[pos+1]; - state = ST_PROC; - } - break; - } - - if(ST_BUF != state) { - pos++; - i++; - } - } - - mResponse->print(p); - delete[] buf; - mRequest->send(mResponse); - } - - private: - AsyncWebServerRequest *mRequest; - AsyncResponseStream *mResponse; -}; - -#endif /*__TMPL_PROC__*/ diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 766bb790..f9112616 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -17,6 +17,7 @@ #include "html/h/setup_html.h" #include "html/h/visualization_html.h" #include "html/h/update_html.h" +#include "html/h/serial_html.h" const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq"}; @@ -28,7 +29,7 @@ web::web(app *main, sysConfig_t *sysCfg, config_t *config, statistics_t *stat, c mStat = stat; mVersion = version; mWeb = new AsyncWebServer(80); - //mEvts = new AsyncEventSource("/events"); + mEvts = new AsyncEventSource("/events"); mApi = new webApi(mWeb, main, sysCfg, config, stat, version); } @@ -39,31 +40,34 @@ void web::setup(void) { DPRINTLN(DBG_VERBOSE, F("app::setup-begin")); mWeb->begin(); DPRINTLN(DBG_VERBOSE, F("app::setup-on")); - mWeb->on("/", HTTP_GET, std::bind(&web::onIndex, this, std::placeholders::_1)); - mWeb->on("/style.css", HTTP_GET, std::bind(&web::onCss, this, std::placeholders::_1)); - mWeb->on("/api.js", HTTP_GET, std::bind(&web::onApiJs, this, std::placeholders::_1)); - mWeb->on("/favicon.ico", HTTP_GET, std::bind(&web::onFavicon, this, std::placeholders::_1)); - mWeb->onNotFound ( std::bind(&web::showNotFound, this, std::placeholders::_1)); - mWeb->on("/reboot", HTTP_ANY, std::bind(&web::showReboot, this, std::placeholders::_1)); - mWeb->on("/erase", HTTP_ANY, std::bind(&web::showErase, this, std::placeholders::_1)); - mWeb->on("/factory", HTTP_ANY, std::bind(&web::showFactoryRst, this, std::placeholders::_1)); + mWeb->on("/", HTTP_GET, std::bind(&web::onIndex, this, std::placeholders::_1)); + mWeb->on("/style.css", HTTP_GET, std::bind(&web::onCss, this, std::placeholders::_1)); + mWeb->on("/api.js", HTTP_GET, std::bind(&web::onApiJs, this, std::placeholders::_1)); + mWeb->on("/favicon.ico", HTTP_GET, std::bind(&web::onFavicon, this, std::placeholders::_1)); + mWeb->onNotFound ( std::bind(&web::showNotFound, this, std::placeholders::_1)); + mWeb->on("/reboot", HTTP_ANY, std::bind(&web::showReboot, this, std::placeholders::_1)); + mWeb->on("/erase", HTTP_ANY, std::bind(&web::showErase, this, std::placeholders::_1)); + mWeb->on("/factory", HTTP_ANY, std::bind(&web::showFactoryRst, this, std::placeholders::_1)); - mWeb->on("/setup", HTTP_GET, std::bind(&web::onSetup, this, std::placeholders::_1)); - mWeb->on("/save", HTTP_ANY, std::bind(&web::showSave, this, std::placeholders::_1)); + mWeb->on("/setup", HTTP_GET, std::bind(&web::onSetup, this, std::placeholders::_1)); + mWeb->on("/save", HTTP_ANY, std::bind(&web::showSave, this, std::placeholders::_1)); - mWeb->on("/visualization", HTTP_ANY, std::bind(&web::showVisualization, this, std::placeholders::_1)); - mWeb->on("/livedata", HTTP_ANY, std::bind(&web::showLiveData, this, std::placeholders::_1)); - mWeb->on("/api1", HTTP_POST, std::bind(&web::showWebApi, this, std::placeholders::_1)); + mWeb->on("/live", HTTP_ANY, std::bind(&web::onLive, this, std::placeholders::_1)); + mWeb->on("/api1", HTTP_POST, std::bind(&web::showWebApi, this, std::placeholders::_1)); - mWeb->on("/update", HTTP_GET, std::bind(&web::showUpdateForm, this, std::placeholders::_1)); - mWeb->on("/update", HTTP_POST, std::bind(&web::showUpdate, this, std::placeholders::_1), - std::bind(&web::showUpdate2, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6)); + mWeb->on("/update", HTTP_GET, std::bind(&web::onUpdate, this, std::placeholders::_1)); + mWeb->on("/update", HTTP_POST, std::bind(&web::showUpdate, this, std::placeholders::_1), + std::bind(&web::showUpdate2, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6)); + mWeb->on("/serial", HTTP_GET, std::bind(&web::onSerial, this, std::placeholders::_1)); - //mEvts->onConnect(std::bind(&web::onConnect, this, std::placeholders::_1)); - //mWeb->addHandler(mEvts); + + mEvts->onConnect(std::bind(&web::onConnect, this, std::placeholders::_1)); + mWeb->addHandler(mEvts); mApi->setup(); + + registerDebugCb(std::bind(&web::serialCb, this, std::placeholders::_1)); } @@ -74,14 +78,14 @@ void web::loop(void) { //----------------------------------------------------------------------------- -/*void web::onConnect(AsyncEventSourceClient *client) { - DPRINTLN(DBG_INFO, "onConnect"); +void web::onConnect(AsyncEventSourceClient *client) { + DPRINTLN(DBG_VERBOSE, "onConnect"); if(client->lastId()) - DPRINTLN(DBG_INFO, "Client reconnected! Last message ID that it got is: " + String(client->lastId())); + DPRINTLN(DBG_VERBOSE, "Client reconnected! Last message ID that it got is: " + String(client->lastId())); client->send("hello!", NULL, millis(), 1000); -}*/ +} //----------------------------------------------------------------------------- @@ -91,11 +95,6 @@ void web::onIndex(AsyncWebServerRequest *request) { AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), index_html, index_html_len); response->addHeader(F("Content-Encoding"), "gzip"); request->send(response); - - /* - html.replace(F("{TS}"), String(mConfig->sendInterval) + " "); - html.replace(F("{JS_TS}"), String(mConfig->sendInterval * 1000)); - request->send(200, "text/html", html);*/ } @@ -318,149 +317,17 @@ void web::showSave(AsyncWebServerRequest *request) { //----------------------------------------------------------------------------- -void web::showVisualization(AsyncWebServerRequest *request) { - DPRINTLN(DBG_VERBOSE, F("web::showVisualization")); - String html = FPSTR(visualization_html); - html.replace(F("{DEVICE}"), mSysCfg->deviceName); - html.replace(F("{VERSION}"), mVersion); - html.replace(F("{TS}"), String(mConfig->sendInterval) + " "); - html.replace(F("{JS_TS}"), String(mConfig->sendInterval * 1000)); - request->send(200, F("text/html"), html); -} - - -//----------------------------------------------------------------------------- -void web::showLiveData(AsyncWebServerRequest *request) { - DPRINTLN(DBG_VERBOSE, F("web::showLiveData")); - - String modHtml, totalModHtml; - float totalYield = 0, totalYieldToday = 0, totalActual = 0; - uint8_t count = 0; - - for (uint8_t id = 0; id < mMain->mSys->getNumInverters(); id++) { - count++; - - Inverter<> *iv = mMain->mSys->getInverterByPos(id); - if (NULL != iv) { -#ifdef LIVEDATA_VISUALIZED - uint8_t modNum, pos; - switch (iv->type) { - default: - case INV_TYPE_1CH: modNum = 1; break; - case INV_TYPE_2CH: modNum = 2; break; - case INV_TYPE_4CH: modNum = 4; break; - } - - modHtml += F("
" - "
") - + String(iv->name) + F(" Limit ") - + String(iv->actPowerLimit) + F("%"); - if(NoPowerLimit == iv->powerLimit[1]) - modHtml += F(" (not controlled)"); - modHtml += F(" | last Alarm: ") + iv->lastAlarmMsg + F(""); - - uint8_t list[] = {FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_PCT, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_PRA, FLD_ALARM_MES_ID}; +void web::onLive(AsyncWebServerRequest *request) { + DPRINTLN(DBG_VERBOSE, F("onLive")); - for (uint8_t fld = 0; fld < 11; fld++) { - pos = (iv->getPosByChFld(CH0, list[fld])); - - if(fld == 6){ - totalYield += iv->getValue(pos); - } - - if(fld == 7){ - totalYieldToday += iv->getValue(pos); - } - - if(fld == 2){ - totalActual += iv->getValue(pos); - } - - if (0xff != pos) { - modHtml += F("
"); - modHtml += F("") + String(iv->getValue(pos)); - modHtml += F("") + String(iv->getUnit(pos)) + F(""); - modHtml += F("") + String(iv->getFieldName(pos)) + F(""); - modHtml += F("
"); - } - } - modHtml += "
"; - - for (uint8_t ch = 1; ch <= modNum; ch++) { - modHtml += F("
"); - if (iv->chName[ch - 1][0] == 0) - modHtml += F("CHANNEL ") + String(ch); - else - modHtml += String(iv->chName[ch - 1]); - modHtml += F(""); - for (uint8_t j = 0; j < 6; j++) { - switch (j) { - default: pos = (iv->getPosByChFld(ch, FLD_UDC)); break; - case 1: pos = (iv->getPosByChFld(ch, FLD_IDC)); break; - case 2: pos = (iv->getPosByChFld(ch, FLD_PDC)); break; - case 3: pos = (iv->getPosByChFld(ch, FLD_YD)); break; - case 4: pos = (iv->getPosByChFld(ch, FLD_YT)); break; - case 5: pos = (iv->getPosByChFld(ch, FLD_IRR)); break; - } - if (0xff != pos) { - modHtml += F("") + String(iv->getValue(pos)); - modHtml += F("") + String(iv->getUnit(pos)) + F(""); - modHtml += F("") + String(iv->getFieldName(pos)) + F(""); - } - } - modHtml += "
"; - } - modHtml += F("
Last received data requested at: ") + mMain->getDateTimeStr(iv->ts) + F("
"); - modHtml += F("
"); -#else - // dump all data to web frontend - modHtml = F("
");
-            char topic[30], val[10];
-            for (uint8_t i = 0; i < iv->listLen; i++) {
-                snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, iv->getFieldName(i));
-                snprintf(val, 10, "%.3f %s", iv->getValue(i), iv->getUnit(i));
-                modHtml += String(topic) + ": " + String(val) + "\n";
-            }
-            modHtml += F("
"); -#endif - } - } - - if(count > 1){ - totalModHtml += F("
" - "
Gesamt"); - - totalModHtml += F("
"); - totalModHtml += F("") + String(totalActual); - totalModHtml += F("W"); - totalModHtml += F("P_AC All"); - totalModHtml += F("
"); - - totalModHtml += F("
"); - totalModHtml += F("") + String(totalYieldToday); - totalModHtml += F("Wh"); - totalModHtml += F("YieldDayAll"); - totalModHtml += F("
"); - - totalModHtml += F("
"); - totalModHtml += F("") + String(totalYield); - totalModHtml += F("kWh"); - totalModHtml += F("YieldTotalAll"); - totalModHtml += F("
"); - - totalModHtml += F("
"); - totalModHtml += F("
"); - request->send(200, F("text/html"), modHtml); - } else { - request->send(200, F("text/html"), modHtml); - - } + AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), visualization_html, visualization_html_len); + response->addHeader(F("Content-Encoding"), "gzip"); + request->send(response); } //----------------------------------------------------------------------------- -void web::showWebApi(AsyncWebServerRequest *request) -{ +void web::showWebApi(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("web::showWebApi")); DPRINTLN(DBG_DEBUG, request->arg("plain")); const size_t capacity = 200; // Use arduinojson.org/assistant to compute the capacity. @@ -531,9 +398,13 @@ void web::showWebApi(AsyncWebServerRequest *request) //----------------------------------------------------------------------------- -void web::showUpdateForm(AsyncWebServerRequest *request) { - tmplProc *proc = new tmplProc(request, 850); - proc->process(update_html, update_html_len, std::bind(&web::showUpdateFormCb, this, std::placeholders::_1)); +void web::onUpdate(AsyncWebServerRequest *request) { + DPRINTLN(DBG_VERBOSE, F("onUpdate")); + + + AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), update_html, update_html_len); + response->addHeader(F("Content-Encoding"), "gzip"); + request->send(response); } @@ -580,27 +451,17 @@ void web::showUpdate2(AsyncWebServerRequest *request, String filename, size_t in //----------------------------------------------------------------------------- -String web::replaceHtmlGenericKeys(char *key) { - if(0 == strncmp(key, "VERSION", 7)) return mVersion; - else if(0 == strncmp(key, "DEVICE", 6)) return mSysCfg->deviceName; - else if(0 == strncmp(key, "IP", 2)) { - if(mMain->getWifiApActive()) return F("http://192.168.1.1"); - else return (F("http://") + String(WiFi.localIP().toString())); - } +void web::onSerial(AsyncWebServerRequest *request) { + DPRINTLN(DBG_VERBOSE, F("onSerial")); - return ""; + AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), serial_html, serial_html_len); + response->addHeader(F("Content-Encoding"), "gzip"); + request->send(response); } //----------------------------------------------------------------------------- -String web::showUpdateFormCb(char *key) { - String generic = replaceHtmlGenericKeys(key); - if(generic.length() == 0) { - if(0 == strncmp(key, "CONTENT", 7)) - return F("
"); - else if(0 == strncmp(key, "HEAD", 4)) - return ""; - } - - return generic; +void web::serialCb(String msg) { + msg.replace("\r\n", ""); + mEvts->send(msg.c_str(), "serial", millis()); } diff --git a/tools/esp8266/web.h b/tools/esp8266/web.h index f8e46ad4..a7185cd4 100644 --- a/tools/esp8266/web.h +++ b/tools/esp8266/web.h @@ -11,7 +11,6 @@ #include "ESPAsyncWebServer.h" #include "app.h" #include "webApi.h" -#include "tmplProc.h" class app; class webApi; @@ -37,17 +36,17 @@ class web { void onSetup(AsyncWebServerRequest *request); void showSave(AsyncWebServerRequest *request); - void showVisualization(AsyncWebServerRequest *request); - void showLiveData(AsyncWebServerRequest *request); + void onLive(AsyncWebServerRequest *request); void showWebApi(AsyncWebServerRequest *request); - void showUpdateForm(AsyncWebServerRequest *request); + void onUpdate(AsyncWebServerRequest *request); void showUpdate(AsyncWebServerRequest *request); void showUpdate2(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final); + void serialCb(String msg); + private: - String replaceHtmlGenericKeys(char *key); - String showUpdateFormCb(char* key); + void onSerial(AsyncWebServerRequest *request); AsyncWebServer *mWeb; AsyncEventSource *mEvts; diff --git a/tools/esp8266/webApi.cpp b/tools/esp8266/webApi.cpp index 150e6865..66baf52f 100644 --- a/tools/esp8266/webApi.cpp +++ b/tools/esp8266/webApi.cpp @@ -59,6 +59,23 @@ void webApi::onApi(AsyncWebServerRequest *request) { } +//----------------------------------------------------------------------------- +void webApi::getNotFound(JsonObject obj, String url) { + JsonObject ep = obj.createNestedObject("avail_endpoints"); + ep[F("system")] = url + F("system"); + ep[F("statistics")] = url + F("statistics"); + ep[F("inverter/list")] = url + F("inverter/list"); + ep[F("mqtt")] = url + F("mqtt"); + ep[F("ntp")] = url + F("ntp"); + ep[F("pinout")] = url + F("pinout"); + ep[F("radio")] = url + F("radio"); + ep[F("serial")] = url + F("serial"); + ep[F("index")] = url + F("index"); + ep[F("setup")] = url + F("setup"); + ep[F("live")] = url + F("live"); +} + + //----------------------------------------------------------------------------- void webApi::getSystem(JsonObject obj) { obj[F("ssid")] = mSysCfg->stationSsid; @@ -148,23 +165,6 @@ void webApi::getSerial(JsonObject obj) { } -//----------------------------------------------------------------------------- -void webApi::getNotFound(JsonObject obj, String url) { - JsonObject ep = obj.createNestedObject("avail_endpoints"); - ep[F("system")] = url + F("system"); - ep[F("statistics")] = url + F("statistics"); - ep[F("inverter/list")] = url + F("inverter/list"); - ep[F("mqtt")] = url + F("mqtt"); - ep[F("ntp")] = url + F("ntp"); - ep[F("pinout")] = url + F("pinout"); - ep[F("radio")] = url + F("radio"); - ep[F("serial")] = url + F("serial"); - ep[F("index")] = url + F("index"); - ep[F("setup")] = url + F("setup"); - ep[F("live")] = url + F("live"); -} - - //----------------------------------------------------------------------------- void webApi::getIndex(JsonObject obj) { getSystem(obj.createNestedObject(F("system"))); @@ -216,7 +216,9 @@ void webApi::getSetup(JsonObject obj) { //----------------------------------------------------------------------------- void webApi::getLive(JsonObject obj) { + getSystem(obj.createNestedObject(F("system"))); JsonArray invArr = obj.createNestedArray(F("inverter")); + obj["refresh_interval"] = SEND_INTERVAL; uint8_t list[] = {FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_PCT, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_PRA, FLD_ALARM_MES_ID}; @@ -235,18 +237,16 @@ void webApi::getLive(JsonObject obj) { JsonArray ch = obj2.createNestedArray("ch"); JsonArray ch0 = ch.createNestedArray(); + obj2[F("ch_names")][0] = "AC"; for (uint8_t fld = 0; fld < 11; fld++) { pos = (iv->getPosByChFld(CH0, list[fld])); - if (0xff != pos) { - JsonObject dat = ch0.createNestedObject(); - dat[F("value")] = iv->getValue(pos); - dat[F("unit")] = String(iv->getUnit(pos)); - dat[F("name")] = String(iv->getFieldName(pos)); - } + ch0[fld] = (0xff != pos) ? iv->getValue(pos) : 0.0; + obj[F("ch0_fld_units")][fld] = (0xff != pos) ? String(iv->getUnit(pos)) : F("n/a"); + obj[F("ch0_fld_names")][fld] = (0xff != pos) ? String(iv->getFieldName(pos)) : F("n/a"); } for(uint8_t j = 1; j <= iv->channels; j ++) { - obj2[F("ch_names")][j-1] = iv->chName[j]; + obj2[F("ch_names")][j] = String(iv->chName[j-1]); JsonArray cur = ch.createNestedArray(); for (uint8_t k = 0; k < 6; k++) { switch(k) { @@ -258,9 +258,9 @@ void webApi::getLive(JsonObject obj) { case 5: pos = (iv->getPosByChFld(j, FLD_IRR)); break; } cur[k] = (0xff != pos) ? iv->getValue(pos) : 0.0; - if((0 == j) && (0xff != pos)) { - obj2[F("fld_units")][k] = String(iv->getUnit(pos)); - obj2[F("fld_names")][k] = String(iv->getFieldName(pos)); + if(1 == j) { + obj[F("fld_units")][k] = (0xff != pos) ? String(iv->getUnit(pos)) : F("n/a"); + obj[F("fld_names")][k] = (0xff != pos) ? String(iv->getFieldName(pos)) : F("n/a"); } } } diff --git a/tools/esp8266/webApi.h b/tools/esp8266/webApi.h index 9a92519a..e4278bfa 100644 --- a/tools/esp8266/webApi.h +++ b/tools/esp8266/webApi.h @@ -19,6 +19,7 @@ class webApi { private: void onApi(AsyncWebServerRequest *request); + void getNotFound(JsonObject obj, String url); void getSystem(JsonObject obj); void getStatistics(JsonObject obj); @@ -29,7 +30,6 @@ class webApi { void getRadio(JsonObject obj); void getSerial(JsonObject obj); - void getNotFound(JsonObject obj, String url); void getIndex(JsonObject obj); void getSetup(JsonObject obj); void getLive(JsonObject obj); From c32927a94ead55b5af4e47ad8843ffc073156a3c Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 8 Sep 2022 21:24:38 +0200 Subject: [PATCH 14/38] added time to serial console --- tools/esp8266/html/serial.html | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/esp8266/html/serial.html b/tools/esp8266/html/serial.html index e8433437..48cbf5fb 100644 --- a/tools/esp8266/html/serial.html +++ b/tools/esp8266/html/serial.html @@ -17,6 +17,8 @@

diff --git a/tools/esp8266/html/visualization.html b/tools/esp8266/html/visualization.html index 856703e6..9be5dc09 100644 --- a/tools/esp8266/html/visualization.html +++ b/tools/esp8266/html/visualization.html @@ -48,10 +48,10 @@ ch0.appendChild(sub); switch(j) { - case 2: total[j] += val; break; // P_AC - case 6: total[j] += val; break; // YieldTotal - case 7: total[j] += val; break; // YieldDay - case 8: total[j] += val; break; // P_DC + case 2: total[j] += val; break; // P_AC + case 6: total[j] += val; break; // YieldTotal + case 7: total[j] += val; break; // YieldDay + case 8: total[j] += val; break; // P_DC case 10: total[j] += val; break; // P_ACr } } diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index ac918664..d7faefbb 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -351,12 +351,10 @@ void web::showWebApi(AsyncWebServerRequest *request) { uint8_t iv_id = response["inverter"]; uint8_t cmd = response["cmd"]; Inverter<> *iv = mMain->mSys->getInverterByPos(iv_id); - if (NULL != iv) - { - if (response["tx_request"] == (uint8_t)TX_REQ_INFO) - { + if (NULL != iv) { + if (response["tx_request"] == (uint8_t)TX_REQ_INFO) { // if the AlarmData is requested set the Alarm Index to the requested one - if (cmd == AlarmData || cmd == AlarmUpdate){ + if (cmd == AlarmData || cmd == AlarmUpdate) { // set the AlarmMesIndex for the request from user input iv->alarmMesIndex = response["payload"]; } @@ -366,43 +364,32 @@ void web::showWebApi(AsyncWebServerRequest *request) { } - if (response["tx_request"] == (uint8_t)TX_REQ_DEVCONTROL) - { - if (response["cmd"] == (uint8_t)ActivePowerContr) - { + if (response["tx_request"] == (uint8_t)TX_REQ_DEVCONTROL) { + if (response["cmd"] == (uint8_t)ActivePowerContr) { uint16_t webapiPayload = response["payload"]; uint16_t webapiPayload2 = response["payload2"]; - if (webapiPayload > 0 && webapiPayload < 10000) - { + if (webapiPayload > 0 && webapiPayload < 10000) { iv->devControlCmd = ActivePowerContr; iv->powerLimit[0] = webapiPayload; if (webapiPayload2 > 0) - { iv->powerLimit[1] = webapiPayload2; // dev option, no sanity check - } - else - { // if not set, set it to 0x0000 default - iv->powerLimit[1] = AbsolutNonPersistent; // payload will be seted temporay in Watt absolut - } + else // if not set, set it to 0x0000 default + iv->powerLimit[1] = AbsolutNonPersistent; // payload will be seted temporary in Watt absolut if (iv->powerLimit[1] & 0x0001) - { DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("% via REST API")); - } else - { DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("W via REST API")); - } iv->devControlRequest = true; // queue it in the request loop } } - if (response["cmd"] == (uint8_t)TurnOff){ + if (response["cmd"] == (uint8_t)TurnOff) { iv->devControlCmd = TurnOff; iv->devControlRequest = true; // queue it in the request loop - } - if (response["cmd"] == (uint8_t)TurnOn){ + } + if (response["cmd"] == (uint8_t)TurnOn) { iv->devControlCmd = TurnOn; iv->devControlRequest = true; // queue it in the request loop - } + } } } request->send(200, "text/json", "{success:true}"); @@ -480,8 +467,10 @@ void web::serialCb(String msg) { strncpy(&mSerialBuf[mSerialBufFill], mMain->getTimeStr().c_str(), 9); mSerialBufFill += 9; } - else + else { + mSerialBufFill = 0; mEvts->send("webSerial, buffer overflow!", "serial", millis()); + } mSerialAddTime = false; } @@ -493,7 +482,9 @@ void web::serialCb(String msg) { strncpy(&mSerialBuf[mSerialBufFill], msg.c_str(), length); mSerialBufFill += length; } - else + else { + mSerialBufFill = 0; mEvts->send("webSerial, buffer overflow!", "serial", millis()); + } } diff --git a/tools/esp8266/web.h b/tools/esp8266/web.h index 569a9790..c5081598 100644 --- a/tools/esp8266/web.h +++ b/tools/esp8266/web.h @@ -12,7 +12,7 @@ #include "app.h" #include "webApi.h" -#define WEB_SERIAL_BUF_SIZE 1024 +#define WEB_SERIAL_BUF_SIZE 2048 class app; class webApi; diff --git a/tools/esp8266/webApi.cpp b/tools/esp8266/webApi.cpp index 66baf52f..312bc212 100644 --- a/tools/esp8266/webApi.cpp +++ b/tools/esp8266/webApi.cpp @@ -23,7 +23,9 @@ webApi::webApi(AsyncWebServer *srv, app *app, sysConfig_t *sysCfg, config_t *con //----------------------------------------------------------------------------- void webApi::setup(void) { - mSrv->on("/api", HTTP_GET, std::bind(&webApi::onApi, this, std::placeholders::_1)); + mSrv->on("/api", HTTP_GET, std::bind(&webApi::onApi, this, std::placeholders::_1)); + mSrv->on("/api", HTTP_POST, std::bind(&webApi::onApiPost, this, std::placeholders::_1)).onBody( + std::bind(&webApi::onApiPostBody, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); } @@ -59,6 +61,44 @@ void webApi::onApi(AsyncWebServerRequest *request) { } +//----------------------------------------------------------------------------- +void webApi::onApiPost(AsyncWebServerRequest *request) { + DPRINTLN(DBG_VERBOSE, "onApiPost"); +} + + +//----------------------------------------------------------------------------- +void webApi::onApiPostBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) { + DPRINTLN(DBG_VERBOSE, "onApiPostBody"); + DynamicJsonDocument json(200); + AsyncJsonResponse* response = new AsyncJsonResponse(false, 200); + JsonObject root = response->getRoot(); + + DeserializationError err = deserializeJson(json, (const char *)data); + root[F("success")] = (err) ? false : true; + if(!err) { + String path = request->url().substring(5); + if(path == "ctrl") + root[F("success")] = setCtrl(json, root); + else { + root[F("success")] = false; + root[F("error")] = "Path not found: " + path; + } + } + else { + switch (err.code()) { + case DeserializationError::Ok: break; + case DeserializationError::InvalidInput: root[F("error")] = F("Invalid input"); break; + case DeserializationError::NoMemory: root[F("error")] = F("Not enough memory"); break; + default: root[F("error")] = F("Deserialization failed"); break; + } + } + + response->setLength(); + request->send(response); +} + + //----------------------------------------------------------------------------- void webApi::getNotFound(JsonObject obj, String url) { JsonObject ep = obj.createNestedObject("avail_endpoints"); @@ -227,43 +267,100 @@ void webApi::getLive(JsonObject obj) { for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) { iv = mApp->mSys->getInverterByPos(i); if(NULL != iv) { - JsonObject obj2 = invArr.createNestedObject(); - obj2[F("name")] = String(iv->name); - obj2[F("channels")] = iv->channels; - obj2[F("power_limit_read")] = iv->actPowerLimit; - obj2[F("power_limit_active")] = NoPowerLimit != iv->powerLimit[1]; - obj2[F("last_alarm")] = String(iv->lastAlarmMsg); - obj2[F("ts_last_success")] = iv->ts; - - JsonArray ch = obj2.createNestedArray("ch"); - JsonArray ch0 = ch.createNestedArray(); - obj2[F("ch_names")][0] = "AC"; - for (uint8_t fld = 0; fld < 11; fld++) { - pos = (iv->getPosByChFld(CH0, list[fld])); - ch0[fld] = (0xff != pos) ? iv->getValue(pos) : 0.0; - obj[F("ch0_fld_units")][fld] = (0xff != pos) ? String(iv->getUnit(pos)) : F("n/a"); - obj[F("ch0_fld_names")][fld] = (0xff != pos) ? String(iv->getFieldName(pos)) : F("n/a"); - } + if(iv->isLiveDataAssignment()) { + JsonObject obj2 = invArr.createNestedObject(); + obj2[F("name")] = String(iv->name); + obj2[F("channels")] = iv->channels; + obj2[F("power_limit_read")] = iv->actPowerLimit; + obj2[F("power_limit_active")] = NoPowerLimit != iv->powerLimit[1]; + obj2[F("last_alarm")] = String(iv->lastAlarmMsg); + obj2[F("ts_last_success")] = iv->ts; + + JsonArray ch = obj2.createNestedArray("ch"); + JsonArray ch0 = ch.createNestedArray(); + obj2[F("ch_names")][0] = "AC"; + for (uint8_t fld = 0; fld < 11; fld++) { + pos = (iv->getPosByChFld(CH0, list[fld])); + ch0[fld] = (0xff != pos) ? iv->getValue(pos) : 0.0; + obj[F("ch0_fld_units")][fld] = (0xff != pos) ? String(iv->getUnit(pos)) : F("n/a"); + obj[F("ch0_fld_names")][fld] = (0xff != pos) ? String(iv->getFieldName(pos)) : F("n/a"); + } - for(uint8_t j = 1; j <= iv->channels; j ++) { - obj2[F("ch_names")][j] = String(iv->chName[j-1]); - JsonArray cur = ch.createNestedArray(); - for (uint8_t k = 0; k < 6; k++) { - switch(k) { - default: pos = (iv->getPosByChFld(j, FLD_UDC)); break; - case 1: pos = (iv->getPosByChFld(j, FLD_IDC)); break; - case 2: pos = (iv->getPosByChFld(j, FLD_PDC)); break; - case 3: pos = (iv->getPosByChFld(j, FLD_YD)); break; - case 4: pos = (iv->getPosByChFld(j, FLD_YT)); break; - case 5: pos = (iv->getPosByChFld(j, FLD_IRR)); break; - } - cur[k] = (0xff != pos) ? iv->getValue(pos) : 0.0; - if(1 == j) { - obj[F("fld_units")][k] = (0xff != pos) ? String(iv->getUnit(pos)) : F("n/a"); - obj[F("fld_names")][k] = (0xff != pos) ? String(iv->getFieldName(pos)) : F("n/a"); + for(uint8_t j = 1; j <= iv->channels; j ++) { + obj2[F("ch_names")][j] = String(iv->chName[j-1]); + JsonArray cur = ch.createNestedArray(); + for (uint8_t k = 0; k < 6; k++) { + switch(k) { + default: pos = (iv->getPosByChFld(j, FLD_UDC)); break; + case 1: pos = (iv->getPosByChFld(j, FLD_IDC)); break; + case 2: pos = (iv->getPosByChFld(j, FLD_PDC)); break; + case 3: pos = (iv->getPosByChFld(j, FLD_YD)); break; + case 4: pos = (iv->getPosByChFld(j, FLD_YT)); break; + case 5: pos = (iv->getPosByChFld(j, FLD_IRR)); break; + } + cur[k] = (0xff != pos) ? iv->getValue(pos) : 0.0; + if(1 == j) { + obj[F("fld_units")][k] = (0xff != pos) ? String(iv->getUnit(pos)) : F("n/a"); + obj[F("fld_names")][k] = (0xff != pos) ? String(iv->getFieldName(pos)) : F("n/a"); + } } } } } } } + + +//----------------------------------------------------------------------------- +bool webApi::setCtrl(DynamicJsonDocument jsonIn, JsonObject jsonOut) { + uint8_t cmd = jsonIn[F("cmd")]; + if(TX_REQ_DEVCONTROL == jsonIn[F("tx_request")]) { + DPRINTLN(DBG_INFO, F("devcontrol, cmd: 0x") + String(cmd, HEX)); + if(ActivePowerContr == cmd) { + Inverter<> *iv = getInverter(jsonIn, jsonOut); + if(NULL != iv) { + JsonArray payload = jsonIn[F("payload")].as(); + iv->powerLimit[0] = payload[0]; + iv->powerLimit[1] = payload[1]; + } + } + else if(TurnOn == cmd) { + Inverter<> *iv = getInverter(jsonIn, jsonOut); + if(NULL != iv) { + iv->devControlCmd = TurnOn; + iv->devControlRequest = true; + } + else + return false; + } + else if(TurnOff == cmd) { + Inverter<> *iv = getInverter(jsonIn, jsonOut); + if(NULL != iv) { + iv->devControlCmd = TurnOff; + iv->devControlRequest = true; + } + else + return false; + } + else { + jsonOut["error"] = "unknown 'cmd' = " + String(cmd); + return false; + } + } + else { + jsonOut["error"] = "unknown 'tx_request'"; + return false; + } + + return true; +} + + +//----------------------------------------------------------------------------- +Inverter<> *webApi::getInverter(DynamicJsonDocument jsonIn, JsonObject jsonOut) { + uint8_t id = jsonIn[F("inverter")]; + Inverter<> *iv = mApp->mSys->getInverterByPos(id); + if(NULL == iv) + jsonOut["error"] = F("inverter index to high: ") + String(id); + return iv; +} diff --git a/tools/esp8266/webApi.h b/tools/esp8266/webApi.h index e4278bfa..e9d7e5e8 100644 --- a/tools/esp8266/webApi.h +++ b/tools/esp8266/webApi.h @@ -19,6 +19,8 @@ class webApi { private: void onApi(AsyncWebServerRequest *request); + void onApiPost(AsyncWebServerRequest *request); + void onApiPostBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total); void getNotFound(JsonObject obj, String url); void getSystem(JsonObject obj); @@ -34,6 +36,10 @@ class webApi { void getSetup(JsonObject obj); void getLive(JsonObject obj); + bool setCtrl(DynamicJsonDocument jsonIn, JsonObject jsonOut); + + Inverter<> *getInverter(DynamicJsonDocument jsonIn, JsonObject jsonOut); + AsyncWebServer *mSrv; app *mApp; From 675c6ce908e4d73a6949e201ef3c1570a5770a9b Mon Sep 17 00:00:00 2001 From: stefan123t Date: Sat, 10 Sep 2022 23:08:44 +0200 Subject: [PATCH 20/38] raise debug level in debug env --- tools/esp8266/include/dbg.h | 2 ++ tools/esp8266/platformio.ini | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/esp8266/include/dbg.h b/tools/esp8266/include/dbg.h index 9573e42f..17b334c9 100644 --- a/tools/esp8266/include/dbg.h +++ b/tools/esp8266/include/dbg.h @@ -22,7 +22,9 @@ //----------------------------------------------------------------------------- // globally used level +#ifndef DEBUG_LEVEL #define DEBUG_LEVEL DBG_INFO +#endif #ifdef ARDUINO #include "Arduino.h" diff --git a/tools/esp8266/platformio.ini b/tools/esp8266/platformio.ini index 657cab44..f18c0877 100644 --- a/tools/esp8266/platformio.ini +++ b/tools/esp8266/platformio.ini @@ -58,7 +58,7 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -build_flags = -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_OOM -DDEBUG_ESP_PORT=Serial +build_flags = -DDEBUG_LEVEL=DBG_DEBUG -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_OOM -DDEBUG_ESP_PORT=Serial build_type = debug monitor_filters = ;default ; Remove typical terminal control codes from input @@ -77,7 +77,7 @@ monitor_filters = [env:esp32-wroom32-debug] platform = espressif32 board = lolin_d32 -build_flags = -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_OOM -DDEBUG_ESP_PORT=Serial +build_flags = -DDEBUG_LEVEL=DBG_DEBUG -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_OOM -DDEBUG_ESP_PORT=Serial build_type = debug monitor_filters = ;default ; Remove typical terminal control codes from input From 56b747709aeca83192d8d7d115a6ab77bee83913 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 12 Sep 2022 22:57:36 +0200 Subject: [PATCH 21/38] improved records in hmInverter.h --- tools/esp8266/app.cpp | 123 +++++---- tools/esp8266/app.h | 1 + tools/esp8266/hmDefines.h | 3 +- tools/esp8266/hmInverter.h | 353 ++++++++++++++------------ tools/esp8266/hmRadio.h | 15 +- tools/esp8266/hmSystem.h | 10 +- tools/esp8266/html/index.html | 6 +- tools/esp8266/html/visualization.html | 5 +- tools/esp8266/webApi.cpp | 86 +++---- 9 files changed, 314 insertions(+), 288 deletions(-) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index bff4c8e8..bb431a50 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -192,12 +192,13 @@ void app::loop(void) { for(uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); if(NULL != iv) { - if(iv->isAvailable(mTimestamp)) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + if(iv->isAvailable(mTimestamp, rec)) { DPRINTLN(DBG_INFO, "Inverter: " + String(id)); - for(uint8_t i = 0; i < iv->listLen; i++) { - if(0.0f != iv->getValue(i)) { - snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, iv->getFieldName(i)); - snprintf(val, 10, "%.3f %s", iv->getValue(i), iv->getUnit(i)); + for(uint8_t i = 0; i < rec->length; i++) { + if(0.0f != iv->getValue(i, rec)) { + snprintf(topic, 30, "%s/ch%d/%s", iv->name, rec->assign[i].ch, iv->getFieldName(i, rec)); + snprintf(val, 10, "%.3f %s", iv->getValue(i, rec), iv->getUnit(i, rec)); DPRINTLN(DBG_INFO, String(topic) + ": " + String(val)); } yield(); @@ -249,17 +250,21 @@ void app::loop(void) { resetPayload(iv); yield(); - if(mConfig.serialDebug) + if(mConfig.serialDebug) { DPRINTLN(DBG_DEBUG, F("app:loop WiFi WiFi.status ") + String(WiFi.status())); DPRINTLN(DBG_INFO, F("Requesting Inverter SN ") + String(iv->serial.u64, HEX)); + } if(iv->devControlRequest && (iv->powerLimit[0] > 0) && (NoPowerLimit != iv->powerLimit[1])) { // prevent to "switch off" if(mConfig.serialDebug) DPRINTLN(DBG_INFO, F("Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0])); - mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd ,iv->powerLimit); + mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit); + mPayload[iv->id].txCmd = iv->devControlCmd; iv->clearCmdQueue(); iv->enqueCommand(SystemConfigPara); } else { - mSys->Radio.sendTimePacket(iv->radioId.u64,iv->getQueuedCmd(), mPayload[iv->id].ts,iv->alarmMesIndex); + uint8_t cmd = iv->getQueuedCmd(); + mSys->Radio.sendTimePacket(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex); + mPayload[iv->id].txCmd = cmd; mRxTicker = 0; } } @@ -320,7 +325,7 @@ void app::processPayload(bool retransmit) { mPayload[iv->id].complete = true; } if(!mPayload[iv->id].complete ) { - if(!buildPayload(iv->id)) { + if(!buildPayload(iv->id)) { // payload not complete if(mPayload[iv->id].requested) { if(retransmit) { if(mPayload[iv->id].retransmits < mConfig.maxRetransPerPyld) { @@ -339,19 +344,26 @@ void app::processPayload(bool retransmit) { else { if(mConfig.serialDebug) DPRINTLN(DBG_ERROR, F("while retrieving data: last frame missing: Request Retransmit")); - if(0x00 != mLastPacketId) - mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, mLastPacketId, true); - else - mSys->Radio.sendTimePacket(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts,iv->alarmMesIndex); + //if(0x00 != mLastPacketId) + // mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, mLastPacketId, true); + //else + mSys->Radio.sendTimePacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex); } mSys->Radio.switchRxCh(100); } } } } - else { + else { // payload complete + DPRINTLN(DBG_INFO, F("procPyld: cmd: ") + String(mPayload[iv->id].txCmd)); + DPRINTLN(DBG_INFO, F("procPyld: txid: ") + String(mPayload[iv->id].txId)); + DPRINTLN(DBG_INFO, F("procPyld: max: ") + String(mPayload[iv->id].maxPackId)); + record_t<> *rec = iv->getRecordStruct(mPayload[iv->id].txCmd); // choose the parser + if(NULL == rec) + DPRINTLN(DBG_ERROR, F("record is NULL!")); mPayload[iv->id].complete = true; - iv->ts = mPayload[iv->id].ts; + rec->ts = mPayload[iv->id].ts; + mStat.rxSuccess++; uint8_t payload[128]; uint8_t offs = 0; @@ -367,14 +379,12 @@ void app::processPayload(bool retransmit) { DPRINT(DBG_INFO, F("Payload (") + String(offs) + "): "); mSys->Radio.dumpBuf(NULL, payload, offs); } - mStat.rxSuccess++; - - iv->getAssignment(); // choose the parser - for(uint8_t i = 0; i < iv->listLen; i++) { - iv->addValue(i, payload); // cmd value decides which parser is used to decode payload + + for(uint8_t i = 0; i < rec->length; i++) { + iv->addValue(i, payload, rec); yield(); } - iv->doCalculations(); // cmd value decides which parser is used to decode payload + iv->doCalculations(); iv->setQueuedCmdFinished(); @@ -386,22 +396,22 @@ void app::processPayload(bool retransmit) { for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); if (NULL != iv) { - if (iv->isAvailable(mTimestamp)) { - for (uint8_t i = 0; i < iv->listLen; i++) { - snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, fields[iv->assign[i].fieldId]); - snprintf(val, 10, "%.3f", iv->getValue(i)); - mMqtt.sendMsg(topic, val); - if(iv->isLiveDataAssignment()) { - if(CH0 == iv->assign[i].ch) { - switch(iv->assign[i].fieldId) { - case FLD_PAC: total[0] += iv->getValue(i); break; - case FLD_YT: total[1] += iv->getValue(i); break; - case FLD_YD: total[2] += iv->getValue(i); break; - case FLD_PDC: total[3] += iv->getValue(i); break; + if(iv->getRecordStruct(RealTimeRunData_Debug) == rec) { + if (iv->isAvailable(mTimestamp, rec)) { + for (uint8_t i = 0; i < rec->length; i++) { + snprintf(topic, 30, "%s/ch%d/%s", iv->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]); + snprintf(val, 10, "%.3f", iv->getValue(i, rec)); + mMqtt.sendMsg(topic, val); + if(CH0 == rec->assign[i].ch) { + switch(rec->assign[i].fieldId) { + case FLD_PAC: total[0] += iv->getValue(i, rec); break; + case FLD_YT: total[1] += iv->getValue(i, rec); break; + case FLD_YD: total[2] += iv->getValue(i, rec); break; + case FLD_PDC: total[3] += iv->getValue(i, rec); break; } } + yield(); } - yield(); } } } @@ -424,6 +434,8 @@ void app::processPayload(bool retransmit) { } } + resetPayload(iv); + #ifdef __MQTT_AFTER_RX__ doMQTT = true; #endif @@ -543,7 +555,8 @@ void app::sendMqttDiscoveryConfig(void) { for(uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); if(NULL != iv) { - if(iv->isAvailable(mTimestamp) && mMqttConfigSendState[id] != true) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + if(iv->isAvailable(mTimestamp, rec) && mMqttConfigSendState[id] != true) { DynamicJsonDocument deviceDoc(128); deviceDoc["name"] = iv->name; deviceDoc["ids"] = String(iv->serial.u64, HEX); @@ -553,21 +566,21 @@ void app::sendMqttDiscoveryConfig(void) { JsonObject deviceObj = deviceDoc.as(); DynamicJsonDocument doc(384); - for(uint8_t i = 0; i < iv->listLen; i++) { - if (iv->assign[i].ch == CH0) { - snprintf(name, 32, "%s %s", iv->name, iv->getFieldName(i)); + for(uint8_t i = 0; i < rec->length; i++) { + if (rec->assign[i].ch == CH0) { + snprintf(name, 32, "%s %s", iv->name, iv->getFieldName(i, rec)); } else { - snprintf(name, 32, "%s CH%d %s", iv->name, iv->assign[i].ch, iv->getFieldName(i)); + snprintf(name, 32, "%s CH%d %s", iv->name, rec->assign[i].ch, iv->getFieldName(i, rec)); } - snprintf(stateTopic, 64, "%s/%s/ch%d/%s", mConfig.mqtt.topic, iv->name, iv->assign[i].ch, iv->getFieldName(i)); - snprintf(discoveryTopic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->name, iv->assign[i].ch, iv->getFieldName(i)); - snprintf(uniq_id, 32, "ch%d_%s", iv->assign[i].ch, iv->getFieldName(i)); - const char* devCls = getFieldDeviceClass(iv->assign[i].fieldId); - const char* stateCls = getFieldStateClass(iv->assign[i].fieldId); + snprintf(stateTopic, 64, "%s/%s/ch%d/%s", mConfig.mqtt.topic, iv->name, rec->assign[i].ch, iv->getFieldName(i, rec)); + snprintf(discoveryTopic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->name, rec->assign[i].ch, iv->getFieldName(i, rec)); + snprintf(uniq_id, 32, "ch%d_%s", rec->assign[i].ch, iv->getFieldName(i, rec)); + const char* devCls = getFieldDeviceClass(rec->assign[i].fieldId); + const char* stateCls = getFieldStateClass(rec->assign[i].fieldId); doc["name"] = name; doc["stat_t"] = stateTopic; - doc["unit_of_meas"] = iv->getUnit(i); + doc["unit_of_meas"] = iv->getUnit(i, rec); doc["uniq_id"] = String(iv->serial.u64, HEX) + "_" + uniq_id; doc["dev"] = deviceObj; doc["exp_aft"] = mMqttInterval + 5; // add 5 sec if connection is bad or ESP too slow @@ -644,7 +657,12 @@ void app::resetSystem(void) { mShowRebootRequest = false; - memset(mPayload, 0, (MAX_NUM_INVERTERS * sizeof(invPayload_t))); + Inverter<> *iv; + for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { + iv = mSys->getInverterByPos(i, false); + if(NULL != iv) + resetPayload(iv); + } memset(&mStat, 0, sizeof(statistics_t)); mLastPacketId = 0x00; } @@ -806,13 +824,12 @@ void app::setupMqtt(void) { } //----------------------------------------------------------------------------- -void app::resetPayload(Inverter<>* iv) -{ - // reset payload data +void app::resetPayload(Inverter<>* iv) { memset(mPayload[iv->id].len, 0, MAX_PAYLOAD_ENTRIES); + mPayload[iv->id].txCmd = 0; mPayload[iv->id].retransmits = 0; - mPayload[iv->id].maxPackId = 0; - mPayload[iv->id].complete = false; - mPayload[iv->id].requested = true; - mPayload[iv->id].ts = mTimestamp; + mPayload[iv->id].maxPackId = 0; + mPayload[iv->id].complete = false; + mPayload[iv->id].requested = true; + mPayload[iv->id].ts = mTimestamp; } diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index 0f42cb2b..012c710b 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -38,6 +38,7 @@ typedef HmSystem HmSyste typedef struct { + uint8_t txCmd; uint8_t txId; uint8_t invId; uint32_t ts; diff --git a/tools/esp8266/hmDefines.h b/tools/esp8266/hmDefines.h index baec0f75..18498fd6 100644 --- a/tools/esp8266/hmDefines.h +++ b/tools/esp8266/hmDefines.h @@ -30,6 +30,7 @@ enum {FLD_UDC = 0, FLD_IDC, FLD_PDC, FLD_YD, FLD_YW, FLD_YT, const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", "YieldTotal", "U_AC", "I_AC", "P_AC", "Freq", "Temp", "Pct", "Efficiency", "Irradiation","P_ACr", "ALARM_MES_ID","FWVersion","FWBuildYear","FWBuildMonthDay","HWPartId","PowerLimit","LastAlarmCode"}; +const char* const notAvail = "n/a"; // mqtt discovery device classes enum {DEVICE_CLS_NONE = 0, DEVICE_CLS_CURRENT, DEVICE_CLS_ENERGY, DEVICE_CLS_PWR, DEVICE_CLS_VOLTAGE, DEVICE_CLS_FREQ, DEVICE_CLS_TEMP}; @@ -207,7 +208,7 @@ const byteAssign_t hm4chAssignment[] = { { FLD_F, UNIT_HZ, CH0, 48, 2, 100 }, { FLD_PCT, UNIT_PCT, CH0, 56, 2, 10 }, { FLD_T, UNIT_C, CH0, 58, 2, 10 }, - { FLD_ALARM_MES_ID, UNIT_NONE, CH0, 60, 2, 1 }, + { FLD_ALARM_MES_ID, UNIT_NONE, CH0, 60, 2, 1 }, { FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC }, { FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }, { FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC }, diff --git a/tools/esp8266/hmInverter.h b/tools/esp8266/hmInverter.h index 6a309590..ea83587d 100644 --- a/tools/esp8266/hmInverter.h +++ b/tools/esp8266/hmInverter.h @@ -23,7 +23,7 @@ */ // forward declaration of class -template +template class Inverter; @@ -55,17 +55,23 @@ struct calcFunc_t { func_t* func; // function pointer }; +template +struct record_t { + byteAssign_t* assign; // assigment of bytes in payload + uint8_t length; // length of the assignment list + T *record; // data pointer + uint32_t ts; // timestamp of last received payload +}; class CommandAbstract { public: - CommandAbstract(uint8_t txType = 0, uint8_t cmd = 0){ + CommandAbstract(uint8_t txType = 0, uint8_t cmd = 0) { _TxType = txType; _Cmd = cmd; }; virtual ~CommandAbstract() {}; - const uint8_t getCmd() - { + const uint8_t getCmd() { return _Cmd; } @@ -75,11 +81,11 @@ class CommandAbstract { }; class InfoCommand : public CommandAbstract { -public: - InfoCommand(uint8_t cmd){ - _TxType = 0x15; - _Cmd = cmd; - } + public: + InfoCommand(uint8_t cmd){ + _TxType = 0x15; + _Cmd = cmd; + } }; // list of all available functions, mapped in hmDefines.h @@ -94,35 +100,34 @@ const calcFunc_t calcFunctions[] = { }; -template +template class Inverter { public: - uint8_t id; // unique id + uint8_t id; // unique id char name[MAX_NAME_LENGTH]; // human readable name, eg. "HM-600.1" - uint8_t type; // integer which refers to inverter type - byteAssign_t* assign; // type of inverter - uint8_t listLen; // length of assignments - uint16_t alarmMesIndex; // Last recorded Alarm Message Index - uint16_t fwVersion; // Firmware Version from Info Command Request - uint16_t powerLimit[2]; // limit power output - uint16_t actPowerLimit; // - uint8_t devControlCmd; // carries the requested cmd - bool devControlRequest; // true if change needed - serial_u serial; // serial number as on barcode - serial_u radioId; // id converted to modbus - uint8_t channels; // number of PV channels (1-4) - uint32_t ts; // timestamp of last received payload - RECORDTYPE *record; // pointer for values - uint16_t chMaxPwr[4]; // maximum power of the modules (Wp) - char chName[4][MAX_NAME_LENGTH]; // human readable name for channel + uint8_t type; // integer which refers to inverter type + uint16_t alarmMesIndex; // Last recorded Alarm Message Index + uint16_t fwVersion; // Firmware Version from Info Command Request + uint16_t powerLimit[2]; // limit power output + uint16_t actPowerLimit; // + uint8_t devControlCmd; // carries the requested cmd + bool devControlRequest; // true if change needed + serial_u serial; // serial number as on barcode + serial_u radioId; // id converted to modbus + uint8_t channels; // number of PV channels (1-4) + record_t recordMeas; // structure for measured values + record_t recordInfo; // structure for info values + record_t recordConfig; // structure for system config values + record_t recordAlarm; // structure for alarm values + uint16_t chMaxPwr[4]; // maximum power of the modules (Wp) + char chName[4][MAX_NAME_LENGTH]; // human readable name for channels String lastAlarmMsg; - bool initialized; // needed to check if the inverter was correctly added (ESP32 specific - union types are never null) + bool initialized; // needed to check if the inverter was correctly added (ESP32 specific - union types are never null) Inverter() { - ts = 0; - powerLimit[0] = 0xffff; // 65535 W Limit -> unlimited - powerLimit[1] = NoPowerLimit; // - actPowerLimit = 0xffff; // init feedback from inverter to -1 + powerLimit[0] = 0xffff; // 65535 W Limit -> unlimited + powerLimit[1] = NoPowerLimit; // default power limit setting + actPowerLimit = 0xffff; // init feedback from inverter to -1 devControlRequest = false; devControlCmd = InitDataState; initialized = false; @@ -174,187 +179,201 @@ class Inverter { void init(void) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:init")); - getAssignment(); + initAssignment(&recordMeas, RealTimeRunData_Debug); + initAssignment(&recordInfo, InverterDevInform_All); + initAssignment(&recordConfig, SystemConfigPara); + initAssignment(&recordAlarm, AlarmData); toRadioId(); - record = new RECORDTYPE[listLen]; memset(name, 0, MAX_NAME_LENGTH); memset(chName, 0, MAX_NAME_LENGTH * 4); - memset(record, 0, sizeof(RECORDTYPE) * listLen); initialized = true; } - uint8_t getPosByChFld(uint8_t channel, uint8_t fieldId) { + uint8_t getPosByChFld(uint8_t channel, uint8_t fieldId, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getPosByChFld")); uint8_t pos = 0; - for(; pos < listLen; pos++) { - if((assign[pos].ch == channel) && (assign[pos].fieldId == fieldId)) - break; + if(NULL != rec) { + for(; pos < rec->length; pos++) { + if((rec->assign[pos].ch == channel) && (rec->assign[pos].fieldId == fieldId)) + break; + } + return (pos >= rec->length) ? 0xff : pos; } - return (pos >= listLen) ? 0xff : pos; + else + return 0xff; } - const char *getFieldName(uint8_t pos) { + const char *getFieldName(uint8_t pos, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getFieldName")); - return fields[assign[pos].fieldId]; + if(NULL != rec) + return fields[rec->assign[pos].fieldId]; + return notAvail; } - const char *getUnit(uint8_t pos) { + const char *getUnit(uint8_t pos, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getUnit")); - return units[assign[pos].unitId]; + if(NULL != rec) + return units[rec->assign[pos].unitId]; + return notAvail; } - uint8_t getChannel(uint8_t pos) { + uint8_t getChannel(uint8_t pos, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getChannel")); - return assign[pos].ch; + if(NULL != rec) + return rec->assign[pos].ch; + return 0; } - void addValue(uint8_t pos, uint8_t buf[]) { + void addValue(uint8_t pos, uint8_t buf[], record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:addValue")); - uint8_t cmd = getQueuedCmd(); - uint8_t ptr = assign[pos].start; - uint8_t end = ptr + assign[pos].num; - uint16_t div = assign[pos].div; - if(CMD_CALC != div) { - uint32_t val = 0; - do { - val <<= 8; - val |= buf[ptr]; - } while(++ptr != end); - if ((RECORDTYPE)(div) > 1){ - record[pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div); - } - else { - record[pos] = (RECORDTYPE)(val); - } - - } - if (cmd == RealTimeRunData_Debug) { - // get last alarm message index and save it in the inverter object - if (getPosByChFld(0, FLD_ALARM_MES_ID) == pos){ - if (alarmMesIndex < record[pos]){ - alarmMesIndex = record[pos]; - //enqueCommand(AlarmUpdate); // What is the function of AlarmUpdate? - enqueCommand(AlarmData); + if(NULL != rec) { + uint8_t ptr = rec->assign[pos].start; + uint8_t end = ptr + rec->assign[pos].num; + uint16_t div = rec->assign[pos].div; + if(rec == &recordMeas) { + if(CMD_CALC != div) { + uint32_t val = 0; + do { + val <<= 8; + val |= buf[ptr]; + } while(++ptr != end); + if ((REC_TYP)(div) > 1) + rec->record[pos] = (REC_TYP)(val) / (REC_TYP)(div); + else + rec->record[pos] = (REC_TYP)(val); } - else { - alarmMesIndex = record[pos]; // no change + // get last alarm message index and save it in the inverter object + if (getPosByChFld(0, FLD_ALARM_MES_ID, rec) == pos){ + if (alarmMesIndex < rec->record[pos]){ + alarmMesIndex = rec->record[pos]; + //enqueCommand(AlarmUpdate); // What is the function of AlarmUpdate? + enqueCommand(AlarmData); + } + else { + alarmMesIndex = rec->record[pos]; // no change + } } } - } - if (cmd == InverterDevInform_All) { - // get at least the firmware version and save it to the inverter object - if (getPosByChFld(0, FLD_FW_VERSION) == pos){ - fwVersion = record[pos]; - DPRINT(DBG_DEBUG, F("Inverter FW-Version: ") + String(fwVersion)); + if (rec == &recordInfo) { + // get at least the firmware version and save it to the inverter object + if (getPosByChFld(0, FLD_FW_VERSION, rec) == pos){ + fwVersion = rec->record[pos]; + DPRINT(DBG_DEBUG, F("Inverter FW-Version: ") + String(fwVersion)); + } } - } - if (cmd == SystemConfigPara) { - // get at least the firmware version and save it to the inverter object - if (getPosByChFld(0, FLD_ACT_PWR_LIMIT) == pos){ - actPowerLimit = record[pos]; - DPRINT(DBG_DEBUG, F("Inverter actual power limit: ") + String(actPowerLimit)); + if (rec == &recordConfig) { + // get at least the firmware version and save it to the inverter object + if (getPosByChFld(0, FLD_ACT_PWR_LIMIT, rec) == pos){ + actPowerLimit = rec->record[pos]; + DPRINT(DBG_DEBUG, F("Inverter actual power limit: ") + String(actPowerLimit)); + } } - } - if (cmd == AlarmData){ - if (getPosByChFld(0, FLD_LAST_ALARM_CODE) == pos){ - lastAlarmMsg = getAlarmStr(record[pos]); + if (rec == &recordAlarm){ + if (getPosByChFld(0, FLD_LAST_ALARM_CODE, rec) == pos){ + lastAlarmMsg = getAlarmStr(rec->record[pos]); + } } } + else + DPRINTLN(DBG_ERROR, F("addValue: assignment not found with cmd 0x")); } - RECORDTYPE getValue(uint8_t pos) { + REC_TYP getValue(uint8_t pos, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getValue")); - return record[pos]; + if(NULL == rec) + return 0; + return rec->record[pos]; } void doCalculations() { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:doCalculations")); - uint8_t cmd = getQueuedCmd(); - getAssignment(); - if (cmd == RealTimeRunData_Debug){ - for(uint8_t i = 0; i < listLen; i++) { - if(CMD_CALC == assign[i].div) { - record[i] = calcFunctions[assign[i].start].func(this, assign[i].num); - } - yield(); + record_t<> *rec = getRecordStruct(RealTimeRunData_Debug); + for(uint8_t i = 0; i < rec->length; i++) { + if(CMD_CALC == rec->assign[i].div) { + rec->record[i] = calcFunctions[rec->assign[i].start].func(this, rec->assign[i].num); } + yield(); } } - bool isAvailable(uint32_t timestamp) { + bool isAvailable(uint32_t timestamp, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:isAvailable")); - return ((timestamp - ts) < INACT_THRES_SEC); + return ((timestamp - rec->ts) < INACT_THRES_SEC); } - bool isProducing(uint32_t timestamp) { + bool isProducing(uint32_t timestamp, record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:isProducing")); - if(isAvailable(timestamp)) { - uint8_t pos = getPosByChFld(CH0, FLD_PAC); - return (getValue(pos) > INACT_PWR_THRESH); + if(isAvailable(timestamp, rec)) { + uint8_t pos = getPosByChFld(CH0, FLD_PAC, rec); + return (getValue(pos, rec) > INACT_PWR_THRESH); } return false; } - uint32_t getLastTs(void) { + uint32_t getLastTs(record_t<> *rec) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getLastTs")); - return ts; + return rec->ts; } - void getAssignment() { - DPRINTLN(DBG_DEBUG, F("hmInverter.h:getAssignment")); - // Default assignment; - if (INV_TYPE_1CH == type) { - listLen = (uint8_t)(HM1CH_LIST_LEN); - assign = (byteAssign_t *)hm1chAssignment; - channels = 1; - } - else if (INV_TYPE_2CH == type) { - listLen = (uint8_t)(HM2CH_LIST_LEN); - assign = (byteAssign_t *)hm2chAssignment; - channels = 2; - } - else if (INV_TYPE_4CH == type) { - listLen = (uint8_t)(HM4CH_LIST_LEN); - assign = (byteAssign_t *)hm4chAssignment; - channels = 4; - } - else { - listLen = 0; - channels = 0; - assign = NULL; + record_t<> *getRecordStruct(uint8_t cmd) { + switch (cmd) { + case RealTimeRunData_Debug: return &recordMeas; + case InverterDevInform_All: return &recordInfo; + case SystemConfigPara: return &recordConfig; + case AlarmData: return &recordAlarm; + default: break; } + return NULL; + } - switch (getQueuedCmd()) { + void initAssignment(record_t<> *rec, uint8_t cmd) { + DPRINTLN(DBG_VERBOSE, F("hmInverter.h:initAssignment")); + rec->ts = 0; + rec->length = 0; + switch (cmd) { case RealTimeRunData_Debug: - // Do nothing will use default + if (INV_TYPE_1CH == type) { + rec->length = (uint8_t)(HM1CH_LIST_LEN); + rec->assign = (byteAssign_t *)hm1chAssignment; + channels = 1; + } + else if (INV_TYPE_2CH == type) { + rec->length = (uint8_t)(HM2CH_LIST_LEN); + rec->assign = (byteAssign_t *)hm2chAssignment; + channels = 2; + } + else if (INV_TYPE_4CH == type) { + rec->length = (uint8_t)(HM4CH_LIST_LEN); + rec->assign = (byteAssign_t *)hm4chAssignment; + channels = 4; + } + else { + rec->length = 0; + rec->assign = NULL; + channels = 0; + } break; case InverterDevInform_All: - listLen = (uint8_t)(HMINFO_LIST_LEN); - assign = (byteAssign_t *)InfoAssignment; + rec->length = (uint8_t)(HMINFO_LIST_LEN); + rec->assign = (byteAssign_t *)InfoAssignment; break; case SystemConfigPara: - listLen = (uint8_t)(HMSYSTEM_LIST_LEN); - assign = (byteAssign_t *)SystemConfigParaAssignment; + rec->length = (uint8_t)(HMSYSTEM_LIST_LEN); + rec->assign = (byteAssign_t *)SystemConfigParaAssignment; break; case AlarmData: - listLen = (uint8_t)(HMALARMDATA_LIST_LEN); - assign = (byteAssign_t *)AlarmDataAssignment; + rec->length = (uint8_t)(HMALARMDATA_LIST_LEN); + rec->assign = (byteAssign_t *)AlarmDataAssignment; break; default: - DPRINTLN(DBG_INFO, "Parser not implemented"); + DPRINTLN(DBG_INFO, F("initAssignment: Parser not implemented")); break; } - } - bool isLiveDataAssignment(void) { - if(assign == (byteAssign_t *)hm1chAssignment) - return true; - else if(assign == (byteAssign_t *)hm2chAssignment) - return true; - else if(assign == (byteAssign_t *)hm4chAssignment) - return true; - else - return false; + if(0 != rec->length) { + rec->record = new REC_TYP[rec->length]; + memset(rec->record, 0, sizeof(REC_TYP) * rec->length); + } } String getAlarmStr(u_int16_t alarmCode) { @@ -455,10 +474,11 @@ template static T calcYieldTotalCh0(Inverter<> *iv, uint8_t arg0) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcYieldTotalCh0")); if(NULL != iv) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); T yield = 0; for(uint8_t i = 1; i <= iv->channels; i++) { - uint8_t pos = iv->getPosByChFld(i, FLD_YT); - yield += iv->getValue(pos); + uint8_t pos = iv->getPosByChFld(i, FLD_YT, rec); + yield += iv->getValue(pos, rec); } return yield; } @@ -469,10 +489,11 @@ template static T calcYieldDayCh0(Inverter<> *iv, uint8_t arg0) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcYieldDayCh0")); if(NULL != iv) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); T yield = 0; for(uint8_t i = 1; i <= iv->channels; i++) { - uint8_t pos = iv->getPosByChFld(i, FLD_YD); - yield += iv->getValue(pos); + uint8_t pos = iv->getPosByChFld(i, FLD_YD, rec); + yield += iv->getValue(pos, rec); } return yield; } @@ -483,9 +504,10 @@ template static T calcUdcCh(Inverter<> *iv, uint8_t arg0) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcUdcCh")); // arg0 = channel of source - for(uint8_t i = 0; i < iv->listLen; i++) { - if((FLD_UDC == iv->assign[i].fieldId) && (arg0 == iv->assign[i].ch)) { - return iv->getValue(i); + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + for(uint8_t i = 0; i < rec->length; i++) { + if((FLD_UDC == rec->assign[i].fieldId) && (arg0 == rec->assign[i].ch)) { + return iv->getValue(i, rec); } } @@ -496,10 +518,11 @@ template static T calcPowerDcCh0(Inverter<> *iv, uint8_t arg0) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcPowerDcCh0")); if(NULL != iv) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); T dcPower = 0; for(uint8_t i = 1; i <= iv->channels; i++) { - uint8_t pos = iv->getPosByChFld(i, FLD_PDC); - dcPower += iv->getValue(pos); + uint8_t pos = iv->getPosByChFld(i, FLD_PDC, rec); + dcPower += iv->getValue(pos, rec); } return dcPower; } @@ -510,12 +533,13 @@ template static T calcEffiencyCh0(Inverter<> *iv, uint8_t arg0) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcEfficiencyCh0")); if(NULL != iv) { - uint8_t pos = iv->getPosByChFld(CH0, FLD_PAC); - T acPower = iv->getValue(pos); + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + uint8_t pos = iv->getPosByChFld(CH0, FLD_PAC, rec); + T acPower = iv->getValue(pos, rec); T dcPower = 0; for(uint8_t i = 1; i <= iv->channels; i++) { - pos = iv->getPosByChFld(i, FLD_PDC); - dcPower += iv->getValue(pos); + pos = iv->getPosByChFld(i, FLD_PDC, rec); + dcPower += iv->getValue(pos, rec); } if(dcPower > 0) return acPower / dcPower * 100.0f; @@ -528,9 +552,10 @@ static T calcIrradiation(Inverter<> *iv, uint8_t arg0) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcIrradiation")); // arg0 = channel if(NULL != iv) { - uint8_t pos = iv->getPosByChFld(arg0, FLD_PDC); + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + uint8_t pos = iv->getPosByChFld(arg0, FLD_PDC, rec); if(iv->chMaxPwr[arg0-1] > 0) - return iv->getValue(pos) / iv->chMaxPwr[arg0-1] * 100.0f; + return iv->getValue(pos, rec) / iv->chMaxPwr[arg0-1] * 100.0f; } return 0.0; } diff --git a/tools/esp8266/hmRadio.h b/tools/esp8266/hmRadio.h index 35b1d08c..8c04ffef 100644 --- a/tools/esp8266/hmRadio.h +++ b/tools/esp8266/hmRadio.h @@ -164,7 +164,7 @@ class HmRadio { } void sendControlPacket(uint64_t invId, uint8_t cmd, uint16_t *data) { - DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendControlPacket")); + DPRINTLN(DBG_INFO, F("sendControlPacket")); sendCmdPacket(invId, TX_REQ_DEVCONTROL, ALL_FRAMES, false); // 0x80 implementation as original DTU code int cnt = 0; mTxBuf[10] = cmd; // cmd --> 0x0b => Type_ActivePowerContr, 0 on, 1 off, 2 restart, 12 reactive power, 13 power factor @@ -187,17 +187,14 @@ class HmRadio { } void sendTimePacket(uint64_t invId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId) { - //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendTimePacket")); + DPRINTLN(DBG_INFO, F("sendTimePacket")); sendCmdPacket(invId, TX_REQ_INFO, ALL_FRAMES, false); mTxBuf[10] = cmd; // cid mTxBuf[11] = 0x00; CP_U32_LittleEndian(&mTxBuf[12], ts); - if (cmd == RealTimeRunData_Debug || cmd == AlarmData ){ + if (cmd == RealTimeRunData_Debug || cmd == AlarmData ) { mTxBuf[18] = (alarmMesId >> 8) & 0xff; mTxBuf[19] = (alarmMesId ) & 0xff; - } else { - mTxBuf[18] = 0x00; - mTxBuf[19] = 0x00; } uint16_t crc = Ahoy::crc16(&mTxBuf[10], 14); mTxBuf[24] = (crc >> 8) & 0xff; @@ -208,7 +205,7 @@ class HmRadio { } void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool calcCrc = true) { - //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendCmdPacket")); + DPRINTLN(DBG_INFO, F("sendCmdPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX)); memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); mTxBuf[0] = mid; // message id CP_U32_BigEndian(&mTxBuf[1], (invId >> 8)); @@ -221,7 +218,7 @@ class HmRadio { } bool checkPaketCrc(uint8_t buf[], uint8_t *len, uint8_t rxCh) { - //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:checkPaketCrc")); + //DPRINTLN(DBG_INFO, F("hmRadio.h:checkPaketCrc")); *len = (buf[0] >> 2); if(*len > (MAX_RF_PAYLOAD_SIZE - 2)) *len = MAX_RF_PAYLOAD_SIZE - 2; @@ -237,8 +234,6 @@ class HmRadio { bool switchRxCh(uint16_t addLoop = 0) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:switchRxCh")); - //DPRINTLN(DBG_VERBOSE, F("R")); - mRxLoopCnt += addLoop; if(mRxLoopCnt != 0) { mRxLoopCnt--; diff --git a/tools/esp8266/hmSystem.h b/tools/esp8266/hmSystem.h index 150853ad..eb246ccb 100644 --- a/tools/esp8266/hmSystem.h +++ b/tools/esp8266/hmSystem.h @@ -63,14 +63,8 @@ class HmSystem { uint8_t len = (uint8_t)strlen(name); strncpy(p->name, name, (len > MAX_NAME_LENGTH) ? MAX_NAME_LENGTH : len); - if(NULL == p->assign) { - DPRINT(DBG_ERROR, F("no assignment for type found!")); - return NULL; - } - else { - mNumInv ++; - return p; - } + mNumInv ++; + return p; } INVERTERTYPE *findInverter(uint8_t buf[]) { diff --git a/tools/esp8266/html/index.html b/tools/esp8266/html/index.html index 26a9728d..201f13d7 100644 --- a/tools/esp8266/html/index.html +++ b/tools/esp8266/html/index.html @@ -27,14 +27,14 @@
This project was started from this discussion. (Mikrocontroller.net)
- New updates can be found on Github: https://github.com/grindylow/ahoy
+ New updates can be found on Github: https://github.com/lumapu/ahoy

- Please report issues using the feature provided by Github
+ Please report issues using the feature provided by Github

Discuss with us on Discord

Creative Commons - https://creativecommons.org/licenses/by-nc-sa/3.0/de/
- Check the licenses which are published on https://github.com/grindylow/ahoy as well

+ Check the licenses which are published on https://github.com/lumapu/ahoy as well