Browse Source

0.8.81

* fixed authentication with empty token #1415
* added new setting for future function to send log via MqTT
* combined firmware and hardware version to JSON topics (MqTT) #1212
pull/1431/head
lumapu 11 months ago
parent
commit
bd532805a6
  1. 5
      src/CHANGES.md
  2. 9
      src/config/settings.h
  3. 2
      src/defines.h
  4. 59
      src/publisher/pubMqttIvData.h
  5. 2
      src/web/Protection.h
  6. 1
      src/web/RestApi.h
  7. 73
      src/web/html/setup.html
  8. 5
      src/web/lang.json
  9. 1
      src/web/web.h

5
src/CHANGES.md

@ -1,5 +1,10 @@
# Development Changes # Development Changes
## 0.8.81 - 2024-02-13
* fixed authentication with empty token #1415
* added new setting for future function to send log via MqTT
* combined firmware and hardware version to JSON topics (MqTT) #1212
## 0.8.80 - 2024-02-12 ## 0.8.80 - 2024-02-12
* optimize API authentication, Error-Codes #1415 * optimize API authentication, Error-Codes #1415
* breaking change: authentication API command changed #1415 * breaking change: authentication API command changed #1415

9
src/config/settings.h

@ -31,7 +31,7 @@
* https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout * https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout
* */ * */
#define CONFIG_VERSION 10 #define CONFIG_VERSION 11
#define PROT_MASK_INDEX 0x0001 #define PROT_MASK_INDEX 0x0001
@ -120,6 +120,7 @@ typedef struct {
bool debug; bool debug;
bool privacyLog; bool privacyLog;
bool printWholeTrace; bool printWholeTrace;
bool log2mqtt;
} cfgSerial_t; } cfgSerial_t;
typedef struct { typedef struct {
@ -436,6 +437,7 @@ class settings {
mCfg.serial.debug = false; mCfg.serial.debug = false;
mCfg.serial.privacyLog = true; mCfg.serial.privacyLog = true;
mCfg.serial.printWholeTrace = false; mCfg.serial.printWholeTrace = false;
mCfg.serial.log2mqtt = false;
mCfg.mqtt.port = DEF_MQTT_PORT; mCfg.mqtt.port = DEF_MQTT_PORT;
snprintf(mCfg.mqtt.broker, MQTT_ADDR_LEN, "%s", DEF_MQTT_BROKER); snprintf(mCfg.mqtt.broker, MQTT_ADDR_LEN, "%s", DEF_MQTT_BROKER);
@ -509,6 +511,9 @@ class settings {
mCfg.sys.region = 0; // Europe mCfg.sys.region = 0; // Europe
mCfg.sys.timezone = 1; mCfg.sys.timezone = 1;
} }
if(mCfg.configVersion < 11) {
mCfg.serial.log2mqtt = false;
}
} }
} }
@ -658,11 +663,13 @@ class settings {
obj[F("debug")] = mCfg.serial.debug; obj[F("debug")] = mCfg.serial.debug;
obj[F("prv")] = (bool) mCfg.serial.privacyLog; obj[F("prv")] = (bool) mCfg.serial.privacyLog;
obj[F("trc")] = (bool) mCfg.serial.printWholeTrace; obj[F("trc")] = (bool) mCfg.serial.printWholeTrace;
obj[F("mqtt")] = (bool) mCfg.serial.log2mqtt;
} else { } else {
getVal<bool>(obj, F("show"), &mCfg.serial.showIv); getVal<bool>(obj, F("show"), &mCfg.serial.showIv);
getVal<bool>(obj, F("debug"), &mCfg.serial.debug); getVal<bool>(obj, F("debug"), &mCfg.serial.debug);
getVal<bool>(obj, F("prv"), &mCfg.serial.privacyLog); getVal<bool>(obj, F("prv"), &mCfg.serial.privacyLog);
getVal<bool>(obj, F("trc"), &mCfg.serial.printWholeTrace); getVal<bool>(obj, F("trc"), &mCfg.serial.printWholeTrace);
getVal<bool>(obj, F("mqtt"), &mCfg.serial.log2mqtt);
} }
} }

2
src/defines.h

