diff --git a/src/CHANGES.md b/src/CHANGES.md index 6590e708..ca05d60e 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes + +## 0.7.12 - 2023-07-09 +* added inverter status - state-machine #1016 + ## 0.7.11 - 2023-07-09 * fix MqTT endless loop #1013 diff --git a/src/app.cpp b/src/app.cpp index 0c51949a..535af4c8 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -51,6 +51,7 @@ void app::setup() { everySec(std::bind(&ahoywifi::tickWifiLoop, &mWifi), "wifiL"); #endif + mSys.setup(&mTimestamp); mSys.addInverters(&mConfig->inst); if(mConfig->nrf.enabled) { mPayload.setup(this, &mSys, &mNrfRadio, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); @@ -413,7 +414,7 @@ void app:: zeroIvValues(bool checkAvail, bool skipYieldDay) { continue; // skip to next inverter if (checkAvail) { - if (!iv->isAvailable(mTimestamp)) + if (!iv->isAvailable()) continue; } @@ -496,7 +497,7 @@ void app::updateLed(void) { if (mConfig->led.led0 != 0xff) { Inverter<> *iv = mSys.getInverterByPos(0); if (NULL != iv) { - if (iv->isProducing(mTimestamp)) + if (iv->isProducing()) digitalWrite(mConfig->led.led0, led_on); else digitalWrite(mConfig->led.led0, led_off); diff --git a/src/defines.h b/src/defines.h index 6cb90b55..60fd78b2 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 11 +#define VERSION_PATCH 12 //------------------------------------- typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 094be658..b926ca7a 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -102,6 +102,13 @@ const calcFunc_t calcFunctions[] = { { CALC_IRR_CH, &calcIrradiation } }; +enum class InverterStatus : uint8_t { + OFF, + STARTING, + PRODUCING, + WAS_PRODUCING, + WAS_ON +}; template class Inverter { @@ -123,6 +130,9 @@ class Inverter { //String lastAlarmMsg; bool initialized; // needed to check if the inverter was correctly added (ESP32 specific - union types are never null) bool isConnected; // shows if inverter was successfully identified (fw version and hardware info) + InverterStatus status; // indicates the current inverter status + + static uint32_t *timestamp; // system timestamp Inverter() { ivGen = IV_HM; @@ -135,6 +145,7 @@ class Inverter { //lastAlarmMsg = "nothing"; alarmMesIndex = 0; isConnected = false; + status = InverterStatus::OFF; } ~Inverter() { @@ -319,6 +330,9 @@ class Inverter { } else DPRINTLN(DBG_ERROR, F("addValue: assignment not found with cmd 0x")); + + // update status state-machine + isProducing(); } /*inline REC_TYP getPowerLimit(void) { @@ -372,25 +386,39 @@ class Inverter { } } - bool isAvailable(uint32_t timestamp) { - if((timestamp - recordMeas.ts) < INACT_THRES_SEC) - return true; - if((timestamp - recordInfo.ts) < INACT_THRES_SEC) - return true; - if((timestamp - recordConfig.ts) < INACT_THRES_SEC) - return true; - if((timestamp - recordAlarm.ts) < INACT_THRES_SEC) - return true; - return false; + bool isAvailable() { + bool val = false; + if((*timestamp - recordMeas.ts) < INACT_THRES_SEC) + val = true; + if((*timestamp - recordInfo.ts) < INACT_THRES_SEC) + val = true; + if((*timestamp - recordConfig.ts) < INACT_THRES_SEC) + val = true; + if((*timestamp - recordAlarm.ts) < INACT_THRES_SEC) + val = true; + + if(val) { + if((InverterStatus::OFF == status) || (InverterStatus::WAS_ON == status)) + status = InverterStatus::STARTING; + } else + status = InverterStatus::WAS_ON; + + return val; } - bool isProducing(uint32_t timestamp) { + bool isProducing() { + bool val = false; DPRINTLN(DBG_VERBOSE, F("hmInverter.h:isProducing")); - if(isAvailable(timestamp)) { + if(isAvailable()) { uint8_t pos = getPosByChFld(CH0, FLD_PAC, &recordMeas); - return (getValue(pos, &recordMeas) > INACT_PWR_THRESH); + val = (getValue(pos, &recordMeas) > INACT_PWR_THRESH); + + if(val) + status = InverterStatus::PRODUCING; + else if(InverterStatus::PRODUCING == status) + status = InverterStatus::WAS_PRODUCING; } - return false; + return val; } uint16_t getFwVersion() { @@ -605,6 +633,9 @@ class Inverter { bool mDevControlRequest; // true if change needed }; +template +uint32_t *Inverter::timestamp {0}; + /** * To calculate values which are not transmitted by the unit there is a generic diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index a5a22885..09f8a8ba 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -13,7 +13,8 @@ class HmSystem { public: HmSystem() {} - void setup() { + void setup(uint32_t *timestamp) { + mInverter[0].timestamp = timestamp; mNumInv = 0; } diff --git a/src/platformio.ini b/src/platformio.ini index c05908f0..e6980552 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -26,7 +26,7 @@ lib_deps = https://github.com/yubox-node-org/ESPAsyncWebServer nrf24/RF24 @ 1.4.5 paulstoffregen/Time @ ^1.6.1 - https://github.com/bertmelis/espMqttClient#v1.4.2 + https://github.com/bertmelis/espMqttClient#v1.4.4 bblanchon/ArduinoJson @ ^6.21.2 https://github.com/JChristensen/Timezone @ ^1.2.4 olikraus/U8g2 @ ^2.34.17 diff --git a/src/plugins/Display/Display.h b/src/plugins/Display/Display.h index ba187c7d..b26218e6 100644 --- a/src/plugins/Display/Display.h +++ b/src/plugins/Display/Display.h @@ -89,7 +89,7 @@ class Display { if (iv == NULL) continue; - if (iv->isProducing(*mUtcTs)) + if (iv->isProducing()) isprod++; totalPower += iv->getChannelFieldValue(CH0, FLD_PAC, rec); diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 60a826a0..943017ed 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -489,9 +489,9 @@ class PubMqtt { // inverter status uint8_t status = MQTT_STATUS_NOT_AVAIL_NOT_PROD; - if (iv->isAvailable(*mUtcTimestamp)) { + if (iv->isAvailable()) { anyAvail = true; - status = (iv->isProducing(*mUtcTimestamp)) ? MQTT_STATUS_AVAIL_PROD : MQTT_STATUS_AVAIL_NOT_PROD; + status = (iv->isProducing()) ? MQTT_STATUS_AVAIL_PROD : MQTT_STATUS_AVAIL_NOT_PROD; } else // inverter is enabled but not available allAvail = false; @@ -551,7 +551,7 @@ class PubMqtt { switch (rec->assign[i].fieldId) { case FLD_YT: case FLD_YD: - if ((rec->assign[i].ch == CH0) && (!iv->isProducing(*mUtcTimestamp))) // avoids returns to 0 on restart + if ((rec->assign[i].ch == CH0) && (!iv->isProducing())) // avoids returns to 0 on restart continue; retained = true; break; diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 1b2827b1..e945598b 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -67,6 +67,7 @@ class PubMqttIvData { void stateStart() { mLastIvId = 0; + mTotalFound = false; if(!mSendList->empty()) { mCmd = mSendList->front().cmd; mIvSend = mSendList->front().iv; @@ -99,7 +100,7 @@ class PubMqttIvData { mPos = 0; if(found) mState = SEND_DATA; - else if(mSendTotals) + else if(mSendTotals && mTotalFound) mState = SEND_TOTALS; else { mSendList->pop(); @@ -122,32 +123,33 @@ class PubMqttIvData { if(FLD_YT == rec->assign[mPos].fieldId) retained = true; else if(FLD_YD == rec->assign[mPos].fieldId) { - /*if(!mZeroValues) { - if ((rec->assign[mPos].ch == CH0) && (!mIv->isProducing(*mUtcTimestamp))) { // avoids returns to 0 on restart + if(!mZeroValues) { + if ((rec->assign[mPos].ch == CH0) && (!mIv->isProducing())) { // avoids returns to 0 on restart mPos++; return; } - }*/ + } retained = true; } // calculate total values for RealTimeRunData_Debug if (CH0 == rec->assign[mPos].ch) { - switch (rec->assign[mPos].fieldId) { - case FLD_PAC: - if(mIv->isAvailable(*mUtcTimestamp)) + if(mIv->status > InverterStatus::STARTING) { + mTotalFound = true; + switch (rec->assign[mPos].fieldId) { + case FLD_PAC: mTotal[0] += mIv->getValue(mPos, rec); - break; - case FLD_YT: - mTotal[1] += mIv->getValue(mPos, rec); - break; - case FLD_YD: - mTotal[2] += mIv->getValue(mPos, rec); - break; - case FLD_PDC: - if(mIv->isAvailable(*mUtcTimestamp)) + break; + case FLD_YT: + mTotal[1] += mIv->getValue(mPos, rec); + break; + case FLD_YD: + mTotal[2] += mIv->getValue(mPos, rec); + break; + case FLD_PDC: mTotal[3] += mIv->getValue(mPos, rec); - break; + break; + } } } } else @@ -207,7 +209,7 @@ class PubMqttIvData { uint8_t mCmd; uint8_t mLastIvId; - bool mSendTotals; + bool mSendTotals, mTotalFound; float mTotal[4]; Inverter<> *mIv, *mIvSend; diff --git a/src/publisher/pubSerial.h b/src/publisher/pubSerial.h index 522a227d..34dc64f2 100644 --- a/src/publisher/pubSerial.h +++ b/src/publisher/pubSerial.h @@ -28,7 +28,7 @@ class PubSerial { Inverter<> *iv = mSys->getInverterByPos(id); if (NULL != iv) { record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); - if (iv->isAvailable(*mUtcTimestamp)) { + if (iv->isAvailable()) { DPRINTLN(DBG_INFO, "Iv: " + String(id)); for (uint8_t i = 0; i < rec->length; i++) { if (0.0f != iv->getValue(i, rec)) { diff --git a/src/web/RestApi.h b/src/web/RestApi.h index c4964dc3..d88e8db8 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -472,8 +472,8 @@ class RestApi { invObj[F("id")] = i; invObj[F("name")] = String(iv->config->name); invObj[F("version")] = String(iv->getFwVersion()); - invObj[F("is_avail")] = iv->isAvailable(mApp->getTimestamp()); - invObj[F("is_producing")] = iv->isProducing(mApp->getTimestamp()); + invObj[F("is_avail")] = iv->isAvailable(); + invObj[F("is_producing")] = iv->isProducing(); invObj[F("ts_last_success")] = iv->getLastTs(rec); } }