From c00be7bb35f04da8a05fd2738925d952b13e9d60 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 22 Apr 2022 07:53:26 +0200 Subject: [PATCH] * added mqtt --- tools/esp8266/app.cpp | 160 ++++++++++++++++++++++----- tools/esp8266/app.h | 9 ++ tools/esp8266/defines.h | 34 ++++-- tools/esp8266/html/h/hoymiles_html.h | 2 +- tools/esp8266/html/h/index_html.h | 2 +- tools/esp8266/html/h/setup_html.h | 2 +- tools/esp8266/html/hoymiles.html | 2 +- tools/esp8266/html/index.html | 2 + tools/esp8266/html/setup.html | 38 ++++++- tools/esp8266/mqtt.h | 90 +++++++++++++++ 10 files changed, 301 insertions(+), 40 deletions(-) create mode 100644 tools/esp8266/mqtt.h diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index b080df25..4db8eeee 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -7,13 +7,15 @@ extern String setup_html; //----------------------------------------------------------------------------- app::app() : Main() { mHoymiles = new hoymiles(); - mDecoder = new hm1200Decode(); + mDecoder = new hm1200Decode(); + mBufCtrl = new CircularBuffer(mBuffer, PACKET_BUFFER_SIZE); - mBufCtrl = new CircularBuffer(mBuffer, PACKET_BUFFER_SIZE); - - mSendCnt = 0; + mSendCnt = 0; mSendTicker = new Ticker(); - mFlagSend = false; + mFlagSend = false; + + mMqttTicker = NULL; + mMqttEvt = false; memset(mCmds, 0, sizeof(uint32_t)); memset(mChannelStat, 0, sizeof(uint32_t)); @@ -30,24 +32,56 @@ app::~app(void) { void app::setup(const char *ssid, const char *pwd, uint32_t timeout) { Main::setup(ssid, pwd, timeout); - mWeb->on("/", std::bind(&app::showIndex, this)); - mWeb->on("/setup", std::bind(&app::showSetup, this)); - mWeb->on("/save", std::bind(&app::showSave, this)); - mWeb->on("/cmdstat", std::bind(&app::showCmdStatistics, this)); - mWeb->on("/hoymiles", std::bind(&app::showHoymiles, this)); - mWeb->on("/livedata", std::bind(&app::showLiveData, this)); - - if(mSettingsValid) - mEep->read(ADDR_HOY_ADDR, mHoymiles->mAddrBytes, HOY_ADDR_LEN); - else + mWeb->on("/", std::bind(&app::showIndex, this)); + mWeb->on("/setup", std::bind(&app::showSetup, this)); + mWeb->on("/save", std::bind(&app::showSave, this)); + mWeb->on("/cmdstat", std::bind(&app::showCmdStatistics, this)); + mWeb->on("/hoymiles", std::bind(&app::showHoymiles, this)); + mWeb->on("/livedata", std::bind(&app::showLiveData, this)); + mWeb->on("/mqttstate", std::bind(&app::showMqtt, this)); + + if(mSettingsValid) { + uint16_t interval; + + // hoymiles + mEep->read(ADDR_INV0_ADDR, mHoymiles->mAddrBytes, INV_ADDR_LEN); + mEep->read(ADDR_INV_INTERVAL, &interval); + + if(interval < 1000) + interval = 1000; + mSendTicker->attach_ms(interval, std::bind(&app::sendTicker, this)); + + + // mqtt + uint8_t mqttAddr[MQTT_ADDR_LEN]; + char mqttUser[MQTT_USER_LEN]; + char mqttPwd[MQTT_PWD_LEN]; + char mqttTopic[MQTT_TOPIC_LEN]; + mEep->read(ADDR_MQTT_ADDR, mqttAddr, MQTT_ADDR_LEN); + mEep->read(ADDR_MQTT_USER, mqttUser, MQTT_USER_LEN); + mEep->read(ADDR_MQTT_PWD, mqttPwd, MQTT_PWD_LEN); + mEep->read(ADDR_MQTT_TOPIC, mqttTopic, MQTT_TOPIC_LEN); + mEep->read(ADDR_MQTT_INTERVAL, &interval); + + char addr[16] = {0}; + sprintf(addr, "%d.%d.%d.%d", mqttAddr[0], mqttAddr[1], mqttAddr[2], mqttAddr[3]); + + if(interval < 1000) + interval = 1000; + mMqtt.setup(addr, mqttTopic, mqttUser, mqttPwd); + mMqttTicker = new Ticker(); + mMqttTicker->attach_ms(interval, std::bind(&app::mqttTicker, this)); + + mMqtt.sendMsg("version", mVersion); + } + else { memset(mHoymiles->mAddrBytes, 0, 6); + } mHoymiles->serial2RadioId(); initRadio(); - if(mSettingsValid) - mSendTicker->attach_ms(1000, std::bind(&app::sendTicker, this)); - else + if(!mSettingsValid) Serial.println("Warn: your settings are not valid! check [IP]/setup"); } @@ -65,8 +99,8 @@ void app::loop(void) { if(mHoymiles->checkCrc(p->packet, &len, &rptCnt)) { // process buffer only on first occurrence if((0 != len) && (0 == rptCnt)) { - Serial.println("CMD " + String(p->packet[11], HEX)); - mHoymiles->dumpBuf("Payload ", p->packet, len); + //Serial.println("CMD " + String(p->packet[11], HEX)); + //mHoymiles->dumpBuf("Payload ", p->packet, len); mDecoder->convert(&p->packet[11], len); @@ -109,6 +143,14 @@ void app::loop(void) { mSendCnt++; } + + + // mqtt + mMqtt.loop(); + if(mMqttEvt) { + mMqttEvt = false; + mMqtt.isConnected(true); + } } @@ -220,6 +262,12 @@ void app::sendTicker(void) { } +//----------------------------------------------------------------------------- +void app::mqttTicker(void) { + mMqttEvt = true; +} + + //----------------------------------------------------------------------------- void app::showIndex(void) { String html = index_html; @@ -233,6 +281,8 @@ void app::showIndex(void) { void app::showSetup(void) { // overrides same method in main.cpp + uint16_t interval; + String html = setup_html; html.replace("{SSID}", mStationSsid); // PWD will be left at the default value (for protection) @@ -240,11 +290,37 @@ void app::showSetup(void) { char addr[20] = {0}; sprintf(addr, "%02X:%02X:%02X:%02X:%02X:%02X", mHoymiles->mAddrBytes[0], mHoymiles->mAddrBytes[1], mHoymiles->mAddrBytes[2], mHoymiles->mAddrBytes[3], mHoymiles->mAddrBytes[4], mHoymiles->mAddrBytes[5]); - html.replace("{HOY_ADDR}", String(addr)); + html.replace("{INV0_ADDR}", String(addr)); html.replace("{DEVICE}", String(mDeviceName)); html.replace("{VERSION}", String(mVersion)); + if(mSettingsValid) { + mEep->read(ADDR_INV_INTERVAL, &interval); + html.replace("{INV_INTERVAL}", String(interval)); + + uint8_t mqttAddr[MQTT_ADDR_LEN] = {0}; + mEep->read(ADDR_MQTT_ADDR, mqttAddr, MQTT_ADDR_LEN); + mEep->read(ADDR_MQTT_INTERVAL, &interval); + + char addr[16] = {0}; + sprintf(addr, "%d.%d.%d.%d", mqttAddr[0], mqttAddr[1], mqttAddr[2], mqttAddr[3]); + html.replace("{MQTT_ADDR}", String(addr)); + html.replace("{MQTT_USER}", String(mMqtt.getUser())); + html.replace("{MQTT_PWD}", String(mMqtt.getPwd())); + html.replace("{MQTT_TOPIC}", String(mMqtt.getTopic())); + html.replace("{MQTT_INTERVAL}", String(interval)); + } + else { + html.replace("{INV_INTERVAL}", "1000"); + + html.replace("{MQTT_ADDR}", ""); + html.replace("{MQTT_USER}", ""); + html.replace("{MQTT_PWD}", ""); + html.replace("{MQTT_TOPIC}", "/inverter"); + html.replace("{MQTT_INTERVAL}", "10000"); + } + mWeb->send(200, "text/html", html); } @@ -311,6 +387,15 @@ void app::showLiveData(void) { } +//----------------------------------------------------------------------------- +void app::showMqtt(void) { + String txt = "connected"; + if(mMqtt.isConnected()) + txt = "not " + txt; + mWeb->send(200, "text/plain", txt); +} + + //----------------------------------------------------------------------------- void app::saveValues(bool webSend = true) { Main::saveValues(false); // general configuration @@ -319,17 +404,42 @@ void app::saveValues(bool webSend = true) { char *p; char addr[20] = {0}; uint8_t i = 0; + uint16_t interval; + // hoymiles memset(mHoymiles->mAddrBytes, 0, 6); - mWeb->arg("hoy_addr").toCharArray(addr, 20); - + mWeb->arg("inv0Addr").toCharArray(addr, 20); p = strtok(addr, ":"); while(NULL != p) { mHoymiles->mAddrBytes[i++] = strtol(p, NULL, 16); p = strtok(NULL, ":"); } - - mEep->write(ADDR_HOY_ADDR, mHoymiles->mAddrBytes, HOY_ADDR_LEN); + interval = mWeb->arg("invInterval").toInt(); + mEep->write(ADDR_INV0_ADDR, mHoymiles->mAddrBytes, INV_ADDR_LEN); + mEep->write(ADDR_INV_INTERVAL, interval); + + + // mqtt + uint8_t mqttAddr[MQTT_ADDR_LEN] = {0}; + char mqttUser[MQTT_USER_LEN]; + char mqttPwd[MQTT_PWD_LEN]; + char mqttTopic[MQTT_TOPIC_LEN]; + mWeb->arg("mqttAddr").toCharArray(addr, 20); + i = 0; + p = strtok(addr, "."); + while(NULL != p) { + mqttAddr[i++] = atoi(p); + p = strtok(NULL, "."); + } + mWeb->arg("mqttUser").toCharArray(mqttUser, MQTT_USER_LEN); + mWeb->arg("mqttPwd").toCharArray(mqttPwd, MQTT_PWD_LEN); + mWeb->arg("mqttTopic").toCharArray(mqttTopic, MQTT_TOPIC_LEN); + interval = mWeb->arg("mqttInterval").toInt(); + mEep->write(ADDR_MQTT_ADDR, mqttAddr, MQTT_ADDR_LEN); + mEep->write(ADDR_MQTT_USER, mqttUser, MQTT_USER_LEN); + mEep->write(ADDR_MQTT_PWD, mqttPwd, MQTT_PWD_LEN); + mEep->write(ADDR_MQTT_TOPIC, mqttTopic, MQTT_TOPIC_LEN); + mEep->write(ADDR_MQTT_INTERVAL, interval); updateCrc(); if((mWeb->arg("reboot") == "on")) diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index 6c4d3157..627cdb1e 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -11,6 +11,8 @@ #include "hoymiles.h" #include "hm1200Decode.h" +#include "mqtt.h" + class app : public Main { public: @@ -26,6 +28,7 @@ class app : public Main { void sendPacket(uint8_t data[], uint8_t length); void sendTicker(void); + void mqttTicker(void); void showIndex(void); void showSetup(void); @@ -33,6 +36,7 @@ class app : public Main { void showCmdStatistics(void); void showHoymiles(void); void showLiveData(void); + void showMqtt(void); void saveValues(bool webSend); void dumpBuf(uint8_t buf[], uint8_t len); @@ -55,6 +59,11 @@ class app : public Main { uint32_t mCmds[6]; uint32_t mChannelStat[4]; + + // mqtt + mqtt mMqtt; + Ticker *mMqttTicker; + bool mMqttEvt; }; #endif /*__APP_H__*/ diff --git a/tools/esp8266/defines.h b/tools/esp8266/defines.h index 9dda73d5..41b729ab 100644 --- a/tools/esp8266/defines.h +++ b/tools/esp8266/defines.h @@ -15,27 +15,47 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 1 -#define VERSION_PATCH 10 +#define VERSION_PATCH 11 //------------------------------------- // EEPROM //------------------------------------- #define SSID_LEN 32 -#define PWD_LEN 64 -#define DEVNAME_LEN 32 +#define PWD_LEN 32 +#define DEVNAME_LEN 16 #define CRC_LEN 2 -#define HOY_ADDR_LEN 6 +#define INV_ADDR_LEN 6 +#define INV_INTERVAL_LEN 2 // uint16_t + + +#define MQTT_ADDR_LEN 4 // IP +#define MQTT_USER_LEN 16 +#define MQTT_PWD_LEN 32 +#define MQTT_TOPIC_LEN 32 +#define MQTT_INTERVAL_LEN 2 // uint16_t + #define ADDR_START 0 #define ADDR_SSID ADDR_START #define ADDR_PWD ADDR_SSID + SSID_LEN #define ADDR_DEVNAME ADDR_PWD + PWD_LEN -#define ADDR_HOY_ADDR ADDR_DEVNAME + DEVNAME_LEN +#define ADDR_INV0_ADDR ADDR_DEVNAME + DEVNAME_LEN +#define ADDR_INV_INTERVAL ADDR_INV0_ADDR + INV_ADDR_LEN + +#define ADDR_MQTT_ADDR ADDR_INV_INTERVAL + INV_INTERVAL_LEN +#define ADDR_MQTT_USER ADDR_MQTT_ADDR + MQTT_ADDR_LEN +#define ADDR_MQTT_PWD ADDR_MQTT_USER + MQTT_USER_LEN +#define ADDR_MQTT_TOPIC ADDR_MQTT_PWD + MQTT_PWD_LEN +#define ADDR_MQTT_INTERVAL ADDR_MQTT_TOPIC + MQTT_TOPIC_LEN + +#define ADDR_NEXT ADDR_MQTT_INTERVAL + MQTT_INTERVAL_LEN -#define ADDR_NEXT ADDR_HOY_ADDR + HOY_ADDR_LEN +#define ADDR_SETTINGS_CRC 400 -#define ADDR_SETTINGS_CRC 200 +#if(ADDR_SETTINGS_CRC <= ADDR_NEXT) +#error address overlap! +#endif #endif /*__DEFINES_H__*/ diff --git a/tools/esp8266/html/h/hoymiles_html.h b/tools/esp8266/html/h/hoymiles_html.h index 8a9f1888..4bc89397 100644 --- a/tools/esp8266/html/h/hoymiles_html.h +++ b/tools/esp8266/html/h/hoymiles_html.h @@ -1 +1 @@ -String hoymiles_html = "Index - {DEVICE}