@ -13,7 +13,7 @@
//------------------------------------- //-------------------------------------
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 8 #define VERSION_MINOR 8
#define VERSION_PATCH 80 #define VERSION_PATCH 81
//------------------------------------- //-------------------------------------
typedef struct { typedef struct {

59
src/publisher/pubMqttIvData.h

@ -6,6 +6,7 @@
#ifndef __PUB_MQTT_IV_DATA_H__ #ifndef __PUB_MQTT_IV_DATA_H__
#define __PUB_MQTT_IV_DATA_H__ #define __PUB_MQTT_IV_DATA_H__
#include <array>
#include "../utils/dbg.h" #include "../utils/dbg.h"
#include "../hm/hmSystem.h" #include "../hm/hmSystem.h"
#include "pubMqttDefs.h" #include "pubMqttDefs.h"
@ -107,14 +108,14 @@ class PubMqttIvData {
if(found) { if(found) {
record_t<> *rec = mIv->getRecordStruct(mCmd); record_t<> *rec = mIv->getRecordStruct(mCmd);
if(MqttSentStatus::NEW_DATA == rec->mqttSentStatus) { if(MqttSentStatus::NEW_DATA == rec->mqttSentStatus) {
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/last_success", mIv->config->name); snprintf(mSubTopic.data(), mSubTopic.size(), "%s/last_success", mIv->config->name);
snprintf(mVal, 40, "%d", mIv->getLastTs(rec)); snprintf(mVal.data(), mVal.size(), "%d", mIv->getLastTs(rec));
mPublish(mSubTopic, mVal, true, QOS_0); mPublish(mSubTopic.data(), mVal.data(), true, QOS_0);
if((mIv->ivGen == IV_HMS) || (mIv->ivGen == IV_HMT)) { if((mIv->ivGen == IV_HMS) || (mIv->ivGen == IV_HMT)) {
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/ch0/rssi", mIv->config->name); snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch0/rssi", mIv->config->name);
snprintf(mVal, 40, "%d", mIv->rssi); snprintf(mVal.data(), mVal.size(), "%d", mIv->rssi);
mPublish(mSubTopic, mVal, false, QOS_0); mPublish(mSubTopic.data(), mVal.data(), false, QOS_0);
} }
rec->mqttSentStatus = MqttSentStatus::LAST_SUCCESS_SENT; rec->mqttSentStatus = MqttSentStatus::LAST_SUCCESS_SENT;
} }
@ -144,7 +145,7 @@ class PubMqttIvData {
if(mPos < rec->length) { if(mPos < rec->length) {
bool retained = false; bool retained = false;
if (mCmd == RealTimeRunData_Debug) { if (RealTimeRunData_Debug == mCmd) {
if((FLD_YT == rec->assign[mPos].fieldId) || (FLD_YD == rec->assign[mPos].fieldId)) if((FLD_YT == rec->assign[mPos].fieldId) || (FLD_YD == rec->assign[mPos].fieldId))
retained = true; retained = true;
@ -176,10 +177,32 @@ class PubMqttIvData {
} }
if (MqttSentStatus::LAST_SUCCESS_SENT == rec->mqttSentStatus) { if (MqttSentStatus::LAST_SUCCESS_SENT == rec->mqttSentStatus) {
if(InverterDevInform_All == mCmd) {
snprintf(mSubTopic.data(), mSubTopic.size(), "%s/firmware", mIv->config->name);
snprintf(mVal.data(), mVal.size(), "{\"version\":%d,\"build_year\":\"%s\",\"build_month_day\":%d,\"build_hour_min\":%d,\"bootloader\":%d}",
mIv->getChannelFieldValue(CH0, FLD_FW_VERSION, rec),
mIv->getChannelFieldValue(CH0, FLD_FW_BUILD_YEAR, rec),
mIv->getChannelFieldValue(CH0, FLD_FW_BUILD_MONTH_DAY, rec),
mIv->getChannelFieldValue(CH0, FLD_FW_BUILD_HOUR_MINUTE, rec),
mIv->getChannelFieldValue(CH0, FLD_BOOTLOADER_VER, rec));
retained = true;
} else if(InverterDevInform_Simple == mCmd) {
snprintf(mSubTopic.data(), mSubTopic.size(), "%s/hardware", mIv->config->name);
snprintf(mVal.data(), mVal.size(), "{\"part\":%d,\"version\":\"%s\",\"grid_profile_code\":%d,\"grid_profile_version\":%d}",
mIv->getChannelFieldValue(CH0, FLD_PART_NUM, rec),
mIv->getChannelFieldValue(CH0, FLD_HW_VERSION, rec),
mIv->getChannelFieldValue(CH0, FLD_GRID_PROFILE_CODE, rec),
mIv->getChannelFieldValue(CH0, FLD_GRID_PROFILE_VERSION, rec));
retained = true;
} 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)));
}
uint8_t qos = (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) ? QOS_2 : QOS_0; uint8_t qos = (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) ? QOS_2 : QOS_0;
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]); if((FLD_EVT != rec->assign[mPos].fieldId)
snprintf(mVal, 40, "%g", ah::round3(mIv->getValue(mPos, rec))); && (FLD_LAST_ALARM_CODE != rec->assign[mPos].fieldId))
mPublish(mSubTopic, mVal, retained, qos); mPublish(mSubTopic.data(), mVal.data(), retained, qos);
} }
mPos++; mPos++;
} else { } else {
@ -192,8 +215,8 @@ class PubMqttIvData {
} }
inline void sendRadioStat(uint8_t start) { inline void sendRadioStat(uint8_t start) {
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/radio_stat", mIv->config->name); snprintf(mSubTopic.data(), mSubTopic.size(), "%s/radio_stat", mIv->config->name);
snprintf(mVal, 140, "{\"tx\":%d,\"success\":%d,\"fail\":%d,\"no_answer\":%d,\"retransmits\":%d,\"lossIvRx\":%d,\"lossIvTx\":%d,\"lossDtuRx\":%d,\"lossDtuTx\":%d}", snprintf(mVal.data(), mVal.size(), "{\"tx\":%d,\"success\":%d,\"fail\":%d,\"no_answer\":%d,\"retransmits\":%d,\"lossIvRx\":%d,\"lossIvTx\":%d,\"lossDtuRx\":%d,\"lossDtuTx\":%d}",
mIv->radioStatistics.txCnt, mIv->radioStatistics.txCnt,
mIv->radioStatistics.rxSuccess, mIv->radioStatistics.rxSuccess,
mIv->radioStatistics.rxFail, mIv->radioStatistics.rxFail,
@ -203,7 +226,7 @@ class PubMqttIvData {
mIv->radioStatistics.ivSent, mIv->radioStatistics.ivSent,
mIv->radioStatistics.dtuLoss, mIv->radioStatistics.dtuLoss,
mIv->radioStatistics.dtuSent); mIv->radioStatistics.dtuSent);
mPublish(mSubTopic, mVal, false, QOS_0); mPublish(mSubTopic.data(), mVal.data(), false, QOS_0);
} }
void stateSendTotals() { void stateSendTotals() {
@ -240,9 +263,9 @@ class PubMqttIvData {
retained = false; retained = false;
break; break;
} }
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); snprintf(mSubTopic.data(), mSubTopic.size(), "total/%s", fields[fieldId]);
snprintf(mVal, 40, "%g", ah::round3(mTotal[mPos])); snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mTotal[mPos]));
mPublish(mSubTopic, mVal, retained, QOS_0); mPublish(mSubTopic.data(), mVal.data(), retained, QOS_0);
mPos++; mPos++;
} else { } else {
mSendList->pop(); mSendList->pop();
@ -266,8 +289,8 @@ class PubMqttIvData {
uint8_t mPos = 0; uint8_t mPos = 0;
bool mRTRDataHasBeenSent = false; bool mRTRDataHasBeenSent = false;
char mSubTopic[32 + MAX_NAME_LENGTH + 1]; std::array<char, (32 + MAX_NAME_LENGTH + 1)> mSubTopic;
char mVal[140]; std::array<char, 140> mVal;
std::queue<sendListCmdIv> *mSendList = nullptr; std::queue<sendListCmdIv> *mSendList = nullptr;
}; };

