diff --git a/scripts/__pycache__/htmlPreprocessorDefines.cpython-311.pyc b/scripts/__pycache__/htmlPreprocessorDefines.cpython-311.pyc new file mode 100644 index 00000000..6dca7de6 Binary files /dev/null and b/scripts/__pycache__/htmlPreprocessorDefines.cpython-311.pyc differ diff --git a/scripts/getVersion.py b/scripts/getVersion.py index d3f1e576..f579b56a 100644 --- a/scripts/getVersion.py +++ b/scripts/getVersion.py @@ -78,7 +78,7 @@ def renameFw(path_define, env): os.rename("src/.pio/build/" + env + "/firmware.bin", dst + fname) os.rename("src/.pio/build/" + env + "/firmware.elf.7z", dst + fname[:-3] + "elf.7z") - if env[:5] == "esp32": + if env[:5] == "esp32" or env[:4] == "open": os.rename("src/.pio/build/" + env + "/bootloader.bin", dst + "bootloader.bin") os.rename("src/.pio/build/" + env + "/partitions.bin", dst + "partitions.bin") genOtaBin(dst) diff --git a/src/CHANGES.md b/src/CHANGES.md index 5efb1610..f4c5d4ce 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,16 @@ # Development Changes +## 0.8.123 - 2024-05-30 +* fix ESP8266, ESP32 static IP #1643 #1608 +* update MqTT library which enhances stability #1646 +* merge PR: MQTT JSON Payload pro Kanal und total, auswählbar #1541 +* add option to publish mqtt as json +* publish rssi not on ch0 any more, published on `topic/rssi` +* add total power to index page (if multiple inverters are configured) +* show device name in html title #1639 +* update AsyncWebserver library to `3.2.2` +* add environment name to filename of coredump + ## 0.8.122 - 2024-05-23 * add button for donwloading coredump (ESP32 variants only) diff --git a/src/config/settings.h b/src/config/settings.h index 25243fe7..02beedce 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -164,6 +164,7 @@ typedef struct { char user[MQTT_USER_LEN]; char pwd[MQTT_PWD_LEN]; char topic[MQTT_TOPIC_LEN]; + bool json; uint16_t interval; bool enableRetain; } cfgMqtt_t; @@ -485,6 +486,7 @@ class settings { snprintf(mCfg.mqtt.pwd, MQTT_PWD_LEN, "%s", DEF_MQTT_PWD); snprintf(mCfg.mqtt.topic, MQTT_TOPIC_LEN, "%s", DEF_MQTT_TOPIC); mCfg.mqtt.interval = 0; // off + mCfg.mqtt.json = false; // off mCfg.mqtt.enableRetain = true; mCfg.inst.sendInterval = SEND_INTERVAL; @@ -742,12 +744,14 @@ class settings { obj[F("user")] = mCfg.mqtt.user; obj[F("pwd")] = mCfg.mqtt.pwd; obj[F("topic")] = mCfg.mqtt.topic; + obj[F("json")] = mCfg.mqtt.json; obj[F("intvl")] = mCfg.mqtt.interval; obj[F("retain")] = mCfg.mqtt.enableRetain; } else { getVal(obj, F("port"), &mCfg.mqtt.port); getVal(obj, F("intvl"), &mCfg.mqtt.interval); + getVal(obj, F("json"), &mCfg.mqtt.json); getChar(obj, F("broker"), mCfg.mqtt.broker, MQTT_ADDR_LEN); getChar(obj, F("user"), mCfg.mqtt.user, MQTT_USER_LEN); getChar(obj, F("clientId"), mCfg.mqtt.clientId, MQTT_CLIENTID_LEN); diff --git a/src/defines.h b/src/defines.h index c0664b7d..ab651821 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 122 +#define VERSION_PATCH 123 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index 98281805..4287d26e 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -62,8 +62,8 @@ enum {FLD_UDC = 0, FLD_IDC, FLD_PDC, FLD_YD, FLD_YW, FLD_YT, FLD_GRID_PROFILE_VERSION, /*FLD_ACT_REACTIVE_PWR_LIMIT, FLD_ACT_PF,*/ FLD_LAST_ALARM_CODE, FLD_MP, FLD_MT}; const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", "YieldTotal", - "U_AC", "U_AC_1N", "U_AC_2N", "U_AC_3N", "UAC_12", "UAC_23", "UAC_31", "I_AC", - "IAC_1", "I_AC_2", "I_AC_3", "P_AC", "F_AC", "Temp", "PF_AC", "Efficiency", "Irradiation","Q_AC", + "U_AC", "U_AC_1N", "U_AC_2N", "U_AC_3N", "U_AC_12", "U_AC_23", "U_AC_31", "I_AC", + "I_AC_1", "I_AC_2", "I_AC_3", "P_AC", "F_AC", "Temp", "PF_AC", "Efficiency", "Irradiation","Q_AC", "ALARM_MES_ID","FWVersion","FWBuildYear","FWBuildMonthDay","FWBuildHourMinute","BootloaderVersion", "active_PowerLimit", "HWPartNumber", "HWVersion", "GridProfileCode", "GridProfileVersion", /*"reactivePowerLimit","Powerfactor",*/ "LastAlarmCode", "MaxPower", "MaxTemp"}; @@ -72,7 +72,7 @@ const char* const notAvail = "n/a"; const uint8_t fieldUnits[] = {UNIT_V, UNIT_A, UNIT_W, UNIT_WH, UNIT_KWH, UNIT_KWH, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_A, UNIT_A, UNIT_A, UNIT_A, UNIT_W, UNIT_HZ, UNIT_C, UNIT_NONE, UNIT_PCT, UNIT_PCT, UNIT_VAR, - UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_PCT, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_W}; + UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_PCT, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_W, UNIT_C}; // 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}; @@ -389,8 +389,11 @@ const devInfo_t devInfo[] = { { 0x102271, 2000 }, // v2 black backplane, 16A // HMT - { 0x103311, 1800 }, - { 0x103331, 2250 } + { 0x103241, 1600 }, // -4T + { 0x103251, 1800 }, // -4T + { 0x103271, 2000 }, // -4T + { 0x103311, 1800 }, // -6T + { 0x103331, 2250 } // -6T }; #define MI_REQ_CH1 0x09 diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 5a9f2130..b72ec5ab 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -538,6 +538,10 @@ class Inverter { rec->length = (uint8_t)(HMS4CH_LIST_LEN); rec->assign = reinterpret_cast(const_cast(hms4chAssignment)); rec->pyldLen = HMS4CH_PAYLOAD_LEN; + } else if(IV_HMT == ivGen){ + rec->length = (uint8_t)(HMT4CH_LIST_LEN); + rec->assign = reinterpret_cast(const_cast(hmt4chAssignment)); + rec->pyldLen = HMT4CH_PAYLOAD_LEN; } channels = 4; } diff --git a/src/hms/hmsDefines.h b/src/hms/hmsDefines.h index c71aa796..07aec682 100644 --- a/src/hms/hmsDefines.h +++ b/src/hms/hmsDefines.h @@ -131,6 +131,67 @@ const byteAssign_t hms4chAssignment[] = { #define HMS4CH_LIST_LEN (sizeof(hms4chAssignment) / sizeof(byteAssign_t)) #define HMS4CH_PAYLOAD_LEN 66 +//------------------------------------- +// HMT-1600, HMT-1800, HMT-2000 +//------------------------------------- +const byteAssign_t hmt4chAssignment[] = { + { FLD_UDC, UNIT_V, CH1, 2, 2, 10 }, + { FLD_IDC, UNIT_A, CH1, 4, 2, 100 }, + { FLD_PDC, UNIT_W, CH1, 8, 2, 10 }, + { FLD_YT, UNIT_KWH, CH1, 12, 4, 1000 }, + { FLD_YD, UNIT_WH, CH1, 20, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC }, + { FLD_MP, UNIT_W, CH1, CALC_MPDC_CH, CH1, CMD_CALC }, + + { FLD_UDC, UNIT_V, CH2, CALC_UDC_CH, CH1, CMD_CALC }, + { FLD_IDC, UNIT_A, CH2, 6, 2, 100 }, + { FLD_PDC, UNIT_W, CH2, 10, 2, 10 }, + { FLD_YT, UNIT_KWH, CH2, 16, 4, 1000 }, + { FLD_YD, UNIT_WH, CH2, 22, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH2, CALC_IRR_CH, CH2, CMD_CALC }, + { FLD_MP, UNIT_W, CH2, CALC_MPDC_CH, CH2, CMD_CALC }, + + { FLD_UDC, UNIT_V, CH3, 24, 2, 10 }, + { FLD_IDC, UNIT_A, CH3, 26, 2, 100 }, + { FLD_PDC, UNIT_W, CH3, 30, 2, 10 }, + { FLD_YT, UNIT_KWH, CH3, 34, 4, 1000 }, + { FLD_YD, UNIT_WH, CH3, 42, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH3, CALC_IRR_CH, CH3, CMD_CALC }, + { FLD_MP, UNIT_W, CH3, CALC_MPDC_CH, CH3, CMD_CALC }, + + { FLD_UDC, UNIT_V, CH4, CALC_UDC_CH, CH3, CMD_CALC }, + { FLD_IDC, UNIT_A, CH4, 28, 2, 100 }, + { FLD_PDC, UNIT_W, CH4, 32, 2, 10 }, + { FLD_YT, UNIT_KWH, CH4, 38, 4, 1000 }, + { FLD_YD, UNIT_WH, CH4, 44, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH4, CALC_IRR_CH, CH4, CMD_CALC }, + { FLD_MP, UNIT_W, CH4, CALC_MPDC_CH, CH4, CMD_CALC }, + + { FLD_UAC_1N, UNIT_V, CH0, 68, 2, 10 }, + { FLD_UAC_2N, UNIT_V, CH0, 70, 2, 10 }, + { FLD_UAC_3N, UNIT_V, CH0, 72, 2, 10 }, + { FLD_UAC_12, UNIT_V, CH0, 74, 2, 10 }, + { FLD_UAC_23, UNIT_V, CH0, 76, 2, 10 }, + { FLD_UAC_31, UNIT_V, CH0, 78, 2, 10 }, + { FLD_F, UNIT_HZ, CH0, 80, 2, 100 }, + { FLD_PAC, UNIT_W, CH0, 82, 2, 10 }, + { FLD_Q, UNIT_VAR, CH0, 84, 2, 10 }, + { FLD_IAC_1, UNIT_A, CH0, 86, 2, 100 }, + { FLD_IAC_2, UNIT_A, CH0, 88, 2, 100 }, + { FLD_IAC_3, UNIT_A, CH0, 90, 2, 100 }, + { FLD_PF, UNIT_NONE, CH0, 92, 2, 1000 }, + { FLD_T, UNIT_C, CH0, 94, 2, 10 }, + { FLD_EVT, UNIT_NONE, CH0, 96, 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 }, + { FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }, + { FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }, + { FLD_MT, UNIT_C, CH0, CALC_MT_CH0, 0, CMD_CALC } +}; +#define HMT4CH_LIST_LEN (sizeof(hmt4chAssignment) / sizeof(byteAssign_t)) +#define HMT4CH_PAYLOAD_LEN 98 + //------------------------------------- // HMT-1800, HMT-2250 //------------------------------------- diff --git a/src/network/AhoyWifiEsp32.h b/src/network/AhoyWifiEsp32.h index 52ad6292..89c9bbb4 100644 --- a/src/network/AhoyWifiEsp32.h +++ b/src/network/AhoyWifiEsp32.h @@ -25,6 +25,7 @@ class AhoyWifi : public AhoyNetwork { #if !defined(AP_ONLY) WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); WiFi.setSortMethod(WIFI_CONNECT_AP_BY_SIGNAL); + setStaticIp(); WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd, WIFI_ALL_CHANNEL_SCAN); mWifiConnecting = true; @@ -41,7 +42,6 @@ class AhoyWifi : public AhoyNetwork { mStatus = NetworkState::CONNECTED; mWifiConnecting = false; DPRINTLN(DBG_INFO, F("Network connected")); - setStaticIp(); } break; diff --git a/src/network/AhoyWifiEsp8266.h b/src/network/AhoyWifiEsp8266.h index 2da0a409..b6ea65d2 100644 --- a/src/network/AhoyWifiEsp8266.h +++ b/src/network/AhoyWifiEsp8266.h @@ -71,6 +71,7 @@ class AhoyWifi : public AhoyNetwork { DBGPRINT(" " + String(bssid[j], HEX)); } DBGPRINTLN(""); + setStaticIp(); WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd, 0, &bssid[0]); mWifiConnecting = true; break; @@ -84,7 +85,6 @@ class AhoyWifi : public AhoyNetwork { break; case NetworkState::CONNECTED: - setStaticIp(); break; case NetworkState::GOT_IP: diff --git a/src/platformio.ini b/src/platformio.ini index 0ed3f298..69359aa4 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -26,7 +26,7 @@ extra_scripts = post:../scripts/add_littlefs_binary.py lib_deps = - https://github.com/esphome/ESPAsyncWebServer @ ^3.2.0 + https://github.com/esphome/ESPAsyncWebServer @ ^3.2.2 https://github.com/nRF24/RF24.git#v1.4.8 paulstoffregen/Time @ ^1.6.1 https://github.com/bertmelis/espMqttClient#v1.7.0 diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 4ce2b76c..f092a159 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -62,7 +62,7 @@ class PubMqtt { mUptime = uptime; mIntervalTimeout = 1; - SendIvData.setup(app, sys, utcTs, &mSendList); + SendIvData.setup(app, sys, cfg_mqtt, utcTs, &mSendList); SendIvData.setPublishFunc([this](const char *subTopic, const char *payload, bool retained, uint8_t qos) { publish(subTopic, payload, retained, true, qos); }); @@ -564,6 +564,9 @@ class PubMqtt { } void sendData(Inverter<> *iv, uint8_t curInfoCmd) { + if (mCfgMqtt->json) + return; + record_t<> *rec = iv->getRecordStruct(curInfoCmd); uint32_t lastTs = iv->getLastTs(rec); diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index aa221be7..3f12afc6 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -24,9 +24,10 @@ class PubMqttIvData { public: PubMqttIvData() : mTotal{}, mSubTopic{}, mVal{} {} - void setup(IApp *app, HMSYSTEM *sys, uint32_t *utcTs, std::queue *sendList) { + void setup(IApp *app, HMSYSTEM *sys, cfgMqtt_t *cfg_mqtt, uint32_t *utcTs, std::queue *sendList) { mApp = app; mSys = sys; + mCfg = cfg_mqtt; mUtcTimestamp = utcTs; mSendList = sendList; mState = IDLE; @@ -115,7 +116,7 @@ class PubMqttIvData { mPublish(mSubTopic.data(), mVal.data(), true, QOS_0); if((mIv->ivGen == IV_HMS) || (mIv->ivGen == IV_HMT)) { - snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch0/rssi", mIv->config->name); + snprintf(mSubTopic.data(), mSubTopic.size(), "%s/rssi", mIv->config->name); snprintf(mVal.data(), mVal.size(), "%d", mIv->rssi); mPublish(mSubTopic.data(), mVal.data(), false, QOS_0); } @@ -193,18 +194,45 @@ class PubMqttIvData { static_cast(mIv->getChannelFieldValue(CH0, FLD_GRID_PROFILE_CODE, rec)), static_cast(mIv->getChannelFieldValue(CH0, FLD_GRID_PROFILE_VERSION, rec))); } else { - snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]); - snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mIv->getValue(mPos, rec))); + if (!mCfg->json) { + snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]); + snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mIv->getValue(mPos, rec))); + } } - uint8_t qos = (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) ? QOS_2 : QOS_0; - if((FLD_EVT != rec->assign[mPos].fieldId) - && (FLD_LAST_ALARM_CODE != rec->assign[mPos].fieldId)) - mPublish(mSubTopic.data(), mVal.data(), retained, qos); + if ((InverterDevInform_All == mCmd) || (InverterDevInform_Simple == mCmd) || !mCfg->json) { + uint8_t qos = (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) ? QOS_2 : QOS_0; + if((FLD_EVT != rec->assign[mPos].fieldId) + && (FLD_LAST_ALARM_CODE != rec->assign[mPos].fieldId)) + mPublish(mSubTopic.data(), mVal.data(), retained, qos); + } } mPos++; } else { if (MqttSentStatus::LAST_SUCCESS_SENT == rec->mqttSentStatus) { + if (mCfg->json && (RealTimeRunData_Debug == mCmd)) { + DynamicJsonDocument doc(300); + + for (mPos = 0; mPos < rec->length; mPos++) { + doc[fields[rec->assign[mPos].fieldId]] = ah::round3(mIv->getValue(mPos, rec)); + + bool publish = false; + if (mPos != (rec->length - 1)) { // not last one + if (rec->assign[mPos].ch != rec->assign[mPos+1].ch) + publish = true; + } else + publish = true; + + if (publish) { + // if next channel or end->publish + serializeJson(doc, mVal.data(), mVal.size()); + snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d", mIv->config->name, rec->assign[mPos].ch); + mPublish(mSubTopic.data(), mVal.data(), false, QOS_0); + doc.clear(); + } + } + } + sendRadioStat(rec->length); rec->mqttSentStatus = MqttSentStatus::DATA_SENT; } @@ -262,11 +290,27 @@ class PubMqttIvData { mTotal[4] = mApp->getTotalMaxPower(); break; } - snprintf(mSubTopic.data(), mSubTopic.size(), "total/%s", fields[fieldId]); - snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mTotal[mPos])); - mPublish(mSubTopic.data(), mVal.data(), retained, QOS_0); + if (!mCfg->json) { + snprintf(mSubTopic.data(), mSubTopic.size(), "total/%s", fields[fieldId]); + snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mTotal[mPos])); + mPublish(mSubTopic.data(), mVal.data(), retained, QOS_0); + } mPos++; } else { + if (mCfg->json) { + int type[5] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC, FLD_MP}; + snprintf(mVal.data(), mVal.size(), "{"); + + for (mPos = 0; mPos < 5; mPos++) { + snprintf(mSubTopic.data(), mSubTopic.size(), "\"%s\":%g", fields[type[mPos]], ah::round3(mTotal[mPos])); + strcat(mVal.data(), mSubTopic.data()); + if (mPos < 4) + strcat(mVal.data(), ","); + else + strcat(mVal.data(), "}"); + } + mPublish("total", mVal.data(), true, QOS_0); + } mSendList->pop(); mSendTotals = false; mState = IDLE; @@ -275,6 +319,7 @@ class PubMqttIvData { private: IApp *mApp = nullptr; + cfgMqtt_t *mCfg = nullptr; HMSYSTEM *mSys = nullptr; uint32_t *mUtcTimestamp = nullptr; @@ -293,7 +338,7 @@ class PubMqttIvData { bool mRTRDataHasBeenSent = false; std::array mSubTopic; - std::array mVal; + std::array mVal; std::queue *mSendList = nullptr; }; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index dd8c5ca5..e7f23055 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -83,7 +83,7 @@ class RestApi { mHeapFrag = ESP.getHeapFragmentation(); #endif - AsyncJsonResponse* response = new AsyncJsonResponse(false, 6000); + AsyncJsonResponse* response = new AsyncJsonResponse(false, 8000); JsonObject root = response->getRoot(); String path = request->url().substring(5); @@ -369,6 +369,7 @@ class RestApi { String filename = ah::getDateTimeStrFile(gTimezone.toLocal(mApp->getTimestamp())); filename += "_v" + String(mApp->getVersion()); + filename += "_" + String(ENV_NAME); response->addHeader("Content-Description", "File Transfer"); response->addHeader("Content-Disposition", "attachment; filename=" + filename + "_coredump.bin"); @@ -391,6 +392,7 @@ class RestApi { obj[F("modules")] = String(mApp->getVersionModules()); obj[F("build")] = String(AUTO_GIT_HASH); obj[F("env")] = String(ENV_NAME); + obj[F("host")] = mConfig->sys.deviceName; obj[F("menu_prot")] = mApp->isProtected(request->client()->remoteIP().toString().c_str(), "", true); obj[F("menu_mask")] = (uint16_t)(mConfig->sys.protectionMask ); obj[F("menu_protEn")] = (bool) (mConfig->sys.adminPwd[0] != '\0'); @@ -418,7 +420,6 @@ class RestApi { obj[F("dark_mode")] = (bool)mConfig->sys.darkMode; obj[F("sched_reboot")] = (bool)mConfig->sys.schedReboot; - obj[F("hostname")] = mConfig->sys.deviceName; obj[F("pwd_set")] = (strlen(mConfig->sys.adminPwd) > 0); obj[F("prot_mask")] = mConfig->sys.protectionMask; @@ -750,6 +751,7 @@ class RestApi { 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); + obj[F("json")] = (bool) mConfig->mqtt.json; obj[F("interval")] = String(mConfig->mqtt.interval); obj[F("retain")] = (bool)mConfig->mqtt.enableRetain; } diff --git a/src/web/html/api.js b/src/web/html/api.js index 6c2ccec2..4930ce17 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -143,7 +143,7 @@ function parseVersion(obj) { function parseESP(obj) { document.getElementById("esp_type").replaceChildren( - document.createTextNode("Board: " + obj["esp_type"]) + document.createTextNode("Board: " + obj.esp_type) ); } @@ -153,7 +153,11 @@ function parseRssi(obj) { icon = iconWifi1; else if(obj["wifi_rssi"] <= -70) icon = iconWifi2; - document.getElementById("wifiicon").replaceChildren(svg(icon, 32, 32, "icon-fg2", obj["wifi_rssi"])); + document.getElementById("wifiicon").replaceChildren(svg(icon, 32, 32, "icon-fg2", obj.wifi_rssi)); +} + +function parseTitle(obj) { + document.title = obj.host + " - " + document.title } function toIsoDateStr(d) { diff --git a/src/web/html/history.html b/src/web/html/history.html index 9e15daa8..8b3b63c7 100644 --- a/src/web/html/history.html +++ b/src/web/html/history.html @@ -149,6 +149,7 @@ parseNav(obj.generic) parseESP(obj.generic) parseRssi(obj.generic) + parseTitle(obj.generic) window.setInterval("getAjax('/api/powerHistory', parsePowerHistory)", obj.refresh * 1000) setTimeout(() => { window.setInterval("getAjax('/api/powerHistoryDay', parsePowerHistoryDay)", obj.refresh * 1000) diff --git a/src/web/html/index.html b/src/web/html/index.html index 70a9cd26..442160d4 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -14,6 +14,7 @@

