Browse Source

0.8.76

* revert changes from yesterday regarding snprintf and its size #1410, #1411
* reduced cppcheck linter warnings significantly
* try to improve ePaper (ghosting) #1107
pull/1414/head
lumapu 1 year ago
parent
commit
7c532ca1cc
  1. 5
      src/CHANGES.md
  2. 5
      src/app.cpp
  3. 2
      src/defines.h
  4. 14
      src/hm/Communication.h
  5. 2
      src/hm/Heuristic.h
  6. 6
      src/hm/hmRadio.h
  7. 14
      src/hm/radio.h
  8. 6
      src/hm/simulator.h
  9. 7
      src/hms/hmsRadio.h
  10. 20
      src/plugins/Display/Display.h
  11. 6
      src/plugins/Display/Display_Mono_128X32.h
  12. 39
      src/plugins/Display/Display_Mono_128X64.h
  13. 6
      src/plugins/Display/Display_Mono_64X48.h
  14. 27
      src/plugins/Display/Display_Mono_84X48.h
  15. 17
      src/plugins/Display/Display_ePaper.cpp
  16. 7
      src/plugins/history.h
  17. 78
      src/publisher/pubMqtt.h
  18. 26
      src/publisher/pubMqttIvData.h
  19. 2
      src/utils/improv.h
  20. 1
      src/utils/syslog.cpp
  21. 5
      src/utils/syslog.h
  22. 2
      src/web/Protection.h
  23. 25
      src/web/web.h

5
src/CHANGES.md

@ -1,5 +1,10 @@
# Development Changes # Development Changes
## 0.8.76 - 2024-02-07
* revert changes from yesterday regarding snprintf and its size #1410, #1411
* reduced cppcheck linter warnings significantly
* try to improve ePaper (ghosting) #1107
## 0.8.75 - 2024-02-06 ## 0.8.75 - 2024-02-06
* fix active power control value #1406, #1409 * fix active power control value #1406, #1409
* update Mqtt lib to version `1.6.0` * update Mqtt lib to version `1.6.0`

5
src/app.cpp