2
src/web/Protection.h

@ -85,7 +85,7 @@ class Protection {
if(isIdentical(clientIp, mApiIp)) if(isIdentical(clientIp, mApiIp))
return (0 != strncmp(token, mToken.data(), 16)); return (0 != strncmp(token, mToken.data(), 16));
return false; return true;
} }
private: private:

1
src/web/RestApi.h

@ -680,6 +680,7 @@ class RestApi {
obj[F("debug")] = mConfig->serial.debug; obj[F("debug")] = mConfig->serial.debug;
obj[F("priv")] = mConfig->serial.privacyLog; obj[F("priv")] = mConfig->serial.privacyLog;
obj[F("wholeTrace")] = mConfig->serial.printWholeTrace; obj[F("wholeTrace")] = mConfig->serial.printWholeTrace;
obj[F("log2mqtt")] = mConfig->serial.log2mqtt;
} }
void getStaticIp(JsonObject obj) { void getStaticIp(JsonObject obj) {

73
src/web/html/setup.html

@ -43,24 +43,8 @@
<div class="col-4 col-sm-9"><input type="text" name="cstLnkTxt"/></div> <div class="col-4 col-sm-9"><input type="text" name="cstLnkTxt"/></div>
</div> </div>
</fieldset> </fieldset>
<fieldset class="mb-4"> <fieldset class="mb-4" id="serialCb">
<legend class="des">{#SERIAL_CONSOLE}</legend> <legend class="des">{#SERIAL_CONSOLE}</legend>
<div class="row mb-3">
<div class="col-8 col-sm-3">{#LOG_PRINT_INVERTER_DATA}</div>
<div class="col-4 col-sm-9"><input type="checkbox" name="serEn"/></div>
</div>
<div class="row mb-3">
<div class="col-8 col-sm-3">{#LOG_SERIAL_DEBUG}</div>
<div class="col-4 col-sm-9"><input type="checkbox" name="serDbg"/></div>
</div>
<div class="row mb-3">
<div class="col-8 col-sm-3">{#LOG_PRIVACY_MODE}</div>
<div class="col-4 col-sm-9"><input type="checkbox" name="priv"/></div>
</div>
<div class="row mb-3">
<div class="col-8 col-sm-3">{#LOG_PRINT_TRACES}</div>
<div class="col-4 col-sm-9"><input type="checkbox" name="wholeTrace"/></div>
</div>
</fieldset> </fieldset>
</div> </div>
@ -716,6 +700,13 @@
ivGlob(obj); ivGlob(obj);
} }
function divRow(item0, item1) {
return ml("div", {class: "row mb-3"}, [
ml("div", {class: "col-3 mt-2"}, item0),
ml("div", {class: "col-9"}, item1)
])
}
function ivModal(obj) { function ivModal(obj) {
var lines = []; var lines = [];
lines.push(ml("tr", {}, [ lines.push(ml("tr", {}, [
@ -743,43 +734,23 @@
var html = ml("div", {}, [ var html = ml("div", {}, [
tabs(["{#TAB_GENERAL}", "{#TAB_INPUTS}", "{#TAB_RADIO}", "{#TAB_ADVANCED}"]), tabs(["{#TAB_GENERAL}", "{#TAB_INPUTS}", "{#TAB_RADIO}", "{#TAB_ADVANCED}"]),
ml("div", {id: "div{#TAB_GENERAL}", class: "tab-content"}, [ ml("div", {id: "div{#TAB_GENERAL}", class: "tab-content"}, [
ml("div", {class: "row mb-3"}, [ divRow("{#INV_ENABLE}", cbEn),
ml("div", {class: "col-2"}, "{#INV_ENABLE}"), divRow("{#INV_SERIAL}", ser),
ml("div", {class: "col-10"}, cbEn) divRow("Name", ml("input", {name: "name", class: "text", type: "text", value: obj.name}, null))
]),
ml("div", {class: "row mb-3"}, [
ml("div", {class: "col-2 mt-2"}, "{#INV_SERIAL}"),
ml("div", {class: "col-10"}, ser)
]),
ml("div", {class: "row mb-3"}, [
ml("div", {class: "col-2 mt-2"}, "Name"),
ml("div", {class: "col-10"}, ml("input", {name: "name", class: "text", type: "text", value: obj.name}, null))
])
]), ]),
ml("div", {id: "div{#TAB_INPUTS}", class: "tab-content hide"}, [ ml("div", {id: "div{#TAB_INPUTS}", class: "tab-content hide"}, [
ml("div", {class: "row mb-3"}, ml("div", {class: "row mb-3"},
ml("table", {class: "table"}, ml("table", {class: "table"}, ml("tbody", {}, lines))
ml("tbody", {}, lines)
)
) )
]), ]),
ml("div", {id: "div{#TAB_RADIO}", class: "tab-content hide"}, [ ml("div", {id: "div{#TAB_RADIO}", class: "tab-content hide"}, [
ml("input", {type: "hidden", name: "isnrf"}, null), ml("input", {type: "hidden", name: "isnrf"}, null),
ml("div", {id: "setcmt"}, [ ml("div", {id: "setcmt"}, [
ml("div", {class: "row mb-3"}, [ divRow("{#INV_FREQUENCY}", sel("freq", esp32cmtFreq, obj.freq)),
ml("div", {class: "col-3 mt-2"}, "{#INV_FREQUENCY}"), divRow("{#INV_POWER_LEVEL}", sel("cmtpa", esp32cmtPa, obj.pa))
ml("div", {class: "col-9"}, sel("freq", esp32cmtFreq, obj.freq))
]),
ml("div", {class: "row mb-3"}, [
ml("div", {class: "col-3 mt-2"}, "{#INV_POWER_LEVEL}"),
ml("div", {class: "col-9"}, sel("cmtpa", esp32cmtPa, obj.pa))
]),
]), ]),
ml("div", {id: "setnrf"}, ml("div", {id: "setnrf"},
ml("div", {class: "row mb-3"}, [ divRow("{#INV_POWER_LEVEL}", sel("nrfpa", nrfPa, obj.pa))
ml("div", {class: "col-3 mt-2"}, "{#INV_POWER_LEVEL}"),
ml("div", {class: "col-9"}, sel("nrfpa", nrfPa, obj.pa))
]),
), ),
]), ]),
ml("div", {id: "div{#TAB_ADVANCED}", class: "tab-content hide"}, [ ml("div", {id: "div{#TAB_ADVANCED}", class: "tab-content hide"}, [
@ -1026,8 +997,18 @@
/*ENDIF_ESP32*/ /*ENDIF_ESP32*/
function parseSerial(obj) { function parseSerial(obj) {
for(var i of [["serEn", "show_live_data"], ["serDbg", "debug"], ["priv", "priv"], ["wholeTrace", "wholeTrace"]]) var e = document.getElementById("serialCb")
document.getElementsByName(i[0])[0].checked = obj[i[1]]; var l = [["serEn", "show_live_data", "{#LOG_PRINT_INVERTER_DATA}"], ["serDbg", "debug", "{#LOG_SERIAL_DEBUG}"], ["priv", "priv", "{#LOG_PRIVACY_MODE}"], ["wholeTrace", "wholeTrace", "{#LOG_PRINT_TRACES}"], ["log2mqtt", "log2mqtt", "{#LOG_TO_MQTT}"]]
for(var i of l) {
var cb = ml("input", {name: i[0], type: "checkbox"}, null)
cb.checked = obj[i[1]]
e.appendChild(
ml("div", {class: "row mb-3"}, [
ml("div", {class: "col-8 col-sm-3"}, i[2]),
ml("div", {class: "col-4 col-sm-9"}, cb)
])
)
}
} }
function parseDisplay(obj, type, system) { function parseDisplay(obj, type, system) {

5
src/web/lang.json

@ -203,6 +203,11 @@
"en": "Print whole traces in Log", "en": "Print whole traces in Log",
"de": "alle Informationen in Log schreiben" "de": "alle Informationen in Log schreiben"
}, },
{
"token": "LOG_TO_MQTT",
"en": "Send Serial debug over MqTT",
"de": "sende serielles Log &uuml;ber MqTT"
},
{ {
"token": "NETWORK", "token": "NETWORK",
"en": "Network", "en": "Network",

1
src/web/web.h

@ -552,6 +552,7 @@ class Web {
mConfig->serial.privacyLog = (request->arg("priv") == "on"); mConfig->serial.privacyLog = (request->arg("priv") == "on");
mConfig->serial.printWholeTrace = (request->arg("wholeTrace") == "on"); mConfig->serial.printWholeTrace = (request->arg("wholeTrace") == "on");
mConfig->serial.showIv = (request->arg("serEn") == "on"); mConfig->serial.showIv = (request->arg("serEn") == "on");
mConfig->serial.log2mqtt = (request->arg("log2mqtt") == "on");
// display // display
mConfig->plugin.display.pwrSaveAtIvOffline = (request->arg("disp_pwr") == "on"); mConfig->plugin.display.pwrSaveAtIvOffline = (request->arg("disp_pwr") == "on");

Loading…
Cancel
Save