AHOY - {DEVICE}

Home

Every 10 seconds the values are updated

© 2022

AHOY :: {VERSION}

"; +String hoymiles_html = "Index - {DEVICE}

AHOY - {DEVICE}

Home

Every 10 seconds the values are updated

© 2022

AHOY :: {VERSION}

"; diff --git a/tools/esp8266/html/h/index_html.h b/tools/esp8266/html/h/index_html.h index 8a4b2c10..8b638b0c 100644 --- a/tools/esp8266/html/h/index_html.h +++ b/tools/esp8266/html/h/index_html.h @@ -1 +1 @@ -String index_html = "Index - {DEVICE}

AHOY - {DEVICE}

Hoymiles
Update

Setup
Reboot

Uptime:

Time:

Statistics:

© 2022

AHOY :: {VERSION}

"; +String index_html = "Index - {DEVICE}

AHOY - {DEVICE}

Hoymiles
Update

Setup
Reboot

Uptime:

Time:

MQTT:

Statistics:

© 2022

AHOY :: {VERSION}

"; diff --git a/tools/esp8266/html/h/setup_html.h b/tools/esp8266/html/h/setup_html.h index 24440e88..f34e8a0f 100644 --- a/tools/esp8266/html/h/setup_html.h +++ b/tools/esp8266/html/h/setup_html.h @@ -1 +1 @@ -String setup_html = "Setup - {DEVICE}

Setup

Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information.

WiFi

SSID
PASSWORD

Device Host Name

DEVICE NAME

General

HOYMILES ADDRESS (eg. 11:22:33:44:55:66)

Home

Update Firmware

AHOY - {VERSION}

"; +String setup_html = "Setup - {DEVICE}

Setup

Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information.

WiFi

SSID
PASSWORD

Device Host Name

DEVICE NAME

Inverter

INVERTER 0 ADDRESS (eg. 11:22:33:44:55:66)
INTERVAL (ms)

MQTT

BROKER (Server IP)
USERNAME (optional)
PASSWORD (optional)
TOPIC
INTERVAL (ms)

Home

Update Firmware

AHOY - {VERSION}

"; diff --git a/tools/esp8266/html/hoymiles.html b/tools/esp8266/html/hoymiles.html index e7985edd..4ac61f25 100644 --- a/tools/esp8266/html/hoymiles.html +++ b/tools/esp8266/html/hoymiles.html @@ -5,7 +5,7 @@