|
@ -34,13 +34,6 @@ struct alarm_t { |
|
|
alarm_t(uint16_t c, uint32_t s, uint32_t e) : code(c), start(s), end(e) {} |
|
|
alarm_t(uint16_t c, uint32_t s, uint32_t e) : code(c), start(s), end(e) {} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
|
bool running; |
|
|
|
|
|
uint8_t lastIvId; |
|
|
|
|
|
uint8_t sub; |
|
|
|
|
|
uint8_t foundIvCnt; |
|
|
|
|
|
} discovery_t; |
|
|
|
|
|
|
|
|
|
|
|
template<class HMSYSTEM> |
|
|
template<class HMSYSTEM> |
|
|
class PubMqtt { |
|
|
class PubMqtt { |
|
|
public: |
|
|
public: |
|
@ -64,6 +57,7 @@ class PubMqtt { |
|
|
mIntervalTimeout = 1; |
|
|
mIntervalTimeout = 1; |
|
|
|
|
|
|
|
|
mDiscovery.running = false; |
|
|
mDiscovery.running = false; |
|
|
|
|
|
mSendIvData.running = false; |
|
|
|
|
|
|
|
|
snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%s/mqtt", mCfgMqtt->topic); |
|
|
snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%s/mqtt", mCfgMqtt->topic); |
|
|
|
|
|
|
|
@ -93,6 +87,11 @@ class PubMqtt { |
|
|
yield(); |
|
|
yield(); |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
if(mSendIvData.running) { |
|
|
|
|
|
sendIvDataLoop(); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if(mDiscovery.running) |
|
|
if(mDiscovery.running) |
|
|
discoveryConfigLoop(); |
|
|
discoveryConfigLoop(); |
|
|
} |
|
|
} |
|
@ -107,13 +106,14 @@ class PubMqtt { |
|
|
return; // next try in a second
|
|
|
return; // next try in a second
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if(0 == mCfgMqtt->interval) // no fixed interval, publish once new data were received (from inverter)
|
|
|
if(0 == mCfgMqtt->interval) { // no fixed interval, publish once new data were received (from inverter)
|
|
|
sendIvData(); |
|
|
sendIvDataStart(); |
|
|
|
|
|
} |
|
|
else { // send mqtt data in a fixed interval
|
|
|
else { // send mqtt data in a fixed interval
|
|
|
if(mIntervalTimeout == 0) { |
|
|
if(mIntervalTimeout == 0) { |
|
|
mIntervalTimeout = mCfgMqtt->interval; |
|
|
mIntervalTimeout = mCfgMqtt->interval; |
|
|
mSendList.push(RealTimeRunData_Debug); |
|
|
mSendList.push(RealTimeRunData_Debug); |
|
|
sendIvData(); |
|
|
sendIvDataStart(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -554,55 +554,65 @@ class PubMqtt { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void sendIvData() { |
|
|
void sendIvDataStart() { |
|
|
|
|
|
mSendIvData.RTRDataHasBeenSent = false; |
|
|
|
|
|
memset(mSendIvData.total, 0, sizeof(float) * 4); |
|
|
|
|
|
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { |
|
|
|
|
|
Inverter<> *iv = mSys->getInverterByPos(id); |
|
|
|
|
|
if (NULL != iv) { |
|
|
|
|
|
if (iv->config->enabled) { |
|
|
|
|
|
mSendIvData.lastIvId = id; |
|
|
|
|
|
mSendIvData.running = true; |
|
|
|
|
|
mSendIvData.lastIvReached = false; |
|
|
|
|
|
mSendIvData.sendTotals = false; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sendIvDataLoop(void) { |
|
|
bool anyAvail = processIvStatus(); |
|
|
bool anyAvail = processIvStatus(); |
|
|
if (mLastAnyAvail != anyAvail) |
|
|
if (mLastAnyAvail != anyAvail) |
|
|
mSendList.push(RealTimeRunData_Debug); // makes shure that total values are calculated
|
|
|
mSendList.push(RealTimeRunData_Debug); // makes sure that total values are calculated
|
|
|
|
|
|
|
|
|
if(mSendList.empty()) |
|
|
if(mSendList.empty()) { |
|
|
|
|
|
mSendIvData.running = false; |
|
|
return; |
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
float total[4]; |
|
|
|
|
|
bool RTRDataHasBeenSent = false; |
|
|
|
|
|
|
|
|
|
|
|
while(!mSendList.empty()) { |
|
|
//while(!mSendList.empty()) {
|
|
|
memset(total, 0, sizeof(float) * 4); |
|
|
|
|
|
uint8_t curInfoCmd = mSendList.front(); |
|
|
uint8_t curInfoCmd = mSendList.front(); |
|
|
|
|
|
if ((curInfoCmd != RealTimeRunData_Debug) || !mSendIvData.RTRDataHasBeenSent) { // send RTR Data only once
|
|
|
|
|
|
mSendIvData.sendTotals = (curInfoCmd == RealTimeRunData_Debug); |
|
|
|
|
|
|
|
|
if ((curInfoCmd != RealTimeRunData_Debug) || !RTRDataHasBeenSent) { // send RTR Data only once
|
|
|
if(!mSendIvData.lastIvReached) { |
|
|
bool sendTotals = (curInfoCmd == RealTimeRunData_Debug); |
|
|
Inverter<> *iv = mSys->getInverterByPos(mSendIvData.lastIvId); |
|
|
|
|
|
|
|
|
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { |
|
|
|
|
|
Inverter<> *iv = mSys->getInverterByPos(id); |
|
|
|
|
|
if (NULL == iv) |
|
|
|
|
|
continue; // skip to next inverter
|
|
|
|
|
|
if (!iv->config->enabled) |
|
|
|
|
|
continue; // skip to next inverter
|
|
|
|
|
|
|
|
|
|
|
|
// send RTR Data only if status is available
|
|
|
// send RTR Data only if status is available
|
|
|
if ((curInfoCmd != RealTimeRunData_Debug) || (MQTT_STATUS_NOT_AVAIL_NOT_PROD != mLastIvState[id])) |
|
|
if ((curInfoCmd != RealTimeRunData_Debug) || (MQTT_STATUS_NOT_AVAIL_NOT_PROD != mLastIvState[mSendIvData.lastIvId])) |
|
|
sendData(iv, curInfoCmd); |
|
|
sendData(iv, curInfoCmd); |
|
|
|
|
|
|
|
|
// calculate total values for RealTimeRunData_Debug
|
|
|
// calculate total values for RealTimeRunData_Debug
|
|
|
if (sendTotals) { |
|
|
if (mSendIvData.sendTotals) { |
|
|
record_t<> *rec = iv->getRecordStruct(curInfoCmd); |
|
|
record_t<> *rec = iv->getRecordStruct(curInfoCmd); |
|
|
|
|
|
|
|
|
sendTotals &= (iv->getLastTs(rec) > 0); |
|
|
mSendIvData.sendTotals &= (iv->getLastTs(rec) > 0); |
|
|
if (sendTotals) { |
|
|
if (mSendIvData.sendTotals) { |
|
|
for (uint8_t i = 0; i < rec->length; i++) { |
|
|
for (uint8_t i = 0; i < rec->length; i++) { |
|
|
if (CH0 == rec->assign[i].ch) { |
|
|
if (CH0 == rec->assign[i].ch) { |
|
|
switch (rec->assign[i].fieldId) { |
|
|
switch (rec->assign[i].fieldId) { |
|
|
case FLD_PAC: |
|
|
case FLD_PAC: |
|
|
total[0] += iv->getValue(i, rec); |
|
|
mSendIvData.total[0] += iv->getValue(i, rec); |
|
|
break; |
|
|
break; |
|
|
case FLD_YT: |
|
|
case FLD_YT: |
|
|
total[1] += iv->getValue(i, rec); |
|
|
mSendIvData.total[1] += iv->getValue(i, rec); |
|
|
break; |
|
|
break; |
|
|
case FLD_YD: |
|
|
case FLD_YD: |
|
|
total[2] += iv->getValue(i, rec); |
|
|
mSendIvData.total[2] += iv->getValue(i, rec); |
|
|
break; |
|
|
break; |
|
|
case FLD_PDC: |
|
|
case FLD_PDC: |
|
|
total[3] += iv->getValue(i, rec); |
|
|
mSendIvData.total[3] += iv->getValue(i, rec); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -610,9 +620,21 @@ class PubMqtt { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
yield(); |
|
|
yield(); |
|
|
|
|
|
|
|
|
|
|
|
// get next inverter
|
|
|
|
|
|
for (uint8_t id = mSendIvData.lastIvId; id < mSys->getNumInverters(); id++) { |
|
|
|
|
|
Inverter<> *iv = mSys->getInverterByPos(id); |
|
|
|
|
|
if (NULL != iv) { |
|
|
|
|
|
if (iv->config->enabled) { |
|
|
|
|
|
mSendIvData.lastIvId = id; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
mSendIvData.lastIvReached = true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (sendTotals) { |
|
|
if (mSendIvData.sendTotals) { |
|
|
uint8_t fieldId; |
|
|
uint8_t fieldId; |
|
|
for (uint8_t i = 0; i < 4; i++) { |
|
|
for (uint8_t i = 0; i < 4; i++) { |
|
|
bool retained = true; |
|
|
bool retained = true; |
|
@ -634,20 +656,36 @@ class PubMqtt { |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); |
|
|
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); |
|
|
snprintf(mVal, 40, "%g", ah::round3(total[i])); |
|
|
snprintf(mVal, 40, "%g", ah::round3(mSendIvData.total[i])); |
|
|
publish(mSubTopic, mVal, retained); |
|
|
publish(mSubTopic, mVal, retained); |
|
|
} |
|
|
} |
|
|
RTRDataHasBeenSent = true; |
|
|
mSendIvData.RTRDataHasBeenSent = true; |
|
|
yield(); |
|
|
yield(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
mSendList.pop(); // remove from list once all inverters were processed
|
|
|
mSendList.pop(); // remove from list once all inverters were processed
|
|
|
} |
|
|
//} // end while
|
|
|
|
|
|
|
|
|
mLastAnyAvail = anyAvail; |
|
|
mLastAnyAvail = anyAvail; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
|
bool running; |
|
|
|
|
|
uint8_t lastIvId; |
|
|
|
|
|
bool lastIvReached; |
|
|
|
|
|
bool sendTotals; |
|
|
|
|
|
float total[4]; |
|
|
|
|
|
bool RTRDataHasBeenSent; |
|
|
|
|
|
} publish_t; |
|
|
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
|
bool running; |
|
|
|
|
|
uint8_t lastIvId; |
|
|
|
|
|
uint8_t sub; |
|
|
|
|
|
uint8_t foundIvCnt; |
|
|
|
|
|
} discovery_t; |
|
|
|
|
|
|
|
|
espMqttClient mClient; |
|
|
espMqttClient mClient; |
|
|
cfgMqtt_t *mCfgMqtt; |
|
|
cfgMqtt_t *mCfgMqtt; |
|
|
#if defined(ESP8266) |
|
|
#if defined(ESP8266) |
|
@ -674,6 +712,7 @@ class PubMqtt { |
|
|
char mSubTopic[32 + MAX_NAME_LENGTH + 1]; |
|
|
char mSubTopic[32 + MAX_NAME_LENGTH + 1]; |
|
|
char mVal[40]; |
|
|
char mVal[40]; |
|
|
discovery_t mDiscovery; |
|
|
discovery_t mDiscovery; |
|
|
|
|
|
publish_t mSendIvData; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
#endif /*__PUB_MQTT_H__*/ |
|
|
#endif /*__PUB_MQTT_H__*/ |
|
|