mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-10 15:36:38 +02:00
0.8.74
* reduced cppcheck linter warnings significantly
This commit is contained in:
parent
6b5435a246
commit
3740a09d2a
31 changed files with 375 additions and 413 deletions
|
@ -1,5 +1,8 @@
|
||||||
# Development Changes
|
# Development Changes
|
||||||
|
|
||||||
|
## 0.8.74 - 2024-02-05
|
||||||
|
* reduced cppcheck linter warnings significantly
|
||||||
|
|
||||||
## 0.8.73 - 2024-02-03
|
## 0.8.73 - 2024-02-03
|
||||||
* fix nullpointer during communication #1401
|
* fix nullpointer during communication #1401
|
||||||
* added `max_power` to MqTT total values #1375
|
* added `max_power` to MqTT total values #1375
|
||||||
|
|
15
src/app.cpp
15
src/app.cpp
|
@ -13,7 +13,10 @@
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
app::app() : ah::Scheduler {} {}
|
app::app() : ah::Scheduler {} {
|
||||||
|
memset(mVersion, 0, sizeof(char) * 12);
|
||||||
|
memset(mVersionModules, 0, sizeof(char) * 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -228,7 +231,6 @@ void app::updateNtp(void) {
|
||||||
onceAt(std::bind(&app::tickMidnight, this), midTrig, "midNi");
|
onceAt(std::bind(&app::tickMidnight, this), midTrig, "midNi");
|
||||||
|
|
||||||
if (mConfig->sys.schedReboot) {
|
if (mConfig->sys.schedReboot) {
|
||||||
uint32_t localTime = gTimezone.toLocal(mTimestamp);
|
|
||||||
uint32_t rebootTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86410); // reboot 10 secs after midnght
|
uint32_t rebootTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86410); // reboot 10 secs after midnght
|
||||||
if (rebootTrig <= mTimestamp) { //necessary for times other than midnight to prevent reboot loop
|
if (rebootTrig <= mTimestamp) { //necessary for times other than midnight to prevent reboot loop
|
||||||
rebootTrig += 86400;
|
rebootTrig += 86400;
|
||||||
|
@ -301,9 +303,8 @@ void app::tickIVCommunication(void) {
|
||||||
bool zeroValues = false;
|
bool zeroValues = false;
|
||||||
uint32_t nxtTrig = 0;
|
uint32_t nxtTrig = 0;
|
||||||
|
|
||||||
Inverter<> *iv;
|
|
||||||
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
|
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
|
||||||
iv = mSys.getInverterByPos(i);
|
Inverter<> *iv = mSys.getInverterByPos(i);
|
||||||
if(NULL == iv)
|
if(NULL == iv)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -390,10 +391,9 @@ void app::tickMidnight(void) {
|
||||||
|
|
||||||
// clear max values
|
// clear max values
|
||||||
if(mConfig->inst.rstMaxValsMidNight) {
|
if(mConfig->inst.rstMaxValsMidNight) {
|
||||||
uint8_t pos;
|
|
||||||
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||||
for(uint8_t i = 0; i <= iv->channels; i++) {
|
for(uint8_t i = 0; i <= iv->channels; i++) {
|
||||||
pos = iv->getPosByChFld(i, FLD_MP, rec);
|
uint8_t pos = iv->getPosByChFld(i, FLD_MP, rec);
|
||||||
iv->setValue(pos, rec, 0.0f);
|
iv->setValue(pos, rec, 0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -592,9 +592,8 @@ void app::updateLed(void) {
|
||||||
uint8_t led_on = (mConfig->led.high_active) ? (mConfig->led.luminance) : (255-mConfig->led.luminance);
|
uint8_t led_on = (mConfig->led.high_active) ? (mConfig->led.luminance) : (255-mConfig->led.luminance);
|
||||||
|
|
||||||
if (mConfig->led.led[0] != DEF_PIN_OFF) {
|
if (mConfig->led.led[0] != DEF_PIN_OFF) {
|
||||||
Inverter<> *iv;
|
|
||||||
for (uint8_t id = 0; id < mSys.getNumInverters(); id++) {
|
for (uint8_t id = 0; id < mSys.getNumInverters(); id++) {
|
||||||
iv = mSys.getInverterByPos(id);
|
Inverter<> *iv = mSys.getInverterByPos(id);
|
||||||
if (NULL != iv) {
|
if (NULL != iv) {
|
||||||
if (iv->isProducing()) {
|
if (iv->isProducing()) {
|
||||||
// turn on when at least one inverter is producing
|
// turn on when at least one inverter is producing
|
||||||
|
|
100
src/app.h
100
src/app.h
|
@ -90,7 +90,7 @@ class app : public IApp, public ah::Scheduler {
|
||||||
void handleIntr(void) {
|
void handleIntr(void) {
|
||||||
mNrfRadio.handleIntr();
|
mNrfRadio.handleIntr();
|
||||||
}
|
}
|
||||||
void* getRadioObj(bool nrf) {
|
void* getRadioObj(bool nrf) override {
|
||||||
if(nrf)
|
if(nrf)
|
||||||
return (void*)&mNrfRadio;
|
return (void*)&mNrfRadio;
|
||||||
else {
|
else {
|
||||||
|
@ -108,19 +108,19 @@ class app : public IApp, public ah::Scheduler {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t getUptime() {
|
uint32_t getUptime() override {
|
||||||
return Scheduler::getUptime();
|
return Scheduler::getUptime();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getTimestamp() {
|
uint32_t getTimestamp() override {
|
||||||
return Scheduler::mTimestamp;
|
return Scheduler::mTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t getTimestampMs() {
|
uint64_t getTimestampMs() override {
|
||||||
return ((uint64_t)Scheduler::mTimestamp * 1000) + ((uint64_t)millis() - (uint64_t)Scheduler::mTsMillis) % 1000;
|
return ((uint64_t)Scheduler::mTimestamp * 1000) + ((uint64_t)millis() - (uint64_t)Scheduler::mTsMillis) % 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool saveSettings(bool reboot) {
|
bool saveSettings(bool reboot) override {
|
||||||
mShowRebootRequest = true; // only message on index, no reboot
|
mShowRebootRequest = true; // only message on index, no reboot
|
||||||
mSavePending = true;
|
mSavePending = true;
|
||||||
mSaveReboot = reboot;
|
mSaveReboot = reboot;
|
||||||
|
@ -131,7 +131,7 @@ class app : public IApp, public ah::Scheduler {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initInverter(uint8_t id) {
|
void initInverter(uint8_t id) override {
|
||||||
mSys.addInverter(id, [this](Inverter<> *iv) {
|
mSys.addInverter(id, [this](Inverter<> *iv) {
|
||||||
if((IV_MI == iv->ivGen) || (IV_HM == iv->ivGen))
|
if((IV_MI == iv->ivGen) || (IV_HM == iv->ivGen))
|
||||||
iv->radio = &mNrfRadio;
|
iv->radio = &mNrfRadio;
|
||||||
|
@ -142,7 +142,7 @@ class app : public IApp, public ah::Scheduler {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readSettings(const char *path) {
|
bool readSettings(const char *path) override {
|
||||||
return mSettings.readSettings(path);
|
return mSettings.readSettings(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,80 +150,80 @@ class app : public IApp, public ah::Scheduler {
|
||||||
return mSettings.eraseSettings(eraseWifi);
|
return mSettings.eraseSettings(eraseWifi);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getSavePending() {
|
bool getSavePending() override {
|
||||||
return mSavePending;
|
return mSavePending;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getLastSaveSucceed() {
|
bool getLastSaveSucceed() override {
|
||||||
return mSettings.getLastSaveSucceed();
|
return mSettings.getLastSaveSucceed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getShouldReboot() {
|
bool getShouldReboot() override {
|
||||||
return mSaveReboot;
|
return mSaveReboot;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(ETHERNET)
|
#if !defined(ETHERNET)
|
||||||
void scanAvailNetworks() {
|
void scanAvailNetworks() override {
|
||||||
mWifi.scanAvailNetworks();
|
mWifi.scanAvailNetworks();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getAvailNetworks(JsonObject obj) {
|
bool getAvailNetworks(JsonObject obj) override {
|
||||||
return mWifi.getAvailNetworks(obj);
|
return mWifi.getAvailNetworks(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupStation(void) {
|
void setupStation(void) override {
|
||||||
mWifi.setupStation();
|
mWifi.setupStation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStopApAllowedMode(bool allowed) {
|
void setStopApAllowedMode(bool allowed) override {
|
||||||
mWifi.setStopApAllowedMode(allowed);
|
mWifi.setStopApAllowedMode(allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
String getStationIp(void) {
|
String getStationIp(void) override {
|
||||||
return mWifi.getStationIp();
|
return mWifi.getStationIp();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getWasInCh12to14(void) const {
|
bool getWasInCh12to14(void) const override {
|
||||||
return mWifi.getWasInCh12to14();
|
return mWifi.getWasInCh12to14();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !defined(ETHERNET) */
|
#endif /* !defined(ETHERNET) */
|
||||||
|
|
||||||
void setRebootFlag() {
|
void setRebootFlag() override {
|
||||||
once(std::bind(&app::tickReboot, this), 3, "rboot");
|
once(std::bind(&app::tickReboot, this), 3, "rboot");
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *getVersion() {
|
const char *getVersion() override {
|
||||||
return mVersion;
|
return mVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *getVersionModules() {
|
const char *getVersionModules() override {
|
||||||
return mVersionModules;
|
return mVersionModules;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getSunrise() {
|
uint32_t getSunrise() override {
|
||||||
return mSunrise;
|
return mSunrise;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getSunset() {
|
uint32_t getSunset() override {
|
||||||
return mSunset;
|
return mSunset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getSettingsValid() {
|
bool getSettingsValid() override {
|
||||||
return mSettings.getValid();
|
return mSettings.getValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getRebootRequestState() {
|
bool getRebootRequestState() override {
|
||||||
return mShowRebootRequest;
|
return mShowRebootRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMqttDiscoveryFlag() {
|
void setMqttDiscoveryFlag() override {
|
||||||
#if defined(ENABLE_MQTT)
|
#if defined(ENABLE_MQTT)
|
||||||
once(std::bind(&PubMqttType::sendDiscoveryConfig, &mMqtt), 1, "disCf");
|
once(std::bind(&PubMqttType::sendDiscoveryConfig, &mMqtt), 1, "disCf");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getMqttIsConnected() {
|
bool getMqttIsConnected() override {
|
||||||
#if defined(ENABLE_MQTT)
|
#if defined(ENABLE_MQTT)
|
||||||
return mMqtt.isConnected();
|
return mMqtt.isConnected();
|
||||||
#else
|
#else
|
||||||
|
@ -231,7 +231,7 @@ class app : public IApp, public ah::Scheduler {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getMqttTxCnt() {
|
uint32_t getMqttTxCnt() override {
|
||||||
#if defined(ENABLE_MQTT)
|
#if defined(ENABLE_MQTT)
|
||||||
return mMqtt.getTxCnt();
|
return mMqtt.getTxCnt();
|
||||||
#else
|
#else
|
||||||
|
@ -239,7 +239,7 @@ class app : public IApp, public ah::Scheduler {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getMqttRxCnt() {
|
uint32_t getMqttRxCnt() override {
|
||||||
#if defined(ENABLE_MQTT)
|
#if defined(ENABLE_MQTT)
|
||||||
return mMqtt.getRxCnt();
|
return mMqtt.getRxCnt();
|
||||||
#else
|
#else
|
||||||
|
@ -267,11 +267,11 @@ class app : public IApp, public ah::Scheduler {
|
||||||
return mProtection->isProtected(clientIp);
|
return mProtection->isProtected(clientIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getNrfEnabled(void) {
|
bool getNrfEnabled(void) override {
|
||||||
return mConfig->nrf.enabled;
|
return mConfig->nrf.enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getCmtEnabled(void) {
|
bool getCmtEnabled(void) override {
|
||||||
return mConfig->cmt.enabled;
|
return mConfig->cmt.enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,19 +283,19 @@ class app : public IApp, public ah::Scheduler {
|
||||||
return mConfig->cmt.pinIrq;
|
return mConfig->cmt.pinIrq;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getTimezoneOffset() {
|
uint32_t getTimezoneOffset() override {
|
||||||
return mApi.getTimezoneOffset();
|
return mApi.getTimezoneOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void getSchedulerInfo(uint8_t *max) {
|
void getSchedulerInfo(uint8_t *max) override {
|
||||||
getStat(max);
|
getStat(max);
|
||||||
}
|
}
|
||||||
|
|
||||||
void getSchedulerNames(void) {
|
void getSchedulerNames(void) override {
|
||||||
printSchedulers();
|
printSchedulers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTimestamp(uint32_t newTime) {
|
void setTimestamp(uint32_t newTime) override {
|
||||||
DPRINT(DBG_DEBUG, F("setTimestamp: "));
|
DPRINT(DBG_DEBUG, F("setTimestamp: "));
|
||||||
DBGPRINTLN(String(newTime));
|
DBGPRINTLN(String(newTime));
|
||||||
if(0 == newTime)
|
if(0 == newTime)
|
||||||
|
@ -310,7 +310,7 @@ class app : public IApp, public ah::Scheduler {
|
||||||
Scheduler::setTimestamp(newTime);
|
Scheduler::setTimestamp(newTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getHistoryValue(uint8_t type, uint16_t i) {
|
uint16_t getHistoryValue(uint8_t type, uint16_t i) override {
|
||||||
#if defined(ENABLE_HISTORY)
|
#if defined(ENABLE_HISTORY)
|
||||||
return mHistory.valueAt((HistoryStorageType)type, i);
|
return mHistory.valueAt((HistoryStorageType)type, i);
|
||||||
#else
|
#else
|
||||||
|
@ -318,7 +318,7 @@ class app : public IApp, public ah::Scheduler {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getHistoryMaxDay() {
|
uint16_t getHistoryMaxDay() override {
|
||||||
#if defined(ENABLE_HISTORY)
|
#if defined(ENABLE_HISTORY)
|
||||||
return mHistory.getMaximumDay();
|
return mHistory.getMaximumDay();
|
||||||
#else
|
#else
|
||||||
|
@ -372,11 +372,11 @@ class app : public IApp, public ah::Scheduler {
|
||||||
void tickNtpUpdate(void);
|
void tickNtpUpdate(void);
|
||||||
#if defined(ETHERNET)
|
#if defined(ETHERNET)
|
||||||
void onNtpUpdate(bool gotTime);
|
void onNtpUpdate(bool gotTime);
|
||||||
bool mNtpReceived;
|
bool mNtpReceived = false;
|
||||||
#endif /* defined(ETHERNET) */
|
#endif /* defined(ETHERNET) */
|
||||||
void updateNtp(void);
|
void updateNtp(void);
|
||||||
|
|
||||||
void triggerTickSend() {
|
void triggerTickSend() override {
|
||||||
once(std::bind(&app::tickSend, this), 0, "tSend");
|
once(std::bind(&app::tickSend, this), 0, "tSend");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +395,7 @@ class app : public IApp, public ah::Scheduler {
|
||||||
HmRadio<> mNrfRadio;
|
HmRadio<> mNrfRadio;
|
||||||
Communication mCommunication;
|
Communication mCommunication;
|
||||||
|
|
||||||
bool mShowRebootRequest;
|
bool mShowRebootRequest = false;
|
||||||
|
|
||||||
#if defined(ETHERNET)
|
#if defined(ETHERNET)
|
||||||
ahoyeth mEth;
|
ahoyeth mEth;
|
||||||
|
@ -404,7 +404,7 @@ class app : public IApp, public ah::Scheduler {
|
||||||
#endif /* defined(ETHERNET) */
|
#endif /* defined(ETHERNET) */
|
||||||
WebType mWeb;
|
WebType mWeb;
|
||||||
RestApiType mApi;
|
RestApiType mApi;
|
||||||
Protection *mProtection;
|
Protection *mProtection = nullptr;
|
||||||
#ifdef ENABLE_SYSLOG
|
#ifdef ENABLE_SYSLOG
|
||||||
DbgSyslog mDbgSyslog;
|
DbgSyslog mDbgSyslog;
|
||||||
#endif
|
#endif
|
||||||
|
@ -421,26 +421,26 @@ class app : public IApp, public ah::Scheduler {
|
||||||
char mVersion[12];
|
char mVersion[12];
|
||||||
char mVersionModules[12];
|
char mVersionModules[12];
|
||||||
settings mSettings;
|
settings mSettings;
|
||||||
settings_t *mConfig;
|
settings_t *mConfig = nullptr;
|
||||||
bool mSavePending;
|
bool mSavePending = false;
|
||||||
bool mSaveReboot;
|
bool mSaveReboot = false;
|
||||||
|
|
||||||
uint8_t mSendLastIvId;
|
uint8_t mSendLastIvId = 0;
|
||||||
bool mSendFirst;
|
bool mSendFirst = false;
|
||||||
bool mAllIvNotAvail;
|
bool mAllIvNotAvail = false;
|
||||||
|
|
||||||
bool mNetworkConnected;
|
bool mNetworkConnected = false;
|
||||||
|
|
||||||
// mqtt
|
// mqtt
|
||||||
#if defined(ENABLE_MQTT)
|
#if defined(ENABLE_MQTT)
|
||||||
PubMqttType mMqtt;
|
PubMqttType mMqtt;
|
||||||
#endif /*ENABLE_MQTT*/
|
#endif /*ENABLE_MQTT*/
|
||||||
bool mMqttReconnect;
|
bool mMqttReconnect = false;
|
||||||
bool mMqttEnabled;
|
bool mMqttEnabled = false;
|
||||||
|
|
||||||
// sun
|
// sun
|
||||||
int32_t mCalculatedTimezoneOffset;
|
int32_t mCalculatedTimezoneOffset = 0;
|
||||||
uint32_t mSunrise, mSunset;
|
uint32_t mSunrise = 0, mSunset = 0;
|
||||||
|
|
||||||
// plugins
|
// plugins
|
||||||
#if defined(PLUGIN_DISPLAY)
|
#if defined(PLUGIN_DISPLAY)
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
#include <algorithm>
|
||||||
#include <LittleFS.h>
|
#include <LittleFS.h>
|
||||||
|
|
||||||
#include "../defines.h"
|
#include "../defines.h"
|
||||||
|
@ -206,7 +207,7 @@ typedef struct {
|
||||||
class settings {
|
class settings {
|
||||||
public:
|
public:
|
||||||
settings() {
|
settings() {
|
||||||
mLastSaveSucceed = false;
|
std::fill(reinterpret_cast<char*>(&mCfg), reinterpret_cast<char*>(&mCfg) + sizeof(mCfg), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
@ -377,7 +378,7 @@ class settings {
|
||||||
memcpy(&tmp, &mCfg.sys, sizeof(cfgSys_t));
|
memcpy(&tmp, &mCfg.sys, sizeof(cfgSys_t));
|
||||||
}
|
}
|
||||||
// erase all settings and reset to default
|
// erase all settings and reset to default
|
||||||
memset(&mCfg, 0, sizeof(settings_t));
|
std::fill(reinterpret_cast<char*>(&mCfg), reinterpret_cast<char*>(&mCfg) + sizeof(mCfg), 0);
|
||||||
mCfg.sys.protectionMask = DEF_PROT_INDEX | DEF_PROT_LIVE | DEF_PROT_SERIAL | DEF_PROT_SETUP
|
mCfg.sys.protectionMask = DEF_PROT_INDEX | DEF_PROT_LIVE | DEF_PROT_SERIAL | DEF_PROT_SETUP
|
||||||
| DEF_PROT_UPDATE | DEF_PROT_SYSTEM | DEF_PROT_API | DEF_PROT_MQTT | DEF_PROT_HISTORY;
|
| DEF_PROT_UPDATE | DEF_PROT_SYSTEM | DEF_PROT_API | DEF_PROT_MQTT | DEF_PROT_HISTORY;
|
||||||
mCfg.sys.darkMode = false;
|
mCfg.sys.darkMode = false;
|
||||||
|
@ -847,7 +848,7 @@ class settings {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
settings_t mCfg;
|
settings_t mCfg;
|
||||||
bool mLastSaveSucceed;
|
bool mLastSaveSucceed = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*__SETTINGS_H__*/
|
#endif /*__SETTINGS_H__*/
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 8
|
#define VERSION_MINOR 8
|
||||||
#define VERSION_PATCH 73
|
#define VERSION_PATCH 74
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -91,7 +91,7 @@ class CommQueue {
|
||||||
inc(&mRdPtr);
|
inc(&mRdPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTs(uint32_t *ts) {
|
void setTs(const uint32_t *ts) {
|
||||||
mQueue[mRdPtr].ts = *ts;
|
mQueue[mRdPtr].ts = *ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#ifndef __COMMUNICATION_H__
|
#ifndef __COMMUNICATION_H__
|
||||||
#define __COMMUNICATION_H__
|
#define __COMMUNICATION_H__
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include "CommQueue.h"
|
#include "CommQueue.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../utils/crc.h"
|
#include "../utils/crc.h"
|
||||||
|
@ -194,7 +195,7 @@ class Communication : public CommQueue<> {
|
||||||
q->iv->radio->mBufCtrl.pop();
|
q->iv->radio->mBufCtrl.pop();
|
||||||
return; // don't wait for empty buffer
|
return; // don't wait for empty buffer
|
||||||
} else if(IV_MI == q->iv->ivGen) {
|
} else if(IV_MI == q->iv->ivGen) {
|
||||||
if(parseMiFrame(p, q))
|
parseMiFrame(p, q);
|
||||||
q->iv->curFrmCnt++;
|
q->iv->curFrmCnt++;
|
||||||
}
|
}
|
||||||
} //else -> serial does not match
|
} //else -> serial does not match
|
||||||
|
@ -385,7 +386,7 @@ class Communication : public CommQueue<> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool validateIvSerial(uint8_t buf[], Inverter<> *iv) {
|
inline bool validateIvSerial(const uint8_t buf[], Inverter<> *iv) {
|
||||||
uint8_t tmp[4];
|
uint8_t tmp[4];
|
||||||
CP_U32_BigEndian(tmp, iv->radioId.u64 >> 8);
|
CP_U32_BigEndian(tmp, iv->radioId.u64 >> 8);
|
||||||
for(uint8_t i = 0; i < 4; i++) {
|
for(uint8_t i = 0; i < 4; i++) {
|
||||||
|
@ -435,7 +436,7 @@ class Communication : public CommQueue<> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool parseMiFrame(packet_t *p, const queue_s *q) {
|
inline void parseMiFrame(packet_t *p, const queue_s *q) {
|
||||||
if((!mIsRetransmit && p->packet[9] == 0x00) && (p->millis < LIMIT_FAST_IV_MI)) //first frame is fast?
|
if((!mIsRetransmit && p->packet[9] == 0x00) && (p->millis < LIMIT_FAST_IV_MI)) //first frame is fast?
|
||||||
mHeu.setIvRetriesGood(q->iv,p->millis < LIMIT_VERYFAST_IV_MI);
|
mHeu.setIvRetriesGood(q->iv,p->millis < LIMIT_VERYFAST_IV_MI);
|
||||||
if ((p->packet[0] == MI_REQ_CH1 + ALL_FRAMES)
|
if ((p->packet[0] == MI_REQ_CH1 + ALL_FRAMES)
|
||||||
|
@ -458,11 +459,9 @@ class Communication : public CommQueue<> {
|
||||||
rec->ts = q->ts;
|
rec->ts = q->ts;
|
||||||
miStsConsolidate(q, ((p->packet[0] == 0x88) ? 1 : 2), rec, p->packet[10], p->packet[12], p->packet[9], p->packet[11]);
|
miStsConsolidate(q, ((p->packet[0] == 0x88) ? 1 : 2), rec, p->packet[10], p->packet[12], p->packet[9], p->packet[11]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool parseDevCtrl(packet_t *p, const queue_s *q) {
|
inline bool parseDevCtrl(const packet_t *p, const queue_s *q) {
|
||||||
switch(p->packet[12]) {
|
switch(p->packet[12]) {
|
||||||
case ActivePowerContr:
|
case ActivePowerContr:
|
||||||
if(p->packet[13] != 0x00)
|
if(p->packet[13] != 0x00)
|
||||||
|
@ -524,7 +523,7 @@ class Communication : public CommQueue<> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(mPayload, 0, MAX_BUFFER);
|
mPayload.fill(0);
|
||||||
int8_t rssi = -127;
|
int8_t rssi = -127;
|
||||||
uint8_t len = 0;
|
uint8_t len = 0;
|
||||||
|
|
||||||
|
@ -547,19 +546,19 @@ class Communication : public CommQueue<> {
|
||||||
DBGPRINT(String(len));
|
DBGPRINT(String(len));
|
||||||
if(*mPrintWholeTrace) {
|
if(*mPrintWholeTrace) {
|
||||||
DBGPRINT(F("): "));
|
DBGPRINT(F("): "));
|
||||||
ah::dumpBuf(mPayload, len);
|
ah::dumpBuf(mPayload.data(), len);
|
||||||
} else
|
} else
|
||||||
DBGPRINTLN(F(")"));
|
DBGPRINTLN(F(")"));
|
||||||
|
|
||||||
if(GridOnProFilePara == q->cmd) {
|
if(GridOnProFilePara == q->cmd) {
|
||||||
q->iv->addGridProfile(mPayload, len);
|
q->iv->addGridProfile(mPayload.data(), len);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
record_t<> *rec = q->iv->getRecordStruct(q->cmd);
|
record_t<> *rec = q->iv->getRecordStruct(q->cmd);
|
||||||
if(NULL == rec) {
|
if(NULL == rec) {
|
||||||
if(GetLossRate == q->cmd) {
|
if(GetLossRate == q->cmd) {
|
||||||
q->iv->parseGetLossRate(mPayload, len);
|
q->iv->parseGetLossRate(mPayload.data(), len);
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
DPRINTLN(DBG_ERROR, F("record is NULL!"));
|
DPRINTLN(DBG_ERROR, F("record is NULL!"));
|
||||||
|
@ -578,7 +577,7 @@ class Communication : public CommQueue<> {
|
||||||
|
|
||||||
rec->ts = q->ts;
|
rec->ts = q->ts;
|
||||||
for (uint8_t i = 0; i < rec->length; i++) {
|
for (uint8_t i = 0; i < rec->length; i++) {
|
||||||
q->iv->addValue(i, mPayload, rec);
|
q->iv->addValue(i, mPayload.data(), rec);
|
||||||
}
|
}
|
||||||
rec->mqttSentStatus = MqttSentStatus::NEW_DATA;
|
rec->mqttSentStatus = MqttSentStatus::NEW_DATA;
|
||||||
|
|
||||||
|
@ -588,7 +587,7 @@ class Communication : public CommQueue<> {
|
||||||
if(AlarmData == q->cmd) {
|
if(AlarmData == q->cmd) {
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
while(1) {
|
while(1) {
|
||||||
if(0 == q->iv->parseAlarmLog(i++, mPayload, len))
|
if(0 == q->iv->parseAlarmLog(i++, mPayload.data(), len))
|
||||||
break;
|
break;
|
||||||
if (NULL != mCbAlarm)
|
if (NULL != mCbAlarm)
|
||||||
(mCbAlarm)(q->iv);
|
(mCbAlarm)(q->iv);
|
||||||
|
@ -670,7 +669,7 @@ class Communication : public CommQueue<> {
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ( p->packet[9] == 0x00 ) {//first frame
|
if ( p->packet[9] == 0x00 ) { //first frame
|
||||||
//FLD_FW_VERSION
|
//FLD_FW_VERSION
|
||||||
for (uint8_t i = 0; i < 5; i++) {
|
for (uint8_t i = 0; i < 5; i++) {
|
||||||
q->iv->setValue(i, rec, (float) ((p->packet[(12+2*i)] << 8) + p->packet[(13+2*i)])/1);
|
q->iv->setValue(i, rec, (float) ((p->packet[(12+2*i)] << 8) + p->packet[(13+2*i)])/1);
|
||||||
|
@ -680,7 +679,7 @@ class Communication : public CommQueue<> {
|
||||||
DBGPRINT(F("HW_VER is "));
|
DBGPRINT(F("HW_VER is "));
|
||||||
DBGPRINTLN(String((p->packet[24] << 8) + p->packet[25]));
|
DBGPRINTLN(String((p->packet[24] << 8) + p->packet[25]));
|
||||||
}
|
}
|
||||||
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(1, rec, (uint32_t) ((p->packet[24] << 8) + p->packet[25])/1);
|
q->iv->setValue(1, rec, (uint32_t) ((p->packet[24] << 8) + p->packet[25])/1);
|
||||||
q->iv->miMultiParts +=4;
|
q->iv->miMultiParts +=4;
|
||||||
|
@ -894,7 +893,7 @@ class Communication : public CommQueue<> {
|
||||||
statusMi = 8310; //trick?
|
statusMi = 8310; //trick?
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t prntsts = statusMi == 3 ? 1 : statusMi;
|
uint16_t prntsts = (statusMi == 3) ? 1 : statusMi;
|
||||||
bool stsok = true;
|
bool stsok = true;
|
||||||
if ( prntsts != rec->record[q->iv->getPosByChFld(0, FLD_EVT, rec)] ) { //sth.'s changed?
|
if ( prntsts != rec->record[q->iv->getPosByChFld(0, FLD_EVT, rec)] ) { //sth.'s changed?
|
||||||
q->iv->alarmCnt = 1; // minimum...
|
q->iv->alarmCnt = 1; // minimum...
|
||||||
|
@ -1017,17 +1016,17 @@ class Communication : public CommQueue<> {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
States mState = States::RESET;
|
States mState = States::RESET;
|
||||||
uint32_t *mTimestamp;
|
uint32_t *mTimestamp = nullptr;
|
||||||
bool *mPrivacyMode, *mSerialDebug, *mPrintWholeTrace;
|
bool *mPrivacyMode = nullptr, *mSerialDebug = nullptr, *mPrintWholeTrace = nullptr;
|
||||||
TimeMonitor mWaitTime = TimeMonitor(0, true); // start as expired (due to code in RESET state)
|
TimeMonitor mWaitTime = TimeMonitor(0, true); // start as expired (due to code in RESET state)
|
||||||
std::array<frame_t, MAX_PAYLOAD_ENTRIES> mLocalBuf;
|
std::array<frame_t, MAX_PAYLOAD_ENTRIES> mLocalBuf;
|
||||||
bool mFirstTry = false; // see, if we should do a second try
|
bool mFirstTry = false; // see, if we should do a second try
|
||||||
bool mCompleteRetry = false; // remember if we did request a complete retransmission
|
bool mCompleteRetry = false; // remember if we did request a complete retransmission
|
||||||
bool mIsRetransmit = false; // we already had waited one complete cycle
|
bool mIsRetransmit = false; // we already had waited one complete cycle
|
||||||
uint8_t mMaxFrameId;
|
uint8_t mMaxFrameId = 0;
|
||||||
uint8_t mFramesExpected = 12; // 0x8c was highest last frame for alarm data
|
uint8_t mFramesExpected = 12; // 0x8c was highest last frame for alarm data
|
||||||
uint16_t mTimeout = 0; // calculating that once should be ok
|
uint16_t mTimeout = 0; // calculating that once should be ok
|
||||||
uint8_t mPayload[MAX_BUFFER];
|
std::array<uint8_t, MAX_BUFFER> mPayload;
|
||||||
payloadListenerType mCbPayload = NULL;
|
payloadListenerType mCbPayload = NULL;
|
||||||
powerLimitAckListenerType mCbPwrAck = NULL;
|
powerLimitAckListenerType mCbPwrAck = NULL;
|
||||||
alarmListenerType mCbAlarm = NULL;
|
alarmListenerType mCbAlarm = NULL;
|
||||||
|
|
|
@ -157,7 +157,7 @@ class Heuristic {
|
||||||
DBGPRINTLN(String(iv->config->powerLevel));
|
DBGPRINTLN(String(iv->config->powerLevel));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getIvRetries(Inverter<> *iv) {
|
uint8_t getIvRetries(const Inverter<> *iv) const {
|
||||||
if(iv->heuristics.rxSpeeds[0])
|
if(iv->heuristics.rxSpeeds[0])
|
||||||
return RETRIES_VERYFAST_IV;
|
return RETRIES_VERYFAST_IV;
|
||||||
if(iv->heuristics.rxSpeeds[1])
|
if(iv->heuristics.rxSpeeds[1])
|
||||||
|
@ -200,7 +200,7 @@ class Heuristic {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isNewTxCh(HeuristicInv *ih) {
|
bool isNewTxCh(const HeuristicInv *ih) const {
|
||||||
return ih->txRfChId != ih->lastBestTxChId;
|
return ih->txRfChId != ih->lastBestTxChId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,9 +222,6 @@ class Heuristic {
|
||||||
}
|
}
|
||||||
return 3; // standard
|
return 3; // standard
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
uint8_t mChList[5] = {03, 23, 40, 61, 75};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ enum {CMD_CALC = 0xffff};
|
||||||
enum {CH0 = 0, CH1, CH2, CH3, CH4, CH5, CH6};
|
enum {CH0 = 0, CH1, CH2, CH3, CH4, CH5, CH6};
|
||||||
|
|
||||||
enum {INV_TYPE_1CH = 0, INV_TYPE_2CH, INV_TYPE_4CH, INV_TYPE_6CH};
|
enum {INV_TYPE_1CH = 0, INV_TYPE_2CH, INV_TYPE_4CH, INV_TYPE_6CH};
|
||||||
enum {INV_RADIO_TYPE_NRF = 0, INV_RADIO_TYPE_CMT};
|
enum {INV_RADIO_TYPE_UNKNOWN = 0, INV_RADIO_TYPE_NRF, INV_RADIO_TYPE_CMT};
|
||||||
|
|
||||||
|
|
||||||
#define DURATION_ONEFRAME 50 // timeout parameter for each expected frame (ms)
|
#define DURATION_ONEFRAME 50 // timeout parameter for each expected frame (ms)
|
||||||
|
|
|
@ -81,12 +81,12 @@ enum class InverterStatus : uint8_t {
|
||||||
|
|
||||||
template<class T=float>
|
template<class T=float>
|
||||||
struct record_t {
|
struct record_t {
|
||||||
byteAssign_t* assign; // assignment of bytes in payload
|
byteAssign_t* assign = nullptr; // assignment of bytes in payload
|
||||||
uint8_t length; // length of the assignment list
|
uint8_t length = 0; // length of the assignment list
|
||||||
T *record; // data pointer
|
T *record = nullptr; // data pointer
|
||||||
uint32_t ts; // timestamp of last received payload
|
uint32_t ts = 0; // timestamp of last received payload
|
||||||
uint8_t pyldLen; // expected payload length for plausibility check
|
uint8_t pyldLen = 0; // expected payload length for plausibility check
|
||||||
MqttSentStatus mqttSentStatus; // indicates the current MqTT sent status
|
MqttSentStatus mqttSentStatus = MqttSentStatus:: NEW_DATA; // indicates the current MqTT sent status
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alarm_t {
|
struct alarm_t {
|
||||||
|
@ -113,42 +113,42 @@ const calcFunc_t<T> calcFunctions[] = {
|
||||||
template <class REC_TYP>
|
template <class REC_TYP>
|
||||||
class Inverter {
|
class Inverter {
|
||||||
public:
|
public:
|
||||||
uint8_t ivGen; // generation of inverter (HM / MI)
|
uint8_t ivGen = IV_UNKNOWN; // generation of inverter (HM / MI)
|
||||||
uint8_t ivRadioType; // refers to used radio (nRF24 / CMT)
|
uint8_t ivRadioType = INV_RADIO_TYPE_UNKNOWN; // refers to used radio (nRF24 / CMT)
|
||||||
cfgIv_t *config; // stored settings
|
cfgIv_t *config = nullptr; // stored settings
|
||||||
uint8_t id; // unique id
|
uint8_t id = 0; // unique id
|
||||||
uint8_t type; // integer which refers to inverter type
|
uint8_t type = INV_TYPE_1CH; // integer which refers to inverter type
|
||||||
uint16_t alarmMesIndex; // Last recorded Alarm Message Index
|
uint16_t alarmMesIndex = 0; // Last recorded Alarm Message Index
|
||||||
uint16_t powerLimit[2]; // limit power output (multiplied by 10)
|
uint16_t powerLimit[2] = {0xffff, AbsolutNonPersistent}; // limit power output (multiplied by 10)
|
||||||
float actPowerLimit; // actual power limit
|
float actPowerLimit = -1; // actual power limit
|
||||||
bool powerLimitAck; // acknowledged power limit (default: false)
|
bool powerLimitAck = false; // acknowledged power limit
|
||||||
uint8_t devControlCmd; // carries the requested cmd
|
uint8_t devControlCmd = InitDataState; // carries the requested cmd
|
||||||
serial_u radioId; // id converted to modbus
|
serial_u radioId; // id converted to modbus
|
||||||
uint8_t channels; // number of PV channels (1-4)
|
uint8_t channels = 1; // number of PV channels (1-4)
|
||||||
record_t<REC_TYP> recordMeas; // structure for measured values
|
record_t<REC_TYP> recordMeas; // structure for measured values
|
||||||
record_t<REC_TYP> recordInfo; // structure for info values
|
record_t<REC_TYP> recordInfo; // structure for info values
|
||||||
record_t<REC_TYP> recordHwInfo; // structure for simple (hardware) info values
|
record_t<REC_TYP> recordHwInfo; // structure for simple (hardware) info values
|
||||||
record_t<REC_TYP> recordConfig; // structure for system config values
|
record_t<REC_TYP> recordConfig; // structure for system config values
|
||||||
record_t<REC_TYP> recordAlarm; // structure for alarm values
|
record_t<REC_TYP> recordAlarm; // structure for alarm values
|
||||||
InverterStatus status; // indicates the current inverter status
|
InverterStatus status = InverterStatus::OFF; // indicates the current inverter status
|
||||||
std::array<alarm_t, 10> lastAlarm; // holds last 10 alarms
|
std::array<alarm_t, 10> lastAlarm; // holds last 10 alarms
|
||||||
uint8_t rxOffset; // holds the default channel offset between tx and rx channel (nRF only)
|
uint8_t rxOffset = 0; // holds the default channel offset between tx and rx channel (nRF only)
|
||||||
int8_t rssi; // RSSI
|
int8_t rssi = 0; // RSSI
|
||||||
uint16_t alarmCnt; // counts the total number of occurred alarms
|
uint16_t alarmCnt = 0; // counts the total number of occurred alarms
|
||||||
uint16_t alarmLastId; // lastId which was received
|
uint16_t alarmLastId = 0; // lastId which was received
|
||||||
uint8_t mCmd; // holds the command to send
|
uint8_t mCmd = InitDataState; // holds the command to send
|
||||||
bool mGotFragment; // shows if inverter has sent at least one fragment
|
bool mGotFragment = false; // shows if inverter has sent at least one fragment
|
||||||
uint8_t miMultiParts; // helper info for MI multiframe msgs
|
uint8_t miMultiParts = 0; // helper info for MI multiframe msgs
|
||||||
uint8_t outstandingFrames; // helper info to count difference between expected and received frames
|
uint8_t outstandingFrames = 0; // helper info to count difference between expected and received frames
|
||||||
uint8_t curFrmCnt; // count received frames in current loop
|
uint8_t curFrmCnt = 0; // count received frames in current loop
|
||||||
bool mGotLastMsg; // shows if inverter has already finished transmission cycle
|
bool mGotLastMsg = false; // shows if inverter has already finished transmission cycle
|
||||||
bool mIsSingleframeReq; // indicates this is a missing single frame request
|
bool mIsSingleframeReq = false; // indicates this is a missing single frame request
|
||||||
Radio *radio; // pointer to associated radio class
|
Radio *radio = nullptr; // pointer to associated radio class
|
||||||
statistics_t radioStatistics; // information about transmitted, failed, ... packets
|
statistics_t radioStatistics; // information about transmitted, failed, ... packets
|
||||||
HeuristicInv heuristics; // heuristic information / logic
|
HeuristicInv heuristics; // heuristic information / logic
|
||||||
uint8_t curCmtFreq; // current used CMT frequency, used to check if freq. was changed during runtime
|
uint8_t curCmtFreq = 0; // current used CMT frequency, used to check if freq. was changed during runtime
|
||||||
bool commEnabled; // 'pause night communication' sets this field to false
|
uint32_t tsMaxAcPower = 0; // holds the timestamp when the MaxAC power was seen
|
||||||
uint32_t tsMaxAcPower; // holds the timestamp when the MaxAC power was seen
|
bool commEnabled = true; // 'pause night communication' sets this field to false
|
||||||
|
|
||||||
static uint32_t *timestamp; // system timestamp
|
static uint32_t *timestamp; // system timestamp
|
||||||
static cfgInst_t *generalConfig; // general inverter configuration from setup
|
static cfgInst_t *generalConfig; // general inverter configuration from setup
|
||||||
|
@ -156,29 +156,10 @@ class Inverter {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Inverter() {
|
Inverter() {
|
||||||
ivGen = IV_HM;
|
|
||||||
powerLimit[0] = 0xffff; // 6553.5 W Limit -> unlimited
|
|
||||||
powerLimit[1] = AbsolutNonPersistent; // default power limit setting
|
|
||||||
powerLimitAck = false;
|
|
||||||
actPowerLimit = 0xffff; // init feedback from inverter to -1
|
|
||||||
mDevControlRequest = false;
|
|
||||||
devControlCmd = InitDataState;
|
|
||||||
alarmMesIndex = 0;
|
|
||||||
status = InverterStatus::OFF;
|
|
||||||
alarmCnt = 0;
|
|
||||||
alarmLastId = 0;
|
|
||||||
rssi = -127;
|
|
||||||
miMultiParts = 0;
|
|
||||||
mGotLastMsg = false;
|
|
||||||
mCmd = InitDataState;
|
|
||||||
mIsSingleframeReq = false;
|
|
||||||
radio = NULL;
|
|
||||||
commEnabled = true;
|
|
||||||
tsMaxAcPower = 0;
|
|
||||||
|
|
||||||
memset(&radioStatistics, 0, sizeof(statistics_t));
|
memset(&radioStatistics, 0, sizeof(statistics_t));
|
||||||
memset(mOffYD, 0, sizeof(float) * 6);
|
memset(mOffYD, 0, sizeof(float) * 6);
|
||||||
memset(mLastYD, 0, sizeof(float) * 6);
|
memset(mLastYD, 0, sizeof(float) * 6);
|
||||||
|
mGridProfile.fill(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tickSend(std::function<void(uint8_t cmd, bool isDevControl)> cb) {
|
void tickSend(std::function<void(uint8_t cmd, bool isDevControl)> cb) {
|
||||||
|
@ -255,8 +236,8 @@ class Inverter {
|
||||||
|
|
||||||
uint8_t getPosByChFld(uint8_t channel, uint8_t fieldId, record_t<> *rec) {
|
uint8_t getPosByChFld(uint8_t channel, uint8_t fieldId, record_t<> *rec) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getPosByChFld"));
|
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getPosByChFld"));
|
||||||
uint8_t pos = 0;
|
|
||||||
if(NULL != rec) {
|
if(NULL != rec) {
|
||||||
|
uint8_t pos = 0;
|
||||||
for(; pos < rec->length; pos++) {
|
for(; pos < rec->length; pos++) {
|
||||||
if((rec->assign[pos].ch == channel) && (rec->assign[pos].fieldId == fieldId))
|
if((rec->assign[pos].ch == channel) && (rec->assign[pos].fieldId == fieldId))
|
||||||
break;
|
break;
|
||||||
|
@ -303,7 +284,7 @@ class Inverter {
|
||||||
return (InverterStatus::OFF != status);
|
return (InverterStatus::OFF != status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addValue(uint8_t pos, uint8_t buf[], record_t<> *rec) {
|
void addValue(uint8_t pos, const uint8_t buf[], record_t<> *rec) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:addValue"));
|
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:addValue"));
|
||||||
if(NULL != rec) {
|
if(NULL != rec) {
|
||||||
uint8_t ptr = rec->assign[pos].start;
|
uint8_t ptr = rec->assign[pos].start;
|
||||||
|
@ -387,8 +368,8 @@ class Inverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
REC_TYP getChannelFieldValue(uint8_t channel, uint8_t fieldId, record_t<> *rec) {
|
REC_TYP getChannelFieldValue(uint8_t channel, uint8_t fieldId, record_t<> *rec) {
|
||||||
uint8_t pos = 0;
|
|
||||||
if(NULL != rec) {
|
if(NULL != rec) {
|
||||||
|
uint8_t pos = 0;
|
||||||
for(; pos < rec->length; pos++) {
|
for(; pos < rec->length; pos++) {
|
||||||
if((rec->assign[pos].ch == channel) && (rec->assign[pos].fieldId == fieldId))
|
if((rec->assign[pos].ch == channel) && (rec->assign[pos].fieldId == fieldId))
|
||||||
break;
|
break;
|
||||||
|
@ -529,11 +510,11 @@ class Inverter {
|
||||||
if (INV_TYPE_1CH == type) {
|
if (INV_TYPE_1CH == type) {
|
||||||
if((IV_HM == ivGen) || (IV_MI == ivGen)) {
|
if((IV_HM == ivGen) || (IV_MI == ivGen)) {
|
||||||
rec->length = (uint8_t)(HM1CH_LIST_LEN);
|
rec->length = (uint8_t)(HM1CH_LIST_LEN);
|
||||||
rec->assign = (byteAssign_t *)hm1chAssignment;
|
rec->assign = reinterpret_cast<byteAssign_t*>(const_cast<byteAssign_t*>(hm1chAssignment));
|
||||||
rec->pyldLen = HM1CH_PAYLOAD_LEN;
|
rec->pyldLen = HM1CH_PAYLOAD_LEN;
|
||||||
} else if(IV_HMS == ivGen) {
|
} else if(IV_HMS == ivGen) {
|
||||||
rec->length = (uint8_t)(HMS1CH_LIST_LEN);
|
rec->length = (uint8_t)(HMS1CH_LIST_LEN);
|
||||||
rec->assign = (byteAssign_t *)hms1chAssignment;
|
rec->assign = reinterpret_cast<byteAssign_t*>(const_cast<byteAssign_t*>(hms1chAssignment));
|
||||||
rec->pyldLen = HMS1CH_PAYLOAD_LEN;
|
rec->pyldLen = HMS1CH_PAYLOAD_LEN;
|
||||||
}
|
}
|
||||||
channels = 1;
|
channels = 1;
|
||||||
|
@ -541,11 +522,11 @@ class Inverter {
|
||||||
else if (INV_TYPE_2CH == type) {
|
else if (INV_TYPE_2CH == type) {
|
||||||
if((IV_HM == ivGen) || (IV_MI == ivGen)) {
|
if((IV_HM == ivGen) || (IV_MI == ivGen)) {
|
||||||
rec->length = (uint8_t)(HM2CH_LIST_LEN);
|
rec->length = (uint8_t)(HM2CH_LIST_LEN);
|
||||||
rec->assign = (byteAssign_t *)hm2chAssignment;
|
rec->assign = reinterpret_cast<byteAssign_t*>(const_cast<byteAssign_t*>(hm2chAssignment));
|
||||||
rec->pyldLen = HM2CH_PAYLOAD_LEN;
|
rec->pyldLen = HM2CH_PAYLOAD_LEN;
|
||||||
} else if(IV_HMS == ivGen) {
|
} else if(IV_HMS == ivGen) {
|
||||||
rec->length = (uint8_t)(HMS2CH_LIST_LEN);
|
rec->length = (uint8_t)(HMS2CH_LIST_LEN);
|
||||||
rec->assign = (byteAssign_t *)hms2chAssignment;
|
rec->assign = reinterpret_cast<byteAssign_t*>(const_cast<byteAssign_t*>(hms2chAssignment));
|
||||||
rec->pyldLen = HMS2CH_PAYLOAD_LEN;
|
rec->pyldLen = HMS2CH_PAYLOAD_LEN;
|
||||||
}
|
}
|
||||||
channels = 2;
|
channels = 2;
|
||||||
|
@ -553,18 +534,18 @@ class Inverter {
|
||||||
else if (INV_TYPE_4CH == type) {
|
else if (INV_TYPE_4CH == type) {
|
||||||
if((IV_HM == ivGen) || (IV_MI == ivGen)) {
|
if((IV_HM == ivGen) || (IV_MI == ivGen)) {
|
||||||
rec->length = (uint8_t)(HM4CH_LIST_LEN);
|
rec->length = (uint8_t)(HM4CH_LIST_LEN);
|
||||||
rec->assign = (byteAssign_t *)hm4chAssignment;
|
rec->assign = reinterpret_cast<byteAssign_t*>(const_cast<byteAssign_t*>(hm4chAssignment));
|
||||||
rec->pyldLen = HM4CH_PAYLOAD_LEN;
|
rec->pyldLen = HM4CH_PAYLOAD_LEN;
|
||||||
} else if(IV_HMS == ivGen) {
|
} else if(IV_HMS == ivGen) {
|
||||||
rec->length = (uint8_t)(HMS4CH_LIST_LEN);
|
rec->length = (uint8_t)(HMS4CH_LIST_LEN);
|
||||||
rec->assign = (byteAssign_t *)hms4chAssignment;
|
rec->assign = reinterpret_cast<byteAssign_t*>(const_cast<byteAssign_t*>(hms4chAssignment));
|
||||||
rec->pyldLen = HMS4CH_PAYLOAD_LEN;
|
rec->pyldLen = HMS4CH_PAYLOAD_LEN;
|
||||||
}
|
}
|
||||||
channels = 4;
|
channels = 4;
|
||||||
}
|
}
|
||||||
else if (INV_TYPE_6CH == type) {
|
else if (INV_TYPE_6CH == type) {
|
||||||
rec->length = (uint8_t)(HMT6CH_LIST_LEN);
|
rec->length = (uint8_t)(HMT6CH_LIST_LEN);
|
||||||
rec->assign = (byteAssign_t *)hmt6chAssignment;
|
rec->assign = reinterpret_cast<byteAssign_t*>(const_cast<byteAssign_t*>(hmt6chAssignment));
|
||||||
rec->pyldLen = HMT6CH_PAYLOAD_LEN;
|
rec->pyldLen = HMT6CH_PAYLOAD_LEN;
|
||||||
channels = 6;
|
channels = 6;
|
||||||
}
|
}
|
||||||
|
@ -577,22 +558,22 @@ class Inverter {
|
||||||
break;
|
break;
|
||||||
case InverterDevInform_All:
|
case InverterDevInform_All:
|
||||||
rec->length = (uint8_t)(HMINFO_LIST_LEN);
|
rec->length = (uint8_t)(HMINFO_LIST_LEN);
|
||||||
rec->assign = (byteAssign_t *)InfoAssignment;
|
rec->assign = reinterpret_cast<byteAssign_t*>(const_cast<byteAssign_t*>(InfoAssignment));
|
||||||
rec->pyldLen = HMINFO_PAYLOAD_LEN;
|
rec->pyldLen = HMINFO_PAYLOAD_LEN;
|
||||||
break;
|
break;
|
||||||
case InverterDevInform_Simple:
|
case InverterDevInform_Simple:
|
||||||
rec->length = (uint8_t)(HMSIMPLE_INFO_LIST_LEN);
|
rec->length = (uint8_t)(HMSIMPLE_INFO_LIST_LEN);
|
||||||
rec->assign = (byteAssign_t *)SimpleInfoAssignment;
|
rec->assign = reinterpret_cast<byteAssign_t*>(const_cast<byteAssign_t*>(SimpleInfoAssignment));
|
||||||
rec->pyldLen = HMSIMPLE_INFO_PAYLOAD_LEN;
|
rec->pyldLen = HMSIMPLE_INFO_PAYLOAD_LEN;
|
||||||
break;
|
break;
|
||||||
case SystemConfigPara:
|
case SystemConfigPara:
|
||||||
rec->length = (uint8_t)(HMSYSTEM_LIST_LEN);
|
rec->length = (uint8_t)(HMSYSTEM_LIST_LEN);
|
||||||
rec->assign = (byteAssign_t *)SystemConfigParaAssignment;
|
rec->assign = reinterpret_cast<byteAssign_t*>(const_cast<byteAssign_t*>(SystemConfigParaAssignment));
|
||||||
rec->pyldLen = HMSYSTEM_PAYLOAD_LEN;
|
rec->pyldLen = HMSYSTEM_PAYLOAD_LEN;
|
||||||
break;
|
break;
|
||||||
case AlarmData:
|
case AlarmData:
|
||||||
rec->length = (uint8_t)(HMALARMDATA_LIST_LEN);
|
rec->length = (uint8_t)(HMALARMDATA_LIST_LEN);
|
||||||
rec->assign = (byteAssign_t *)AlarmDataAssignment;
|
rec->assign = reinterpret_cast<byteAssign_t*>(const_cast<byteAssign_t*>(AlarmDataAssignment));
|
||||||
rec->pyldLen = HMALARMDATA_PAYLOAD_LEN;
|
rec->pyldLen = HMALARMDATA_PAYLOAD_LEN;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -616,7 +597,7 @@ class Inverter {
|
||||||
memset(mLastYD, 0, sizeof(float) * 6);
|
memset(mLastYD, 0, sizeof(float) * 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseGetLossRate(uint8_t pyld[], uint8_t len) {
|
bool parseGetLossRate(const uint8_t pyld[], uint8_t len) {
|
||||||
if (len == HMGETLOSSRATE_PAYLOAD_LEN) {
|
if (len == HMGETLOSSRATE_PAYLOAD_LEN) {
|
||||||
uint16_t rxCnt = (pyld[0] << 8) + pyld[1];
|
uint16_t rxCnt = (pyld[0] << 8) + pyld[1];
|
||||||
uint16_t txCnt = (pyld[2] << 8) + pyld[3];
|
uint16_t txCnt = (pyld[2] << 8) + pyld[3];
|
||||||
|
@ -815,7 +796,7 @@ class Inverter {
|
||||||
|
|
||||||
void addGridProfile(uint8_t buf[], uint8_t length) {
|
void addGridProfile(uint8_t buf[], uint8_t length) {
|
||||||
mGridLen = (length > MAX_GRID_LENGTH) ? MAX_GRID_LENGTH : length;
|
mGridLen = (length > MAX_GRID_LENGTH) ? MAX_GRID_LENGTH : length;
|
||||||
std::copy(buf, &buf[mGridLen], mGridProfile);
|
std::copy(buf, &buf[mGridLen], mGridProfile.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
String getGridProfile(void) {
|
String getGridProfile(void) {
|
||||||
|
@ -847,9 +828,9 @@ class Inverter {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float mOffYD[6], mLastYD[6];
|
float mOffYD[6], mLastYD[6];
|
||||||
bool mDevControlRequest; // true if change needed
|
bool mDevControlRequest = false; // true if change needed
|
||||||
uint8_t mGridLen = 0;
|
uint8_t mGridLen = 0;
|
||||||
uint8_t mGridProfile[MAX_GRID_LENGTH];
|
std::array<uint8_t, MAX_GRID_LENGTH> mGridProfile;
|
||||||
uint8_t mAlarmNxtWrPos = 0; // indicates the position in array (rolling buffer)
|
uint8_t mAlarmNxtWrPos = 0; // indicates the position in array (rolling buffer)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -52,7 +52,7 @@ class HmRadio : public Radio {
|
||||||
mPrintWholeTrace = printWholeTrace;
|
mPrintWholeTrace = printWholeTrace;
|
||||||
|
|
||||||
generateDtuSn();
|
generateDtuSn();
|
||||||
DTU_RADIO_ID = ((uint64_t)(((mDtuSn >> 24) & 0xFF) | ((mDtuSn >> 8) & 0xFF00) | ((mDtuSn << 8) & 0xFF0000) | ((mDtuSn << 24) & 0xFF000000)) << 8) | 0x01;
|
mDtuRadioId = ((uint64_t)(((mDtuSn >> 24) & 0xFF) | ((mDtuSn >> 8) & 0xFF00) | ((mDtuSn << 8) & 0xFF0000) | ((mDtuSn << 24) & 0xFF000000)) << 8) | 0x01;
|
||||||
|
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL)
|
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL)
|
||||||
|
@ -85,7 +85,7 @@ class HmRadio : public Radio {
|
||||||
mNrf24->enableDynamicPayloads();
|
mNrf24->enableDynamicPayloads();
|
||||||
mNrf24->setCRCLength(RF24_CRC_16);
|
mNrf24->setCRCLength(RF24_CRC_16);
|
||||||
mNrf24->setAddressWidth(5);
|
mNrf24->setAddressWidth(5);
|
||||||
mNrf24->openReadingPipe(1, reinterpret_cast<uint8_t*>(&DTU_RADIO_ID));
|
mNrf24->openReadingPipe(1, reinterpret_cast<uint8_t*>(&mDtuRadioId));
|
||||||
mNrf24->maskIRQ(false, false, false); // enable all receiving interrupts
|
mNrf24->maskIRQ(false, false, false); // enable all receiving interrupts
|
||||||
mNrf24->setPALevel(1); // low is default
|
mNrf24->setPALevel(1); // low is default
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ class HmRadio : public Radio {
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if communication is active
|
// returns true if communication is active
|
||||||
bool loop(void) {
|
bool loop(void) override {
|
||||||
if (!mIrqRcvd && !mNRFisInRX)
|
if (!mIrqRcvd && !mNRFisInRX)
|
||||||
return false; // first quick check => nothing to do at all here
|
return false; // first quick check => nothing to do at all here
|
||||||
|
|
||||||
|
@ -198,11 +198,11 @@ class HmRadio : public Radio {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isChipConnected(void) const {
|
bool isChipConnected(void) const override {
|
||||||
return mNrf24->isChipConnected();
|
return mNrf24->isChipConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) {
|
void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) override {
|
||||||
DPRINT_IVID(DBG_INFO, iv->id);
|
DPRINT_IVID(DBG_INFO, iv->id);
|
||||||
DBGPRINT(F("sendControlPacket cmd: "));
|
DBGPRINT(F("sendControlPacket cmd: "));
|
||||||
DBGHEXLN(cmd);
|
DBGHEXLN(cmd);
|
||||||
|
@ -423,15 +423,15 @@ class HmRadio : public Radio {
|
||||||
mNRFisInRX = false;
|
mNRFisInRX = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t getIvId(Inverter<> *iv) const {
|
uint64_t getIvId(Inverter<> *iv) const override {
|
||||||
return iv->radioId.u64;
|
return iv->radioId.u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getIvGen(Inverter<> *iv) const {
|
uint8_t getIvGen(Inverter<> *iv) const override {
|
||||||
return iv->ivGen;
|
return iv->ivGen;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool checkIvSerial(uint8_t buf[], Inverter<> *iv) {
|
inline bool checkIvSerial(const uint8_t buf[], Inverter<> *iv) {
|
||||||
for(uint8_t i = 1; i < 5; i++) {
|
for(uint8_t i = 1; i < 5; i++) {
|
||||||
if(buf[i] != iv->radioId.b[i])
|
if(buf[i] != iv->radioId.b[i])
|
||||||
return false;
|
return false;
|
||||||
|
@ -439,14 +439,14 @@ class HmRadio : public Radio {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DTU_RADIO_ID;
|
uint64_t mDtuRadioId = 0ULL;
|
||||||
uint8_t mRfChLst[RF_CHANNELS] = {03, 23, 40, 61, 75}; // channel List:2403, 2423, 2440, 2461, 2475MHz
|
const uint8_t mRfChLst[RF_CHANNELS] = {03, 23, 40, 61, 75}; // channel List:2403, 2423, 2440, 2461, 2475MHz
|
||||||
uint8_t mTxChIdx = 0;
|
uint8_t mTxChIdx = 0;
|
||||||
uint8_t mRxChIdx = 0;
|
uint8_t mRxChIdx = 0;
|
||||||
uint8_t tempRxChIdx = mRxChIdx;
|
uint8_t tempRxChIdx = 0;
|
||||||
bool mGotLastMsg = false;
|
bool mGotLastMsg = false;
|
||||||
uint32_t mMillis;
|
uint32_t mMillis = 0;
|
||||||
bool tx_ok, tx_fail, rx_ready = false;
|
bool tx_ok = false, tx_fail = false, rx_ready = false;
|
||||||
unsigned long mTimeslotStart = 0;
|
unsigned long mTimeslotStart = 0;
|
||||||
unsigned long mLastIrqTime = 0;
|
unsigned long mLastIrqTime = 0;
|
||||||
bool mNRFloopChannels = false;
|
bool mNRFloopChannels = false;
|
||||||
|
@ -454,7 +454,6 @@ class HmRadio : public Radio {
|
||||||
bool isRxInit = true;
|
bool isRxInit = true;
|
||||||
bool mRxPendular = false;
|
bool mRxPendular = false;
|
||||||
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN;
|
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN;
|
||||||
//uint8_t mTxSetupTime = 0;
|
|
||||||
uint8_t mTxRetries = 15; // memorize last setting for mNrf24->setRetries(3, 15);
|
uint8_t mTxRetries = 15; // memorize last setting for mNrf24->setRetries(3, 15);
|
||||||
|
|
||||||
std::unique_ptr<SPIClass> mSpi;
|
std::unique_ptr<SPIClass> mSpi;
|
||||||
|
|
|
@ -98,35 +98,33 @@ class HmSystem {
|
||||||
#ifdef DYNAMIC_OFFSET
|
#ifdef DYNAMIC_OFFSET
|
||||||
iv->rxOffset = (iv->ivGen == IV_HM) ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting
|
iv->rxOffset = (iv->ivGen == IV_HM) ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting
|
||||||
#else
|
#else
|
||||||
iv->rxOffset = ((iv->ivGen == IV_HM) && (iv->type == INV_TYPE_4CH)) ? 3 : 2;
|
//iv->rxOffset = ((iv->ivGen == IV_HM) && (iv->type == INV_TYPE_4CH)) ? 3 : 2;
|
||||||
iv->rxOffset = (iv->ivGen == IV_HM) ? 3 : 2;
|
iv->rxOffset = (iv->ivGen == IV_HM) ? 3 : 2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cb(iv);
|
cb(iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
INVERTERTYPE *findInverter(uint8_t buf[]) {
|
INVERTERTYPE *findInverter(const uint8_t buf[]) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("hmSystem.h:findInverter"));
|
|
||||||
INVERTERTYPE *p;
|
|
||||||
for(uint8_t i = 0; i < MAX_INVERTER; i++) {
|
for(uint8_t i = 0; i < MAX_INVERTER; i++) {
|
||||||
p = &mInverter[i];
|
INVERTERTYPE *p = &mInverter[i];
|
||||||
if((p->config->serial.b[3] == buf[0])
|
if((p->config->serial.b[3] == buf[0])
|
||||||
&& (p->config->serial.b[2] == buf[1])
|
&& (p->config->serial.b[2] == buf[1])
|
||||||
&& (p->config->serial.b[1] == buf[2])
|
&& (p->config->serial.b[1] == buf[2])
|
||||||
&& (p->config->serial.b[0] == buf[3]))
|
&& (p->config->serial.b[0] == buf[3]))
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
INVERTERTYPE *getInverterByPos(uint8_t pos, bool check = true) {
|
INVERTERTYPE *getInverterByPos(uint8_t pos, bool check = true) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("hmSystem.h:getInverterByPos"));
|
DPRINTLN(DBG_VERBOSE, F("hmSystem.h:getInverterByPos"));
|
||||||
if(pos >= MAX_INVERTER)
|
if(pos >= MAX_INVERTER)
|
||||||
return NULL;
|
return nullptr;
|
||||||
else if((mInverter[pos].config->serial.u64 != 0ULL) || (false == check))
|
else if((mInverter[pos].config->serial.u64 != 0ULL) || (false == check))
|
||||||
return &mInverter[pos];
|
return &mInverter[pos];
|
||||||
else
|
else
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getNumInverters(void) {
|
uint8_t getNumInverters(void) {
|
||||||
|
|
|
@ -142,7 +142,7 @@ class nrfHal: public RF24_hal, public SpiPatcherHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t read(uint8_t cmd, uint8_t* buf, uint8_t len) override {
|
uint8_t read(uint8_t cmd, uint8_t* buf, uint8_t len) override {
|
||||||
uint8_t data[NRF_MAX_TRANSFER_SZ];
|
uint8_t data[NRF_MAX_TRANSFER_SZ + 1];
|
||||||
data[0] = cmd;
|
data[0] = cmd;
|
||||||
if(len > NRF_MAX_TRANSFER_SZ)
|
if(len > NRF_MAX_TRANSFER_SZ)
|
||||||
len = NRF_MAX_TRANSFER_SZ;
|
len = NRF_MAX_TRANSFER_SZ;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#define ALL_FRAMES 0x80
|
#define ALL_FRAMES 0x80
|
||||||
#define SINGLE_FRAME 0x81
|
#define SINGLE_FRAME 0x81
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include "../utils/dbg.h"
|
#include "../utils/dbg.h"
|
||||||
#include "../utils/crc.h"
|
#include "../utils/crc.h"
|
||||||
#include "../utils/timemonitor.h"
|
#include "../utils/timemonitor.h"
|
||||||
|
@ -119,9 +120,8 @@ class Radio {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mDtuSn = 0;
|
mDtuSn = 0;
|
||||||
uint8_t t;
|
|
||||||
for(int i = 0; i < (7 << 2); i += 4) {
|
for(int i = 0; i < (7 << 2); i += 4) {
|
||||||
t = (chipID >> i) & 0x0f;
|
uint8_t t = (chipID >> i) & 0x0f;
|
||||||
if(t > 0x09)
|
if(t > 0x09)
|
||||||
t -= 6;
|
t -= 6;
|
||||||
mDtuSn |= (t << i);
|
mDtuSn |= (t << i);
|
||||||
|
@ -132,8 +132,8 @@ class Radio {
|
||||||
|
|
||||||
|
|
||||||
uint32_t mDtuSn;
|
uint32_t mDtuSn;
|
||||||
volatile bool mIrqRcvd;
|
std::atomic<bool> mIrqRcvd;
|
||||||
bool *mSerialDebug, *mPrivacyMode, *mPrintWholeTrace;
|
bool *mSerialDebug = nullptr, *mPrivacyMode = nullptr, *mPrintWholeTrace = nullptr;
|
||||||
uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE];
|
uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -529,7 +529,8 @@ class Cmt2300a {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool switchDtuFreq(const uint32_t freqKhz) {
|
// maybe used in future
|
||||||
|
/*inline bool switchDtuFreq(const uint32_t freqKhz) {
|
||||||
uint8_t toCh = freq2Chan(freqKhz);
|
uint8_t toCh = freq2Chan(freqKhz);
|
||||||
if(0xff == toCh)
|
if(0xff == toCh)
|
||||||
return false;
|
return false;
|
||||||
|
@ -537,7 +538,7 @@ class Cmt2300a {
|
||||||
switchChannel(toCh);
|
switchChannel(toCh);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
inline uint8_t getChipStatus(void) {
|
inline uint8_t getChipStatus(void) {
|
||||||
return mSpi.readReg(CMT2300A_CUS_MODE_STA) & CMT2300A_MASK_CHIP_MODE_STA;
|
return mSpi.readReg(CMT2300A_CUS_MODE_STA) & CMT2300A_MASK_CHIP_MODE_STA;
|
||||||
|
@ -549,11 +550,11 @@ class Cmt2300a {
|
||||||
#else
|
#else
|
||||||
esp32_3wSpi mSpi;
|
esp32_3wSpi mSpi;
|
||||||
#endif
|
#endif
|
||||||
uint8_t mCnt;
|
uint8_t mCnt = 0;
|
||||||
bool mTxPending;
|
bool mTxPending = false;
|
||||||
bool mInRxMode;
|
bool mInRxMode = false;
|
||||||
uint8_t mCusIntFlag;
|
uint8_t mCusIntFlag = 0;
|
||||||
uint8_t mRqstCh, mCurCh;
|
uint8_t mRqstCh = 0, mCurCh = 0;
|
||||||
RegionCfg mRegionCfg = RegionCfg::EUROPE;
|
RegionCfg mRegionCfg = RegionCfg::EUROPE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ class cmtHal : public SpiPatcherHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t readReg(uint8_t addr) {
|
uint8_t readReg(uint8_t addr) {
|
||||||
uint8_t data;
|
uint8_t data = 0;
|
||||||
|
|
||||||
request_spi();
|
request_spi();
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
#include "driver/spi_master.h"
|
#include "driver/spi_master.h"
|
||||||
#include "esp_rom_gpio.h" // for esp_rom_gpio_connect_out_signal
|
#include "esp_rom_gpio.h" // for esp_rom_gpio_connect_out_signal
|
||||||
|
#include "../config/config.h"
|
||||||
|
|
||||||
#define SPI_CLK 1 * 1000 * 1000 // 1MHz
|
#define SPI_CLK 1 * 1000 * 1000 // 1MHz
|
||||||
|
|
||||||
|
@ -104,7 +105,7 @@ class esp32_3wSpi {
|
||||||
if(!mInitialized)
|
if(!mInitialized)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint8_t rx_data;
|
uint8_t rx_data = 0;
|
||||||
spi_transaction_t t = {
|
spi_transaction_t t = {
|
||||||
.cmd = 0,
|
.cmd = 0,
|
||||||
.addr = (uint64_t)(~addr),
|
.addr = (uint64_t)(~addr),
|
||||||
|
@ -121,7 +122,7 @@ class esp32_3wSpi {
|
||||||
return rx_data;
|
return rx_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeFifo(uint8_t buf[], uint8_t len) {
|
void writeFifo(const uint8_t buf[], uint8_t len) {
|
||||||
if(!mInitialized)
|
if(!mInitialized)
|
||||||
return;
|
return;
|
||||||
uint8_t tx_data;
|
uint8_t tx_data;
|
||||||
|
@ -144,7 +145,7 @@ class esp32_3wSpi {
|
||||||
void readFifo(uint8_t buf[], uint8_t *len, uint8_t maxlen) {
|
void readFifo(uint8_t buf[], uint8_t *len, uint8_t maxlen) {
|
||||||
if(!mInitialized)
|
if(!mInitialized)
|
||||||
return;
|
return;
|
||||||
uint8_t rx_data;
|
uint8_t rx_data = 0;
|
||||||
|
|
||||||
spi_transaction_t t = {
|
spi_transaction_t t = {
|
||||||
.length = 8,
|
.length = 8,
|
||||||
|
|
|
@ -15,10 +15,6 @@ template<uint32_t DTU_SN = 0x81001765>
|
||||||
class CmtRadio : public Radio {
|
class CmtRadio : public Radio {
|
||||||
typedef Cmt2300a CmtType;
|
typedef Cmt2300a CmtType;
|
||||||
public:
|
public:
|
||||||
CmtRadio() {
|
|
||||||
mDtuSn = DTU_SN;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t pinSclk, uint8_t pinSdio, uint8_t pinCsb, uint8_t pinFcsb, uint8_t region = 0, bool genDtuSn = true) {
|
void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t pinSclk, uint8_t pinSdio, uint8_t pinCsb, uint8_t pinFcsb, uint8_t region = 0, bool genDtuSn = true) {
|
||||||
mCmt.setup(pinSclk, pinSdio, pinCsb, pinFcsb);
|
mCmt.setup(pinSclk, pinSdio, pinCsb, pinFcsb);
|
||||||
reset(genDtuSn, static_cast<RegionCfg>(region));
|
reset(genDtuSn, static_cast<RegionCfg>(region));
|
||||||
|
@ -27,7 +23,7 @@ class CmtRadio : public Radio {
|
||||||
mPrintWholeTrace = printWholeTrace;
|
mPrintWholeTrace = printWholeTrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool loop() {
|
bool loop() override {
|
||||||
mCmt.loop();
|
mCmt.loop();
|
||||||
if((!mIrqRcvd) && (!mRqstGetRx))
|
if((!mIrqRcvd) && (!mRqstGetRx))
|
||||||
return false;
|
return false;
|
||||||
|
@ -39,11 +35,11 @@ class CmtRadio : public Radio {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isChipConnected(void) const {
|
bool isChipConnected(void) const override {
|
||||||
return mCmtAvail;
|
return mCmtAvail;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) {
|
void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) override {
|
||||||
DPRINT(DBG_INFO, F("sendControlPacket cmd: "));
|
DPRINT(DBG_INFO, F("sendControlPacket cmd: "));
|
||||||
DBGHEXLN(cmd);
|
DBGHEXLN(cmd);
|
||||||
initPacket(iv->radioId.u64, TX_REQ_DEVCONTROL, SINGLE_FRAME);
|
initPacket(iv->radioId.u64, TX_REQ_DEVCONTROL, SINGLE_FRAME);
|
||||||
|
@ -61,14 +57,14 @@ class CmtRadio : public Radio {
|
||||||
sendPacket(iv, cnt, isRetransmit);
|
sendPacket(iv, cnt, isRetransmit);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) {
|
bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) override {
|
||||||
uint8_t fromCh = mCmt.freq2Chan(fromkHz);
|
uint8_t fromCh = mCmt.freq2Chan(fromkHz);
|
||||||
uint8_t toCh = mCmt.freq2Chan(tokHz);
|
uint8_t toCh = mCmt.freq2Chan(tokHz);
|
||||||
|
|
||||||
return switchFrequencyCh(iv, fromCh, toCh);
|
return switchFrequencyCh(iv, fromCh, toCh);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) {
|
bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) override {
|
||||||
if((0xff == fromCh) || (0xff == toCh))
|
if((0xff == fromCh) || (0xff == toCh))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -92,7 +88,7 @@ class CmtRadio : public Radio {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) {
|
void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) override {
|
||||||
// inverters have maybe different settings regarding frequency
|
// inverters have maybe different settings regarding frequency
|
||||||
if(mCmt.getCurrentChannel() != iv->config->frequency)
|
if(mCmt.getCurrentChannel() != iv->config->frequency)
|
||||||
mCmt.switchChannel(iv->config->frequency);
|
mCmt.switchChannel(iv->config->frequency);
|
||||||
|
@ -129,11 +125,11 @@ class CmtRadio : public Radio {
|
||||||
iv->mDtuTxCnt++;
|
iv->mDtuTxCnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t getIvId(Inverter<> *iv) const {
|
uint64_t getIvId(Inverter<> *iv) const override {
|
||||||
return iv->radioId.u64;
|
return iv->radioId.u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getIvGen(Inverter<> *iv) const {
|
uint8_t getIvGen(Inverter<> *iv) const override {
|
||||||
return iv->ivGen;
|
return iv->ivGen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,6 +176,7 @@ class CmtRadio : public Radio {
|
||||||
p.millis = millis() - mMillis;
|
p.millis = millis() - mMillis;
|
||||||
if(CmtStatus::SUCCESS == mCmt.getRx(p.packet, &p.len, 28, &p.rssi)) {
|
if(CmtStatus::SUCCESS == mCmt.getRx(p.packet, &p.len, 28, &p.rssi)) {
|
||||||
mSwitchCycle = 0;
|
mSwitchCycle = 0;
|
||||||
|
p.ch = 0; // not used for CMT inverters
|
||||||
mBufCtrl.push(p);
|
mBufCtrl.push(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,14 +184,12 @@ class CmtRadio : public Radio {
|
||||||
setExpectedFrames(p.packet[9] - ALL_FRAMES);
|
setExpectedFrames(p.packet[9] - ALL_FRAMES);
|
||||||
mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first get back to rx mode?
|
mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first get back to rx mode?
|
||||||
}
|
}
|
||||||
// optionally instead:
|
|
||||||
// mRadioWaitTime.stopTimeMonitor(); // we got everything we expected and can exit rx mode...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CmtType mCmt;
|
CmtType mCmt;
|
||||||
bool mCmtAvail = false;
|
bool mCmtAvail = false;
|
||||||
bool mRqstGetRx = false;
|
bool mRqstGetRx = false;
|
||||||
uint32_t mMillis;
|
uint32_t mMillis = 0;
|
||||||
uint8_t mSwitchCycle = 0;
|
uint8_t mSwitchCycle = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -192,15 +192,14 @@ class Display {
|
||||||
if ((mCfg->screenSaver == 2) && (mCfg->pirPin != DEF_PIN_OFF)) {
|
if ((mCfg->screenSaver == 2) && (mCfg->pirPin != DEF_PIN_OFF)) {
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
if (mCfg->pirPin == A0)
|
if (mCfg->pirPin == A0)
|
||||||
return((analogRead(A0) >= 512));
|
return (analogRead(A0) >= 512);
|
||||||
else
|
else
|
||||||
return(digitalRead(mCfg->pirPin));
|
return digitalRead(mCfg->pirPin);
|
||||||
#elif defined(ESP32)
|
#elif defined(ESP32)
|
||||||
return(digitalRead(mCfg->pirPin));
|
return digitalRead(mCfg->pirPin);
|
||||||
#endif
|
#endif
|
||||||
}
|
} else
|
||||||
else
|
return false;
|
||||||
return(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// approximate RSSI in dB by invQuality levels from heuristic function (very unscientific but better than nothing :-) )
|
// approximate RSSI in dB by invQuality levels from heuristic function (very unscientific but better than nothing :-) )
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
|
|
||||||
class DisplayMono {
|
class DisplayMono {
|
||||||
public:
|
public:
|
||||||
DisplayMono() {};
|
|
||||||
|
|
||||||
virtual void init(DisplayData *displayData) = 0;
|
virtual void init(DisplayData *displayData) = 0;
|
||||||
virtual void config(display_t *cfg) = 0;
|
virtual void config(display_t *cfg) = 0;
|
||||||
virtual void disp(void) = 0;
|
virtual void disp(void) = 0;
|
||||||
|
@ -289,11 +287,11 @@ class DisplayMono {
|
||||||
DispSwitchState mDispSwitchState = DispSwitchState::TEXT;
|
DispSwitchState mDispSwitchState = DispSwitchState::TEXT;
|
||||||
|
|
||||||
uint16_t mDispWidth;
|
uint16_t mDispWidth;
|
||||||
uint8_t mExtra;
|
uint8_t mExtra = 0;
|
||||||
int8_t mPixelshift=0;
|
int8_t mPixelshift=0;
|
||||||
char mFmtText[DISP_FMT_TEXT_LEN];
|
char mFmtText[DISP_FMT_TEXT_LEN];
|
||||||
uint8_t mLineXOffsets[5] = {};
|
uint8_t mLineXOffsets[5] = {0, 0, 0, 0, 0};
|
||||||
uint8_t mLineYOffsets[5] = {};
|
uint8_t mLineYOffsets[5] = {0, 0, 0, 0, 0};
|
||||||
|
|
||||||
uint8_t mPgWidth = 0;
|
uint8_t mPgWidth = 0;
|
||||||
|
|
||||||
|
@ -308,8 +306,8 @@ class DisplayMono {
|
||||||
uint32_t mPgLastTime = 0;
|
uint32_t mPgLastTime = 0;
|
||||||
PowerGraphState mPgState = PowerGraphState::NO_TIME_SYNC;
|
PowerGraphState mPgState = PowerGraphState::NO_TIME_SYNC;
|
||||||
|
|
||||||
uint16_t mDispHeight;
|
uint16_t mDispHeight = 0;
|
||||||
uint8_t mLuminance;
|
uint8_t mLuminance = 0;
|
||||||
|
|
||||||
TimeMonitor mDisplayTime = TimeMonitor(1000 * DISP_DEFAULT_TIMEOUT, true);
|
TimeMonitor mDisplayTime = TimeMonitor(1000 * DISP_DEFAULT_TIMEOUT, true);
|
||||||
TimeMonitor mDispSwitchTime = TimeMonitor();
|
TimeMonitor mDispSwitchTime = TimeMonitor();
|
||||||
|
|
|
@ -24,23 +24,15 @@ template<class HMSYSTEM>
|
||||||
class HistoryData {
|
class HistoryData {
|
||||||
private:
|
private:
|
||||||
struct storage_t {
|
struct storage_t {
|
||||||
uint16_t refreshCycle;
|
uint16_t refreshCycle = 0;
|
||||||
uint16_t loopCnt;
|
uint16_t loopCnt = 0;
|
||||||
uint16_t listIdx; // index for next Element to write into WattArr
|
uint16_t listIdx = 0; // index for next Element to write into WattArr
|
||||||
uint16_t dispIdx; // index for 1st Element to display from WattArr
|
uint16_t dispIdx = 0; // index for 1st Element to display from WattArr
|
||||||
bool wrapped;
|
bool wrapped = false;
|
||||||
// ring buffer for watt history
|
// ring buffer for watt history
|
||||||
std::array<uint16_t, (HISTORY_DATA_ARR_LENGTH + 1)> data;
|
std::array<uint16_t, (HISTORY_DATA_ARR_LENGTH + 1)> data;
|
||||||
|
|
||||||
void reset() {
|
storage_t() { data.fill(0); }
|
||||||
loopCnt = 0;
|
|
||||||
listIdx = 0;
|
|
||||||
dispIdx = 0;
|
|
||||||
wrapped = false;
|
|
||||||
for(uint16_t i = 0; i < (HISTORY_DATA_ARR_LENGTH + 1); i++) {
|
|
||||||
data[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -50,9 +42,7 @@ class HistoryData {
|
||||||
mConfig = config;
|
mConfig = config;
|
||||||
mTs = ts;
|
mTs = ts;
|
||||||
|
|
||||||
mCurPwr.reset();
|
|
||||||
mCurPwr.refreshCycle = mConfig->inst.sendInterval;
|
mCurPwr.refreshCycle = mConfig->inst.sendInterval;
|
||||||
//mYieldDay.reset();
|
|
||||||
//mYieldDay.refreshCycle = 60;
|
//mYieldDay.refreshCycle = 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,14 +103,13 @@ class HistoryData {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IApp *mApp;
|
IApp *mApp = nullptr;
|
||||||
HMSYSTEM *mSys;
|
HMSYSTEM *mSys = nullptr;
|
||||||
settings *mSettings;
|
settings *mSettings = nullptr;
|
||||||
settings_t *mConfig;
|
settings_t *mConfig = nullptr;
|
||||||
uint32_t *mTs;
|
uint32_t *mTs = nullptr;
|
||||||
|
|
||||||
storage_t mCurPwr;
|
storage_t mCurPwr;
|
||||||
//storage_t mYieldDay;
|
|
||||||
bool mDayStored = false;
|
bool mDayStored = false;
|
||||||
uint16_t mMaximumDay = 0;
|
uint16_t mMaximumDay = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include "../utils/dbg.h"
|
#include "../utils/dbg.h"
|
||||||
#include "../config/config.h"
|
#include "../config/config.h"
|
||||||
#include <espMqttClient.h>
|
#include <espMqttClient.h>
|
||||||
|
@ -38,12 +39,15 @@ template<class HMSYSTEM>
|
||||||
class PubMqtt {
|
class PubMqtt {
|
||||||
public:
|
public:
|
||||||
PubMqtt() {
|
PubMqtt() {
|
||||||
mRxCnt = 0;
|
mLastIvState.fill(InverterStatus::OFF);
|
||||||
mTxCnt = 0;
|
mIvLastRTRpub.fill(0);
|
||||||
mSubscriptionCb = NULL;
|
|
||||||
memset(mLastIvState, (uint8_t)InverterStatus::OFF, MAX_NUM_INVERTERS);
|
mVal.fill(0);
|
||||||
memset(mIvLastRTRpub, 0, MAX_NUM_INVERTERS * 4);
|
mTopic.fill(0);
|
||||||
mLastAnyAvail = false;
|
mSubTopic.fill(0);
|
||||||
|
mClientId.fill(0);
|
||||||
|
mLwtTopic.fill(0);
|
||||||
|
mSendAlarm.fill(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
~PubMqtt() { }
|
~PubMqtt() { }
|
||||||
|
@ -63,16 +67,16 @@ class PubMqtt {
|
||||||
});
|
});
|
||||||
mDiscovery.running = false;
|
mDiscovery.running = false;
|
||||||
|
|
||||||
snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%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, 23, "%s", mCfgMqtt->clientId);
|
snprintf(mClientId.data(), mClientId.size(), "%s", mCfgMqtt->clientId);
|
||||||
else {
|
else {
|
||||||
snprintf(mClientId, 23, "%s-", mDevName);
|
snprintf(mClientId.data(), mClientId.size(), "%s-", mDevName);
|
||||||
uint8_t pos = strlen(mClientId);
|
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];
|
||||||
mClientId[pos++] = WiFi.macAddress().substring(12, 13).c_str()[0];
|
mClientId[pos++] = WiFi.macAddress().substring(12, 13).c_str()[0];
|
||||||
|
@ -82,9 +86,9 @@ class PubMqtt {
|
||||||
mClientId[pos++] = '\0';
|
mClientId[pos++] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
mClient.setClientId(mClientId);
|
mClient.setClientId(mClientId.data());
|
||||||
mClient.setServer(mCfgMqtt->broker, mCfgMqtt->port);
|
mClient.setServer(mCfgMqtt->broker, mCfgMqtt->port);
|
||||||
mClient.setWill(mLwtTopic, QOS_0, true, mqttStr[MQTT_STR_LWT_NOT_CONN]);
|
mClient.setWill(mLwtTopic.data(), QOS_0, true, mqttStr[MQTT_STR_LWT_NOT_CONN]);
|
||||||
mClient.onConnect(std::bind(&PubMqtt::onConnect, this, std::placeholders::_1));
|
mClient.onConnect(std::bind(&PubMqtt::onConnect, this, std::placeholders::_1));
|
||||||
mClient.onDisconnect(std::bind(&PubMqtt::onDisconnect, this, std::placeholders::_1));
|
mClient.onDisconnect(std::bind(&PubMqtt::onDisconnect, this, std::placeholders::_1));
|
||||||
mClient.onMessage(std::bind(&PubMqtt::onMessage, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6));
|
mClient.onMessage(std::bind(&PubMqtt::onMessage, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6));
|
||||||
|
@ -125,8 +129,8 @@ class PubMqtt {
|
||||||
}
|
}
|
||||||
|
|
||||||
void tickerMinute() {
|
void tickerMinute() {
|
||||||
snprintf(mVal, 40, "%d", (*mUptime));
|
snprintf(mVal.data(), mVal.size(), "%u", (*mUptime));
|
||||||
publish(subtopics[MQTT_UPTIME], mVal);
|
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());
|
||||||
#ifndef ESP32
|
#ifndef ESP32
|
||||||
|
@ -143,18 +147,17 @@ class PubMqtt {
|
||||||
publish(subtopics[MQTT_COMM_START], String(sunrise + offsM).c_str(), true);
|
publish(subtopics[MQTT_COMM_START], String(sunrise + offsM).c_str(), true);
|
||||||
publish(subtopics[MQTT_COMM_STOP], String(sunset + offsE).c_str(), true);
|
publish(subtopics[MQTT_COMM_STOP], String(sunset + offsE).c_str(), true);
|
||||||
|
|
||||||
Inverter<> *iv;
|
|
||||||
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
||||||
iv = mSys->getInverterByPos(i);
|
Inverter<> *iv = mSys->getInverterByPos(i);
|
||||||
if(NULL == iv)
|
if(NULL == iv)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/dis_night_comm", iv->config->name);
|
snprintf(mSubTopic.data(), mSubTopic.size(), "%s/dis_night_comm", iv->config->name);
|
||||||
publish(mSubTopic, ((iv->commEnabled) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
|
publish(mSubTopic.data(), ((iv->commEnabled) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "comm_disabled");
|
snprintf(mSubTopic.data(), mSubTopic.size(), "comm_disabled");
|
||||||
publish(mSubTopic, (((*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;
|
||||||
}
|
}
|
||||||
|
@ -176,9 +179,9 @@ class PubMqtt {
|
||||||
|
|
||||||
void tickerMidnight() {
|
void tickerMidnight() {
|
||||||
// set Total YieldDay to zero
|
// set Total YieldDay to zero
|
||||||
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[FLD_YD]);
|
snprintf(mSubTopic.data(), mSubTopic.size(), "total/%s", fields[FLD_YD]);
|
||||||
snprintf(mVal, 2, "0");
|
snprintf(mVal.data(), mVal.size(), "0");
|
||||||
publish(mSubTopic, mVal, true);
|
publish(mSubTopic.data(), mVal.data(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void payloadEventListener(uint8_t cmd, Inverter<> *iv) {
|
void payloadEventListener(uint8_t cmd, Inverter<> *iv) {
|
||||||
|
@ -197,11 +200,11 @@ class PubMqtt {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(addTopic)
|
if(addTopic)
|
||||||
snprintf(mTopic, MQTT_TOPIC_LEN + 32 + MAX_NAME_LENGTH + 1, "%s/%s", mCfgMqtt->topic, subTopic);
|
snprintf(mTopic.data(), mTopic.size(), "%s/%s", mCfgMqtt->topic, subTopic);
|
||||||
else
|
else
|
||||||
snprintf(mTopic, MQTT_TOPIC_LEN + 32 + MAX_NAME_LENGTH + 1, "%s", subTopic);
|
snprintf(mTopic.data(), mTopic.size(), "%s", subTopic);
|
||||||
|
|
||||||
mClient.publish(mTopic, qos, retained, payload);
|
mClient.publish(mTopic.data(), qos, retained, payload);
|
||||||
yield();
|
yield();
|
||||||
mTxCnt++;
|
mTxCnt++;
|
||||||
}
|
}
|
||||||
|
@ -238,8 +241,8 @@ class PubMqtt {
|
||||||
|
|
||||||
void setPowerLimitAck(Inverter<> *iv) {
|
void setPowerLimitAck(Inverter<> *iv) {
|
||||||
if (NULL != iv) {
|
if (NULL != iv) {
|
||||||
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%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, "true", true, true, QOS_2);
|
publish(mSubTopic.data(), "true", true, true, QOS_2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,15 +258,15 @@ class PubMqtt {
|
||||||
publish(subtopics[MQTT_IP_ADDR], WiFi.localIP().toString().c_str(), true);
|
publish(subtopics[MQTT_IP_ADDR], WiFi.localIP().toString().c_str(), true);
|
||||||
#endif
|
#endif
|
||||||
tickerMinute();
|
tickerMinute();
|
||||||
publish(mLwtTopic, 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, 20, "ctrl/limit/%d", i);
|
snprintf(mVal.data(), mVal.size(), "ctrl/limit/%d", i);
|
||||||
subscribe(mVal, QOS_2);
|
subscribe(mVal.data(), QOS_2);
|
||||||
snprintf(mVal, 20, "ctrl/restart/%d", i);
|
snprintf(mVal.data(), mVal.size(), "ctrl/restart/%d", i);
|
||||||
subscribe(mVal);
|
subscribe(mVal.data());
|
||||||
snprintf(mVal, 20, "ctrl/power/%d", i);
|
snprintf(mVal.data(), mVal.size(), "ctrl/power/%d", i);
|
||||||
subscribe(mVal);
|
subscribe(mVal.data());
|
||||||
}
|
}
|
||||||
subscribe(subscr[MQTT_SUBS_SET_TIME]);
|
subscribe(subscr[MQTT_SUBS_SET_TIME]);
|
||||||
}
|
}
|
||||||
|
@ -359,11 +362,9 @@ class PubMqtt {
|
||||||
}
|
}
|
||||||
|
|
||||||
void discoveryConfigLoop(void) {
|
void discoveryConfigLoop(void) {
|
||||||
char topic[64], name[32], uniq_id[32], buf[350];
|
|
||||||
DynamicJsonDocument doc(256);
|
DynamicJsonDocument doc(256);
|
||||||
|
|
||||||
uint8_t fldTotal[4] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC};
|
constexpr static uint8_t fldTotal[] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC};
|
||||||
const char* unitTotal[4] = {"W", "kWh", "Wh", "W"};
|
|
||||||
|
|
||||||
String node_id = String(mDevName) + "_TOTAL";
|
String node_id = String(mDevName) + "_TOTAL";
|
||||||
bool total = (mDiscovery.lastIvId == MAX_NUM_INVERTERS);
|
bool total = (mDiscovery.lastIvId == MAX_NUM_INVERTERS);
|
||||||
|
@ -392,32 +393,37 @@ class PubMqtt {
|
||||||
doc[F("mf")] = F("Hoymiles");
|
doc[F("mf")] = F("Hoymiles");
|
||||||
JsonObject deviceObj = doc.as<JsonObject>(); // deviceObj is only pointer!?
|
JsonObject deviceObj = doc.as<JsonObject>(); // deviceObj is only pointer!?
|
||||||
|
|
||||||
|
std::array<char, 64> topic;
|
||||||
|
std::array<char, 32> name;
|
||||||
|
std::array<char, 32> uniq_id;
|
||||||
|
std::array<char, 350> buf;
|
||||||
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, 32, "%s", iv->getFieldName(mDiscovery.sub, rec));
|
snprintf(name.data(), name.size(), "%s", iv->getFieldName(mDiscovery.sub, rec));
|
||||||
else
|
else
|
||||||
snprintf(name, 32, "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, 64, "/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, 32, "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, 32, "Total %s", fields[fldTotal[mDiscovery.sub]]);
|
snprintf(name.data(), name.size(), "Total %s", fields[fldTotal[mDiscovery.sub]]);
|
||||||
snprintf(topic, 64, "/%s", fields[fldTotal[mDiscovery.sub]]);
|
snprintf(topic.data(), topic.size(), "/%s", fields[fldTotal[mDiscovery.sub]]);
|
||||||
snprintf(uniq_id, 32, "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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument doc2(512);
|
DynamicJsonDocument doc2(512);
|
||||||
|
constexpr static char* unitTotal[] = {"W", "kWh", "Wh", "W"};
|
||||||
doc2[F("name")] = name;
|
doc2[F("name")] = name;
|
||||||
doc2[F("stat_t")] = String(mCfgMqtt->topic) + "/" + ((!total) ? String(iv->config->name) : "total" ) + String(topic);
|
doc2[F("stat_t")] = String(mCfgMqtt->topic) + "/" + ((!total) ? String(iv->config->name) : "total" ) + String(topic.data());
|
||||||
doc2[F("unit_of_meas")] = ((!total) ? (iv->getUnit(mDiscovery.sub, rec)) : (unitTotal[mDiscovery.sub]));
|
doc2[F("unit_of_meas")] = ((!total) ? (iv->getUnit(mDiscovery.sub, rec)) : (unitTotal[mDiscovery.sub]));
|
||||||
doc2[F("uniq_id")] = ((!total) ? (String(iv->config->serial.u64, HEX)) : (node_id)) + "_" + uniq_id;
|
doc2[F("uniq_id")] = ((!total) ? (String(iv->config->serial.u64, HEX)) : (node_id)) + "_" + uniq_id.data();
|
||||||
doc2[F("dev")] = deviceObj;
|
doc2[F("dev")] = deviceObj;
|
||||||
if (!(String(stateCls) == String("total_increasing")))
|
if (!(String(stateCls) == String("total_increasing")))
|
||||||
doc2[F("exp_aft")] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!?
|
doc2[F("exp_aft")] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!?
|
||||||
|
@ -427,13 +433,13 @@ class PubMqtt {
|
||||||
doc2[F("stat_cla")] = String(stateCls);
|
doc2[F("stat_cla")] = String(stateCls);
|
||||||
|
|
||||||
if (!total)
|
if (!total)
|
||||||
snprintf(topic, 64, "%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, 64, "%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;
|
||||||
memset(buf, 0, size);
|
buf.fill(0);
|
||||||
serializeJson(doc2, buf, size);
|
serializeJson(doc2, buf.data(), size);
|
||||||
publish(topic, buf, true, false);
|
publish(topic.data(), buf.data(), true, false);
|
||||||
|
|
||||||
if(++mDiscovery.sub == ((!total) ? (rec->length) : 4)) {
|
if(++mDiscovery.sub == ((!total) ? (rec->length) : 4)) {
|
||||||
mDiscovery.sub = 0;
|
mDiscovery.sub = 0;
|
||||||
|
@ -503,15 +509,15 @@ class PubMqtt {
|
||||||
mLastIvState[id] = status;
|
mLastIvState[id] = status;
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name);
|
snprintf(mSubTopic.data(), mSubTopic.size(), "%s/available", iv->config->name);
|
||||||
snprintf(mVal, 40, "%d", (uint8_t)status);
|
snprintf(mVal.data(), mVal.size(), "%d", (uint8_t)status);
|
||||||
publish(mSubTopic, mVal, true);
|
publish(mSubTopic.data(), mVal.data(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(changed) {
|
if(changed) {
|
||||||
snprintf(mVal, 32, "%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, true);
|
publish("status", mVal.data(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return anyAvail;
|
return anyAvail;
|
||||||
|
@ -533,19 +539,19 @@ class PubMqtt {
|
||||||
|
|
||||||
mSendAlarm[i] = false;
|
mSendAlarm[i] = false;
|
||||||
|
|
||||||
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/alarm/cnt", iv->config->name);
|
snprintf(mSubTopic.data(), mSubTopic.size(), "%s/alarm/cnt", iv->config->name);
|
||||||
snprintf(mVal, 40, "%d", iv->alarmCnt);
|
snprintf(mVal.data(), mVal.size(), "%d", iv->alarmCnt);
|
||||||
publish(mSubTopic, mVal, 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, 32 + MAX_NAME_LENGTH, "%s/alarm/%d", iv->config->name, j);
|
snprintf(mSubTopic.data(), mSubTopic.size(), "%s/alarm/%d", iv->config->name, j);
|
||||||
snprintf(mVal, 100, "{\"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,
|
||||||
iv->lastAlarm[j].end + lastMidnight);
|
iv->lastAlarm[j].end + lastMidnight);
|
||||||
publish(mSubTopic, mVal, false);
|
publish(mSubTopic.data(), mVal.data(), false);
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -575,9 +581,9 @@ class PubMqtt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%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, 40, "%g", ah::round3(iv->getValue(i, rec)));
|
snprintf(mVal.data(), mVal.size(), "%g", ah::round3(iv->getValue(i, rec)));
|
||||||
publish(mSubTopic, mVal, retained);
|
publish(mSubTopic.data(), mVal.data(), retained);
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
@ -597,33 +603,33 @@ class PubMqtt {
|
||||||
}
|
}
|
||||||
|
|
||||||
espMqttClient mClient;
|
espMqttClient mClient;
|
||||||
cfgMqtt_t *mCfgMqtt;
|
cfgMqtt_t *mCfgMqtt = nullptr;
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
WiFiEventHandler mHWifiCon, mHWifiDiscon;
|
WiFiEventHandler mHWifiCon, mHWifiDiscon;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HMSYSTEM *mSys;
|
HMSYSTEM *mSys = nullptr;
|
||||||
PubMqttIvData<HMSYSTEM> mSendIvData;
|
PubMqttIvData<HMSYSTEM> mSendIvData;
|
||||||
|
|
||||||
uint32_t *mUtcTimestamp, *mUptime;
|
uint32_t *mUtcTimestamp = nullptr, *mUptime = nullptr;
|
||||||
uint32_t mRxCnt, mTxCnt;
|
uint32_t mRxCnt = 0, mTxCnt = 0;
|
||||||
std::queue<sendListCmdIv> mSendList;
|
std::queue<sendListCmdIv> mSendList;
|
||||||
std::array<bool, MAX_NUM_INVERTERS> mSendAlarm{};
|
std::array<bool, MAX_NUM_INVERTERS> mSendAlarm;
|
||||||
subscriptionCb mSubscriptionCb;
|
subscriptionCb mSubscriptionCb = nullptr;
|
||||||
bool mLastAnyAvail;
|
bool mLastAnyAvail = false;
|
||||||
InverterStatus mLastIvState[MAX_NUM_INVERTERS];
|
std::array<InverterStatus, MAX_NUM_INVERTERS> mLastIvState;
|
||||||
uint32_t mIvLastRTRpub[MAX_NUM_INVERTERS];
|
std::array<uint32_t, MAX_NUM_INVERTERS> mIvLastRTRpub;
|
||||||
uint16_t mIntervalTimeout;
|
uint16_t mIntervalTimeout = 0;
|
||||||
|
|
||||||
// last will topic and payload must be available through lifetime of 'espMqttClient'
|
// last will topic and payload must be available through lifetime of 'espMqttClient'
|
||||||
char mLwtTopic[MQTT_TOPIC_LEN+5];
|
std::array<char, (MQTT_TOPIC_LEN + 5)> mLwtTopic;
|
||||||
const char *mDevName, *mVersion;
|
const char *mDevName = nullptr, *mVersion = nullptr;
|
||||||
char mClientId[24]; // number of chars is limited to 23 up to v3.1 of MQTT
|
std::array<char, 24> mClientId; // number of chars is limited to 23 up to v3.1 of MQTT
|
||||||
// global buffer for mqtt topic. Used when publishing mqtt messages.
|
// global buffer for mqtt topic. Used when publishing mqtt messages.
|
||||||
char mTopic[MQTT_TOPIC_LEN + 32 + MAX_NAME_LENGTH + 1];
|
std::array<char, (MQTT_TOPIC_LEN + 32 + MAX_NAME_LENGTH + 1)> mTopic;
|
||||||
char mSubTopic[32 + MAX_NAME_LENGTH + 1];
|
std::array<char, (32 + MAX_NAME_LENGTH + 1)> mSubTopic;
|
||||||
char mVal[100];
|
std::array<char, 100> mVal;
|
||||||
discovery_t mDiscovery;
|
discovery_t mDiscovery = {true, 0, 0, 0};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*ENABLE_MQTT*/
|
#endif /*ENABLE_MQTT*/
|
||||||
|
|
|
@ -205,9 +205,9 @@ class PubMqttIvData {
|
||||||
}
|
}
|
||||||
|
|
||||||
void stateSendTotals() {
|
void stateSendTotals() {
|
||||||
uint8_t fieldId;
|
|
||||||
mRTRDataHasBeenSent = true;
|
mRTRDataHasBeenSent = true;
|
||||||
if(mPos < 5) {
|
if(mPos < 5) {
|
||||||
|
uint8_t fieldId;
|
||||||
bool retained = true;
|
bool retained = true;
|
||||||
switch (mPos) {
|
switch (mPos) {
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// 2022 Ahoy, https://ahoydtu.de
|
// 2024 Ahoy, https://github.com/lumpapu/ahoy
|
||||||
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#ifndef __PUB_SERIAL_H__
|
#ifndef __PUB_SERIAL_H__
|
||||||
|
@ -13,8 +13,6 @@
|
||||||
template<class HMSYSTEM>
|
template<class HMSYSTEM>
|
||||||
class PubSerial {
|
class PubSerial {
|
||||||
public:
|
public:
|
||||||
PubSerial() {}
|
|
||||||
|
|
||||||
void setup(settings_t *cfg, HMSYSTEM *sys, uint32_t *utcTs) {
|
void setup(settings_t *cfg, HMSYSTEM *sys, uint32_t *utcTs) {
|
||||||
mCfg = cfg;
|
mCfg = cfg;
|
||||||
mSys = sys;
|
mSys = sys;
|
||||||
|
@ -46,9 +44,9 @@ class PubSerial {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
settings_t *mCfg;
|
settings_t *mCfg = nullptr;
|
||||||
HMSYSTEM *mSys;
|
HMSYSTEM *mSys = nullptr;
|
||||||
uint32_t *mUtcTimestamp;
|
uint32_t *mUtcTimestamp = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "dbg.h"
|
#include "dbg.h"
|
||||||
#include "AsyncJson.h"
|
#include "AsyncJson.h"
|
||||||
|
#include "../appInterface.h"
|
||||||
|
|
||||||
// https://www.improv-wifi.com/serial/
|
// https://www.improv-wifi.com/serial/
|
||||||
// https://github.com/jnthas/improv-wifi-demo/blob/main/src/esp32-wifiimprov/esp32-wifiimprov.ino
|
// https://github.com/jnthas/improv-wifi-demo/blob/main/src/esp32-wifiimprov/esp32-wifiimprov.ino
|
||||||
|
@ -78,7 +79,7 @@ class Improv {
|
||||||
DBGPRINTLN("");
|
DBGPRINTLN("");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t buildChecksum(uint8_t buf[], uint8_t len) {
|
inline uint8_t buildChecksum(const uint8_t buf[], uint8_t len) {
|
||||||
uint8_t calc = 0;
|
uint8_t calc = 0;
|
||||||
for(uint8_t i = 0; i < len; i++) {
|
for(uint8_t i = 0; i < len; i++) {
|
||||||
calc += buf[i];
|
calc += buf[i];
|
||||||
|
@ -86,7 +87,7 @@ class Improv {
|
||||||
return calc;
|
return calc;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool checkChecksum(uint8_t buf[], uint8_t len) {
|
inline bool checkChecksum(const uint8_t buf[], uint8_t len) {
|
||||||
/*DHEX(buf[len], false);
|
/*DHEX(buf[len], false);
|
||||||
DBGPRINT(F(" == "), false);
|
DBGPRINT(F(" == "), false);
|
||||||
DBGHEXLN(buildChecksum(buf, len), false);*/
|
DBGHEXLN(buildChecksum(buf, len), false);*/
|
||||||
|
@ -97,7 +98,7 @@ class Improv {
|
||||||
if(len < 11)
|
if(len < 11)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(0 != strncmp((char*)buf, "IMPROV", 6))
|
if(0 != strncmp(reinterpret_cast<char*>(buf), "IMPROV", 6))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// version check (only version 1 is supported!)
|
// version check (only version 1 is supported!)
|
||||||
|
@ -199,7 +200,7 @@ class Improv {
|
||||||
dumpBuf(buf, len);
|
dumpBuf(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void parsePayload(uint8_t type, uint8_t buf[], uint8_t len) {
|
void parsePayload(uint8_t type, const uint8_t buf[], uint8_t len) {
|
||||||
if(TYPE_RPC == type) {
|
if(TYPE_RPC == type) {
|
||||||
if(GET_CURRENT_STATE == buf[0]) {
|
if(GET_CURRENT_STATE == buf[0]) {
|
||||||
setDebugEn(false);
|
setDebugEn(false);
|
||||||
|
@ -212,9 +213,10 @@ class Improv {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IApp *mApp;
|
IApp *mApp = nullptr;
|
||||||
const char *mDevName, *mVersion;
|
const char *mDevName = nullptr;
|
||||||
bool mScanRunning;
|
const char *mVersion = nullptr;
|
||||||
|
bool mScanRunning = false;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#define __SCHEDULER_H__
|
#define __SCHEDULER_H__
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <array>
|
||||||
#include "dbg.h"
|
#include "dbg.h"
|
||||||
|
|
||||||
namespace ah {
|
namespace ah {
|
||||||
|
@ -28,8 +29,6 @@ namespace ah {
|
||||||
|
|
||||||
class Scheduler {
|
class Scheduler {
|
||||||
public:
|
public:
|
||||||
Scheduler() {}
|
|
||||||
|
|
||||||
void setup(bool directStart) {
|
void setup(bool directStart) {
|
||||||
mUptime = 0;
|
mUptime = 0;
|
||||||
mTimestamp = (directStart) ? 1 : 0;
|
mTimestamp = (directStart) ? 1 : 0;
|
||||||
|
@ -93,8 +92,7 @@ namespace ah {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void resetTicker(void) {
|
inline void resetTicker(void) {
|
||||||
for (uint8_t i = 0; i < MAX_NUM_TICKER; i++)
|
mTickerInUse.fill(false);
|
||||||
mTickerInUse[i] = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void getStat(uint8_t *max) {
|
void getStat(uint8_t *max) {
|
||||||
|
@ -159,11 +157,11 @@ namespace ah {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sP mTicker[MAX_NUM_TICKER];
|
std::array<sP, MAX_NUM_TICKER> mTicker;
|
||||||
bool mTickerInUse[MAX_NUM_TICKER];
|
std::array<bool, MAX_NUM_TICKER> mTickerInUse;
|
||||||
uint32_t mMillis, mPrevMillis, mDiff;
|
uint32_t mMillis = 0, mPrevMillis = 0, mDiff = 0;
|
||||||
uint8_t mDiffSeconds;
|
uint8_t mDiffSeconds = 0;
|
||||||
uint8_t mMax;
|
uint8_t mMax = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
class SpiPatcher {
|
class SpiPatcher {
|
||||||
protected:
|
protected:
|
||||||
SpiPatcher(spi_host_device_t dev) :
|
explicit SpiPatcher(spi_host_device_t dev) :
|
||||||
mHostDevice(dev), mCurHandle(nullptr) {
|
mHostDevice(dev), mCurHandle(nullptr) {
|
||||||
// Use binary semaphore instead of mutex for performance reasons
|
// Use binary semaphore instead of mutex for performance reasons
|
||||||
mutex = xSemaphoreCreateBinaryStatic(&mutex_buffer);
|
mutex = xSemaphoreCreateBinaryStatic(&mutex_buffer);
|
||||||
|
|
|
@ -22,14 +22,14 @@ class TimeMonitor {
|
||||||
/**
|
/**
|
||||||
* A constructor for creating a TimeMonitor object
|
* A constructor for creating a TimeMonitor object
|
||||||
*/
|
*/
|
||||||
TimeMonitor(void) {}
|
TimeMonitor() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A constructor for initializing a TimeMonitor object
|
* A constructor for initializing a TimeMonitor object
|
||||||
* @param timeout timeout in ms
|
* @param timeout timeout in ms
|
||||||
* @param start (optional) if true, start TimeMonitor immediately
|
* @param start (optional) if true, start TimeMonitor immediately
|
||||||
*/
|
*/
|
||||||
TimeMonitor(uint32_t timeout, bool start = false) {
|
explicit TimeMonitor(uint32_t timeout, bool start = false) {
|
||||||
if (start)
|
if (start)
|
||||||
startTimeMonitor(timeout);
|
startTimeMonitor(timeout);
|
||||||
else
|
else
|
||||||
|
@ -80,7 +80,7 @@ class TimeMonitor {
|
||||||
* true: TimeMonitor already timed out
|
* true: TimeMonitor already timed out
|
||||||
* false: TimeMonitor still in time or TimeMonitor was stopped
|
* false: TimeMonitor still in time or TimeMonitor was stopped
|
||||||
*/
|
*/
|
||||||
bool isTimeout(void) {
|
bool isTimeout(void) const {
|
||||||
if ((mStarted) && ((millis() - mStartTime) >= mTimeout))
|
if ((mStarted) && ((millis() - mStartTime) >= mTimeout))
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
|
|
|
@ -141,7 +141,7 @@ class RestApi {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void onApiPostBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
|
void onApiPostBody(AsyncWebServerRequest *request, const uint8_t *data, size_t len, size_t index, size_t total) {
|
||||||
DPRINTLN(DBG_VERBOSE, "onApiPostBody");
|
DPRINTLN(DBG_VERBOSE, "onApiPostBody");
|
||||||
|
|
||||||
if(0 == index) {
|
if(0 == index) {
|
||||||
|
@ -158,7 +158,7 @@ class RestApi {
|
||||||
|
|
||||||
DynamicJsonDocument json(1000);
|
DynamicJsonDocument json(1000);
|
||||||
|
|
||||||
DeserializationError err = deserializeJson(json, (const char *)mTmpBuf, mTmpSize);
|
DeserializationError err = deserializeJson(json, reinterpret_cast<const char*>(mTmpBuf), mTmpSize);
|
||||||
JsonObject obj = json.as<JsonObject>();
|
JsonObject obj = json.as<JsonObject>();
|
||||||
|
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 200);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, 200);
|
||||||
|
@ -930,20 +930,20 @@ class RestApi {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
IApp *mApp;
|
IApp *mApp = nullptr;
|
||||||
HMSYSTEM *mSys;
|
HMSYSTEM *mSys = nullptr;
|
||||||
HmRadio<> *mRadioNrf;
|
HmRadio<> *mRadioNrf = nullptr;
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
CmtRadio<> *mRadioCmt;
|
CmtRadio<> *mRadioCmt = nullptr;
|
||||||
#endif
|
#endif
|
||||||
AsyncWebServer *mSrv;
|
AsyncWebServer *mSrv = nullptr;
|
||||||
settings_t *mConfig;
|
settings_t *mConfig = nullptr;
|
||||||
|
|
||||||
uint32_t mTimezoneOffset;
|
uint32_t mTimezoneOffset = 0;
|
||||||
uint32_t mHeapFree, mHeapFreeBlk;
|
uint32_t mHeapFree = 0, mHeapFreeBlk = 0;
|
||||||
uint8_t mHeapFrag;
|
uint8_t mHeapFrag = 0;
|
||||||
uint8_t *mTmpBuf = NULL;
|
uint8_t *mTmpBuf = NULL;
|
||||||
uint32_t mTmpSize;
|
uint32_t mTmpSize = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*__WEB_API_H__*/
|
#endif /*__WEB_API_H__*/
|
||||||
|
|
|
@ -48,9 +48,6 @@ class Web {
|
||||||
public:
|
public:
|
||||||
Web(void) : mWeb(80), mEvts("/events") {
|
Web(void) : mWeb(80), mEvts("/events") {
|
||||||
memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE);
|
memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE);
|
||||||
mSerialBufFill = 0;
|
|
||||||
mSerialAddTime = true;
|
|
||||||
mSerialClientConnnected = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup(IApp *app, HMSYSTEM *sys, settings_t *config) {
|
void setup(IApp *app, HMSYSTEM *sys, settings_t *config) {
|
||||||
|
@ -490,9 +487,8 @@ class Web {
|
||||||
|
|
||||||
|
|
||||||
// pinout
|
// pinout
|
||||||
uint8_t pin;
|
|
||||||
for (uint8_t i = 0; i < 16; i++) {
|
for (uint8_t i = 0; i < 16; i++) {
|
||||||
pin = request->arg(String(pinArgNames[i])).toInt();
|
uint8_t pin = request->arg(String(pinArgNames[i])).toInt();
|
||||||
switch(i) {
|
switch(i) {
|
||||||
case 0: mConfig->nrf.pinCs = ((pin != 0xff) ? pin : DEF_NRF_CS_PIN); break;
|
case 0: mConfig->nrf.pinCs = ((pin != 0xff) ? pin : DEF_NRF_CS_PIN); break;
|
||||||
case 1: mConfig->nrf.pinCe = ((pin != 0xff) ? pin : DEF_NRF_CE_PIN); break;
|
case 1: mConfig->nrf.pinCe = ((pin != 0xff) ? pin : DEF_NRF_CE_PIN); break;
|
||||||
|
@ -633,8 +629,8 @@ class Web {
|
||||||
// NOTE: Grouping for fields with channels and totals is currently not working
|
// NOTE: Grouping for fields with channels and totals is currently not working
|
||||||
// TODO: Handle grouping and sorting for independant from channel number
|
// TODO: Handle grouping and sorting for independant from channel number
|
||||||
// NOTE: Check packetsize for MAX_NUM_INVERTERS. Successfully Tested with 4 Inverters (each with 4 channels)
|
// NOTE: Check packetsize for MAX_NUM_INVERTERS. Successfully Tested with 4 Inverters (each with 4 channels)
|
||||||
const char * metricConstPrefix = "ahoy_solar_";
|
const char* metricConstPrefix = "ahoy_solar_";
|
||||||
const char * metricConstInverterFormat = " {inverter=\"%s\"} %d\n";
|
const char* metricConstInverterFormat = " {inverter=\"%s\"} %d\n";
|
||||||
typedef enum {
|
typedef enum {
|
||||||
metricsStateInverterInfo=0, metricsStateInverterEnabled=1, metricsStateInverterAvailable=2,
|
metricsStateInverterInfo=0, metricsStateInverterEnabled=1, metricsStateInverterAvailable=2,
|
||||||
metricsStateInverterProducing=3, metricsStateInverterPowerLimitRead=4, metricsStateInverterPowerLimitAck=5,
|
metricsStateInverterProducing=3, metricsStateInverterPowerLimitRead=4, metricsStateInverterPowerLimitAck=5,
|
||||||
|
@ -648,7 +644,7 @@ class Web {
|
||||||
metricsStateStart,
|
metricsStateStart,
|
||||||
metricsStateEnd
|
metricsStateEnd
|
||||||
} MetricStep_t;
|
} MetricStep_t;
|
||||||
MetricStep_t metricsStep;
|
MetricStep_t metricsStep = metricsStateInverterInfo;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *topic;
|
const char *topic;
|
||||||
const char *type;
|
const char *type;
|
||||||
|
@ -674,9 +670,6 @@ class Web {
|
||||||
{ "radio_dtu_loss_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.dtuLoss;} },
|
{ "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;} }
|
{ "radio_dtu_sent_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.dtuSent;} }
|
||||||
};
|
};
|
||||||
int metricsInverterId;
|
|
||||||
uint8_t metricsFieldId;
|
|
||||||
bool metricDeclared, metricTotalDeclard;
|
|
||||||
|
|
||||||
void showMetrics(AsyncWebServerRequest *request) {
|
void showMetrics(AsyncWebServerRequest *request) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("web::showMetrics"));
|
DPRINTLN(DBG_VERBOSE, F("web::showMetrics"));
|
||||||
|
@ -715,7 +708,7 @@ class Web {
|
||||||
snprintf(topic,sizeof(topic),"%swifi_rssi_db{devicename=\"%s\"} %d\n",metricConstPrefix, mConfig->sys.deviceName, WiFi.RSSI());
|
snprintf(topic,sizeof(topic),"%swifi_rssi_db{devicename=\"%s\"} %d\n",metricConstPrefix, mConfig->sys.deviceName, WiFi.RSSI());
|
||||||
metrics += String(type) + String(topic);
|
metrics += String(type) + String(topic);
|
||||||
|
|
||||||
len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str());
|
len = snprintf(reinterpret_cast<char*>(buffer), maxLen,"%s",metrics.c_str());
|
||||||
// Next is Inverter information
|
// Next is Inverter information
|
||||||
metricsStep = metricsStateInverterInfo;
|
metricsStep = metricsStateInverterInfo;
|
||||||
break;
|
break;
|
||||||
|
@ -743,7 +736,7 @@ class Web {
|
||||||
(String("ahoy_solar_inverter_") + inverterMetrics[metricsStep].topic +
|
(String("ahoy_solar_inverter_") + inverterMetrics[metricsStep].topic +
|
||||||
inverterMetrics[metricsStep].format).c_str(),
|
inverterMetrics[metricsStep].format).c_str(),
|
||||||
inverterMetrics[metricsStep].valueFunc);
|
inverterMetrics[metricsStep].valueFunc);
|
||||||
len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str());
|
len = snprintf(reinterpret_cast<char*>(buffer), maxLen, "%s", metrics.c_str());
|
||||||
// ugly hack to increment the enum
|
// ugly hack to increment the enum
|
||||||
metricsStep = static_cast<MetricStep_t>( static_cast<int>(metricsStep) + 1);
|
metricsStep = static_cast<MetricStep_t>( static_cast<int>(metricsStep) + 1);
|
||||||
// Prepare Realtime Field loop, which may be startet next
|
// Prepare Realtime Field loop, which may be startet next
|
||||||
|
@ -763,7 +756,7 @@ class Web {
|
||||||
metrics = "# Info: all realtime fields processed\n";
|
metrics = "# Info: all realtime fields processed\n";
|
||||||
metricsStep = metricsStateAlarmData;
|
metricsStep = metricsStateAlarmData;
|
||||||
}
|
}
|
||||||
len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str());
|
len = snprintf(reinterpret_cast<char *>(buffer), maxLen, "%s", metrics.c_str());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case metricStateRealtimeInverterId: // Iterate over all inverters for this field
|
case metricStateRealtimeInverterId: // Iterate over all inverters for this field
|
||||||
|
@ -837,7 +830,7 @@ class Web {
|
||||||
metricsFieldId++; // Process next field Id
|
metricsFieldId++; // Process next field Id
|
||||||
metricsStep = metricStateRealtimeFieldId;
|
metricsStep = metricStateRealtimeFieldId;
|
||||||
}
|
}
|
||||||
len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str());
|
len = snprintf(reinterpret_cast<char *>(buffer), maxLen, "%s", metrics.c_str());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case metricsStateAlarmData: // Alarm Info loop : fit to one packet
|
case metricsStateAlarmData: // Alarm Info loop : fit to one packet
|
||||||
|
@ -861,7 +854,7 @@ class Web {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
len = snprintf((char*)buffer,maxLen,"%s",metrics.c_str());
|
len = snprintf(reinterpret_cast<char*>(buffer), maxLen, "%s", metrics.c_str());
|
||||||
metricsStep = metricsStateEnd;
|
metricsStep = metricsStateEnd;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -880,10 +873,9 @@ 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) {
|
||||||
Inverter<> *iv;
|
|
||||||
String metric = "";
|
String metric = "";
|
||||||
for (int metricsInverterId = 0; metricsInverterId < mSys->getNumInverters();metricsInverterId++) {
|
for (int metricsInverterId = 0; metricsInverterId < mSys->getNumInverters();metricsInverterId++) {
|
||||||
iv = mSys->getInverterByPos(metricsInverterId);
|
Inverter<> *iv = mSys->getInverterByPos(metricsInverterId);
|
||||||
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);
|
||||||
|
@ -904,21 +896,27 @@ class Web {
|
||||||
if(shortUnit == "Hz") return {"_hertz", "gauge"};
|
if(shortUnit == "Hz") return {"_hertz", "gauge"};
|
||||||
return {"", "gauge"};
|
return {"", "gauge"};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int metricsInverterId = 0;
|
||||||
|
uint8_t metricsFieldId = 0;
|
||||||
|
bool metricDeclared = false, metricTotalDeclard = false;
|
||||||
#endif
|
#endif
|
||||||
|
private:
|
||||||
AsyncWebServer mWeb;
|
AsyncWebServer mWeb;
|
||||||
AsyncEventSource mEvts;
|
AsyncEventSource mEvts;
|
||||||
IApp *mApp;
|
IApp *mApp = nullptr;
|
||||||
HMSYSTEM *mSys;
|
HMSYSTEM *mSys = nullptr;
|
||||||
|
|
||||||
settings_t *mConfig;
|
settings_t *mConfig = nullptr;
|
||||||
|
|
||||||
bool mSerialAddTime;
|
bool mSerialAddTime = true;
|
||||||
char mSerialBuf[WEB_SERIAL_BUF_SIZE];
|
char mSerialBuf[WEB_SERIAL_BUF_SIZE];
|
||||||
uint16_t mSerialBufFill;
|
uint16_t mSerialBufFill = 0;
|
||||||
bool mSerialClientConnnected;
|
bool mSerialClientConnnected = false;
|
||||||
|
|
||||||
File mUploadFp;
|
File mUploadFp;
|
||||||
bool mUploadFail;
|
bool mUploadFail = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*__WEB_H__*/
|
#endif /*__WEB_H__*/
|
||||||
|
|
|
@ -71,7 +71,7 @@ class ahoywifi {
|
||||||
void welcome(String ip, String mode);
|
void welcome(String ip, String mode);
|
||||||
|
|
||||||
|
|
||||||
settings_t *mConfig = NULL;
|
settings_t *mConfig = nullptr;
|
||||||
appWifiCb mAppWifiCb;
|
appWifiCb mAppWifiCb;
|
||||||
|
|
||||||
DNSServer mDns;
|
DNSServer mDns;
|
||||||
|
@ -81,15 +81,15 @@ class ahoywifi {
|
||||||
WiFiEventHandler wifiConnectHandler, wifiDisconnectHandler, wifiGotIPHandler;
|
WiFiEventHandler wifiConnectHandler, wifiDisconnectHandler, wifiGotIPHandler;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
WiFiStatus_t mStaConn;
|
WiFiStatus_t mStaConn = DISCONNECTED;
|
||||||
uint8_t mCnt;
|
uint8_t mCnt = 0;
|
||||||
uint32_t *mUtcTimestamp;
|
uint32_t *mUtcTimestamp = nullptr;
|
||||||
|
|
||||||
uint8_t mScanCnt;
|
uint8_t mScanCnt = 0;
|
||||||
bool mScanActive;
|
bool mScanActive = false;
|
||||||
bool mGotDisconnect;
|
bool mGotDisconnect = false;
|
||||||
std::list<uint8_t> mBSSIDList;
|
std::list<uint8_t> mBSSIDList;
|
||||||
bool mStopApAllowed;
|
bool mStopApAllowed = false;
|
||||||
bool mWasInCh12to14 = false;
|
bool mWasInCh12to14 = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue