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. 35
      src/plugins/Display/Display_Mono_128X64.h
  13. 6
      src/plugins/Display/Display_Mono_64X48.h
  14. 25
      src/plugins/Display/Display_Mono_84X48.h
  15. 11
      src/plugins/Display/Display_ePaper.cpp
  16. 7
      src/plugins/history.h
  17. 78
      src/publisher/pubMqtt.h
  18. 24
      src/publisher/pubMqttIvData.h
  19. 2
      src/utils/improv.h
  20. 1
      src/utils/syslog.cpp
  21. 3
      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
## 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
* fix active power control value #1406, #1409
* update Mqtt lib to version `1.6.0`

5
src/app.cpp

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

2
src/defines.h

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

14
src/hm/Communication.h

@ -698,7 +698,7 @@ class Communication : public CommQueue<> {
byte[23] to byte[26] Matching_APPFW_PN*/
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]));
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;
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;
@ -899,14 +899,16 @@ class Communication : public CommQueue<> {
q->iv->alarmCnt = 1; // minimum...
stsok = false;
//sth is or was wrong?
if ( (q->iv->type != INV_TYPE_1CH) && ( (statusMi != 3)
|| ((q->iv->lastAlarm[stschan].code) && (statusMi == 3) && (q->iv->lastAlarm[stschan].code != 1)))
if ((q->iv->type != INV_TYPE_1CH)
&& ((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] = alarm_t(prntsts, q->ts,0);
q->iv->alarmCnt = q->iv->type == INV_TYPE_2CH ? 3 : 5;
} else if ( (q->iv->type == INV_TYPE_1CH) && ( (statusMi != 3)
|| ((q->iv->lastAlarm[stschan].code) && (statusMi == 3) && (q->iv->lastAlarm[stschan].code != 1)))
} else if ((q->iv->type == INV_TYPE_1CH)
&& ( (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);
} 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.dtuLoss = iv->mIvTxCnt; // this is somehow the requests w/o answers in that periode
iv->radioStatistics.dtuSent = iv->mDtuTxCnt;
if (mSerialDebug) {
if (*mSerialDebug) {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINTLN("DTU loss: " +
String (iv->radioStatistics.ivLoss) + "/" +

2
src/hm/Heuristic.h

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

6
src/hm/hmRadio.h

@ -395,9 +395,9 @@ class HmRadio : public Radio {
#endif*/
if(*mPrintWholeTrace) {
if(*mPrivacyMode)
ah::dumpBuf(mTxBuf, len, 1, 4);
ah::dumpBuf(mTxBuf.data(), len, 1, 4);
else
ah::dumpBuf(mTxBuf, len);
ah::dumpBuf(mTxBuf.data(), len);
} else {
DHEX(mTxBuf[0]);
DBGPRINT(F(" "));
@ -415,7 +415,7 @@ class HmRadio : public Radio {
}
mNrf24->setChannel(mRfChLst[mTxChIdx]);
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();
mLastIv = iv;

14
src/hm/radio.h

@ -11,6 +11,7 @@
#define ALL_FRAMES 0x80
#define SINGLE_FRAME 0x81
#include <array>
#include <atomic>
#include "../utils/dbg.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 bool loop(void) = 0;
Radio() : mTxBuf{} {}
void handleIntr(void) {
mIrqRcvd = true;
mIrqOk = IRQ_OK;
@ -107,7 +110,7 @@ class Radio {
mTxBuf[(*len)++] = (crc ) & 0xff;
}
// crc over all
mTxBuf[*len] = ah::crc8(mTxBuf, *len);
mTxBuf[*len] = ah::crc8(mTxBuf.data(), *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
}
uint32_t mDtuSn;
std::atomic<bool> mIrqRcvd;
protected:
uint32_t mDtuSn = 0;
std::atomic<bool> mIrqRcvd = false;
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__*/

6
src/hm/simulator.h

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

7
src/hms/hmsRadio.h

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

20
src/plugins/Display/Display.h

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

6
src/plugins/Display/Display_Mono_128X32.h

@ -12,11 +12,11 @@ class DisplayMono128X32 : public DisplayMono {
mExtra = 0;
}
void config(display_t *cfg) {
void config(display_t *cfg) override {
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);
monoInit(new U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C(rot, 0xff, mCfg->disp_clk, mCfg->disp_data), displayData);
calcLinePositions();
@ -26,7 +26,7 @@ class DisplayMono128X32 : public DisplayMono {
mDisplay->sendBuffer();
}
void disp(void) {
void disp(void) override {
mDisplay->clearBuffer();
// calculate current pixelshift for pixelshift screensaver

35
src/plugins/Display/Display_Mono_128X64.h

@ -13,11 +13,11 @@ class DisplayMono128X64 : public DisplayMono {
mExtra = 0;
}
void config(display_t *cfg) {
void config(display_t *cfg) override {
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);
switch (mCfg->type) {
case DISP_TYPE_T1_SSD1306_128X64:
@ -68,9 +68,7 @@ class DisplayMono128X64 : public DisplayMono {
mDisplay->sendBuffer();
}
void disp(void) {
uint8_t pos, sun_pos, moon_pos;
void disp(void) override {
mDisplay->clearBuffer();
// Layout-Test
@ -106,8 +104,8 @@ class DisplayMono128X64 : public DisplayMono {
}
// print status of inverters
else {
sun_pos = -1;
moon_pos = -1;
int8_t sun_pos = -1;
int8_t moon_pos = -1;
setLineFont(l_Status);
if (0 == mDisplayData->nrSleeping + mDisplayData->nrProducing)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "no inverter");
@ -128,7 +126,7 @@ class DisplayMono128X64 : public DisplayMono {
}
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);
if (sun_pos != -1)
mDisplay->drawStr(pos + sun_pos + mPixelshift, mLineYOffsets[l_Status], "G"); // sun symbol
@ -181,12 +179,11 @@ class DisplayMono128X64 : public DisplayMono {
// draw dynamic RSSI bars
int rssi_bar_height = 9;
for (int i = 0; i < 4; i++) {
int radio_rssi_threshold = -60 - i * 10;
int wifi_rssi_threshold = -60 - i * 10;
int rssi_threshold = -60 - i * 10;
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);
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);
}
// draw dynamic antenna and WiFi symbols
@ -223,23 +220,22 @@ class DisplayMono128X64 : public DisplayMono {
l_MAX_LINES = 5,
};
uint8_t graph_first_line;
uint8_t graph_last_line;
uint8_t graph_first_line = 0;
uint8_t graph_last_line = 0;
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() {
uint8_t yOff = 0;
uint8_t i = 0;
uint8_t asc, dsc;
do {
setLineFont(i);
asc = mDisplay->getAscent();
uint8_t asc = mDisplay->getAscent();
yOff += asc;
mLineYOffsets[i] = yOff;
dsc = mDisplay->getDescent();
uint8_t dsc = mDisplay->getDescent();
yOff -= dsc;
if (l_Time == i) // prevent time and status line to touch
yOff++; // -> one pixels space
@ -248,8 +244,7 @@ class DisplayMono128X64 : public DisplayMono {
}
inline void setLineFont(uint8_t line) {
if ((line == l_TotalPower) ||
(line == l_Ahoy))
if (line == l_TotalPower) // || (line == l_Ahoy) -> l_TotalPower == l_Ahoy == 2
mDisplay->setFont(u8g2_font_ncenB14_tr);
else if ((line == l_YieldDay) ||
(line == l_YieldTotal))

6
src/plugins/Display/Display_Mono_64X48.h

@ -12,11 +12,11 @@ class DisplayMono64X48 : public DisplayMono {
mExtra = 0;
}
void config(display_t *cfg) {
void config(display_t *cfg) override {
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);
// 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);
@ -28,7 +28,7 @@ class DisplayMono64X48 : public DisplayMono {
mDisplay->sendBuffer();
}
void disp(void) {
void disp(void) override {
mDisplay->clearBuffer();
// calculate current pixelshift for pixelshift screensaver

25
src/plugins/Display/Display_Mono_84X48.h

@ -12,11 +12,11 @@ class DisplayMono84X48 : public DisplayMono {
mExtra = 0;
}
void config(display_t *cfg) {
void config(display_t *cfg) override {
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);
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();
}
void disp(void) {
void disp(void) override {
mDisplay->clearBuffer();
// Layout-Test
@ -143,12 +143,11 @@ class DisplayMono84X48 : public DisplayMono {
// draw dynamic RSSI bars
int rssi_bar_height = 7;
for (int i = 0; i < 4; i++) {
int radio_rssi_threshold = -60 - i * 10;
int wifi_rssi_threshold = -60 - i * 10;
int rssi_threshold = -60 - i * 10;
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);
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);
}
@ -184,20 +183,19 @@ class DisplayMono84X48 : public DisplayMono {
l_MAX_LINES = 5,
};
uint8_t graph_first_line;
uint8_t graph_last_line;
uint8_t graph_first_line = 0;
uint8_t graph_last_line = 0;
void calcLinePositions() {
uint8_t yOff = 0;
uint8_t i = 0;
uint8_t asc, dsc;
do {
setLineFont(i);
asc = mDisplay->getAscent();
uint8_t asc = mDisplay->getAscent();
yOff += asc;
mLineYOffsets[i] = yOff;
dsc = mDisplay->getDescent();
uint8_t dsc = mDisplay->getDescent();
if (l_TotalPower != i) // power line needs no descent spacing
yOff -= dsc;
yOff++; // instead lets spend one pixel space between all lines
@ -206,8 +204,7 @@ class DisplayMono84X48 : public DisplayMono {
}
inline void setLineFont(uint8_t line) {
if ((line == l_TotalPower) ||
(line == l_Ahoy))
if (line == l_TotalPower) // || (line == l_Ahoy) -> l_TotalPower == l_Ahoy == 2
mDisplay->setFont(u8g2_font_logisoso16_tr);
else
mDisplay->setFont(u8g2_font_5x8_symbols_ahoy);

11
src/plugins/Display/Display_ePaper.cpp

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

7
src/plugins/history.h

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

78
src/publisher/pubMqtt.h

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

24
src/publisher/pubMqttIvData.h

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

2
src/utils/improv.h

@ -71,7 +71,7 @@ class Improv {
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++) {
DHEX(buf[i]);
DBGPRINT(F(" "));

1
src/utils/syslog.cpp

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

3
src/utils/syslog.h

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

2
src/web/Protection.h

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

25
src/web/web.h

@ -684,7 +684,6 @@ class Web {
char type[60], topic[100], val[25];
size_t len = 0;
int alarmChannelId;
int metricsChannelId;
// Perform grouping on metrics according to format specification
// Each step must return at least one character. Otherwise the processing of AsyncWebServerResponse stops.
@ -766,7 +765,7 @@ class Web {
iv = mSys->getInverterByPos(metricsInverterId);
if (NULL != iv) {
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;
// Try inverter channel (channel 0) or any channel with maxPwr > 0
@ -786,14 +785,14 @@ class Web {
char total[7];
if (metricDeclared) {
// 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) {
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;
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 {
// Report (non zero) channel value
// 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) {
strncpy(chName, iv->config->chName[channel-1], sizeof(chName));
} 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 += val;
}
@ -835,7 +834,7 @@ class Web {
case metricsStateAlarmData: // Alarm Info loop : fit to one packet
// 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;
for (metricsInverterId = 0; metricsInverterId < mSys->getNumInverters();metricsInverterId++) {
@ -847,8 +846,8 @@ class Web {
alarmChannelId = 0;
if (alarmChannelId < rec->length) {
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(val, sizeof(val)-1, " %.3f\n", iv->getValue(alarmChannelId, rec));
snprintf(topic, sizeof(topic), "%s%s%s{inverter=\"%s\"}",metricConstPrefix, iv->getFieldName(alarmChannelId, rec), promUnit.c_str(), iv->config->name);
snprintf(val, sizeof(val), " %.3f\n", iv->getValue(alarmChannelId, rec));
metrics += topic;
metrics += val;
}
@ -874,8 +873,8 @@ class Web {
// 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 metric = "";
for (int metricsInverterId = 0; metricsInverterId < mSys->getNumInverters();metricsInverterId++) {
Inverter<> *iv = mSys->getInverterByPos(metricsInverterId);
for (int id = 0; id < mSys->getNumInverters();id++) {
Inverter<> *iv = mSys->getInverterByPos(id);
if (NULL != iv) {
snprintf(buffer,len,format,iv->config->name, valueFunc(iv));
metric += String(buffer);

Loading…
Cancel
Save