fix #521 no reconnect at beginning of day

added immediate (each minute) report of inverter status MQTT #522
added protection mask to select which pages should be protected
This commit is contained in:
lumapu 2022-12-26 23:32:22 +01:00
parent 6bb8a4e448
commit c3fc01b956
12 changed files with 222 additions and 96 deletions

View file

@ -36,6 +36,7 @@ class PubMqtt {
mSubscriptionCb = NULL;
mIsDay = false;
mIvAvail = true;
memset(mLastIvState, 0xff, MAX_NUM_INVERTERS);
}
~PubMqtt() { }
@ -77,6 +78,7 @@ class PubMqtt {
}
void tickerMinute() {
processIvStatus();
char val[12];
snprintf(val, 12, "%ld", millis() / 1000);
publish("uptime", val);
@ -368,6 +370,72 @@ class PubMqtt {
return (pos >= DEVICE_CLS_ASSIGN_LIST_LEN) ? NULL : stateClasses[deviceFieldAssignment[pos].stateClsId];
}
bool processIvStatus() {
// returns true if all inverters are available
bool allAvail = true;
bool first = true;
bool changed = false;
char topic[7 + MQTT_TOPIC_LEN], val[40];
Inverter<> *iv;
record_t<> *rec;
bool totalComplete = true;
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
iv = mSys->getInverterByPos(id);
if (NULL == iv)
continue; // skip to next inverter
rec = iv->getRecordStruct(RealTimeRunData_Debug);
if(first)
mIvAvail = false;
first = false;
// inverter status
uint8_t status = MQTT_STATUS_AVAIL_PROD;
if ((!iv->isAvailable(*mUtcTimestamp, rec)) || (!iv->config->enabled)) {
status = MQTT_STATUS_NOT_AVAIL_NOT_PROD;
if(iv->config->enabled) { // only change all-avail if inverter is enabled!
totalComplete = false;
allAvail = false;
}
}
else if (!iv->isProducing(*mUtcTimestamp, rec)) {
mIvAvail = true;
if (MQTT_STATUS_AVAIL_PROD == status)
status = MQTT_STATUS_AVAIL_NOT_PROD;
}
else
mIvAvail = true;
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->config->name);
snprintf(val, 40, "%s%s%s%s",
(status == MQTT_STATUS_NOT_AVAIL_NOT_PROD) ? "not " : "",
"available and ",
(status == MQTT_STATUS_AVAIL_NOT_PROD) ? "not " : "",
"producing"
);
publish(topic, val, true);
if(mLastIvState[id] != status) {
mLastIvState[id] = status;
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name);
snprintf(val, 40, "%d", status);
publish(topic, val, true);
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->config->name);
snprintf(val, 40, "%d", iv->getLastTs(rec));
publish(topic, val, true);
}
}
if(changed) {
snprintf(val, 32, "%s", ((allAvail) ? "online" : ((mIvAvail) ? "partial" : "offline")));
publish("status", val, true);
}
return totalComplete;
}
void sendIvData(void) {
if(mSendList.empty())
return;
@ -375,9 +443,6 @@ class PubMqtt {
char topic[7 + MQTT_TOPIC_LEN], val[40];
float total[4];
bool sendTotal = false;
bool totalIncomplete = false;
bool allAvail = true;
bool first = true;
while(!mSendList.empty()) {
memset(total, 0, sizeof(float) * 4);
@ -388,45 +453,6 @@ class PubMqtt {
record_t<> *rec = iv->getRecordStruct(mSendList.front());
if(mSendList.front() == RealTimeRunData_Debug) {
if(first)
mIvAvail = false;
first = false;
// inverter status
uint8_t status = MQTT_STATUS_AVAIL_PROD;
if ((!iv->isAvailable(*mUtcTimestamp, rec)) || (!iv->config->enabled)) {
status = MQTT_STATUS_NOT_AVAIL_NOT_PROD;
if(iv->config->enabled) { // only change all-avail if inverter is enabled!
totalIncomplete = true;
allAvail = false;
}
}
else if (!iv->isProducing(*mUtcTimestamp, rec)) {
mIvAvail = true;
if (MQTT_STATUS_AVAIL_PROD == status)
status = MQTT_STATUS_AVAIL_NOT_PROD;
}
else
mIvAvail = true;
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->config->name);
snprintf(val, 40, "%s%s%s%s",
(status == MQTT_STATUS_NOT_AVAIL_NOT_PROD) ? "not " : "",
"available and ",
(status == MQTT_STATUS_AVAIL_NOT_PROD) ? "not " : "",
"producing"
);
publish(topic, val, true);
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name);
snprintf(val, 40, "%d", status);
publish(topic, val, true);
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->config->name);
snprintf(val, 40, "%d", iv->getLastTs(rec));
publish(topic, val, true);
}
// data
if(iv->isAvailable(*mUtcTimestamp, rec)) {
for (uint8_t i = 0; i < rec->length; i++) {
@ -471,10 +497,7 @@ class PubMqtt {
mSendList.pop(); // remove from list once all inverters were processed
snprintf(val, 32, "%s", ((allAvail) ? "online" : ((mIvAvail) ? "partial" : "offline")));
publish("status", val, true);
if ((true == sendTotal) && (false == totalIncomplete)) {
if ((true == sendTotal) && processIvStatus()) {
uint8_t fieldId;
for (uint8_t i = 0; i < 4; i++) {
switch (i) {
@ -514,6 +537,7 @@ class PubMqtt {
subscriptionCb mSubscriptionCb;
bool mIsDay;
bool mIvAvail; // shows if at least one inverter is available
uint8_t mLastIvState[MAX_NUM_INVERTERS];
// last will topic and payload must be available trough lifetime of 'espMqttClient'
char mLwtTopic[MQTT_TOPIC_LEN+5];