From 24de3ac39b32b6446231602d91e2a9d016ef8a87 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 12 Nov 2022 02:29:00 +0100 Subject: [PATCH] clean up mqtt stuff fix workflow --- .github/workflows/compile_development.yml | 2 +- .github/workflows/compile_esp8266.yml | 2 +- src/app.cpp | 43 ++---- src/app.h | 22 +-- src/utils/ahoyTimer.h | 27 ++++ src/web/mqtt.h | 173 ++++++++++++---------- src/web/web.cpp | 4 +- src/wifi/ahoywifi.cpp | 5 +- 8 files changed, 140 insertions(+), 138 deletions(-) create mode 100644 src/utils/ahoyTimer.h diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index 4c14fe64..274a6c73 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -47,7 +47,7 @@ jobs: run: python convert.py - name: Run PlatformIO - run: pio run -d src --environment esp8266-release --environment esp8266-1m-release --environment esp32-wroom32-release + run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release - name: Rename Binary files id: rename-binary-files diff --git a/.github/workflows/compile_esp8266.yml b/.github/workflows/compile_esp8266.yml index 168779b4..cf61b1f9 100644 --- a/.github/workflows/compile_esp8266.yml +++ b/.github/workflows/compile_esp8266.yml @@ -49,7 +49,7 @@ jobs: working-directory: src/web/html run: python convert.py - name: Run PlatformIO - run: pio run -d tools/esp8266 --environment esp8266-release --environment esp8266-1m-release --environment esp32-wroom32-release + run: pio run -d tools/esp8266 --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release - name: Rename Binary files id: rename-binary-files diff --git a/src/app.cpp b/src/app.cpp index 1f894519..2080bb23 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -40,9 +40,10 @@ void app::setup(uint32_t timeout) { mSys->setup(mConfig.amplifierPower, mConfig.pinIrq, mConfig.pinCe, mConfig.pinCs); mPayload.setup(mSys); mPayload.enableSerialDebug(mConfig.serialDebug); - mPayload.addListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); #ifndef AP_ONLY setupMqtt(); + if(mMqttActive) + mPayload.addListener(std::bind(&MqttType::payloadEventListener, mMqtt, std::placeholders::_1)); #endif setupLed(); @@ -74,7 +75,7 @@ void app::loop(void) { } } - if (checkTicker(&mNtpRefreshTicker, mNtpRefreshInterval)) { + if (ah::checkTicker(&mNtpRefreshTicker, mNtpRefreshInterval)) { if (!apActive) mUpdateNtp = true; } @@ -87,14 +88,14 @@ void app::loop(void) { if (mFlagSendDiscoveryConfig) { mFlagSendDiscoveryConfig = false; - mMqtt.sendMqttDiscoveryConfig(mConfig.mqtt.topic, mMqttInterval); + mMqtt.sendMqttDiscoveryConfig(mConfig.mqtt.topic); } mSys->Radio.loop(); yield(); - if (checkTicker(&mRxTicker, 5)) { + if (ah::checkTicker(&mRxTicker, 5)) { bool rxRdy = mSys->Radio.switchRxCh(); if (!mSys->BufCtrl.empty()) { @@ -110,23 +111,21 @@ void app::loop(void) { mStat.frmCnt++; - if (0 != len) { + if (0 != len) mPayload.add(p, len); - } } mSys->BufCtrl.popBack(); } yield(); - if (rxRdy) { + if (rxRdy) mPayload.process(true, mConfig.maxRetransPerPyld, &mStat); - } } if (mMqttActive) mMqtt.loop(); - if (checkTicker(&mTicker, 1000)) { + if (ah::checkTicker(&mTicker, 1000)) { if (mUtcTimestamp > 946684800 && mConfig.sunLat && mConfig.sunLon && (mUtcTimestamp + mCalculatedTimezoneOffset) / 86400 != (mLatestSunTimestamp + mCalculatedTimezoneOffset) / 86400) { // update on reboot or midnight if (!mLatestSunTimestamp) { // first call: calculate time zone from longitude to refresh at local midnight mCalculatedTimezoneOffset = (int8_t)((mConfig.sunLon >= 0 ? mConfig.sunLon + 7.5 : mConfig.sunLon - 7.5) / 15) * 3600; @@ -135,11 +134,6 @@ void app::loop(void) { mLatestSunTimestamp = mUtcTimestamp; } - if ((++mMqttTicker >= mMqttInterval) && (mMqttInterval != 0xffff) && mMqttActive) { - mMqttTicker = 0; - mMqtt.sendIvData(mUtcTimestamp, mMqttSendList); - } - if (mConfig.serialShowIv) { if (++mSerialTicker >= mConfig.serialInterval) { mSerialTicker = 0; @@ -277,8 +271,6 @@ void app::resetSystem(void) { mHeapStatCnt = 0; mSendTicker = 0xffff; - mMqttTicker = 0xffff; - mMqttInterval = MQTT_INTERVAL; mSerialTicker = 0xffff; mMqttActive = false; @@ -372,9 +364,6 @@ void app::loadEEpconfig(void) { mEep->read(ADDR_INV_CH_NAME + (i * 4 * MAX_NAME_LENGTH) + j * MAX_NAME_LENGTH, iv->chName[j], MAX_NAME_LENGTH); } } - - // TODO: the original mqttinterval value is not needed any more - mMqttInterval += mConfig.sendInterval; } } @@ -413,23 +402,11 @@ void app::saveValues(void) { //----------------------------------------------------------------------------- void app::setupMqtt(void) { if (mSettingsValid) { - if (mConfig.mqtt.broker[0] > 0) { + if (mConfig.mqtt.broker[0] > 0) mMqttActive = true; - if (mMqttInterval < MIN_MQTT_INTERVAL) mMqttInterval = MIN_MQTT_INTERVAL; - } else - mMqttInterval = 0xffff; - mMqttTicker = 0; if(mMqttActive) - mMqtt.setup(&mConfig.mqtt, mSysConfig.deviceName, mSys); - - if (mMqttActive) { - mMqtt.sendMsg("version", mVersion); - if (mMqtt.isConnected()) { - mMqtt.sendMsg("device", mSysConfig.deviceName); - mMqtt.sendMsg("uptime", "0"); - } - } + mMqtt.setup(&mConfig.mqtt, mSysConfig.deviceName, mVersion, mSys, &mUtcTimestamp); } } diff --git a/src/app.h b/src/app.h index 167ef306..21031dbc 100644 --- a/src/app.h +++ b/src/app.h @@ -18,6 +18,7 @@ #include "config/eep.h" #include "defines.h" #include "utils/crc.h" +#include "utils/ahoyTimer.h" #include "hm/CircularBuffer.h" #include "hm/hmSystem.h" @@ -54,9 +55,6 @@ class app { void scanAvailNetworks(void); void getAvailNetworks(JsonObject obj); - void payloadEventListener(uint8_t cmd) { - mMqttSendList.push(cmd); - } uint8_t getIrqPin(void) { return mConfig.pinIrq; @@ -142,20 +140,6 @@ class app { mEep->commit(); } - inline bool checkTicker(uint32_t *ticker, uint32_t interval) { - uint32_t mil = millis(); - if(mil >= *ticker) { - *ticker = mil + interval; - return true; - } - else if(mil < (*ticker - interval)) { - *ticker = mil + interval; - return true; - } - - return false; - } - inline bool mqttIsConnected(void) { return mMqtt.isConnected(); } inline bool getSettingsValid(void) { return mSettingsValid; } inline bool getRebootRequestState(void) { return mShowRebootRequest; } @@ -171,7 +155,6 @@ class app { void loadEEpconfig(void); void setupMqtt(void); - void sendMqtt(void); void setupLed(void); void updateLed(void); @@ -273,10 +256,7 @@ class app { // mqtt MqttType mMqtt; - uint16_t mMqttTicker; - uint16_t mMqttInterval; bool mMqttActive; - std::queue mMqttSendList; // serial uint16_t mSerialTicker; diff --git a/src/utils/ahoyTimer.h b/src/utils/ahoyTimer.h new file mode 100644 index 00000000..41a4b09a --- /dev/null +++ b/src/utils/ahoyTimer.h @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------------- +// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778 +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +//----------------------------------------------------------------------------- + +#ifndef __AHOY_TIMER_H__ +#define __AHOY_TIMER_H__ + +#include + +namespace ah { + inline bool checkTicker(uint32_t *ticker, uint32_t interval) { + uint32_t mil = millis(); + if(mil >= *ticker) { + *ticker = mil + interval; + return true; + } + else if(mil < (*ticker - interval)) { + *ticker = mil + interval; + return true; + } + + return false; + } +} + +#endif /*__AHOY_TIMER_H__*/ diff --git a/src/web/mqtt.h b/src/web/mqtt.h index d5b46ae7..6b731ffe 100644 --- a/src/web/mqtt.h +++ b/src/web/mqtt.h @@ -18,6 +18,8 @@ #endif #include "../utils/dbg.h" +#include "../utils/ahoyTimer.h" +#include "../config/config.h" #include #include "../defines.h" #include "../hm/hmSystem.h" @@ -38,18 +40,34 @@ class mqtt { ~mqtt() { } - void setup(mqttConfig_t *cfg, const char *devname, HMSYSTEM *sys) { + void setup(mqttConfig_t *cfg, const char *devname, const char *version, HMSYSTEM *sys, uint32_t *utcTs) { DPRINTLN(DBG_VERBOSE, F("mqtt.h:setup")); mAddressSet = true; - mCfg = cfg; - snprintf(mDevName, DEVNAME_LEN, "%s", devname); - mSys = sys; + snprintf(mDevName, DEVNAME_LEN, "%s", devname); + mCfg = cfg; + mSys = sys; + mUtcTimestamp = utcTs; mClient->setServer(mCfg->broker, mCfg->port); mClient->setBufferSize(MQTT_MAX_PACKET_SIZE); setCallback(std::bind(&mqtt::cbMqtt, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + + sendMsg("version", version); + sendMsg("device", devname); + sendMsg("uptime", "0"); + } + + void loop() { + if(mAddressSet) { + if(!mClient->connected()) + reconnect(); + mClient->loop(); + + if(!mSendList.empty()) + sendIvData(); + } } void setCallback(MQTT_CALLBACK_SIGNATURE) { @@ -84,20 +102,15 @@ class mqtt { return mClient->connected(); } - void loop() { - //DPRINT(F("m")); - if(mAddressSet) { - if(!mClient->connected()) - reconnect(); - mClient->loop(); - } + void payloadEventListener(uint8_t cmd) { + mSendList.push(cmd); } uint32_t getTxCnt(void) { return mTxCnt; } - void sendMqttDiscoveryConfig(const char *topic, uint32_t invertval) { + void sendMqttDiscoveryConfig(const char *topic) { DPRINTLN(DBG_VERBOSE, F("sendMqttDiscoveryConfig")); char stateTopic[64], discoveryTopic[64], buffer[512], name[32], uniq_id[32]; @@ -131,7 +144,7 @@ class mqtt { doc["unit_of_meas"] = iv->getUnit(i, rec); doc["uniq_id"] = String(iv->serial.u64, HEX) + "_" + uniq_id; doc["dev"] = deviceObj; - doc["exp_aft"] = invertval + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!? + doc["exp_aft"] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!? if (devCls != NULL) doc["dev_cla"] = devCls; if (stateCls != NULL) @@ -148,7 +161,62 @@ class mqtt { } } - void sendIvData(uint32_t mUtcTs, std::queue list) { + private: + void reconnect(void) { + DPRINTLN(DBG_DEBUG, F("mqtt.h:reconnect")); + DPRINTLN(DBG_DEBUG, F("MQTT mClient->_state ") + String(mClient->state()) ); + + #ifdef ESP8266 + DPRINTLN(DBG_DEBUG, F("WIFI mEspClient.status ") + String(mEspClient.status()) ); + #endif + + boolean resub = false; + if(!mClient->connected() && (millis() - mLastReconnect) > MQTT_RECONNECT_DELAY ) { + mLastReconnect = millis(); + if(strlen(mDevName) > 0) { + // der Server und der Port müssen neu gesetzt werden, + // da ein MQTT_CONNECTION_LOST -3 die Werte zerstört hat. + mClient->setServer(mCfg->broker, mCfg->port); + mClient->setBufferSize(MQTT_MAX_PACKET_SIZE); + + char lwt[MQTT_TOPIC_LEN + 7 ]; // "/uptime" --> + 7 byte + snprintf(lwt, MQTT_TOPIC_LEN + 7, "%s/uptime", mCfg->topic); + + if((strlen(mCfg->user) > 0) && (strlen(mCfg->pwd) > 0)) + resub = mClient->connect(mDevName, mCfg->user, mCfg->pwd, lwt, 0, false, "offline"); + else + resub = mClient->connect(mDevName, lwt, 0, false, "offline"); + // ein Subscribe ist nur nach einem connect notwendig + if(resub) { + char topic[MQTT_TOPIC_LEN + 13 ]; // "/devcontrol/#" --> + 6 byte + // ToDo: "/devcontrol/#" is hardcoded + snprintf(topic, MQTT_TOPIC_LEN + 13, "%s/devcontrol/#", mCfg->topic); + DPRINTLN(DBG_INFO, F("subscribe to ") + String(topic)); + mClient->subscribe(topic); // subscribe to mTopic + "/devcontrol/#" + } + } + } + } + + const char *getFieldDeviceClass(uint8_t fieldId) { + uint8_t pos = 0; + for (; pos < DEVICE_CLS_ASSIGN_LIST_LEN; pos++) { + if (deviceFieldAssignment[pos].fieldId == fieldId) + break; + } + return (pos >= DEVICE_CLS_ASSIGN_LIST_LEN) ? NULL : deviceClasses[deviceFieldAssignment[pos].deviceClsId]; + } + + const char *getFieldStateClass(uint8_t fieldId) { + uint8_t pos = 0; + for (; pos < DEVICE_CLS_ASSIGN_LIST_LEN; pos++) { + if (deviceFieldAssignment[pos].fieldId == fieldId) + break; + } + return (pos >= DEVICE_CLS_ASSIGN_LIST_LEN) ? NULL : stateClasses[deviceFieldAssignment[pos].stateClsId]; + } + + void sendIvData() { isConnected(true); // really needed? See comment from HorstG-57 #176 char topic[32 + MAX_NAME_LENGTH], val[32]; float total[4]; @@ -158,26 +226,26 @@ class mqtt { sendMsg("uptime", val); - if(list.empty()) + if(mSendList.empty()) return; - while(!list.empty()) { + while(!mSendList.empty()) { memset(total, 0, sizeof(float) * 4); for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); if (NULL == iv) continue; // skip to next inverter - record_t<> *rec = iv->getRecordStruct(list.front()); + record_t<> *rec = iv->getRecordStruct(mSendList.front()); - if(list.front() == RealTimeRunData_Debug) { + if(mSendList.front() == RealTimeRunData_Debug) { // inverter status uint8_t status = MQTT_STATUS_AVAIL_PROD; - if (!iv->isAvailable(mUtcTs, rec)) { + if (!iv->isAvailable(*mUtcTimestamp, rec)) { status = MQTT_STATUS_NOT_AVAIL_NOT_PROD; totalIncomplete = true; } - else if (!iv->isProducing(mUtcTs, rec)) { + else if (!iv->isProducing(*mUtcTimestamp, rec)) { if (MQTT_STATUS_AVAIL_PROD == status) status = MQTT_STATUS_AVAIL_NOT_PROD; } @@ -200,14 +268,14 @@ class mqtt { } // data - if(iv->isAvailable(mUtcTs, rec)) { + if(iv->isAvailable(*mUtcTimestamp, rec)) { for (uint8_t i = 0; i < rec->length; i++) { snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]); snprintf(val, 10, "%.3f", iv->getValue(i, rec)); sendMsg(topic, val); // calculate total values for RealTimeRunData_Debug - if (list.front() == RealTimeRunData_Debug) { + if (mSendList.front() == RealTimeRunData_Debug) { if (CH0 == rec->assign[i].ch) { switch (rec->assign[i].fieldId) { case FLD_PAC: @@ -231,7 +299,7 @@ class mqtt { } } - list.pop(); // remove from list once all inverters were processed + mSendList.pop(); // remove from list once all inverters were processed if ((true == sendTotal) && (false == totalIncomplete)) { uint8_t fieldId; @@ -259,61 +327,6 @@ class mqtt { } } - private: - void reconnect(void) { - DPRINTLN(DBG_DEBUG, F("mqtt.h:reconnect")); - DPRINTLN(DBG_DEBUG, F("MQTT mClient->_state ") + String(mClient->state()) ); - - #ifdef ESP8266 - DPRINTLN(DBG_DEBUG, F("WIFI mEspClient.status ") + String(mEspClient.status()) ); - #endif - - boolean resub = false; - if(!mClient->connected() && (millis() - mLastReconnect) > MQTT_RECONNECT_DELAY ) { - mLastReconnect = millis(); - if(strlen(mDevName) > 0) { - // der Server und der Port müssen neu gesetzt werden, - // da ein MQTT_CONNECTION_LOST -3 die Werte zerstört hat. - mClient->setServer(mCfg->broker, mCfg->port); - mClient->setBufferSize(MQTT_MAX_PACKET_SIZE); - - char lwt[MQTT_TOPIC_LEN + 7 ]; // "/uptime" --> + 7 byte - snprintf(lwt, MQTT_TOPIC_LEN + 7, "%s/uptime", mCfg->topic); - - if((strlen(mCfg->user) > 0) && (strlen(mCfg->pwd) > 0)) - resub = mClient->connect(mDevName, mCfg->user, mCfg->pwd, lwt, 0, false, "offline"); - else - resub = mClient->connect(mDevName, lwt, 0, false, "offline"); - // ein Subscribe ist nur nach einem connect notwendig - if(resub) { - char topic[MQTT_TOPIC_LEN + 13 ]; // "/devcontrol/#" --> + 6 byte - // ToDo: "/devcontrol/#" is hardcoded - snprintf(topic, MQTT_TOPIC_LEN + 13, "%s/devcontrol/#", mCfg->topic); - DPRINTLN(DBG_INFO, F("subscribe to ") + String(topic)); - mClient->subscribe(topic); // subscribe to mTopic + "/devcontrol/#" - } - } - } - } - - const char *getFieldDeviceClass(uint8_t fieldId) { - uint8_t pos = 0; - for (; pos < DEVICE_CLS_ASSIGN_LIST_LEN; pos++) { - if (deviceFieldAssignment[pos].fieldId == fieldId) - break; - } - return (pos >= DEVICE_CLS_ASSIGN_LIST_LEN) ? NULL : deviceClasses[deviceFieldAssignment[pos].deviceClsId]; - } - - const char *getFieldStateClass(uint8_t fieldId) { - uint8_t pos = 0; - for (; pos < DEVICE_CLS_ASSIGN_LIST_LEN; pos++) { - if (deviceFieldAssignment[pos].fieldId == fieldId) - break; - } - return (pos >= DEVICE_CLS_ASSIGN_LIST_LEN) ? NULL : stateClasses[deviceFieldAssignment[pos].stateClsId]; - } - void cbMqtt(char *topic, byte *payload, unsigned int length) { // callback handling on subscribed devcontrol topic DPRINTLN(DBG_INFO, F("cbMqtt")); @@ -420,12 +433,14 @@ class mqtt { WiFiClient mEspClient; PubSubClient *mClient; HMSYSTEM *mSys; - + uint32_t *mUtcTimestamp; + bool mAddressSet; mqttConfig_t *mCfg; char mDevName[DEVNAME_LEN]; uint32_t mLastReconnect; uint32_t mTxCnt; + std::queue mSendList; }; #endif /*__MQTT_H_*/ diff --git a/src/web/web.cpp b/src/web/web.cpp index 6b4f9179..50e6fcb0 100644 --- a/src/web/web.cpp +++ b/src/web/web.cpp @@ -10,6 +10,8 @@ #include "web.h" +#include "../utils/ahoyTimer.h" + #include "html/h/index_html.h" #include "html/h/login_html.h" #include "html/h/style_css.h" @@ -93,7 +95,7 @@ void web::setup(void) { void web::loop(void) { mApi->loop(); - if(mMain->checkTicker(&mWebSerialTicker, mWebSerialInterval)) { + if(ah::checkTicker(&mWebSerialTicker, mWebSerialInterval)) { if(mSerialBufFill > 0) { mEvts->send(mSerialBuf, "serial", millis()); memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE); diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index bdbea216..05d2720d 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -8,6 +8,7 @@ #define F(sl) (sl) #endif #include "ahoywifi.h" +#include "../utils/ahoyTimer.h" // NTP CONFIG @@ -71,7 +72,7 @@ bool ahoywifi::loop(void) { if(mApActive) { mDns->processNextRequest(); #ifndef AP_ONLY - if(mMain->checkTicker(&mNextTryTs, (WIFI_AP_ACTIVE_TIME * 1000))) { + if(ah::checkTicker(&mNextTryTs, (WIFI_AP_ACTIVE_TIME * 1000))) { mApActive = (mStationWifiIsDef) ? true : setupStation(mWifiStationTimeout); if(mApActive) { if(strlen(WIFI_AP_PWD) < 8) @@ -244,7 +245,7 @@ void ahoywifi::getAvailNetworks(JsonObject obj) { for (int i = 0; i < n; i++) for (int j = i + 1; j < n; j++) if (WiFi.RSSI(sort[j]) > WiFi.RSSI(sort[i])) - std::swap(sort[i], sort[j]); + std::swap(sort[i], sort[j]); for (int i = 0; i < n; ++i) { nets[i]["ssid"] = WiFi.SSID(sort[i]); nets[i]["rssi"] = WiFi.RSSI(sort[i]);