mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-22 21:36:11 +02:00
parent
0be3a23603
commit
be9c505407
11 changed files with 83 additions and 44 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
//-------------------------------------
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 7
|
||||
#define VERSION_PATCH 11
|
||||
#define VERSION_PATCH 12
|
||||
|
||||
//-------------------------------------
|
||||
typedef struct {
|
||||
|
|
|
@ -102,6 +102,13 @@ const calcFunc_t<T> calcFunctions[] = {
|
|||
{ CALC_IRR_CH, &calcIrradiation }
|
||||
};
|
||||
|
||||
enum class InverterStatus : uint8_t {
|
||||
OFF,
|
||||
STARTING,
|
||||
PRODUCING,
|
||||
WAS_PRODUCING,
|
||||
WAS_ON
|
||||
};
|
||||
|
||||
template <class REC_TYP>
|
||||
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 <class REC_TYP>
|
||||
uint32_t *Inverter<REC_TYP>::timestamp {0};
|
||||
|
||||
|
||||
/**
|
||||
* To calculate values which are not transmitted by the unit there is a generic
|
||||
|
|
|
@ -13,7 +13,8 @@ class HmSystem {
|
|||
public:
|
||||
HmSystem() {}
|
||||
|
||||
void setup() {
|
||||
void setup(uint32_t *timestamp) {
|
||||
mInverter[0].timestamp = timestamp;
|
||||
mNumInv = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue