diff --git a/src/CHANGES.md b/src/CHANGES.md index ba3c661b..a2be1750 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -4,6 +4,9 @@ * add LED to display whether it's night time or not. Can be reused as output to control battery system #1308 * merge PR: beautifiying typography, added spaces between value and unit for `/visualization` #1314 * merge PR: Prometheus add `getLossRate` and bugfixing #1315 +* add loss rate to `/visualization` in the statistics window +* corrected `getLossRate` infos for MqTT and prometheus +* added information about working IRQ for NRF24 and CMT2300A to `/system` ## 0.8.41 - 2024-01-02 * fix display timeout (OLED) to 60s diff --git a/src/defines.h b/src/defines.h index 56bdf5e6..4b3482a2 100644 --- a/src/defines.h +++ b/src/defines.h @@ -103,10 +103,10 @@ typedef struct { uint32_t frmCnt; uint32_t txCnt; uint32_t retransmits; - uint16_t ivRxCnt; // last iv rx frames (from GetLossRate) - uint16_t ivTxCnt; // last iv tx frames (from GetLossRate) - uint16_t dtuRxCnt; // current DTU rx frames (since last GetLossRate) - uint16_t dtuTxCnt; // current DTU tx frames (since last GetLossRate) + uint16_t ivLoss; // lost frames (from GetLossRate) + uint16_t ivSent; // sent frames (from GetLossRate) + uint16_t dtuLoss; // current DTU lost frames (since last GetLossRate) + uint16_t dtuSent; // current DTU sent frames (since last GetLossRate) } statistics_t; #endif /*__DEFINES_H__*/ diff --git a/src/hm/Communication.h b/src/hm/Communication.h index d44e860f..e31984b6 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -151,7 +151,7 @@ class Communication : public CommQueue<> { if(validateIvSerial(&p->packet[1], q->iv)) { q->iv->radioStatistics.frmCnt++; - q->iv->radioStatistics.dtuRxCnt++; + q->iv->mDtuRxCnt++; if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command if(parseFrame(p)) diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 25f575e5..57de135f 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -595,22 +595,27 @@ class Inverter { uint16_t rxCnt = (pyld[0] << 8) + pyld[1]; uint16_t txCnt = (pyld[2] << 8) + pyld[3]; - if (radioStatistics.ivRxCnt || radioStatistics.ivTxCnt) { // there was successful GetLossRate in the past + if (mIvRxCnt || mIvTxCnt) { // there was successful GetLossRate in the past + radioStatistics.ivLoss = mDtuTxCnt - (rxCnt - mIvRxCnt); + radioStatistics.ivSent = mDtuTxCnt; + radioStatistics.dtuLoss = txCnt - mIvTxCnt - mDtuRxCnt; + radioStatistics.dtuSent = txCnt - mIvTxCnt; + DPRINT_IVID(DBG_INFO, id); DBGPRINT(F("Inv loss: ")); - DBGPRINT(String (radioStatistics.dtuTxCnt - (rxCnt - radioStatistics.ivRxCnt))); + DBGPRINT(String(radioStatistics.ivLoss)); DBGPRINT(F(" of ")); - DBGPRINT(String (radioStatistics.dtuTxCnt)); + DBGPRINT(String(radioStatistics.ivSent)); DBGPRINT(F(", DTU loss: ")); - DBGPRINT(String (txCnt - radioStatistics.ivTxCnt - radioStatistics.dtuRxCnt)); + DBGPRINT(String(radioStatistics.dtuLoss)); DBGPRINT(F(" of ")); - DBGPRINTLN(String (txCnt - radioStatistics.ivTxCnt)); + DBGPRINTLN(String(radioStatistics.dtuSent)); } - radioStatistics.ivRxCnt = rxCnt; - radioStatistics.ivTxCnt = txCnt; - radioStatistics.dtuRxCnt = 0; // start new interval - radioStatistics.dtuTxCnt = 0; // start new interval + mIvRxCnt = rxCnt; + mIvTxCnt = txCnt; + mDtuRxCnt = 0; // start new interval + mDtuTxCnt = 0; // start new interval return true; } @@ -806,6 +811,12 @@ class Inverter { uint8_t mGridLen = 0; uint8_t mGridProfile[MAX_GRID_LENGTH]; uint8_t mGetLossInterval; // request iv every AHOY_GET_LOSS_INTERVAL RealTimeRunData_Debug + uint16_t mIvRxCnt = 0; + uint16_t mIvTxCnt = 0; + + public: + uint16_t mDtuRxCnt = 0; + uint16_t mDtuTxCnt = 0; }; template diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index c7b9581c..6539dd21 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -339,7 +339,7 @@ class HmRadio : public Radio { mMillis = millis(); mLastIv = iv; - iv->radioStatistics.dtuTxCnt++; + iv->mDtuTxCnt++; } uint64_t getIvId(Inverter<> *iv) { diff --git a/src/hm/radio.h b/src/hm/radio.h index 2fe4f640..1ef32e05 100644 --- a/src/hm/radio.h +++ b/src/hm/radio.h @@ -14,6 +14,8 @@ #include "../utils/dbg.h" #include "../utils/crc.h" +enum { IRQ_UNKNOWN = 0, IRQ_OK, IRQ_ERROR }; + // forward declaration of class template class Inverter; @@ -30,6 +32,7 @@ class Radio { void handleIntr(void) { mIrqRcvd = true; + mIrqOk = IRQ_OK; } void sendCmdPacket(Inverter<> *iv, uint8_t mid, uint8_t pid, bool isRetransmit, bool appendCrc16=true) { @@ -65,6 +68,7 @@ class Radio { public: std::queue mBufCtrl; + uint8_t mIrqOk = IRQ_UNKNOWN; protected: virtual void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) = 0; @@ -77,6 +81,8 @@ class Radio { CP_U32_LittleEndian(&mTxBuf[5], mDtuSn); mTxBuf[9] = pid; memset(&mTxBuf[10], 0x00, (MAX_RF_PAYLOAD_SIZE-10)); + if(IRQ_UNKNOWN == mIrqOk) + mIrqOk = IRQ_ERROR; } void updateCrcs(uint8_t *len, bool appendCrc16=true) { diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index 3b3893ac..6b502816 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -112,7 +112,7 @@ class CmtRadio : public Radio { if(CMT_ERR_RX_IN_FIFO == status) mIrqRcvd = true; } - iv->radioStatistics.dtuTxCnt++; + iv->mDtuTxCnt++; } uint64_t getIvId(Inverter<> *iv) { diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 3a38a5ed..c645c70b 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// 2023 Ahoy, https://ahoydtu.de +// 2024 Ahoy, https://ahoydtu.de // Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- @@ -201,10 +201,10 @@ class PubMqttIvData { mIv->radioStatistics.rxFail, mIv->radioStatistics.rxFailNoAnser, mIv->radioStatistics.retransmits, - mIv->radioStatistics.ivRxCnt, - mIv->radioStatistics.ivTxCnt, - mIv->radioStatistics.dtuRxCnt, - mIv->radioStatistics.dtuTxCnt); + mIv->radioStatistics.ivLoss, + mIv->radioStatistics.ivSent, + mIv->radioStatistics.dtuLoss, + mIv->radioStatistics.dtuSent); mPublish(mSubTopic, mVal, false, QOS_0); } diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 7541e095..03275eed 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -405,6 +405,10 @@ class RestApi { obj[F("frame_cnt")] = iv->radioStatistics.frmCnt; obj[F("tx_cnt")] = iv->radioStatistics.txCnt; obj[F("retransmits")] = iv->radioStatistics.retransmits; + obj[F("ivLoss")] = iv->radioStatistics.ivLoss; + obj[F("ivSent")] = iv->radioStatistics.ivSent; + obj[F("dtuLoss")] = iv->radioStatistics.dtuLoss; + obj[F("dtuSent")] = iv->radioStatistics.dtuSent; } void getIvPowerLimitAck(JsonObject obj, uint8_t id) { @@ -633,6 +637,7 @@ class RestApi { if(mConfig->cmt.enabled) { obj[F("isconnected")] = mRadioCmt->isChipConnected(); obj[F("sn")] = String(mRadioCmt->getDTUSn(), HEX); + obj[F("irqOk")] = mRadioCmt->mIrqOk; } } #endif @@ -643,6 +648,7 @@ class RestApi { obj[F("isconnected")] = mRadioNrf->isChipConnected(); obj[F("dataRate")] = mRadioNrf->getDataRate(); obj[F("sn")] = String(mRadioNrf->getDTUSn(), HEX); + obj[F("irqOk")] = mRadioNrf->mIrqOk; } } diff --git a/src/web/html/system.html b/src/web/html/system.html index 035f30ff..f400db41 100644 --- a/src/web/html/system.html +++ b/src/web/html/system.html @@ -44,12 +44,21 @@ return ml("div", {class: "head p-2 mt-3"}, ml("div", {class: "row"}, ml("div", {class: "col a-c"}, text))) } + function irqBadge(state) { + switch(state) { + case 0: return badge(false, "unknown", "warning"); break; + case 1: return badge(true, "true"); break; + default: return badge(false, "false"); break; + } + } + function parseRadio(obj) { const dr = ["1 M", "2 M", "250 k"] if(obj.radioNrf.en) { lines = [ tr("NRF24L01", badge(obj.radioNrf.isconnected, ((obj.radioNrf.isconnected) ? "" : "not ") + "connected")), + tr("Interrupt Pin working", irqBadge(obj.radioNrf.irqOk)), tr("NRF24 Data Rate", dr[obj.radioNrf.dataRate] + "bps"), tr("DTU Radio ID", obj.radioNrf.sn) ]; @@ -67,6 +76,7 @@ if(obj.radioCmt.en) { cmt = [ tr("CMT2300A", badge(obj.radioCmt.isconnected, ((obj.radioCmt.isconnected) ? "" : "not ") + "connected")), + tr("Interrupt Pin working", irqBadge(obj.radioCmt.irqOk)), tr("DTU Radio ID", obj.radioCmt.sn) ]; } else diff --git a/src/web/html/visualization.html b/src/web/html/visualization.html index 88bbdc9b..ec6596bb 100644 --- a/src/web/html/visualization.html +++ b/src/web/html/visualization.html @@ -388,7 +388,9 @@ tr2(["RX fail", obj.rx_fail, String(Math.round(obj.rx_fail / obj.tx_cnt * 10000) / 100) + " %"]), tr2(["RX no answer", obj.rx_fail_answer, String(Math.round(obj.rx_fail_answer / obj.tx_cnt * 10000) / 100) + " %"]), tr2(["RX fragments", obj.frame_cnt, ""]), - tr2(["TX retransmits", obj.retransmits, ""]) + tr2(["TX retransmits", obj.retransmits, ""]), + tr2(["Inverter loss rate", "lost " + obj.ivLoss + " of " + obj.ivSent, String(Math.round(obj.ivLoss / obj.ivSent * 10000) / 100) + " %"]), + tr2(["DTU loss rate", "lost " + obj.dtuLoss + " of " + obj.dtuSent, String(Math.round(obj.dtuLoss / obj.dtuSent * 10000) / 100) + " %"]) ]) ]) modal("Radio statistics for inverter " + obj.name, ml("div", {}, html)) diff --git a/src/web/web.h b/src/web/web.h index 2bcc031a..ea25e5ff 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -665,10 +665,10 @@ class Web { { "radio_frame_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.frmCnt;} }, { "radio_tx_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.txCnt;} }, { "radio_retransmits", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.retransmits;} }, - { "radio_iv_rx_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.ivRxCnt;} }, - { "radio_iv_tx_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.ivTxCnt;} }, - { "radio_dtu_rx_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.dtuRxCnt;} }, - { "radio_dtu_tx_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.dtuTxCnt;} } + { "radio_iv_loss_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.ivLoss;} }, + { "radio_iv_sent_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.ivSent;} }, + { "radio_dtu_loss_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.dtuLoss;} }, + { "radio_dtu_sent_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.dtuSent;} } }; int metricsInverterId; uint8_t metricsFieldId;