System Infos: +

@@ -56,8 +57,10 @@ } function parseGeneric(obj) { - if(exeOnce) + if(exeOnce) { parseESP(obj) + parseTitle(obj) + } parseRssi(obj) } @@ -111,6 +114,8 @@ function parseIv(obj, ts) { var p = div(["none"]); + var total = 0; + var count = 0; for(var i of obj) { var icon = iconSuccess; var cl = "icon-success"; @@ -131,7 +136,9 @@ avail += "{#NOT_PRODUCING}"; else { icon = iconSuccessFull; - avail += "{#PRODUCING} " + i.cur_pwr + "W"; + avail += "{#PRODUCING} " + i.cur_pwr + " W"; + total += i.cur_pwr; + count += 1; } } @@ -149,6 +156,13 @@ } } document.getElementById("iv").replaceChildren(p); + + if (count > 1) { + var t = div(["none"]); + t.append(svg(iconInfo, 30, 30, "icon icon-info"), span("Total: " + Math.round(total).toLocaleString() + " W"), br()); + document.getElementById("total").replaceChildren(t); + document.getElementById("total").appendChild(div(["hr"])); + } } function parseWarn(warn) { @@ -165,7 +179,7 @@ p.append(svg(iconInfo, 30, 30, "icon icon-info"), span("{#UPDATE_AVAIL}: " + release), br()); else if(getVerInt("{#VERSION}") > getVerInt(release)) p.append(svg(iconInfo, 30, 30, "icon icon-info"), span("{#USING_DEV_VERSION} {#VERSION}. {#DEV_ISSUE_RELEASE_VERSION}: " + release), br()); - else + else p.append(svg(iconInfo, 30, 30, "icon icon-info"), span("{#RELEASE_INSTALLED}: " + release), br()); } diff --git a/src/web/html/serial.html b/src/web/html/serial.html index 835f1766..39ba0ac2 100644 --- a/src/web/html/serial.html +++ b/src/web/html/serial.html @@ -40,10 +40,11 @@ + ("0"+min).substr(-2) + ":" + ("0"+sec).substr(-2); - parseRssi(obj); + parseRssi(obj) if(true == exeOnce) { - parseNav(obj); - parseESP(obj); + parseNav(obj) + parseESP(obj) + parseTitle(obj) window.setInterval("getAjax('/api/generic', parseGeneric)", 5000); exeOnce = false; setTimeOffset(); diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 37193be1..26b7100c 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -238,6 +238,10 @@
Topic
+
+
{#MQTT_JSON}
+
+

{#MQTT_NOTE}

{#INTERVAL}
@@ -713,9 +717,10 @@ } function parseGeneric(obj) { - parseNav(obj); - parseESP(obj); - parseRssi(obj); + parseNav(obj) + parseESP(obj) + parseRssi(obj) + parseTitle(obj) if(0 != obj.cst_lnk.length) { document.getElementsByName("cstLnk")[0].value = obj.cst_lnk @@ -946,6 +951,7 @@ function parseMqtt(obj) { for(var i of [["Addr", "broker"], ["Port", "port"], ["ClientId", "clientId"], ["User", "user"], ["Pwd", "pwd"], ["Topic", "topic"], ["Interval", "interval"]]) document.getElementsByName("mqtt"+i[0])[0].value = obj[i[1]]; + document.getElementsByName("mqttJson")[0].checked = obj["json"]; document.getElementsByName("retain")[0].checked = obj.retain } diff --git a/src/web/html/system.html b/src/web/html/system.html index 4b2ea1f7..ec21f8bd 100644 --- a/src/web/html/system.html +++ b/src/web/html/system.html @@ -15,9 +15,10 @@ {#HTML_FOOTER}