mirror of
https://github.com/lumapu/ahoy.git
synced 2025-04-28 17:56:21 +02:00
Merge branch 'geronet1-development03' into development03
This commit is contained in:
commit
fd563572f4
13 changed files with 631 additions and 21 deletions
BIN
scripts/__pycache__/htmlPreprocessorDefines.cpython-311.pyc
Normal file
BIN
scripts/__pycache__/htmlPreprocessorDefines.cpython-311.pyc
Normal file
Binary file not shown.
|
@ -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<uint16_t>(obj, F("port"), &mCfg.mqtt.port);
|
||||
getVal<uint16_t>(obj, F("intvl"), &mCfg.mqtt.interval);
|
||||
getVal<bool>(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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -538,6 +538,10 @@ class Inverter {
|
|||
rec->length = (uint8_t)(HMS4CH_LIST_LEN);
|
||||
rec->assign = reinterpret_cast<byteAssign_t*>(const_cast<byteAssign_t*>(hms4chAssignment));
|
||||
rec->pyldLen = HMS4CH_PAYLOAD_LEN;
|
||||
} else if(IV_HMT == ivGen){
|
||||
rec->length = (uint8_t)(HMT4CH_LIST_LEN);
|
||||
rec->assign = reinterpret_cast<byteAssign_t*>(const_cast<byteAssign_t*>(hmt4chAssignment));
|
||||
rec->pyldLen = HMT4CH_PAYLOAD_LEN;
|
||||
}
|
||||
channels = 4;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
//-------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -24,9 +24,10 @@ class PubMqttIvData {
|
|||
public:
|
||||
PubMqttIvData() : mTotal{}, mSubTopic{}, mVal{} {}
|
||||
|
||||
void setup(IApp *app, HMSYSTEM *sys, uint32_t *utcTs, std::queue<sendListCmdIv> *sendList) {
|
||||
void setup(IApp *app, HMSYSTEM *sys, cfgMqtt_t *cfg_mqtt, uint32_t *utcTs, std::queue<sendListCmdIv> *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<int>(mIv->getChannelFieldValue(CH0, FLD_GRID_PROFILE_CODE, rec)),
|
||||
static_cast<int>(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(F("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<char, (32 + MAX_NAME_LENGTH + 1)> mSubTopic;
|
||||
std::array<char, 160> mVal;
|
||||
std::array<char, 300> mVal;
|
||||
|
||||
std::queue<sendListCmdIv> *mSendList = nullptr;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
@ -750,6 +750,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;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
</p>
|
||||
<p>
|
||||
<span class="des">System Infos:</span>
|
||||
<div id="total"></div>
|
||||
<div id="iv"></div>
|
||||
<div class="hr"></div>
|
||||
<div id="warn_info"></div>
|
||||
|
@ -111,6 +112,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 +134,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 +154,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 +177,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());
|
||||
}
|
||||
|
||||
|
|
|
@ -238,6 +238,10 @@
|
|||
<div class="col-12 col-sm-3 my-2">Topic</div>
|
||||
<div class="col-12 col-sm-9"><input type="text" name="mqttTopic" pattern="[\-\+A-Za-z0-9\.\/#\$%&=_]+" title="Invalid input" /></div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-12 col-sm-3 my-2">{#MQTT_JSON}</div>
|
||||
<div class="col-12 col-sm-9"><input type="checkbox" name="mqttJson" /></div>
|
||||
</div>
|
||||
<p class="des">{#MQTT_NOTE}</p>
|
||||
<div class="row mb-3">
|
||||
<div class="col-12 col-sm-3 my-2">{#INTERVAL}</div>
|
||||
|
@ -946,6 +950,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
|
||||
}
|
||||
|
||||
|
|
|
@ -413,6 +413,11 @@
|
|||
"en": "Password (optional)",
|
||||
"de": "Passwort (optional)"
|
||||
},
|
||||
{
|
||||
"token": "MQTT_JSON",
|
||||
"en": "Payload as JSON",
|
||||
"de": "Ausgabe als JSON"
|
||||
},
|
||||
{
|
||||
"token": "MQTT_NOTE",
|
||||
"en": "Send Inverter data in a fixed interval, even if there is no change. A value of '0' disables the fixed interval. The data is published once it was successfully received from inverter. (default: 0)",
|
||||
|
|
|
@ -582,6 +582,7 @@ class Web {
|
|||
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.json = (request->arg("mqttJson") == "on");
|
||||
mConfig->mqtt.port = request->arg("mqttPort").toInt();
|
||||
mConfig->mqtt.interval = request->arg("mqttInterval").toInt();
|
||||
mConfig->mqtt.enableRetain = (request->arg("retain") == "on");
|
||||
|
|
466
tools/NodeRED/flows-mqtt-json-example.json
Normal file
466
tools/NodeRED/flows-mqtt-json-example.json
Normal file
|
@ -0,0 +1,466 @@
|
|||
[
|
||||
{
|
||||
"id": "67bced2c4e728783",
|
||||
"type": "mqtt in",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "",
|
||||
"topic": "hoymiles/+",
|
||||
"qos": "0",
|
||||
"datatype": "auto-detect",
|
||||
"broker": "319864a4e0fd913f",
|
||||
"nl": false,
|
||||
"rap": true,
|
||||
"rh": 0,
|
||||
"inputs": 0,
|
||||
"x": 80,
|
||||
"y": 2100,
|
||||
"wires": [
|
||||
[
|
||||
"a55632ad0dff0b69"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a7f0d307d7cf77e2",
|
||||
"type": "mqtt in",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "",
|
||||
"topic": "hoymiles/X/#",
|
||||
"qos": "0",
|
||||
"datatype": "auto-detect",
|
||||
"broker": "319864a4e0fd913f",
|
||||
"nl": false,
|
||||
"rap": true,
|
||||
"rh": 0,
|
||||
"inputs": 0,
|
||||
"x": 90,
|
||||
"y": 2260,
|
||||
"wires": [
|
||||
[
|
||||
"7e17e5a3f4df3011",
|
||||
"1a8cca488d53394a"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "7e17e5a3f4df3011",
|
||||
"type": "debug",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "Inverter X",
|
||||
"active": false,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 340,
|
||||
"y": 2260,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "fb7357db50501627",
|
||||
"type": "change",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "Tags setzen",
|
||||
"rules": [
|
||||
{
|
||||
"t": "set",
|
||||
"p": "payload",
|
||||
"pt": "msg",
|
||||
"to": "(\t $a := $split(topic, '/');\t [\t payload,\t {\t \"device\":$a[0],\t \"name\":$a[1],\t \"channel\":$a[2]\t }\t ]\t)\t",
|
||||
"tot": "jsonata"
|
||||
},
|
||||
{
|
||||
"t": "delete",
|
||||
"p": "topic",
|
||||
"pt": "msg"
|
||||
}
|
||||
],
|
||||
"action": "",
|
||||
"property": "",
|
||||
"from": "",
|
||||
"to": "",
|
||||
"reg": false,
|
||||
"x": 610,
|
||||
"y": 2360,
|
||||
"wires": [
|
||||
[
|
||||
"91a4607dfda84b67"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "670eb9fbb5c31b2c",
|
||||
"type": "debug",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "InfluxDB",
|
||||
"active": false,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 940,
|
||||
"y": 2360,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "1a8cca488d53394a",
|
||||
"type": "switch",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "",
|
||||
"property": "$split(topic, '/')[2]",
|
||||
"propertyType": "jsonata",
|
||||
"rules": [
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "available",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "last_success",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "regex",
|
||||
"v": "(ch[0-6])\\b",
|
||||
"vt": "str",
|
||||
"case": false
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "radio_stat",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "firmware",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "hardware",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "alarm",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"checkall": "true",
|
||||
"repair": false,
|
||||
"outputs": 7,
|
||||
"x": 330,
|
||||
"y": 2380,
|
||||
"wires": [
|
||||
[
|
||||
"845aeb93e39092c5"
|
||||
],
|
||||
[
|
||||
"241a8e70e9fde93c"
|
||||
],
|
||||
[
|
||||
"fb7357db50501627"
|
||||
],
|
||||
[
|
||||
"9d38f021308664c1"
|
||||
],
|
||||
[
|
||||
"a508355f0cc87966"
|
||||
],
|
||||
[
|
||||
"d2c9aa1a8978aca6"
|
||||
],
|
||||
[
|
||||
"b27032beb597d5a7"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "845aeb93e39092c5",
|
||||
"type": "debug",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "available",
|
||||
"active": true,
|
||||
"tosidebar": false,
|
||||
"console": false,
|
||||
"tostatus": true,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "payload",
|
||||
"statusType": "auto",
|
||||
"x": 600,
|
||||
"y": 2240,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "241a8e70e9fde93c",
|
||||
"type": "debug",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "last_success",
|
||||
"active": true,
|
||||
"tosidebar": false,
|
||||
"console": false,
|
||||
"tostatus": true,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "payload",
|
||||
"statusType": "auto",
|
||||
"x": 610,
|
||||
"y": 2300,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "9d38f021308664c1",
|
||||
"type": "debug",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "radio_stat",
|
||||
"active": false,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 600,
|
||||
"y": 2400,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "a508355f0cc87966",
|
||||
"type": "debug",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "firmware",
|
||||
"active": false,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 600,
|
||||
"y": 2440,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "d2c9aa1a8978aca6",
|
||||
"type": "debug",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "hardware",
|
||||
"active": false,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 600,
|
||||
"y": 2480,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "b27032beb597d5a7",
|
||||
"type": "debug",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "alarm",
|
||||
"active": false,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 590,
|
||||
"y": 2520,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "d814738cf55ad663",
|
||||
"type": "debug",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "total",
|
||||
"active": false,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 590,
|
||||
"y": 2160,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "a55632ad0dff0b69",
|
||||
"type": "switch",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "",
|
||||
"property": "$split(topic, '/')[1]",
|
||||
"propertyType": "jsonata",
|
||||
"rules": [
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "uptime",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "wifi_rssi",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "status",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"t": "eq",
|
||||
"v": "total",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"checkall": "true",
|
||||
"repair": false,
|
||||
"outputs": 4,
|
||||
"x": 330,
|
||||
"y": 2100,
|
||||
"wires": [
|
||||
[
|
||||
"1fbb0674d2576ee7"
|
||||
],
|
||||
[
|
||||
"e6be1c98ac55f511"
|
||||
],
|
||||
[
|
||||
"f9c2d3b30e34fdda"
|
||||
],
|
||||
[
|
||||
"d814738cf55ad663"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "f9c2d3b30e34fdda",
|
||||
"type": "debug",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "status",
|
||||
"active": false,
|
||||
"tosidebar": false,
|
||||
"console": false,
|
||||
"tostatus": true,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "payload",
|
||||
"statusType": "auto",
|
||||
"x": 590,
|
||||
"y": 2100,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "e6be1c98ac55f511",
|
||||
"type": "debug",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "wifi_rssi",
|
||||
"active": false,
|
||||
"tosidebar": false,
|
||||
"console": false,
|
||||
"tostatus": true,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "payload",
|
||||
"statusType": "auto",
|
||||
"x": 600,
|
||||
"y": 2040,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "1fbb0674d2576ee7",
|
||||
"type": "debug",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "uptime",
|
||||
"active": false,
|
||||
"tosidebar": false,
|
||||
"console": false,
|
||||
"tostatus": true,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "payload",
|
||||
"statusType": "auto",
|
||||
"x": 590,
|
||||
"y": 1980,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "91a4607dfda84b67",
|
||||
"type": "change",
|
||||
"z": "5de5756d190f9086",
|
||||
"name": "Lösche",
|
||||
"rules": [
|
||||
{
|
||||
"t": "delete",
|
||||
"p": "payload[0].YieldDay",
|
||||
"pt": "msg"
|
||||
},
|
||||
{
|
||||
"t": "delete",
|
||||
"p": "payload[0].MaxPower",
|
||||
"pt": "msg"
|
||||
},
|
||||
{
|
||||
"t": "delete",
|
||||
"p": "payload[0].ALARM_MES_ID",
|
||||
"pt": "msg"
|
||||
}
|
||||
],
|
||||
"action": "",
|
||||
"property": "",
|
||||
"from": "",
|
||||
"to": "",
|
||||
"reg": false,
|
||||
"x": 780,
|
||||
"y": 2360,
|
||||
"wires": [
|
||||
[
|
||||
"670eb9fbb5c31b2c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "319864a4e0fd913f",
|
||||
"type": "mqtt-broker",
|
||||
"name": "broker",
|
||||
"broker": "localhost",
|
||||
"port": "1883",
|
||||
"clientid": "",
|
||||
"autoConnect": true,
|
||||
"usetls": false,
|
||||
"protocolVersion": "4",
|
||||
"keepalive": "60",
|
||||
"cleansession": true,
|
||||
"birthTopic": "",
|
||||
"birthQos": "0",
|
||||
"birthPayload": "",
|
||||
"birthMsg": {},
|
||||
"closeTopic": "",
|
||||
"closeQos": "0",
|
||||
"closePayload": "",
|
||||
"closeMsg": {},
|
||||
"willTopic": "",
|
||||
"willQos": "0",
|
||||
"willPayload": "",
|
||||
"willMsg": {},
|
||||
"userProps": "",
|
||||
"sessionExpiry": ""
|
||||
}
|
||||
]
|
Loading…
Add table
Reference in a new issue