diff --git a/tools/esp8266/ahoywifi.cpp b/tools/esp8266/ahoywifi.cpp index af1729fa..b3feb43c 100644 --- a/tools/esp8266/ahoywifi.cpp +++ b/tools/esp8266/ahoywifi.cpp @@ -54,7 +54,7 @@ void ahoywifi::setup(uint32_t timeout, bool settingValid) { if(mApActive) DBGPRINTLN(F("192.168.1.1")); else - DBGPRINTLN(WiFi.localIP()); + DBGPRINTLN(WiFi.localIP().toString()); DPRINTLN(DBG_INFO, F("to configure your device")); DPRINTLN(DBG_INFO, F("----------------------------------------\n")); } diff --git a/tools/esp8266/config.h b/tools/esp8266/config.h index bfbfeb86..26ff32c5 100644 --- a/tools/esp8266/config.h +++ b/tools/esp8266/config.h @@ -108,9 +108,6 @@ // default MQTT topic #define DEF_MQTT_TOPIC "inverter" -// changes the style of "/setup" page, visualized = nicer -#define LIVEDATA_VISUALIZED - #if __has_include("config_override.h") #include "config_override.h" #endif diff --git a/tools/esp8266/dbg.cpp b/tools/esp8266/dbg.cpp new file mode 100644 index 00000000..9f7c9fd3 --- /dev/null +++ b/tools/esp8266/dbg.cpp @@ -0,0 +1,3 @@ +#include "dbg.h" + +DBG_CB mCb = NULL; diff --git a/tools/esp8266/html/api.js b/tools/esp8266/html/api.js index f8b002a9..d21a653a 100644 --- a/tools/esp8266/html/api.js +++ b/tools/esp8266/html/api.js @@ -16,8 +16,10 @@ function getAjax(url, ptr) { http.send(null); } function p() { - if(http.readyState == 4) - ptr(JSON.parse(http.responseText)); + if(http.readyState == 4) { + if(null != http.responseText) + ptr(JSON.parse(http.responseText)); + } } } @@ -60,6 +62,13 @@ function sel(name, opt, selId) { function div(cl) { e = document.createElement('div'); - e.classList.add(cl); + e.classList.add(...cl); + return e; +} + +function span(val, cl) { + e = document.createElement('span'); + e.innerHTML = val; + e.classList.add(...cl); return e; } diff --git a/tools/esp8266/html/convert.py b/tools/esp8266/html/convert.py index 62f831e4..36877dec 100755 --- a/tools/esp8266/html/convert.py +++ b/tools/esp8266/html/convert.py @@ -64,7 +64,8 @@ def convert2Header(inFile, compress): convert2Header("index.html", True) convert2Header("setup.html", True) -convert2Header("visualization.html", False) -convert2Header("update.html", False) +convert2Header("visualization.html", True) +convert2Header("update.html", True) +convert2Header("serial.html", True) convert2Header("style.css", True) convert2Header("api.js", True) diff --git a/tools/esp8266/html/index.html b/tools/esp8266/html/index.html index 627b3b03..f9c8814f 100644 --- a/tools/esp8266/html/index.html +++ b/tools/esp8266/html/index.html @@ -10,9 +10,10 @@

AHOY

- Visualization
+ Visualization

Setup
+ Serial Console

Uptime:

ESP-Time:

@@ -80,8 +81,10 @@ html += "producing\n"; if(false == i["is_avail"]) { - var date = new Date(i["ts_last_success"] * 1000); - html += "-> last successful transmission: " + date.toLocaleString('de-DE', {timeZone: 'UTC'}); + if(i["ts_last_success"] > 0) { + var date = new Date(i["ts_last_success"] * 1000); + html += "-> last successful transmission: " + date.toLocaleString('de-DE', {timeZone: 'UTC'}); + } } } @@ -100,13 +103,19 @@ } function parse(obj) { - parseSys(obj["system"]); - parseStat(obj["statistics"]); - parseIv(obj["inverter"]); - parseWarnInfo(obj["warnings"], obj["infos"]); - document.getElementById("refresh").innerHTML = obj["refresh_interval"]; - if(false == intervalSet) - window.setInterval("getAjax('/api/index', parse)", obj["refresh_interval"] * 1000); + if(null != obj) { + parseSys(obj["system"]); + parseStat(obj["statistics"]); + parseIv(obj["inverter"]); + parseWarnInfo(obj["warnings"], obj["infos"]); + document.getElementById("refresh").innerHTML = obj["refresh_interval"]; + if(false == intervalSet) { + window.setInterval("getAjax('/api/index', parse)", obj["refresh_interval"] * 1000); + intervalSet = true; + } + } + else + document.getElementById("refresh").innerHTML = "n/a"; } getAjax("/api/index", parse); diff --git a/tools/esp8266/html/serial.html b/tools/esp8266/html/serial.html new file mode 100644 index 00000000..e8433437 --- /dev/null +++ b/tools/esp8266/html/serial.html @@ -0,0 +1,50 @@ + + + + Serial Console + + + + + +

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::onLive(AsyncWebServerRequest *request) { + DPRINTLN(DBG_VERBOSE, F("onLive")); + + 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::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}; - - 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); - - } -} - - -//----------------------------------------------------------------------------- -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);