@ -264,11 +264,10 @@ void app::tickNtpUpdate(void) {
#endif #endif
if (isOK) { if (isOK) {
this->updateNtp(); this->updateNtp();
nxtTrig = mConfig->ntp.interval * 60; // check again in 12h
nxtTrig = isOK ? (mConfig->ntp.interval * 60) : 60; // depending on NTP update success check again in 12h (depends on setting) or in 1 min
// immediately start communicating // immediately start communicating
if (isOK && mSendFirst) { if (mSendFirst) {
mSendFirst = false; mSendFirst = false;
once(std::bind(&app::tickSend, this), 1, "senOn"); once(std::bind(&app::tickSend, this), 1, "senOn");
} }

2
src/defines.h

@ -13,7 +13,7 @@
//------------------------------------- //-------------------------------------
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 8 #define VERSION_MINOR 8
#define VERSION_PATCH 75 #define VERSION_PATCH 76
//------------------------------------- //-------------------------------------
typedef struct { typedef struct {

14
src/hm/Communication.h

@ -698,7 +698,7 @@ class Communication : public CommQueue<> {
byte[23] to byte[26] Matching_APPFW_PN*/ byte[23] to byte[26] Matching_APPFW_PN*/
DPRINT(DBG_INFO,F("HW_PartNo ")); DPRINT(DBG_INFO,F("HW_PartNo "));
DBGPRINTLN(String((uint32_t) (((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])); DBGPRINTLN(String((uint32_t) (((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13]));
record_t<> *rec = q->iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure rec = q->iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure
rec->ts = q->ts; rec->ts = q->ts;
q->iv->setValue(0, rec, (uint32_t) ((((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])/1); q->iv->setValue(0, rec, (uint32_t) ((((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])/1);
rec->mqttSentStatus = MqttSentStatus::NEW_DATA; rec->mqttSentStatus = MqttSentStatus::NEW_DATA;
@ -899,14 +899,16 @@ class Communication : public CommQueue<> {
q->iv->alarmCnt = 1; // minimum... q->iv->alarmCnt = 1; // minimum...
stsok = false; stsok = false;
//sth is or was wrong? //sth is or was wrong?
if ( (q->iv->type != INV_TYPE_1CH) && ( (statusMi != 3) if ((q->iv->type != INV_TYPE_1CH)
|| ((q->iv->lastAlarm[stschan].code) && (statusMi == 3) && (q->iv->lastAlarm[stschan].code != 1))) && ((statusMi != 3)
|| ((q->iv->lastAlarm[stschan].code) && (q->iv->lastAlarm[stschan].code != 1)))
) { ) {
q->iv->lastAlarm[stschan+q->iv->type==INV_TYPE_2CH ? 2: 4] = alarm_t(q->iv->lastAlarm[stschan].code, q->iv->lastAlarm[stschan].start,q->ts); q->iv->lastAlarm[stschan+q->iv->type==INV_TYPE_2CH ? 2: 4] = alarm_t(q->iv->lastAlarm[stschan].code, q->iv->lastAlarm[stschan].start,q->ts);
q->iv->lastAlarm[stschan] = alarm_t(prntsts, q->ts,0); q->iv->lastAlarm[stschan] = alarm_t(prntsts, q->ts,0);
q->iv->alarmCnt = q->iv->type == INV_TYPE_2CH ? 3 : 5; q->iv->alarmCnt = q->iv->type == INV_TYPE_2CH ? 3 : 5;
} else if ( (q->iv->type == INV_TYPE_1CH) && ( (statusMi != 3) } else if ((q->iv->type == INV_TYPE_1CH)
|| ((q->iv->lastAlarm[stschan].code) && (statusMi == 3) && (q->iv->lastAlarm[stschan].code != 1))) && ( (statusMi != 3)
|| ((q->iv->lastAlarm[stschan].code) && (q->iv->lastAlarm[stschan].code != 1)))
) { ) {
q->iv->lastAlarm[stschan] = alarm_t(q->iv->lastAlarm[0].code, q->iv->lastAlarm[0].start,q->ts); q->iv->lastAlarm[stschan] = alarm_t(q->iv->lastAlarm[0].code, q->iv->lastAlarm[0].start,q->ts);
} else if (q->iv->type == INV_TYPE_1CH) } else if (q->iv->type == INV_TYPE_1CH)
@ -962,7 +964,7 @@ class Communication : public CommQueue<> {
iv->radioStatistics.ivLoss = iv->radioStatistics.ivSent - iv->mDtuRxCnt; // this is what we didn't receive iv->radioStatistics.ivLoss = iv->radioStatistics.ivSent - iv->mDtuRxCnt; // this is what we didn't receive
iv->radioStatistics.dtuLoss = iv->mIvTxCnt; // this is somehow the requests w/o answers in that periode iv->radioStatistics.dtuLoss = iv->mIvTxCnt; // this is somehow the requests w/o answers in that periode
iv->radioStatistics.dtuSent = iv->mDtuTxCnt; iv->radioStatistics.dtuSent = iv->mDtuTxCnt;
if (mSerialDebug) { if (*mSerialDebug) {
DPRINT_IVID(DBG_INFO, iv->id); DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINTLN("DTU loss: " + DBGPRINTLN("DTU loss: " +
String (iv->radioStatistics.ivLoss) + "/" + String (iv->radioStatistics.ivLoss) + "/" +

2
src/hm/Heuristic.h

@ -132,7 +132,7 @@ class Heuristic {
ih->lastRxFragments = rxFragments; ih->lastRxFragments = rxFragments;
} }
void printStatus(Inverter<> *iv) { void printStatus(const Inverter<> *iv) {
DPRINT_IVID(DBG_INFO, iv->id); DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINT(F("Radio infos:")); DBGPRINT(F("Radio infos:"));
if((IV_HMS != iv->ivGen) && (IV_HMT != iv->ivGen)) { if((IV_HMS != iv->ivGen) && (IV_HMT != iv->ivGen)) {

6
src/hm/hmRadio.h

@ -395,9 +395,9 @@ class HmRadio : public Radio {
#endif*/ #endif*/
if(*mPrintWholeTrace) { if(*mPrintWholeTrace) {
if(*mPrivacyMode) if(*mPrivacyMode)
ah::dumpBuf(mTxBuf, len, 1, 4); ah::dumpBuf(mTxBuf.data(), len, 1, 4);
else else
ah::dumpBuf(mTxBuf, len); ah::dumpBuf(mTxBuf.data(), len);
} else { } else {
DHEX(mTxBuf[0]); DHEX(mTxBuf[0]);
DBGPRINT(F(" ")); DBGPRINT(F(" "));
@ -415,7 +415,7 @@ class HmRadio : public Radio {
} }
mNrf24->setChannel(mRfChLst[mTxChIdx]); mNrf24->setChannel(mRfChLst[mTxChIdx]);
mNrf24->openWritingPipe(reinterpret_cast<uint8_t*>(&iv->radioId.u64)); mNrf24->openWritingPipe(reinterpret_cast<uint8_t*>(&iv->radioId.u64));
mNrf24->startWrite(mTxBuf, len, false); // false = request ACK response mNrf24->startWrite(mTxBuf.data(), len, false); // false = request ACK response
mMillis = millis(); mMillis = millis();
mLastIv = iv; mLastIv = iv;

14
src/hm/radio.h

@ -11,6 +11,7 @@
#define ALL_FRAMES 0x80 #define ALL_FRAMES 0x80
#define SINGLE_FRAME 0x81 #define SINGLE_FRAME 0x81
#include <array>
#include <atomic> #include <atomic>
#include "../utils/dbg.h" #include "../utils/dbg.h"
#include "../utils/crc.h" #include "../utils/crc.h"
@ -34,6 +35,8 @@ class Radio {
virtual std::pair<uint16_t,uint16_t> getFreqRangeMhz(void) { return std::make_pair(0, 0); } virtual std::pair<uint16_t,uint16_t> getFreqRangeMhz(void) { return std::make_pair(0, 0); }
virtual bool loop(void) = 0; virtual bool loop(void) = 0;
Radio() : mTxBuf{} {}
void handleIntr(void) { void handleIntr(void) {
mIrqRcvd = true; mIrqRcvd = true;
mIrqOk = IRQ_OK; mIrqOk = IRQ_OK;
@ -107,7 +110,7 @@ class Radio {
mTxBuf[(*len)++] = (crc ) & 0xff; mTxBuf[(*len)++] = (crc ) & 0xff;
} }
// crc over all // crc over all
mTxBuf[*len] = ah::crc8(mTxBuf, *len); mTxBuf[*len] = ah::crc8(mTxBuf.data(), *len);
(*len)++; (*len)++;
} }
@ -129,12 +132,11 @@ class Radio {
mDtuSn |= 0x80000000; // the first digit is an 8 for DTU production year 2022, the rest is filled with the ESP chipID in decimal mDtuSn |= 0x80000000; // the first digit is an 8 for DTU production year 2022, the rest is filled with the ESP chipID in decimal
} }
protected:
uint32_t mDtuSn = 0;
uint32_t mDtuSn; std::atomic<bool> mIrqRcvd = false;
std::atomic<bool> mIrqRcvd;
bool *mSerialDebug = nullptr, *mPrivacyMode = nullptr, *mPrintWholeTrace = nullptr; bool *mSerialDebug = nullptr, *mPrivacyMode = nullptr, *mPrintWholeTrace = nullptr;
uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; std::array<uint8_t, MAX_RF_PAYLOAD_SIZE> mTxBuf;
}; };
#endif /*__RADIO_H__*/ #endif /*__RADIO_H__*/

6
src/hm/simulator.h

@ -118,9 +118,9 @@ class Simulator {
} }
private: private:
HMSYSTEM *mSys; HMSYSTEM *mSys = nullptr;
uint8_t mIvId; uint8_t mIvId = 0;
uint32_t *mTimestamp; uint32_t *mTimestamp = nullptr;
payloadListenerType mCbPayload = nullptr; payloadListenerType mCbPayload = nullptr;
uint8_t payloadCtrl = 0; uint8_t payloadCtrl = 0;

7
src/hms/hmsRadio.h

@ -21,6 +21,7 @@ class CmtRadio : public Radio {
mPrivacyMode = privacyMode; mPrivacyMode = privacyMode;
mSerialDebug = serialDebug; mSerialDebug = serialDebug;
mPrintWholeTrace = printWholeTrace; mPrintWholeTrace = printWholeTrace;
mTxBuf.fill(0);
} }
bool loop() override { bool loop() override {
@ -102,9 +103,9 @@ class CmtRadio : public Radio {
DBGPRINT(F("Mhz | ")); DBGPRINT(F("Mhz | "));
if(*mPrintWholeTrace) { if(*mPrintWholeTrace) {
if(*mPrivacyMode) if(*mPrivacyMode)
ah::dumpBuf(mTxBuf, len, 1, 4); ah::dumpBuf(mTxBuf.data(), len, 1, 4);
else else
ah::dumpBuf(mTxBuf, len); ah::dumpBuf(mTxBuf.data(), len);
} else { } else {
DHEX(mTxBuf[0]); DHEX(mTxBuf[0]);
DBGPRINT(F(" ")); DBGPRINT(F(" "));
@ -114,7 +115,7 @@ class CmtRadio : public Radio {
} }
} }
CmtStatus status = mCmt.tx(mTxBuf, len); CmtStatus status = mCmt.tx(mTxBuf.data(), len);
mMillis = millis(); mMillis = millis();
if(CmtStatus::SUCCESS != status) { if(CmtStatus::SUCCESS != status) {
DPRINT(DBG_WARN, F("CMT TX failed, code: ")); DPRINT(DBG_WARN, F("CMT TX failed, code: "));

20
src/plugins/Display/Display.h

@ -223,21 +223,21 @@ class Display {
} }
// private member variables // private member variables
IApp *mApp; IApp *mApp = nullptr;
DisplayData mDisplayData; DisplayData mDisplayData;
bool mNewPayload; bool mNewPayload = false;
uint8_t mLoopCnt; uint8_t mLoopCnt = 0;
uint32_t *mUtcTs; uint32_t *mUtcTs = nullptr;
display_t *mCfg; display_t *mCfg = nullptr;
HMSYSTEM *mSys; HMSYSTEM *mSys = nullptr;
RADIO *mHmRadio; RADIO *mHmRadio = nullptr;
RADIO *mHmsRadio; RADIO *mHmsRadio = nullptr;
uint16_t mRefreshCycle; uint16_t mRefreshCycle = 0;
#if defined(ESP32) && !defined(ETHERNET) #if defined(ESP32) && !defined(ETHERNET)
DisplayEPaper mEpaper; DisplayEPaper mEpaper;
#endif #endif
DisplayMono *mMono; DisplayMono *mMono = nullptr;
}; };
#endif /*PLUGIN_DISPLAY*/ #endif /*PLUGIN_DISPLAY*/

6
src/plugins/Display/Display_Mono_128X32.h

@ -12,11 +12,11 @@ class DisplayMono128X32 : public DisplayMono {
mExtra = 0; mExtra = 0;
} }
void config(display_t *cfg) { void config(display_t *cfg) override {
mCfg = cfg; mCfg = cfg;
} }
void init(DisplayData *displayData) { void init(DisplayData *displayData) override {
u8g2_cb_t *rot = (u8g2_cb_t *)((mCfg->rot != 0x00) ? U8G2_R2 : U8G2_R0); u8g2_cb_t *rot = (u8g2_cb_t *)((mCfg->rot != 0x00) ? U8G2_R2 : U8G2_R0);
monoInit(new U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C(rot, 0xff, mCfg->disp_clk, mCfg->disp_data), displayData); monoInit(new U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C(rot, 0xff, mCfg->disp_clk, mCfg->disp_data), displayData);
calcLinePositions(); calcLinePositions();
@ -26,7 +26,7 @@ class DisplayMono128X32 : public DisplayMono {
mDisplay->sendBuffer(); mDisplay->sendBuffer();
} }
void disp(void) { void disp(void) override {
mDisplay->clearBuffer(); mDisplay->clearBuffer();
// calculate current pixelshift for pixelshift screensaver // calculate current pixelshift for pixelshift screensaver

39
src/plugins/Display/Display_Mono_128X64.h

@ -13,11 +13,11 @@ class DisplayMono128X64 : public DisplayMono {
mExtra = 0; mExtra = 0;
} }
void config(display_t *cfg) { void config(display_t *cfg) override {
mCfg = cfg; mCfg = cfg;
} }
void init(DisplayData *displayData) { void init(DisplayData *displayData) override {
u8g2_cb_t *rot = (u8g2_cb_t *)(( mCfg->rot != 0x00) ? U8G2_R2 : U8G2_R0); u8g2_cb_t *rot = (u8g2_cb_t *)(( mCfg->rot != 0x00) ? U8G2_R2 : U8G2_R0);
switch (mCfg->type) { switch (mCfg->type) {
case DISP_TYPE_T1_SSD1306_128X64: case DISP_TYPE_T1_SSD1306_128X64:
@ -68,9 +68,7 @@ class DisplayMono128X64 : public DisplayMono {
mDisplay->sendBuffer(); mDisplay->sendBuffer();
} }
void disp(void) { void disp(void) override {
uint8_t pos, sun_pos, moon_pos;
mDisplay->clearBuffer(); mDisplay->clearBuffer();
// Layout-Test // Layout-Test
@ -106,8 +104,8 @@ class DisplayMono128X64 : public DisplayMono {
} }
// print status of inverters // print status of inverters
else { else {
sun_pos = -1; int8_t sun_pos = -1;
moon_pos = -1; int8_t moon_pos = -1;
setLineFont(l_Status); setLineFont(l_Status);
if (0 == mDisplayData->nrSleeping + mDisplayData->nrProducing) if (0 == mDisplayData->nrSleeping + mDisplayData->nrProducing)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "no inverter"); snprintf(mFmtText, DISP_FMT_TEXT_LEN, "no inverter");
@ -128,11 +126,11 @@ class DisplayMono128X64 : public DisplayMono {
} }
printText(mFmtText, l_Status, 0xff); printText(mFmtText, l_Status, 0xff);
pos = (mDispWidth - mDisplay->getStrWidth(mFmtText)) / 2; uint8_t pos = (mDispWidth - mDisplay->getStrWidth(mFmtText)) / 2;
mDisplay->setFont(u8g2_font_ncenB08_symbols8_ahoy); mDisplay->setFont(u8g2_font_ncenB08_symbols8_ahoy);
if (sun_pos!=-1) if (sun_pos != -1)
mDisplay->drawStr(pos + sun_pos + mPixelshift, mLineYOffsets[l_Status], "G"); // sun symbol mDisplay->drawStr(pos + sun_pos + mPixelshift, mLineYOffsets[l_Status], "G"); // sun symbol
if (moon_pos!=-1) if (moon_pos != -1)
mDisplay->drawStr(pos + moon_pos + mPixelshift, mLineYOffsets[l_Status], "H"); // moon symbol mDisplay->drawStr(pos + moon_pos + mPixelshift, mLineYOffsets[l_Status], "H"); // moon symbol
} }
} }
@ -181,12 +179,11 @@ class DisplayMono128X64 : public DisplayMono {
// draw dynamic RSSI bars // draw dynamic RSSI bars
int rssi_bar_height = 9; int rssi_bar_height = 9;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
int radio_rssi_threshold = -60 - i * 10; int rssi_threshold = -60 - i * 10;
int wifi_rssi_threshold = -60 - i * 10;
uint8_t barwidth = std::min(4 - i, 3); uint8_t barwidth = std::min(4 - i, 3);
if (mDisplayData->RadioRSSI > radio_rssi_threshold) if (mDisplayData->RadioRSSI > rssi_threshold)
mDisplay->drawBox(widthShrink / 2 + mPixelshift, 8 + (rssi_bar_height + 1) * i, barwidth, rssi_bar_height); mDisplay->drawBox(widthShrink / 2 + mPixelshift, 8 + (rssi_bar_height + 1) * i, barwidth, rssi_bar_height);
if (mDisplayData->WifiRSSI > wifi_rssi_threshold) if (mDisplayData->WifiRSSI > rssi_threshold)
mDisplay->drawBox(mDispWidth - barwidth - widthShrink / 2 + mPixelshift, 8 + (rssi_bar_height + 1) * i, barwidth, rssi_bar_height); mDisplay->drawBox(mDispWidth - barwidth - widthShrink / 2 + mPixelshift, 8 + (rssi_bar_height + 1) * i, barwidth, rssi_bar_height);
} }
// draw dynamic antenna and WiFi symbols // draw dynamic antenna and WiFi symbols
@ -223,23 +220,22 @@ class DisplayMono128X64 : public DisplayMono {
l_MAX_LINES = 5, l_MAX_LINES = 5,
}; };
uint8_t graph_first_line; uint8_t graph_first_line = 0;
uint8_t graph_last_line; uint8_t graph_last_line = 0;
const uint8_t pixelShiftRange = 11; // number of pixels to shift from left to right (centered -> must be odd!) const uint8_t pixelShiftRange = 11; // number of pixels to shift from left to right (centered -> must be odd!)
uint8_t widthShrink; uint8_t widthShrink = 0;
void calcLinePositions() { void calcLinePositions() {
uint8_t yOff = 0; uint8_t yOff = 0;
uint8_t i = 0; uint8_t i = 0;
uint8_t asc, dsc;
do { do {
setLineFont(i); setLineFont(i);
asc = mDisplay->getAscent(); uint8_t asc = mDisplay->getAscent();
yOff += asc; yOff += asc;
mLineYOffsets[i] = yOff; mLineYOffsets[i] = yOff;
dsc = mDisplay->getDescent(); uint8_t dsc = mDisplay->getDescent();
yOff -= dsc; yOff -= dsc;
if (l_Time == i) // prevent time and status line to touch if (l_Time == i) // prevent time and status line to touch
yOff++; // -> one pixels space yOff++; // -> one pixels space
@ -248,8 +244,7 @@ class DisplayMono128X64 : public DisplayMono {
} }
inline void setLineFont(uint8_t line) { inline void setLineFont(uint8_t line) {
if ((line == l_TotalPower) || if (line == l_TotalPower) // || (line == l_Ahoy) -> l_TotalPower == l_Ahoy == 2
(line == l_Ahoy))
mDisplay->setFont(u8g2_font_ncenB14_tr); mDisplay->setFont(u8g2_font_ncenB14_tr);
else if ((line == l_YieldDay) || else if ((line == l_YieldDay) ||
(line == l_YieldTotal)) (line == l_YieldTotal))

6
src/plugins/Display/Display_Mono_64X48.h

@ -12,11 +12,11 @@ class DisplayMono64X48 : public DisplayMono {
mExtra = 0; mExtra = 0;
} }
void config(display_t *cfg) { void config(display_t *cfg) override {
mCfg = cfg; mCfg = cfg;
} }
void init(DisplayData *displayData) { void init(DisplayData *displayData) override {
u8g2_cb_t *rot = (u8g2_cb_t *)((mCfg->rot != 0x00) ? U8G2_R2 : U8G2_R0); u8g2_cb_t *rot = (u8g2_cb_t *)((mCfg->rot != 0x00) ? U8G2_R2 : U8G2_R0);
// Wemos OLed Shield is not defined in u8 lib -> use nearest compatible // Wemos OLed Shield is not defined in u8 lib -> use nearest compatible
monoInit(new U8G2_SSD1306_64X48_ER_F_HW_I2C(rot, 0xff, mCfg->disp_clk, mCfg->disp_data), displayData); monoInit(new U8G2_SSD1306_64X48_ER_F_HW_I2C(rot, 0xff, mCfg->disp_clk, mCfg->disp_data), displayData);
@ -28,7 +28,7 @@ class DisplayMono64X48 : public DisplayMono {
mDisplay->sendBuffer(); mDisplay->sendBuffer();
} }
void disp(void) { void disp(void) override {
mDisplay->clearBuffer(); mDisplay->clearBuffer();
// calculate current pixelshift for pixelshift screensaver // calculate current pixelshift for pixelshift screensaver

27
src/plugins/Display/Display_Mono_84X48.h

@ -12,11 +12,11 @@ class DisplayMono84X48 : public DisplayMono {
mExtra = 0; mExtra = 0;
} }
void config(display_t *cfg) { void config(display_t *cfg) override {
mCfg = cfg; mCfg = cfg;
} }
void init(DisplayData *displayData) { void init(DisplayData *displayData) override {
u8g2_cb_t *rot = (u8g2_cb_t *)((mCfg->rot != 0x00) ? U8G2_R2 : U8G2_R0); u8g2_cb_t *rot = (u8g2_cb_t *)((mCfg->rot != 0x00) ? U8G2_R2 : U8G2_R0);
monoInit(new U8G2_PCD8544_84X48_F_4W_SW_SPI(rot, mCfg->disp_clk, mCfg->disp_data, mCfg->disp_cs, mCfg->disp_dc, 0xff), displayData); monoInit(new U8G2_PCD8544_84X48_F_4W_SW_SPI(rot, mCfg->disp_clk, mCfg->disp_data, mCfg->disp_cs, mCfg->disp_dc, 0xff), displayData);
@ -55,7 +55,7 @@ class DisplayMono84X48 : public DisplayMono {
mDisplay->sendBuffer(); mDisplay->sendBuffer();
} }
void disp(void) { void disp(void) override {
mDisplay->clearBuffer(); mDisplay->clearBuffer();
// Layout-Test // Layout-Test
@ -143,12 +143,11 @@ class DisplayMono84X48 : public DisplayMono {
// draw dynamic RSSI bars // draw dynamic RSSI bars
int rssi_bar_height = 7; int rssi_bar_height = 7;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
int radio_rssi_threshold = -60 - i * 10; int rssi_threshold = -60 - i * 10;
int wifi_rssi_threshold = -60 - i * 10;
uint8_t barwidth = std::min(4 - i, 3); uint8_t barwidth = std::min(4 - i, 3);
if (mDisplayData->RadioRSSI > radio_rssi_threshold) if (mDisplayData->RadioRSSI > rssi_threshold)
mDisplay->drawBox(0, 8 + (rssi_bar_height + 1) * i, barwidth, rssi_bar_height); mDisplay->drawBox(0, 8 + (rssi_bar_height + 1) * i, barwidth, rssi_bar_height);
if (mDisplayData->WifiRSSI > wifi_rssi_threshold) if (mDisplayData->WifiRSSI > rssi_threshold)
mDisplay->drawBox(mDispWidth - barwidth, 8 + (rssi_bar_height + 1) * i, barwidth, rssi_bar_height); mDisplay->drawBox(mDispWidth - barwidth, 8 + (rssi_bar_height + 1) * i, barwidth, rssi_bar_height);
} }
@ -184,30 +183,28 @@ class DisplayMono84X48 : public DisplayMono {
l_MAX_LINES = 5, l_MAX_LINES = 5,
}; };
uint8_t graph_first_line; uint8_t graph_first_line = 0;
uint8_t graph_last_line; uint8_t graph_last_line = 0;
void calcLinePositions() { void calcLinePositions() {
uint8_t yOff = 0; uint8_t yOff = 0;
uint8_t i = 0; uint8_t i = 0;
uint8_t asc, dsc;
do { do {
setLineFont(i); setLineFont(i);
asc = mDisplay->getAscent(); uint8_t asc = mDisplay->getAscent();
yOff += asc; yOff += asc;
mLineYOffsets[i] = yOff; mLineYOffsets[i] = yOff;
dsc = mDisplay->getDescent(); uint8_t dsc = mDisplay->getDescent();
if (l_TotalPower != i) // power line needs no descent spacing if (l_TotalPower != i) // power line needs no descent spacing
yOff -= dsc; yOff -= dsc;
yOff++; // instead lets spend one pixel space between all lines yOff++; // instead lets spend one pixel space between all lines
i++; i++;
} while(l_MAX_LINES>i); } while(l_MAX_LINES > i);
} }
inline void setLineFont(uint8_t line) { inline void setLineFont(uint8_t line) {
if ((line == l_TotalPower) || if (line == l_TotalPower) // || (line == l_Ahoy) -> l_TotalPower == l_Ahoy == 2
(line == l_Ahoy))
mDisplay->setFont(u8g2_font_logisoso16_tr); mDisplay->setFont(u8g2_font_logisoso16_tr);
else else
mDisplay->setFont(u8g2_font_5x8_symbols_ahoy); mDisplay->setFont(u8g2_font_5x8_symbols_ahoy);

17
src/plugins/Display/Display_ePaper.cpp

@ -67,7 +67,7 @@ void DisplayEPaper::refreshLoop() {
case RefreshStatus::LOGO: case RefreshStatus::LOGO:
_display->fillScreen(GxEPD_BLACK); _display->fillScreen(GxEPD_BLACK);
_display->drawBitmap(0, 0, logo, 200, 200, GxEPD_WHITE); _display->drawBitmap(0, 0, logo, 200, 200, GxEPD_WHITE);
_display->display(false); // full update mSecondCnt = 2;
mNextRefreshState = RefreshStatus::PARTITIALS; mNextRefreshState = RefreshStatus::PARTITIALS;
mRefreshState = RefreshStatus::WAIT; mRefreshState = RefreshStatus::WAIT;
break; break;
@ -79,11 +79,11 @@ void DisplayEPaper::refreshLoop() {
break; break;
case RefreshStatus::WHITE: case RefreshStatus::WHITE:
if(mSecondCnt == 0) { if(0 != mSecondCnt)
_display->fillScreen(GxEPD_WHITE); break;
mNextRefreshState = RefreshStatus::PARTITIALS; _display->fillScreen(GxEPD_WHITE);
mRefreshState = RefreshStatus::WAIT; mNextRefreshState = RefreshStatus::PARTITIALS;
} mRefreshState = RefreshStatus::WAIT;
break; break;
case RefreshStatus::WAIT: case RefreshStatus::WAIT:
@ -92,10 +92,13 @@ void DisplayEPaper::refreshLoop() {
break; break;
case RefreshStatus::PARTITIALS: case RefreshStatus::PARTITIALS:
if(0 != mSecondCnt)
break;
headlineIP(); headlineIP();
versionFooter(); versionFooter();
mSecondCnt = 4; // display Logo time during boot up mSecondCnt = 4; // display Logo time during boot up
mRefreshState = RefreshStatus::DONE; mNextRefreshState = RefreshStatus::DONE;
mRefreshState = RefreshStatus::WAIT;
break; break;
default: // RefreshStatus::DONE default: // RefreshStatus::DONE

7
src/plugins/history.h

@ -47,14 +47,13 @@ class HistoryData {
} }
void tickerSecond() { void tickerSecond() {
Inverter<> *iv; ;
record_t<> *rec;
float curPwr = 0; float curPwr = 0;
float maxPwr = 0; float maxPwr = 0;
float yldDay = -0.1; float yldDay = -0.1;
for (uint8_t i = 0; i < mSys->getNumInverters(); i++) { for (uint8_t i = 0; i < mSys->getNumInverters(); i++) {
iv = mSys->getInverterByPos(i); Inverter<> *iv = mSys->getInverterByPos(i);
rec = iv->getRecordStruct(RealTimeRunData_Debug); record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
if (iv == NULL) if (iv == NULL)
continue; continue;
curPwr += iv->getChannelFieldValue(CH0, FLD_PAC, rec); curPwr += iv->getChannelFieldValue(CH0, FLD_PAC, rec);

78
src/publisher/pubMqtt.h

@ -38,7 +38,7 @@ typedef struct {
template<class HMSYSTEM> template<class HMSYSTEM>
class PubMqtt { class PubMqtt {
public: public:
PubMqtt() { PubMqtt() : SendIvData() {
mLastIvState.fill(InverterStatus::OFF); mLastIvState.fill(InverterStatus::OFF);
mIvLastRTRpub.fill(0); mIvLastRTRpub.fill(0);
@ -61,21 +61,21 @@ class PubMqtt {
mUptime = uptime; mUptime = uptime;
mIntervalTimeout = 1; mIntervalTimeout = 1;
mSendIvData.setup(sys, utcTs, &mSendList); SendIvData.setup(sys, utcTs, &mSendList);
mSendIvData.setPublishFunc([this](const char *subTopic, const char *payload, bool retained, uint8_t qos) { SendIvData.setPublishFunc([this](const char *subTopic, const char *payload, bool retained, uint8_t qos) {
publish(subTopic, payload, retained, true, qos); publish(subTopic, payload, retained, true, qos);
}); });
mDiscovery.running = false; mDiscovery.running = false;
snprintf(mLwtTopic.data(), mLwtTopic.size() - 1, "%s/mqtt", mCfgMqtt->topic); snprintf(mLwtTopic.data(), mLwtTopic.size(), "%s/mqtt", mCfgMqtt->topic);
if((strlen(mCfgMqtt->user) > 0) && (strlen(mCfgMqtt->pwd) > 0)) if((strlen(mCfgMqtt->user) > 0) && (strlen(mCfgMqtt->pwd) > 0))
mClient.setCredentials(mCfgMqtt->user, mCfgMqtt->pwd); mClient.setCredentials(mCfgMqtt->user, mCfgMqtt->pwd);
if(strlen(mCfgMqtt->clientId) > 0) if(strlen(mCfgMqtt->clientId) > 0)
snprintf(mClientId.data(), mClientId.size() - 1, "%s", mCfgMqtt->clientId); snprintf(mClientId.data(), mClientId.size(), "%s", mCfgMqtt->clientId);
else { else {
snprintf(mClientId.data(), mClientId.size() - 1, "%s-", mDevName); snprintf(mClientId.data(), mClientId.size(), "%s-", mDevName);
uint8_t pos = strlen(mClientId.data()); uint8_t pos = strlen(mClientId.data());
mClientId[pos++] = WiFi.macAddress().substring( 9, 10).c_str()[0]; mClientId[pos++] = WiFi.macAddress().substring( 9, 10).c_str()[0];
mClientId[pos++] = WiFi.macAddress().substring(10, 11).c_str()[0]; mClientId[pos++] = WiFi.macAddress().substring(10, 11).c_str()[0];
@ -95,7 +95,7 @@ class PubMqtt {
} }
void loop() { void loop() {
mSendIvData.loop(); SendIvData.loop();
#if defined(ESP8266) #if defined(ESP8266)
mClient.loop(); mClient.loop();
@ -129,7 +129,7 @@ class PubMqtt {
} }
void tickerMinute() { void tickerMinute() {
snprintf(mVal.data(), mVal.size() - 1, "%u", (*mUptime)); snprintf(mVal.data(), mVal.size(), "%u", (*mUptime));
publish(subtopics[MQTT_UPTIME], mVal.data()); publish(subtopics[MQTT_UPTIME], mVal.data());
publish(subtopics[MQTT_RSSI], String(WiFi.RSSI()).c_str()); publish(subtopics[MQTT_RSSI], String(WiFi.RSSI()).c_str());
publish(subtopics[MQTT_FREE_HEAP], String(ESP.getFreeHeap()).c_str()); publish(subtopics[MQTT_FREE_HEAP], String(ESP.getFreeHeap()).c_str());
@ -152,11 +152,11 @@ class PubMqtt {
if(NULL == iv) if(NULL == iv)
continue; continue;
snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/dis_night_comm", iv->config->name); snprintf(mSubTopic.data(), mSubTopic.size(), "%s/dis_night_comm", iv->config->name);
publish(mSubTopic.data(), ((iv->commEnabled) ? dict[STR_TRUE] : dict[STR_FALSE]), true); publish(mSubTopic.data(), ((iv->commEnabled) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
} }
snprintf(mSubTopic.data(), mSubTopic.size() - 1, "comm_disabled"); snprintf(mSubTopic.data(), mSubTopic.size(), "comm_disabled");
publish(mSubTopic.data(), (((*mUtcTimestamp > (sunset + offsE)) || (*mUtcTimestamp < (sunrise + offsM))) ? dict[STR_TRUE] : dict[STR_FALSE]), true); publish(mSubTopic.data(), (((*mUtcTimestamp > (sunset + offsE)) || (*mUtcTimestamp < (sunrise + offsM))) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
return true; return true;
@ -164,7 +164,7 @@ class PubMqtt {
void notAvailChanged(bool allNotAvail) { void notAvailChanged(bool allNotAvail) {
if(!allNotAvail) if(!allNotAvail)
mSendIvData.resetYieldDay(); SendIvData.resetYieldDay();
} }
bool tickerComm(bool disabled) { bool tickerComm(bool disabled) {
@ -179,8 +179,8 @@ class PubMqtt {
void tickerMidnight() { void tickerMidnight() {
// set Total YieldDay to zero // set Total YieldDay to zero
snprintf(mSubTopic.data(), mSubTopic.size() - 1, "total/%s", fields[FLD_YD]); snprintf(mSubTopic.data(), mSubTopic.size(), "total/%s", fields[FLD_YD]);
snprintf(mVal.data(), mVal.size() - 1, "0"); snprintf(mVal.data(), mVal.size(), "0");
publish(mSubTopic.data(), mVal.data(), true); publish(mSubTopic.data(), mVal.data(), true);
} }
@ -200,9 +200,9 @@ class PubMqtt {
return; return;
if(addTopic) if(addTopic)
snprintf(mTopic.data(), mTopic.size() - 1, "%s/%s", mCfgMqtt->topic, subTopic); snprintf(mTopic.data(), mTopic.size(), "%s/%s", mCfgMqtt->topic, subTopic);
else else
snprintf(mTopic.data(), mTopic.size() - 1, "%s", subTopic); snprintf(mTopic.data(), mTopic.size(), "%s", subTopic);
mClient.publish(mTopic.data(), qos, retained, payload); mClient.publish(mTopic.data(), qos, retained, payload);
yield(); yield();
@ -241,7 +241,7 @@ class PubMqtt {
void setPowerLimitAck(Inverter<> *iv) { void setPowerLimitAck(Inverter<> *iv) {
if (NULL != iv) { if (NULL != iv) {
snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/%s", iv->config->name, subtopics[MQTT_ACK_PWR_LMT]); snprintf(mSubTopic.data(), mSubTopic.size(), "%s/%s", iv->config->name, subtopics[MQTT_ACK_PWR_LMT]);
publish(mSubTopic.data(), "true", true, true, QOS_2); publish(mSubTopic.data(), "true", true, true, QOS_2);
} }
} }
@ -261,11 +261,11 @@ class PubMqtt {
publish(mLwtTopic.data(), mqttStr[MQTT_STR_LWT_CONN], true, false); publish(mLwtTopic.data(), mqttStr[MQTT_STR_LWT_CONN], true, false);
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
snprintf(mVal.data(), mVal.size() - 1, "ctrl/limit/%d", i); snprintf(mVal.data(), mVal.size(), "ctrl/limit/%d", i);
subscribe(mVal.data(), QOS_2); subscribe(mVal.data(), QOS_2);
snprintf(mVal.data(), mVal.size() - 1, "ctrl/restart/%d", i); snprintf(mVal.data(), mVal.size(), "ctrl/restart/%d", i);
subscribe(mVal.data()); subscribe(mVal.data());
snprintf(mVal.data(), mVal.size() - 1, "ctrl/power/%d", i); snprintf(mVal.data(), mVal.size(), "ctrl/power/%d", i);
subscribe(mVal.data()); subscribe(mVal.data());
} }
subscribe(subscr[MQTT_SUBS_SET_TIME]); subscribe(subscr[MQTT_SUBS_SET_TIME]);
@ -400,20 +400,20 @@ class PubMqtt {
const char *devCls, *stateCls; const char *devCls, *stateCls;
if (!total) { if (!total) {
if (rec->assign[mDiscovery.sub].ch == CH0) if (rec->assign[mDiscovery.sub].ch == CH0)
snprintf(name.data(), name.size() - 1, "%s", iv->getFieldName(mDiscovery.sub, rec)); snprintf(name.data(), name.size(), "%s", iv->getFieldName(mDiscovery.sub, rec));
else else
snprintf(name.data(), name.size() - 1, "CH%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec)); snprintf(name.data(), name.size(), "CH%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
snprintf(topic.data(), name.size() - 1, "/ch%d/%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec)); snprintf(topic.data(), name.size(), "/ch%d/%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
snprintf(uniq_id.data(), uniq_id.size() - 1, "ch%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec)); snprintf(uniq_id.data(), uniq_id.size(), "ch%d_%s", rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
devCls = getFieldDeviceClass(rec->assign[mDiscovery.sub].fieldId); devCls = getFieldDeviceClass(rec->assign[mDiscovery.sub].fieldId);
stateCls = getFieldStateClass(rec->assign[mDiscovery.sub].fieldId); stateCls = getFieldStateClass(rec->assign[mDiscovery.sub].fieldId);
} }
else { // total values else { // total values
snprintf(name.data(), name.size() - 1, "Total %s", fields[fldTotal[mDiscovery.sub]]); snprintf(name.data(), name.size(), "Total %s", fields[fldTotal[mDiscovery.sub]]);
snprintf(topic.data(), topic.size() - 1, "/%s", fields[fldTotal[mDiscovery.sub]]); snprintf(topic.data(), topic.size(), "/%s", fields[fldTotal[mDiscovery.sub]]);
snprintf(uniq_id.data(), uniq_id.size() - 1, "total_%s", fields[fldTotal[mDiscovery.sub]]); snprintf(uniq_id.data(), uniq_id.size(), "total_%s", fields[fldTotal[mDiscovery.sub]]);
devCls = getFieldDeviceClass(fldTotal[mDiscovery.sub]); devCls = getFieldDeviceClass(fldTotal[mDiscovery.sub]);
stateCls = getFieldStateClass(fldTotal[mDiscovery.sub]); stateCls = getFieldStateClass(fldTotal[mDiscovery.sub]);
} }
@ -433,9 +433,9 @@ class PubMqtt {
doc2[F("stat_cla")] = String(stateCls); doc2[F("stat_cla")] = String(stateCls);
if (!total) if (!total)
snprintf(topic.data(), topic.size() - 1, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec)); snprintf(topic.data(), topic.size(), "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec));
else // total values else // total values
snprintf(topic.data(), topic.size() - 1, "%s/sensor/%s/total_%s/config", MQTT_DISCOVERY_PREFIX, node_id.c_str(), fields[fldTotal[mDiscovery.sub]]); snprintf(topic.data(), topic.size(), "%s/sensor/%s/total_%s/config", MQTT_DISCOVERY_PREFIX, node_id.c_str(), fields[fldTotal[mDiscovery.sub]]);
size_t size = measureJson(doc2) + 1; size_t size = measureJson(doc2) + 1;
buf.fill(0); buf.fill(0);
serializeJson(doc2, buf.data(), size); serializeJson(doc2, buf.data(), size);
@ -509,14 +509,14 @@ class PubMqtt {
mLastIvState[id] = status; mLastIvState[id] = status;
changed = true; changed = true;
snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/available", iv->config->name); snprintf(mSubTopic.data(), mSubTopic.size(), "%s/available", iv->config->name);
snprintf(mVal.data(), mVal.size() - 1, "%d", (uint8_t)status); snprintf(mVal.data(), mVal.size(), "%d", (uint8_t)status);
publish(mSubTopic.data(), mVal.data(), true); publish(mSubTopic.data(), mVal.data(), true);
} }
} }
if(changed) { if(changed) {
snprintf(mVal.data(), mVal.size() - 1, "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((anyAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE))); snprintf(mVal.data(), mVal.size(), "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((anyAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE)));
publish("status", mVal.data(), true); publish("status", mVal.data(), true);
} }
@ -539,14 +539,14 @@ class PubMqtt {
mSendAlarm[i] = false; mSendAlarm[i] = false;
snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/alarm/cnt", iv->config->name); snprintf(mSubTopic.data(), mSubTopic.size(), "%s/alarm/cnt", iv->config->name);
snprintf(mVal.data(), mVal.size() - 1, "%d", iv->alarmCnt); snprintf(mVal.data(), mVal.size(), "%d", iv->alarmCnt);
publish(mSubTopic.data(), mVal.data(), false); publish(mSubTopic.data(), mVal.data(), false);
for(uint8_t j = 0; j < 10; j++) { for(uint8_t j = 0; j < 10; j++) {
if(0 != iv->lastAlarm[j].code) { if(0 != iv->lastAlarm[j].code) {
snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/alarm/%d", iv->config->name, j); snprintf(mSubTopic.data(), mSubTopic.size(), "%s/alarm/%d", iv->config->name, j);
snprintf(mVal.data(), mVal.size() - 1, "{\"code\":%d,\"str\":\"%s\",\"start\":%d,\"end\":%d}", snprintf(mVal.data(), mVal.size(), "{\"code\":%d,\"str\":\"%s\",\"start\":%d,\"end\":%d}",
iv->lastAlarm[j].code, iv->lastAlarm[j].code,
iv->getAlarmStr(iv->lastAlarm[j].code).c_str(), iv->getAlarmStr(iv->lastAlarm[j].code).c_str(),
iv->lastAlarm[j].start + lastMidnight, iv->lastAlarm[j].start + lastMidnight,
@ -581,8 +581,8 @@ class PubMqtt {
} }
} }
snprintf(mSubTopic.data(), mSubTopic.size() - 1, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]); snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
snprintf(mVal.data(), mVal.size() - 1, "%g", ah::round3(iv->getValue(i, rec))); snprintf(mVal.data(), mVal.size(), "%g", ah::round3(iv->getValue(i, rec)));
publish(mSubTopic.data(), mVal.data(), retained); publish(mSubTopic.data(), mVal.data(), retained);
yield(); yield();
@ -598,7 +598,7 @@ class PubMqtt {
if(mSendList.empty()) if(mSendList.empty())
return; return;
mSendIvData.start(); SendIvData.start();
mLastAnyAvail = anyAvail; mLastAnyAvail = anyAvail;
} }
@ -609,7 +609,7 @@ class PubMqtt {
#endif #endif
HMSYSTEM *mSys = nullptr; HMSYSTEM *mSys = nullptr;
PubMqttIvData<HMSYSTEM> mSendIvData; PubMqttIvData<HMSYSTEM> SendIvData;
uint32_t *mUtcTimestamp = nullptr, *mUptime = nullptr; uint32_t *mUtcTimestamp = nullptr, *mUptime = nullptr;
uint32_t mRxCnt = 0, mTxCnt = 0; uint32_t mRxCnt = 0, mTxCnt = 0;

26
src/publisher/pubMqttIvData.h

@ -1,4 +1,4 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 2024 Ahoy, https://ahoydtu.de // 2024 Ahoy, https://ahoydtu.de
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed // Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -21,6 +21,8 @@ struct sendListCmdIv {
template<class HMSYSTEM> template<class HMSYSTEM>
class PubMqttIvData { class PubMqttIvData {
public: public:
PubMqttIvData() : mTotal{}, mSubTopic{}, mVal{} {}
void setup(HMSYSTEM *sys, uint32_t *utcTs, std::queue<sendListCmdIv> *sendList) { void setup(HMSYSTEM *sys, uint32_t *utcTs, std::queue<sendListCmdIv> *sendList) {
mSys = sys; mSys = sys;
mUtcTimestamp = utcTs; mUtcTimestamp = utcTs;
@ -249,25 +251,25 @@ class PubMqttIvData {
} }
} }
HMSYSTEM *mSys; HMSYSTEM *mSys = nullptr;
uint32_t *mUtcTimestamp; uint32_t *mUtcTimestamp = nullptr;
pubMqttPublisherType mPublish; pubMqttPublisherType mPublish;
State mState; State mState = IDLE;
StateFunction mTable[NUM_STATES]; StateFunction mTable[NUM_STATES];
uint8_t mCmd; uint8_t mCmd = 0;
uint8_t mLastIvId; uint8_t mLastIvId = 0;
bool mSendTotals, mTotalFound, mAllTotalFound, mSendTotalYd; bool mSendTotals = false, mTotalFound = false, mAllTotalFound = false, mSendTotalYd = false;
float mTotal[5], mYldTotalStore; float mTotal[5], mYldTotalStore = 0;
Inverter<> *mIv, *mIvSend; Inverter<> *mIv = nullptr, *mIvSend = nullptr;
uint8_t mPos; uint8_t mPos = 0;
bool mRTRDataHasBeenSent; bool mRTRDataHasBeenSent = false;
char mSubTopic[32 + MAX_NAME_LENGTH + 1]; char mSubTopic[32 + MAX_NAME_LENGTH + 1];
char mVal[140]; char mVal[140];
std::queue<sendListCmdIv> *mSendList; std::queue<sendListCmdIv> *mSendList = nullptr;
}; };
#endif /*__PUB_MQTT_IV_DATA_H__*/ #endif /*__PUB_MQTT_IV_DATA_H__*/

2
src/utils/improv.h

@ -71,7 +71,7 @@ class Improv {
TYPE_RPC_RESPONSE = 0x04 TYPE_RPC_RESPONSE = 0x04
}; };
void dumpBuf(uint8_t buf[], uint8_t len) { void dumpBuf(const uint8_t buf[], uint8_t len) {
for(uint8_t i = 0; i < len; i++) { for(uint8_t i = 0; i < len; i++) {
DHEX(buf[i]); DHEX(buf[i]);
DBGPRINT(F(" ")); DBGPRINT(F(" "));

1
src/utils/syslog.cpp

@ -10,6 +10,7 @@
#define SYSLOG_MAX_PACKET_SIZE 256 #define SYSLOG_MAX_PACKET_SIZE 256
DbgSyslog::DbgSyslog() : mSyslogBuffer{} {}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void DbgSyslog::setup(settings_t *config) { void DbgSyslog::setup(settings_t *config) {

5
src/utils/syslog.h

@ -36,6 +36,7 @@
class DbgSyslog { class DbgSyslog {
public: public:
DbgSyslog();
void setup (settings_t *config); void setup (settings_t *config);
void syslogCb(String msg); void syslogCb(String msg);
void log(const char *hostname, uint8_t facility, uint8_t severity, char* msg); void log(const char *hostname, uint8_t facility, uint8_t severity, char* msg);
@ -43,7 +44,7 @@ class DbgSyslog {
private: private:
WiFiUDP mSyslogUdp; WiFiUDP mSyslogUdp;
IPAddress mSyslogIP; IPAddress mSyslogIP;
settings_t *mConfig; settings_t *mConfig = nullptr;
char mSyslogBuffer[SYSLOG_BUF_SIZE+1]; char mSyslogBuffer[SYSLOG_BUF_SIZE+1];
uint16_t mSyslogBufFill = 0; uint16_t mSyslogBufFill = 0;
int mSyslogSeverity = PRI_NOTICE; int mSyslogSeverity = PRI_NOTICE;
@ -51,4 +52,4 @@ class DbgSyslog {
#endif /*ENABLE_SYSLOG*/ #endif /*ENABLE_SYSLOG*/
#endif /*__SYSLOG_H__*/ #endif /*__SYSLOG_H__*/

2
src/web/Protection.h

@ -15,7 +15,7 @@
class Protection { class Protection {
protected: protected:
Protection(const char *pwd) { explicit Protection(const char *pwd) {
mPwd = pwd; mPwd = pwd;
mLogoutTimeout = 0; mLogoutTimeout = 0;
mLoginIp.fill(0); mLoginIp.fill(0);

25
src/web/web.h

@ -684,7 +684,6 @@ class Web {
char type[60], topic[100], val[25]; char type[60], topic[100], val[25];
size_t len = 0; size_t len = 0;
int alarmChannelId; int alarmChannelId;
int metricsChannelId;
// Perform grouping on metrics according to format specification // Perform grouping on metrics according to format specification
// Each step must return at least one character. Otherwise the processing of AsyncWebServerResponse stops. // Each step must return at least one character. Otherwise the processing of AsyncWebServerResponse stops.
@ -766,7 +765,7 @@ class Web {
iv = mSys->getInverterByPos(metricsInverterId); iv = mSys->getInverterByPos(metricsInverterId);
if (NULL != iv) { if (NULL != iv) {
rec = iv->getRecordStruct(RealTimeRunData_Debug); rec = iv->getRecordStruct(RealTimeRunData_Debug);
for (metricsChannelId=0; metricsChannelId < rec->length;metricsChannelId++) { for (int metricsChannelId=0; metricsChannelId < rec->length;metricsChannelId++) {
uint8_t channel = rec->assign[metricsChannelId].ch; uint8_t channel = rec->assign[metricsChannelId].ch;
// Try inverter channel (channel 0) or any channel with maxPwr > 0 // Try inverter channel (channel 0) or any channel with maxPwr > 0
@ -786,14 +785,14 @@ class Web {
char total[7]; char total[7];
if (metricDeclared) { if (metricDeclared) {
// A declaration and value for channels have been delivered. So declare and deliver a _total metric // A declaration and value for channels have been delivered. So declare and deliver a _total metric
snprintf(total, sizeof(total)-1, "_total"); snprintf(total, sizeof(total), "_total");
} }
if (!metricTotalDeclard) { if (!metricTotalDeclard) {
snprintf(type, sizeof(type)-1, "# TYPE %s%s%s%s %s\n",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), total, promType.c_str()); snprintf(type, sizeof(type), "# TYPE %s%s%s%s %s\n",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), total, promType.c_str());
metrics += type; metrics += type;
metricTotalDeclard = true; metricTotalDeclard = true;
} }
snprintf(topic, sizeof(topic)-1, "%s%s%s%s{inverter=\"%s\"}",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), total,iv->config->name); snprintf(topic, sizeof(topic), "%s%s%s%s{inverter=\"%s\"}",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), total,iv->config->name);
} else { } else {
// Report (non zero) channel value // Report (non zero) channel value
// Use a fallback channel name (ch0, ch1, ...)if non is given by user // Use a fallback channel name (ch0, ch1, ...)if non is given by user
@ -801,11 +800,11 @@ class Web {
if (iv->config->chName[channel-1][0] != 0) { if (iv->config->chName[channel-1][0] != 0) {
strncpy(chName, iv->config->chName[channel-1], sizeof(chName)); strncpy(chName, iv->config->chName[channel-1], sizeof(chName));
} else { } else {
snprintf(chName,sizeof(chName)-1,"ch%1d",channel); snprintf(chName,sizeof(chName),"ch%1d",channel);
} }
snprintf(topic, sizeof(topic)-1, "%s%s%s{inverter=\"%s\",channel=\"%s\"}",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), iv->config->name,chName); snprintf(topic, sizeof(topic), "%s%s%s{inverter=\"%s\",channel=\"%s\"}",metricConstPrefix, iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), iv->config->name,chName);
} }
snprintf(val, sizeof(val)-1, " %.3f\n", iv->getValue(metricsChannelId, rec)); snprintf(val, sizeof(val), " %.3f\n", iv->getValue(metricsChannelId, rec));
metrics += topic; metrics += topic;
metrics += val; metrics += val;
} }
@ -835,7 +834,7 @@ class Web {
case metricsStateAlarmData: // Alarm Info loop : fit to one packet case metricsStateAlarmData: // Alarm Info loop : fit to one packet
// Perform grouping on metrics according to Prometheus exposition format specification // Perform grouping on metrics according to Prometheus exposition format specification
snprintf(type, sizeof(type)-1,"# TYPE %s%s gauge\n",metricConstPrefix,fields[FLD_LAST_ALARM_CODE]); snprintf(type, sizeof(type),"# TYPE %s%s gauge\n",metricConstPrefix,fields[FLD_LAST_ALARM_CODE]);
metrics = type; metrics = type;
for (metricsInverterId = 0; metricsInverterId < mSys->getNumInverters();metricsInverterId++) { for (metricsInverterId = 0; metricsInverterId < mSys->getNumInverters();metricsInverterId++) {
@ -847,8 +846,8 @@ class Web {
alarmChannelId = 0; alarmChannelId = 0;
if (alarmChannelId < rec->length) { if (alarmChannelId < rec->length) {
std::tie(promUnit, promType) = convertToPromUnits(iv->getUnit(alarmChannelId, rec)); std::tie(promUnit, promType) = convertToPromUnits(iv->getUnit(alarmChannelId, rec));
snprintf(topic, sizeof(topic)-1, "%s%s%s{inverter=\"%s\"}",metricConstPrefix, iv->getFieldName(alarmChannelId, rec), promUnit.c_str(), iv->config->name); snprintf(topic, sizeof(topic), "%s%s%s{inverter=\"%s\"}",metricConstPrefix, iv->getFieldName(alarmChannelId, rec), promUnit.c_str(), iv->config->name);
snprintf(val, sizeof(val)-1, " %.3f\n", iv->getValue(alarmChannelId, rec)); snprintf(val, sizeof(val), " %.3f\n", iv->getValue(alarmChannelId, rec));
metrics += topic; metrics += topic;
metrics += val; metrics += val;
} }
@ -874,8 +873,8 @@ class Web {
// Traverse all inverters and collect the metric via valueFunc // Traverse all inverters and collect the metric via valueFunc
String inverterMetric(char *buffer, size_t len, const char *format, std::function<uint64_t(Inverter<> *iv)> valueFunc) { String inverterMetric(char *buffer, size_t len, const char *format, std::function<uint64_t(Inverter<> *iv)> valueFunc) {
String metric = ""; String metric = "";
for (int metricsInverterId = 0; metricsInverterId < mSys->getNumInverters();metricsInverterId++) { for (int id = 0; id < mSys->getNumInverters();id++) {
Inverter<> *iv = mSys->getInverterByPos(metricsInverterId); Inverter<> *iv = mSys->getInverterByPos(id);
if (NULL != iv) { if (NULL != iv) {
snprintf(buffer,len,format,iv->config->name, valueFunc(iv)); snprintf(buffer,len,format,iv->config->name, valueFunc(iv));
metric += String(buffer); metric += String(buffer);

Loading…
Cancel
Save