From 8f389f89391b11064d24b324819dab83e464dfdd Mon Sep 17 00:00:00 2001 From: DanielR92 Date: Sat, 20 Aug 2022 22:44:44 +0200 Subject: [PATCH 01/31] Delete checkserial() in the input field Webbrowser error when the site 'setup' is called. JS function not exist. https://github.com/grindylow/ahoy/issues/184 (first row) --- tools/esp8266/web.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 9e4e9802..5ccdb002 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -185,7 +185,7 @@ void web::showSetup(void) { inv += F("serial.u64, HEX); - inv += F("\"/ maxlength=\"12\" onkeyup=\"checkSerial()\">"); + inv += F("\"/ maxlength=\"12\">"); inv += F(""); inv += F(" Date: Sat, 20 Aug 2022 23:17:37 +0200 Subject: [PATCH 02/31] Update Readme start Start to review the whole documentation and rewrite it. First draft. :) --- README.md | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b28364bb..2411a7f2 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,21 @@ ![Logo](https://github.com/grindylow/ahoy/blob/main/doc/logo1_small.png?raw=true) # ahoy -Various tools, examples, and documentation for communicating with Hoymiles microinverters. +Ahoi is a project to bypass the original Hoymiles cloud solution. +In order to use this project, it is important what the area of ​​​​application looks like. +With each version it is necessary to have an NRF24L01+. -In particular: +Click on the link below you are interested in. +There you will find further explanations on how to proceed. (*Note: It is still under construction!*) -* `doc/hoymiles-format-description.txt` is a [detailed description of the communications format](doc/hoymiles-format-description.md) and the history of this project -* `doc/getting-started-ESP8266.md` shows the [hardware setup for an ESP8266-based system](doc/getting-started-ESP8266.md) -* The `tools` folder contains various software tools for RaspberryPi, Arduino and ESP8266/ESP32: - * A [version for ESP8266](tools/esp8266/) that includes an web interface ![](../../actions/workflows/compile_esp8266.yml/badge.svg) - * A [version for Arduino Nano](tools/nano/NRF24_SendRcv/) - * An [alternative Version of the above](tools/NRF24_SendRcv/) - * A [different implementation](tools/HoyDtuSim/) - * An [implementation for Raspberry Pi](tools/rpi/) that polls an inverter and archives results as log files/stdout as well as posting them to an MQTT broker. +##### Most updated section +- [ESP8266](tools/esp8266/) that includes an web interface ![](../../actions/workflows/compile_esp8266.yml/badge.svg) -Contributors are always welcome! +##### will be updated as needed +- [Arduino Nano](tools/nano/NRF24_SendRcv/) +- [Raspberry Pi](tools/rpi/) +- [others](tools/nano/NRF24_SendRcv/) + +If errors occur or you have suggestions for ideas, please feel free to contact us [here](https://github.com/grindylow/ahoy/issues). + +**Contributors are always welcome!** From 9fbfd9389e759d444d587df0c8301bd9d64c43b2 Mon Sep 17 00:00:00 2001 From: DanielR92 Date: Sat, 20 Aug 2022 23:23:32 +0200 Subject: [PATCH 03/31] Update first draft added the todo list from the post https://github.com/grindylow/ahoy/issues/142 --- tools/esp8266/README.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tools/esp8266/README.md b/tools/esp8266/README.md index 8ea1ade0..bd835c5a 100644 --- a/tools/esp8266/README.md +++ b/tools/esp8266/README.md @@ -68,4 +68,24 @@ For now the following inverters should work out of the box: - `Time` 1.6.1 - `RF24` 1.4.5 - `PubSubClient` 2.8 -- `ArduinoJson` 6.19.4 \ No newline at end of file +- `ArduinoJson` 6.19.4 + + ## Todo's [See this post](https://github.com/grindylow/ahoy/issues/142) + +- [ ] Wechsel zu AsyncWebServer und ElegantOTA für Stabilität +- [ ] klarer Scheduler / Task manager, der ggf. den Receive Task priorisieren kann +- [x] Device Info Kommandos (Firmware Version, etc.) über das Dashboard anzeigen [Device Information ( `0x15` `REQ_ARW_DAT_ALL` ) SubCmd Kommandos #145](https://github.com/grindylow/ahoy/issues/145) +- [ ] AlarmData & AlarmUpdate Parsen und auf eigener Seite darstellen + +------------------ SWIM LANE --------------------------- + +- [ ] Device Control Kommandos aus dem Setup ermöglichen (TurnOn, TurnOff, Restart, ActivePower Limit, ReactivePower Limit, SetPowerFactor, etc.) +- [ ] Settings exportieren / importieren (API/UI) +- [ ] Settings in settings.ini speichern (LittleFS statt EEPROM) [Settings in settings.ini speichern (LittleFS statt EEPROM) #164](https://github.com/grindylow/ahoy/issues/164) +- [ ] Homepage aufräumen nur ein Status (aktuell drei AJAX Calls /uptime, /time, /cmdstat) +- [ ] app.cpp aufräumen und in hmRadio / hmProtokollGen3 auslagern +- [ ] MI Wechselrichter unterstützen (miSystem, miInverter, miDefines, miProtokollGen2 etc.) +- [ ] nRF24 Interrupt Handling sinnvoll oder warum macht die nRF24 Bibliothek ständig `0x07` Statusabfragen [NRF24 polling trotz aktiviertem IRQ #83](https://github.com/grindylow/ahoy/issues/83) +- [ ] Debug Level im Setup änderbar -auch Livedata Visualisierung abschalten ? +- [ ] MQTT Discovery (HomeAssistant) im Setup optional machen +- [x] MQTT Subscribe nur beim Reconnect [Das subscribe in der Reconnect Procedure sollte doch nur nach einem conect ausgeführt werden und nicht bei jedem Duchlauf #139](https://github.com/grindylow/ahoy/issues/139) From 83a2c9879251b7b16633d2ef68c28660e5ad001c Mon Sep 17 00:00:00 2001 From: DanielR92 Date: Sun, 21 Aug 2022 11:26:57 +0200 Subject: [PATCH 04/31] updated the ESP8266 readme --- tools/esp8266/README.md | 126 ++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 58 deletions(-) diff --git a/tools/esp8266/README.md b/tools/esp8266/README.md index bd835c5a..3f37baa0 100644 --- a/tools/esp8266/README.md +++ b/tools/esp8266/README.md @@ -1,56 +1,9 @@ ## OVERVIEW -This code is intended to run on a Wemos D1mini or similar. The code is based on 'Hubi's code, which can be found here: - -The NRF24L01+ radio module is connected to the standard SPI pins. Additional there are 3 pins, which can be set individual: CS, CE and IRQ -These pins can be changed from the /setup URL - - -## Compile - -This code can be compiled using Visual Studio Code and **PlatformIO** Addon. The settings were: - -- Board: Generic ESP8266 Module -- Flash-Size: 1MB (FS: none, OTA: 502kB) -- Install libraries (not included in the Arduino IDE 1.8.19): - - Time Arduino Time library (TimeLib.h) - - RF24 Optimized high speed nRF24L01+ driver class documentation - - PubSubClient A client library for MQTT messaging. By Nick O'Leary - - ArduinoJson Arduino Json library - -### Optional Configuration before compilation - -- number of supported inverters (set to 3 by default) `defines.h` -- DTU radio id `hmRadio.h` -- unformated list in webbrowser `/livedata` `config.h`, `LIVEDATA_VISUALIZED` - - -## Flash ESP with firmware - -1. flash the ESP with the compiled firmware using the UART pins or any preinstalled firmware with OTA capabilities -2. repower the ESP -3. the ESP will start as access point (AP) if there is no network config stored in its eeprom -4. connect to the AP, you will be forwarded to the setup page -5. configure your WiFi settings, save, repower -6. check your router or serial console for the IP address of the module. You can try ping the configured device name as well. - - -## Usage - -Connect the ESP to power and to your serial console (optional). The webinterface has the following abilities: - -- OTA Update (over the air update) -- Configuration (Wifi, inverter(s), Pinout, MQTT) -- visual display of the connected inverters / modules -- some statistics about communication (debug) - -The serial console will print the converted values which were read out of the inverter(s) - - -## Compatiblity +This page describes how the module of a Wemos D1 mini and ESP8266 is wired to the radio module, flashed and how the further steps are to communicate with the WR HM series. +#### Compatiblity For now the following inverters should work out of the box: - - HM350 - HM400 - HM600 @@ -59,16 +12,73 @@ For now the following inverters should work out of the box: - HM1200 - HM1500 -## USED LIBRARIES +The NRF24L01+ radio module is connected to the standard SPI pins. +Additional there are 3 pins, which can be set individual: CS, CE and IRQ +These pins can be changed in the http:///setup URL or with a click on the Setup link. -- `ESP8266WiFi` 1.0 -- `DNSServer` 1.1.0 -- `Ticker` 1.0 -- `ESP8266HTTPUpdateServer` 1.0 -- `Time` 1.6.1 -- `RF24` 1.4.5 -- `PubSubClient` 2.8 -- `ArduinoJson` 6.19.4 +## ESP8266 electr. associate + + +## Compile + +This code can be compiled using Visual Studio Code and **PlatformIO** Addon. The settings were: + +- Board: Generic ESP8266 Module +- Flash-Size: 1MB (FS: none, OTA: 502kB) +- Install libraries (not included in the Arduino IDE 1.8.19): + - `Time` 1.6.1 + - `RF24` 1.4.5 + - `PubSubClient` 2.8 + - `ArduinoJson` 6.19.4 + +### Optional Configuration before compilation + +- number of supported inverters (set to 3 by default) `config.h` +- DTU radio id `hmRadio.h` (default = 1234567801 +- unformated list in webbrowser `/livedata` `config.h`, `LIVEDATA_VISUALIZED` + + +## Flash ESP with firmware + +#### nodemcu-pyflasher (easy way) +1. download the flash-tool [nodemcu-pyflasher](https://github.com/marcelstoer/nodemcu-pyflasher) +2. download latest release bin-file from [ahoy_](https://github.com/grindylow/ahoy/releases) +3. connect the target device with your pc. +4. Set the correct serial port and select the correct *.bin file +5. click now on "Flash NodeMCU" + +1. flash the ESP with the compiled firmware using the UART pins or any preinstalled firmware with OTA capabilities +2. repower the ESP +3. the ESP will start as access point (AP) if there is no network config stored in its eeprom +4. connect to the AP, you will be forwarded to the setup page + +X. configure your WiFi settings, save, repower +Y. check your router or serial console for the IP address of the module. You can try ping the configured device name as well. + +## pages +| page | output | +| ---- | ------ | +| /uptime | 0 Days, 01:37:34; now: 2022-08-21 11:13:53 | +| /reboot | reboot dtu device | +| /erase | | +| /factory | | +| /setup | | +| /save | open the setup site | +| /cmdstat | show stat from the home site | +| /visualization | | +| /livedata | | +| /json | json output from the livedata | +| /api | | + +## Usage + +The webinterface has the following abilities: +- OTA Update (over the air update) +- Configuration (Wifi, inverter(s), NTP Server, Pinout, MQTT, Amplifier Power Level, Debug) +- visual display of the connected inverters / modules +- some statistics about communication (debug) + +The serial console will print the converted values which were read out of the inverter(s) ## Todo's [See this post](https://github.com/grindylow/ahoy/issues/142) From 079ba896d13d53889e6b8390bcb68e38526e8d16 Mon Sep 17 00:00:00 2001 From: tastendruecker123 <111116980+tastendruecker123@users.noreply.github.com> Date: Mon, 22 Aug 2022 19:59:45 +0200 Subject: [PATCH 05/31] MQTT reconnect delay, fixed ESP32 build --- tools/esp8266/defines.h | 1 + tools/esp8266/mqtt.h | 20 +++++++++++--------- tools/esp8266/web.cpp | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/tools/esp8266/defines.h b/tools/esp8266/defines.h index 31b65b77..4d55a7fc 100644 --- a/tools/esp8266/defines.h +++ b/tools/esp8266/defines.h @@ -104,6 +104,7 @@ typedef enum { // ToDo: to be verified by field tests #define MQTT_PORT_LEN 2 // uint16_t #define MQTT_DISCOVERY_PREFIX "homeassistant" #define MQTT_MAX_PACKET_SIZE 384 +#define MQTT_RECONNECT_DELAY 5000 #define SER_ENABLE_LEN 1 // uint8_t #define SER_DEBUG_LEN 1 // uint8_t diff --git a/tools/esp8266/mqtt.h b/tools/esp8266/mqtt.h index 74193afa..28ca2c1c 100644 --- a/tools/esp8266/mqtt.h +++ b/tools/esp8266/mqtt.h @@ -85,7 +85,8 @@ class mqtt { #endif boolean resub = false; - if(!mClient->connected()) { + if(!mClient->connected() && (millis() - lastReconnect) > MQTT_RECONNECT_DELAY ) { + lastReconnect = 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. @@ -95,14 +96,14 @@ class mqtt { resub = mClient->connect(mDevName, mCfg->user, mCfg->pwd); else resub = mClient->connect(mDevName); - } - // 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/#" + // 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/#" + } } } } @@ -113,6 +114,7 @@ class mqtt { bool mAddressSet; mqttConfig_t *mCfg; char mDevName[DEVNAME_LEN]; + unsigned long lastReconnect = 0; }; #endif /*__MQTT_H_*/ diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 5ccdb002..72d680df 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -453,7 +453,7 @@ void web::showWebApi(void) if (cmd == AlarmData){ iv->alarmMesIndex = response["payload"]; } - DPRINTLN(DBG_INFO, F("Will make tx-request 0x15 with subcmd ") + String(cmd) + F(" and payload ") + String(response["payload"])); + DPRINTLN(DBG_INFO, F("Will make tx-request 0x15 with subcmd ") + String(cmd) + F(" and payload ") + String((uint16_t) response["payload"])); // process payload from web request corresponding to the cmd iv->enqueCommand(cmd); } From f76fbea5c2c4ef77199988fe33381b15659282ec Mon Sep 17 00:00:00 2001 From: Andreas Schiffler Date: Tue, 23 Aug 2022 17:52:07 +0200 Subject: [PATCH 06/31] added last alarm msg request --- tools/esp8266/app.cpp | 18 ++- tools/esp8266/defines.h | 2 +- tools/esp8266/hmDefines.h | 12 +- tools/esp8266/hmInverter.h | 244 ++++++++++++++++++++++++++++++++++++- tools/esp8266/web.cpp | 8 ++ 5 files changed, 268 insertions(+), 16 deletions(-) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 75fe77df..1d088840 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -239,6 +239,10 @@ void app::loop(void) { if(!mPayload[iv->id].complete) { mRxFailed++; + iv->setQueuedCmdFinished(); // command failed + if(mConfig.serialDebug) { + DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); + } if(mConfig.serialDebug) { DPRINT(DBG_INFO, F("Inverter #") + String(iv->id) + " "); DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload[iv->id].retransmits) + ")"); @@ -551,18 +555,12 @@ String app::getLiveData(void) modHtml += F("
" "
") + - String(iv->name) + F(" Limit ") + String(iv->actPowerLimit); - if (true) - { // live Power Limit from inverter is always in % - modHtml += F(" %"); - } - else - { - modHtml += F(" W"); - } + String(iv->name) + F(" Limit ") + String(iv->actPowerLimit) + + F("% | last Alarm: ") + iv->lastAlarmMsg + F(""); + uint8_t list[] = {FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_PCT, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_PRA, FLD_ALARM_MES_ID}; - for (uint8_t fld = 0; fld < 12; fld++) + for (uint8_t fld = 0; fld < 11; fld++) { pos = (iv->getPosByChFld(CH0, list[fld])); if (0xff != pos) diff --git a/tools/esp8266/defines.h b/tools/esp8266/defines.h index 4d55a7fc..ef0ea40a 100644 --- a/tools/esp8266/defines.h +++ b/tools/esp8266/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 15 +#define VERSION_PATCH 16 //------------------------------------- diff --git a/tools/esp8266/hmDefines.h b/tools/esp8266/hmDefines.h index 36139bb2..6330db98 100644 --- a/tools/esp8266/hmDefines.h +++ b/tools/esp8266/hmDefines.h @@ -23,9 +23,13 @@ const char* const units[] = {"V", "A", "W", "Wh", "kWh", "Hz", "°C", "%","VAr", // field types enum {FLD_UDC = 0, FLD_IDC, FLD_PDC, FLD_YD, FLD_YW, FLD_YT, - FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_T, FLD_PCT, FLD_EFF, FLD_IRR, FLD_PRA,FLD_ALARM_MES_ID,FLD_FW_VERSION,FLD_FW_BUILD_YEAR,FLD_FW_BUILD_MONTH_DAY,FLD_HW_ID,FLD_ACT_PWR_LIMIT}; + FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_T, FLD_PCT, FLD_EFF, + FLD_IRR, FLD_PRA,FLD_ALARM_MES_ID,FLD_FW_VERSION,FLD_FW_BUILD_YEAR, + FLD_FW_BUILD_MONTH_DAY,FLD_HW_ID,FLD_ACT_PWR_LIMIT,FLD_LAST_ALARM_CODE}; + const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", "YieldTotal", - "U_AC", "I_AC", "P_AC", "Freq", "Temp", "Pct", "Efficiency", "Irradiation","P_ACr","ALARM_MES_ID","FWVersion","FWBuildYear","FWBuildMonthDay","HWPartId","PowerLimit"}; + "U_AC", "I_AC", "P_AC", "Freq", "Temp", "Pct", "Efficiency", "Irradiation","P_ACr", + "ALARM_MES_ID","FWVersion","FWBuildYear","FWBuildMonthDay","HWPartId","PowerLimit","LastAlarmCode"}; // mqtt discovery device classes enum {DEVICE_CLS_NONE = 0, DEVICE_CLS_CURRENT, DEVICE_CLS_ENERGY, DEVICE_CLS_PWR, DEVICE_CLS_VOLTAGE, DEVICE_CLS_FREQ, DEVICE_CLS_TEMP}; @@ -97,6 +101,10 @@ const byteAssign_t SystemConfigParaAssignment[] = { }; #define HMSYSTEM_LIST_LEN (sizeof(SystemConfigParaAssignment) / sizeof(byteAssign_t)) +const byteAssign_t AlarmDataAssignment[] = { + { FLD_LAST_ALARM_CODE, UNIT_NONE, CH0, 0, 2, 1 } +}; +#define HMALARMDATA_LIST_LEN (sizeof(AlarmDataAssignment) / sizeof(byteAssign_t)) diff --git a/tools/esp8266/hmInverter.h b/tools/esp8266/hmInverter.h index 774fd809..f1250ffd 100644 --- a/tools/esp8266/hmInverter.h +++ b/tools/esp8266/hmInverter.h @@ -115,6 +115,7 @@ class Inverter { RECORDTYPE *record; // pointer for values uint16_t chMaxPwr[4]; // maximum power of the modules (Wp) char chName[4][MAX_NAME_LENGTH]; // human readable name for channel + String lastAlarmMsg; bool initialized; // needed to check if the inverter was correctly added (ESP32 specific - union types are never null) Inverter() { @@ -126,6 +127,8 @@ class Inverter { devControlCmd = 0xff; initialized = false; fwVersion = 0; + lastAlarmMsg = "nothing"; + alarmMesIndex = 0; } ~Inverter() { @@ -164,8 +167,8 @@ class Inverter { memset(name, 0, MAX_NAME_LENGTH); memset(chName, 0, MAX_NAME_LENGTH * 4); memset(record, 0, sizeof(RECORDTYPE) * listLen); - enqueCommand(InverterDevInform_All); enqueCommand(SystemConfigPara); + enqueCommand(InverterDevInform_All); initialized = true; } @@ -206,12 +209,25 @@ class Inverter { val <<= 8; val |= buf[ptr]; } while(++ptr != end); - record[pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div); + if ((RECORDTYPE)(div) > 1){ + record[pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div); + } + else { + record[pos] = (RECORDTYPE)(val); + } + } if (cmd == RealTimeRunData_Debug) { // get last alarm message index and save it in the inverter object if (getPosByChFld(0, FLD_ALARM_MES_ID) == pos){ - alarmMesIndex = record[pos]; + if (alarmMesIndex < record[pos]){ + alarmMesIndex = record[pos]; + enqueCommand(AlarmUpdate); + enqueCommand(AlarmData); + } + else { + alarmMesIndex = record[pos]; // no change + } } } if (cmd == InverterDevInform_All) { @@ -228,6 +244,11 @@ class Inverter { DPRINT(DBG_DEBUG, F("Inverter actual power limit: ") + String(actPowerLimit)); } } + if (cmd == AlarmData){ + if (getPosByChFld(0, FLD_LAST_ALARM_CODE) == pos){ + lastAlarmMsg = getAlarmStr(record[pos]); + } + } } RECORDTYPE getValue(uint8_t pos) { @@ -307,10 +328,227 @@ class Inverter { listLen = (uint8_t)(HMSYSTEM_LIST_LEN); assign = (byteAssign_t *)SystemConfigParaAssignment; break; + case AlarmData: + listLen = (uint8_t)(HMALARMDATA_LIST_LEN); + assign = (byteAssign_t *)AlarmDataAssignment; + break; default: DPRINTLN(DBG_INFO, "Parser not implemented"); } } + String getAlarmStr(u_int16_t alarmCode) + { + switch (alarmCode) + { + case 1: + return String(F("Inverter start")); + break; + case 2: + return String(F("DTU command failed")); + break; + case 121: + return String(F("Over temperature protection")); + break; + case 125: + return String(F("Grid configuration parameter error")); + break; + case 126: + return String(F("Software error code 126")); + break; + case 127: + return String(F("Firmware error")); + break; + case 128: + return String(F("Software error code 128")); + break; + case 129: + return String(F("Software error code 129")); + break; + case 130: + return String(F("Offline")); + break; + case 141: + return String(F("Grid overvoltage")); + break; + case 142: + return String(F("Average grid overvoltage")); + break; + case 143: + return String(F("Grid undervoltage")); + break; + case 144: + return String(F("Grid overfrequency")); + break; + case 145: + return String(F("Grid underfrequency")); + break; + case 146: + return String(F("Rapid grid frequency change")); + break; + case 147: + return String(F("Power grid outage")); + break; + case 148: + return String(F("Grid disconnection")); + break; + case 149: + return String(F("Island detected")); + break; + case 205: + return String(F("Input port 1 & 2 overvoltage")); + break; + case 206: + return String(F("Input port 3 & 4 overvoltage")); + break; + case 207: + return String(F("Input port 1 & 2 undervoltage")); + break; + case 208: + return String(F("Input port 3 & 4 undervoltage")); + break; + case 209: + return String(F("Port 1 no input")); + break; + case 210: + return String(F("Port 2 no input")); + break; + case 211: + return String(F("Port 3 no input")); + break; + case 212: + return String(F("Port 4 no input")); + break; + case 213: + return String(F("PV-1 & PV-2 abnormal wiring")); + break; + case 214: + return String(F("PV-3 & PV-4 abnormal wiring")); + break; + case 215: + return String(F("PV-1 Input overvoltage")); + break; + case 216: + return String(F("PV-1 Input undervoltage")); + break; + case 217: + return String(F("PV-2 Input overvoltage")); + break; + case 218: + return String(F("PV-2 Input undervoltage")); + break; + case 219: + return String(F("PV-3 Input overvoltage")); + break; + case 220: + return String(F("PV-3 Input undervoltage")); + break; + case 221: + return String(F("PV-4 Input overvoltage")); + break; + case 222: + return String(F("PV-4 Input undervoltage")); + break; + case 301: + return String(F("Hardware error code 301")); + break; + case 302: + return String(F("Hardware error code 302")); + break; + case 303: + return String(F("Hardware error code 303")); + break; + case 304: + return String(F("Hardware error code 304")); + break; + case 305: + return String(F("Hardware error code 305")); + break; + case 306: + return String(F("Hardware error code 306")); + break; + case 307: + return String(F("Hardware error code 307")); + break; + case 308: + return String(F("Hardware error code 308")); + break; + case 309: + return String(F("Hardware error code 309")); + break; + case 310: + return String(F("Hardware error code 310")); + break; + case 311: + return String(F("Hardware error code 311")); + break; + case 312: + return String(F("Hardware error code 312")); + break; + case 313: + return String(F("Hardware error code 313")); + break; + case 314: + return String(F("Hardware error code 314")); + break; + case 5041: + return String(F("Error code-04 Port 1")); + break; + case 5042: + return String(F("Error code-04 Port 2")); + break; + case 5043: + return String(F("Error code-04 Port 3")); + break; + case 5044: + return String(F("Error code-04 Port 4")); + break; + case 5051: + return String(F("PV Input 1 Overvoltage/Undervoltage")); + break; + case 5052: + return String(F("PV Input 2 Overvoltage/Undervoltage")); + break; + case 5053: + return String(F("PV Input 3 Overvoltage/Undervoltage")); + break; + case 5054: + return String(F("PV Input 4 Overvoltage/Undervoltage")); + break; + case 5060: + return String(F("Abnormal bias")); + break; + case 5070: + return String(F("Over temperature protection")); + break; + case 5080: + return String(F("Grid Overvoltage/Undervoltage")); + break; + case 5090: + return String(F("Grid Overfrequency/Underfrequency")); + break; + case 5100: + return String(F("Island detected")); + break; + case 5120: + return String(F("EEPROM reading and writing error")); + break; + case 5150: + return String(F("10 min value grid overvoltage")); + break; + case 5200: + return String(F("Firmware error")); + break; + case 8310: + return String(F("Shut down")); + break; + case 9000: + return String(F("Microinverter is suspected of being stolen")); + break; + default: + return String(F("Unknown")); + break; + } + } private: std::queue> _commandQueue; diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 72d680df..426a9803 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -488,6 +488,14 @@ void web::showWebApi(void) iv->devControlRequest = true; // queue it in the request loop } } + if (response["cmd"] == (uint8_t)TurnOff){ + iv->devControlCmd = TurnOff; + iv->devControlRequest = true; // queue it in the request loop + } + if (response["cmd"] == (uint8_t)TurnOn){ + iv->devControlCmd = TurnOn; + iv->devControlRequest = true; // queue it in the request loop + } } } mWeb->send(200, "text/json", "{success:true}"); From 0af251bff996a9a93e90074e4bf376f32d7a54ba Mon Sep 17 00:00:00 2001 From: Andreas Schiffler Date: Tue, 23 Aug 2022 19:44:22 +0200 Subject: [PATCH 07/31] added esp32 to release work flow --- .github/workflows/compile_esp8266.yml | 4 ++-- tools/esp8266/scripts/getVersion.py | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile_esp8266.yml b/.github/workflows/compile_esp8266.yml index 245a5aac..787465d3 100644 --- a/.github/workflows/compile_esp8266.yml +++ b/.github/workflows/compile_esp8266.yml @@ -39,7 +39,7 @@ jobs: working-directory: tools/esp8266/html run: python convert.py - name: Run PlatformIO - run: pio run -d tools/esp8266 --environment esp8266-release + run: pio run -d tools/esp8266 --environment esp8266-release --environment esp32-wroom32-release - name: rename-binary-files id: rename-binary-files working-directory: tools/esp8266/scripts @@ -72,4 +72,4 @@ jobs: upload_url: ${{ steps.create-release.outputs.upload_url }} asset_path: ./${{ steps.rename-binary-files.outputs.name }}.zip asset_name: ${{ steps.rename-binary-files.outputs.name }}.zip - asset_content_type: application/zip \ No newline at end of file + asset_content_type: application/zip diff --git a/tools/esp8266/scripts/getVersion.py b/tools/esp8266/scripts/getVersion.py index 9907eb55..6ebe71b0 100644 --- a/tools/esp8266/scripts/getVersion.py +++ b/tools/esp8266/scripts/getVersion.py @@ -24,6 +24,12 @@ def readVersion(path, infile): src = path + ".pio/build/esp8266-release/firmware.bin" dst = path + ".pio/build/out/" + versionout os.rename(src, dst) + + versionout = version[:-1] + "_esp32_" + sha + ".bin" + src = path + ".pio/build/esp32-wroom32-release/firmware.bin" + dst = path + ".pio/build/out/" + versionout + os.rename(src, dst) + print("::set-output name=name::" + versionnumber[:-1] ) From 146a1d5eea77ac208775b37e747305436b0c1fcc Mon Sep 17 00:00:00 2001 From: Andreas Schiffler Date: Wed, 24 Aug 2022 08:31:33 +0200 Subject: [PATCH 08/31] improvment mqtt after add values --- tools/esp8266/app.cpp | 26 ++++++++++++- tools/esp8266/hmInverter.h | 75 ++++++++++++++++++++++---------------- tools/esp8266/hmRadio.h | 3 +- tools/esp8266/web.cpp | 5 ++- 4 files changed, 72 insertions(+), 37 deletions(-) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 1d088840..64923559 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -160,6 +160,7 @@ void app::loop(void) { if((++mMqttTicker >= mMqttInterval) && (mMqttInterval != 0xffff) && mMqttActive) { mMqttTicker = 0; mMqtt.isConnected(true); // really needed? See comment from HorstG-57 #176 + /* char topic[30], val[10]; for(uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); @@ -174,6 +175,8 @@ void app::loop(void) { } } } + */ + char val[10]; snprintf(val, 10, "%ld", millis()/1000); #ifndef __MQTT_NO_DISCOVERCONFIG__ @@ -370,11 +373,32 @@ void app::processPayload(bool retransmit) { yield(); } iv->doCalculations(); // cmd value decides which parser is used to decode payload + + iv->setQueuedCmdFinished(); + + // send out + char topic[30], val[10]; + for (uint8_t id = 0; id < mSys->getNumInverters(); id++) + { + Inverter<> *iv = mSys->getInverterByPos(id); + if (NULL != iv) + { + if (iv->isAvailable(mTimestamp)) + { + for (uint8_t i = 0; i < iv->listLen; i++) + { + snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, fields[iv->assign[i].fieldId]); + snprintf(val, 10, "%.3f", iv->getValue(i)); + mMqtt.sendMsg(topic, val); + yield(); + } + } + } + } #ifdef __MQTT_AFTER_RX__ doMQTT = true; #endif - iv->setQueuedCmdFinished(); } } yield(); diff --git a/tools/esp8266/hmInverter.h b/tools/esp8266/hmInverter.h index f1250ffd..6a8d2994 100644 --- a/tools/esp8266/hmInverter.h +++ b/tools/esp8266/hmInverter.h @@ -144,7 +144,8 @@ class Inverter { void setQueuedCmdFinished(){ if (!_commandQueue.empty()){ - _commandQueue.pop(); // Will destroy CommandAbstract Class Object (?) + // Will destroy CommandAbstract Class Object (?) + _commandQueue.pop(); } } @@ -153,7 +154,14 @@ class Inverter { if (_commandQueue.empty()){ // Fill with default commands enqueCommand(RealTimeRunData_Debug); - //enqueCommand(SystemConfigPara); + if (fwVersion == 0) + { // info needed maybe after "one nigth" (=> DC>0 to DC=0 and to DC>0) or reboot + enqueCommand(InverterDevInform_All); + } + if (actPowerLimit == 0xffff) + { // info needed maybe after "one nigth" (=> DC>0 to DC=0 and to DC>0) or reboot + enqueCommand(SystemConfigPara); + } } return _commandQueue.front().get()->getCmd(); } @@ -167,8 +175,6 @@ class Inverter { memset(name, 0, MAX_NAME_LENGTH); memset(chName, 0, MAX_NAME_LENGTH * 4); memset(record, 0, sizeof(RECORDTYPE) * listLen); - enqueCommand(SystemConfigPara); - enqueCommand(InverterDevInform_All); initialized = true; } @@ -222,7 +228,7 @@ class Inverter { if (getPosByChFld(0, FLD_ALARM_MES_ID) == pos){ if (alarmMesIndex < record[pos]){ alarmMesIndex = record[pos]; - enqueCommand(AlarmUpdate); + //enqueCommand(AlarmUpdate); // What is the function of AlarmUpdate? enqueCommand(AlarmData); } else { @@ -284,41 +290,46 @@ class Inverter { return false; } - uint32_t getLastTs(void) { + uint32_t getLastTs(void) + { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getLastTs")); return ts; } - void getAssignment() { + void getAssignment() + { DPRINTLN(DBG_DEBUG, F("hmInverter.h:getAssignment")); + // Default assignment; + if (INV_TYPE_1CH == type) + { + listLen = (uint8_t)(HM1CH_LIST_LEN); + assign = (byteAssign_t *)hm1chAssignment; + channels = 1; + } + else if (INV_TYPE_2CH == type) + { + listLen = (uint8_t)(HM2CH_LIST_LEN); + assign = (byteAssign_t *)hm2chAssignment; + channels = 2; + } + else if (INV_TYPE_4CH == type) + { + listLen = (uint8_t)(HM4CH_LIST_LEN); + assign = (byteAssign_t *)hm4chAssignment; + channels = 4; + } + else + { + listLen = 0; + channels = 0; + assign = NULL; + } + uint8_t cmd = getQueuedCmd(); switch (cmd) { case RealTimeRunData_Debug: - if (INV_TYPE_1CH == type) - { - listLen = (uint8_t)(HM1CH_LIST_LEN); - assign = (byteAssign_t *)hm1chAssignment; - channels = 1; - } - else if (INV_TYPE_2CH == type) - { - listLen = (uint8_t)(HM2CH_LIST_LEN); - assign = (byteAssign_t *)hm2chAssignment; - channels = 2; - } - else if (INV_TYPE_4CH == type) - { - listLen = (uint8_t)(HM4CH_LIST_LEN); - assign = (byteAssign_t *)hm4chAssignment; - channels = 4; - } - else - { - listLen = 0; - channels = 0; - assign = NULL; - } + // Do nothing will use default break; case InverterDevInform_All: listLen = (uint8_t)(HMINFO_LIST_LEN); @@ -333,7 +344,7 @@ class Inverter { assign = (byteAssign_t *)AlarmDataAssignment; break; default: - DPRINTLN(DBG_INFO, "Parser not implemented"); + DPRINTLN(DBG_INFO, "Parser not implemented"); } } String getAlarmStr(u_int16_t alarmCode) diff --git a/tools/esp8266/hmRadio.h b/tools/esp8266/hmRadio.h index 7decd2c2..de900218 100644 --- a/tools/esp8266/hmRadio.h +++ b/tools/esp8266/hmRadio.h @@ -192,10 +192,9 @@ class HmRadio { mTxBuf[10] = cmd; // cid mTxBuf[11] = 0x00; CP_U32_LittleEndian(&mTxBuf[12], ts); - if (cmd == RealTimeRunData_Debug || cmd == AlarmData || cmd == AlarmUpdate ){ + if (cmd == RealTimeRunData_Debug || cmd == AlarmData ){ mTxBuf[18] = (alarmMesId >> 8) & 0xff; mTxBuf[19] = (alarmMesId ) & 0xff; - //mTxBuf[19] = 0x05; // ToDo: Shall be the last received Alarm Index Number } else { mTxBuf[18] = 0x00; mTxBuf[19] = 0x00; diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 426a9803..070bfcbb 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -450,8 +450,9 @@ void web::showWebApi(void) if (response["tx_request"] == (uint8_t)TX_REQ_INFO) { // if the AlarmData is requested set the Alarm Index to the requested one - if (cmd == AlarmData){ - iv->alarmMesIndex = response["payload"]; + if (cmd == AlarmData || cmd == AlarmUpdate){ + // set the AlarmMesIndex for the request from user input + iv->alarmMesIndex = response["payload"]; } DPRINTLN(DBG_INFO, F("Will make tx-request 0x15 with subcmd ") + String(cmd) + F(" and payload ") + String((uint16_t) response["payload"])); // process payload from web request corresponding to the cmd From 41e67e1782cbdf7c22fcda64fe7dd2ec141c6762 Mon Sep 17 00:00:00 2001 From: DanielR92 Date: Wed, 24 Aug 2022 19:36:34 +0200 Subject: [PATCH 09/31] Added a Hint for update from a low version to new --- tools/esp8266/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/esp8266/README.md b/tools/esp8266/README.md index 3f37baa0..c8fcbccb 100644 --- a/tools/esp8266/README.md +++ b/tools/esp8266/README.md @@ -54,6 +54,8 @@ This code can be compiled using Visual Studio Code and **PlatformIO** Addon. The X. configure your WiFi settings, save, repower Y. check your router or serial console for the IP address of the module. You can try ping the configured device name as well. + +! ATTENTION: If you update from a very low version to the newest, please make sure to wipe all flash data! ## pages | page | output | From 5c33690f1ac71ca6814d93530f403669cd33375f Mon Sep 17 00:00:00 2001 From: DanielR92 Date: Wed, 24 Aug 2022 20:06:48 +0200 Subject: [PATCH 10/31] Update Scheduler / Task manager + MQTT --- tools/esp8266/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/esp8266/README.md b/tools/esp8266/README.md index 3f37baa0..143982dc 100644 --- a/tools/esp8266/README.md +++ b/tools/esp8266/README.md @@ -79,11 +79,14 @@ The webinterface has the following abilities: - some statistics about communication (debug) The serial console will print the converted values which were read out of the inverter(s) + +### MQTT command to set the DTU without webinterface + [Read here](https://github.com/grindylow/ahoy/blob/development02/tools/esp8266/User_Manual.md) ## Todo's [See this post](https://github.com/grindylow/ahoy/issues/142) - [ ] Wechsel zu AsyncWebServer und ElegantOTA für Stabilität -- [ ] klarer Scheduler / Task manager, der ggf. den Receive Task priorisieren kann +- [x] klarer Scheduler / Task manager, der ggf. den Receive Task priorisieren kann - [x] Device Info Kommandos (Firmware Version, etc.) über das Dashboard anzeigen [Device Information ( `0x15` `REQ_ARW_DAT_ALL` ) SubCmd Kommandos #145](https://github.com/grindylow/ahoy/issues/145) - [ ] AlarmData & AlarmUpdate Parsen und auf eigener Seite darstellen From 3212aeb1423a88fa3c49cbd397e5584812eaaabd Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 25 Aug 2022 09:59:21 +0200 Subject: [PATCH 11/31] code review: added check if mqtt is enabled before sending out values --- tools/esp8266/app.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 64923559..938a3e5a 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -376,21 +376,23 @@ void app::processPayload(bool retransmit) { iv->setQueuedCmdFinished(); - // send out - char topic[30], val[10]; - for (uint8_t id = 0; id < mSys->getNumInverters(); id++) - { - Inverter<> *iv = mSys->getInverterByPos(id); - if (NULL != iv) + // MQTT send out + if(mMqttActive) { + char topic[30], val[10]; + for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { - if (iv->isAvailable(mTimestamp)) + Inverter<> *iv = mSys->getInverterByPos(id); + if (NULL != iv) { - for (uint8_t i = 0; i < iv->listLen; i++) + if (iv->isAvailable(mTimestamp)) { - snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, fields[iv->assign[i].fieldId]); - snprintf(val, 10, "%.3f", iv->getValue(i)); - mMqtt.sendMsg(topic, val); - yield(); + for (uint8_t i = 0; i < iv->listLen; i++) + { + snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, fields[iv->assign[i].fieldId]); + snprintf(val, 10, "%.3f", iv->getValue(i)); + mMqtt.sendMsg(topic, val); + yield(); + } } } } @@ -968,4 +970,4 @@ void app::resetPayload(Inverter<>* iv) mPayload[iv->id].complete = false; mPayload[iv->id].requested = true; mPayload[iv->id].ts = mTimestamp; -} \ No newline at end of file +} From 3a51f3545c687106e338c99ba109c1f77611f95d Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 25 Aug 2022 10:49:31 +0200 Subject: [PATCH 12/31] improved generation of power limit control html select element --- tools/esp8266/web.cpp | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 070bfcbb..535fac1f 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -16,6 +16,21 @@ #include "html/h/setup_html.h" #include "html/h/visualization_html.h" + +const uint16_t pwrLimitOptionValues[] { + AbsolutNonPersistent, + AbsolutPersistent, + RelativNonPersistent, + RelativPersistent +}; + +const char* const pwrLimitOptions[] { + "absolute in Watt non persistent", + "absolute in Watt persistent", + "relativ in percent non persistent", + "relativ in percent persistent" +}; + //----------------------------------------------------------------------------- web::web(app *main, sysConfig_t *sysCfg, config_t *config, char version[]) { mMain = main; @@ -200,21 +215,16 @@ void web::showSetup(void) { inv += F("\"/ maxlength=\"") + String(6) + "\">"; inv += F(""); - inv += F(""); - if(iv->powerLimit[1] == RelativNonPersistent) - inv += F("PowerLimitControl\">"); - if(iv->powerLimit[1] == AbsolutPersistent) - inv += F("PowerLimitControl\">"); - if(iv->powerLimit[1] == RelativPersistent) - inv += F("PowerLimitControl\">"); - } else - inv += F("PowerLimitControl\">"); - // UGLY! But I do not know it a better way --// + inv += F(""); inv += F("
"); From fec8758de73116158625770ea5bf747cb4079aca Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 26 Aug 2022 12:47:32 +0200 Subject: [PATCH 13/31] * fix empty inverters save on a brandnew ESP * replaced several {0} by memset * erase now erases the flash with 0xff (identical to a brandnew ESP) --- tools/esp8266/app.cpp | 25 +++++++++++++------------ tools/esp8266/app.h | 9 ++++++--- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 938a3e5a..2cc048d4 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -353,8 +353,11 @@ void app::processPayload(bool retransmit) { else { mPayload[iv->id].complete = true; iv->ts = mPayload[iv->id].ts; - uint8_t payload[128] = {0}; + uint8_t payload[128]; uint8_t offs = 0; + + memset(payload, 0, 128); + for(uint8_t i = 0; i < (mPayload[iv->id].maxPackId); i ++) { memcpy(&payload[offs], mPayload[iv->id].data[i], (mPayload[iv->id].len[i])); offs += (mPayload[iv->id].len[i]); @@ -903,17 +906,15 @@ void app::saveValues(void) { mEep->write(ADDR_CFG, (uint8_t*)&mConfig, CFG_LEN); Inverter<> *iv; for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) { - iv = mSys->getInverterByPos(i); - if(NULL != iv) { - mEep->write(ADDR_INV_ADDR + (i * 8), iv->serial.u64); - mEep->write(ADDR_INV_PWR_LIM + i * 2, iv->powerLimit[0]); - mEep->write(ADDR_INV_PWR_LIM_CON + i * 2, iv->powerLimit[1]); - mEep->write(ADDR_INV_NAME + (i * MAX_NAME_LENGTH), iv->name, MAX_NAME_LENGTH); - // max channel power / name - for(uint8_t j = 0; j < 4; j++) { - mEep->write(ADDR_INV_CH_PWR + (i * 2 * 4) + (j*2), iv->chMaxPwr[j]); - mEep->write(ADDR_INV_CH_NAME + (i * 4 * MAX_NAME_LENGTH) + j * MAX_NAME_LENGTH, iv->chName[j], MAX_NAME_LENGTH); - } + iv = mSys->getInverterByPos(i, false); + mEep->write(ADDR_INV_ADDR + (i * 8), iv->serial.u64); + mEep->write(ADDR_INV_PWR_LIM + i * 2, iv->powerLimit[0]); + mEep->write(ADDR_INV_PWR_LIM_CON + i * 2, iv->powerLimit[1]); + mEep->write(ADDR_INV_NAME + (i * MAX_NAME_LENGTH), iv->name, MAX_NAME_LENGTH); + // max channel power / name + for(uint8_t j = 0; j < 4; j++) { + mEep->write(ADDR_INV_CH_PWR + (i * 2 * 4) + (j*2), iv->chMaxPwr[j]); + mEep->write(ADDR_INV_CH_NAME + (i * 4 * MAX_NAME_LENGTH) + j * MAX_NAME_LENGTH, iv->chName[j], MAX_NAME_LENGTH); } } diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index 0e09701a..3f3686ab 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -80,9 +80,10 @@ class app { } uint64_t Serial2u64(const char *val) { - char tmp[3] = {0}; + char tmp[3]; uint64_t ret = 0ULL; uint64_t u64; + memset(tmp, 0, 3); for(uint8_t i = 0; i < 6; i++) { tmp[0] = val[i*2]; tmp[1] = val[i*2 + 1]; @@ -95,7 +96,7 @@ class app { } String getDateTimeStr(time_t t) { - char str[20] = {0}; + char str[20]; if(0 == t) sprintf(str, "n/a"); else @@ -113,9 +114,11 @@ class app { void eraseSettings(bool all = false) { //DPRINTLN(DBG_VERBOSE, F("main.h:eraseSettings")); - uint8_t buf[64] = {0}; + uint8_t buf[64]; uint16_t addr = (all) ? ADDR_START : ADDR_START_SETTINGS; uint16_t end; + + memset(buf, 0xff, 64); do { end = addr + 64; if(end > (ADDR_SETTINGS_CRC + 2)) From ae968d618a1932c04904a853646b6335a432b773 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 26 Aug 2022 16:34:10 +0200 Subject: [PATCH 14/31] * added option for no powerlimit (setup) * moved function showLiveData to web.cpp * improved debug messages * cleaned some code --- tools/esp8266/app.cpp | 202 +++++++----------------------- tools/esp8266/app.h | 1 - tools/esp8266/defines.h | 1 + tools/esp8266/hmInverter.h | 45 ++++--- tools/esp8266/html/h/setup_html.h | 2 +- tools/esp8266/html/setup.html | 2 +- tools/esp8266/web.cpp | 90 ++++++++++++- 7 files changed, 152 insertions(+), 191 deletions(-) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 2cc048d4..c5989562 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -20,7 +20,7 @@ app::app() { mWifi = new ahoywifi(this, &mSysConfig, &mConfig); resetSystem(); - loadDefaultConfig(); + loadDefaultConfig(); mSys = new HmSystemType(); } @@ -64,7 +64,7 @@ void app::loop(void) { } } - + mSys->Radio.loop(); yield(); @@ -114,31 +114,31 @@ void app::loop(void) { } if(NULL != iv && p->packet[0] == (TX_REQ_DEVCONTROL + 0x80)) { // response from dev control command DPRINTLN(DBG_DEBUG, F("Response from devcontrol request received")); - iv->devControlRequest = false; - switch (p->packet[12]){ - case ActivePowerContr: - if (iv->devControlCmd >= ActivePowerContr && iv->devControlCmd <= PFSet){ // ok inverter accepted the set point copy it to dtu eeprom - if ((iv->powerLimit[1] & 0xff00) >0){ // User want to have it persistent - mEep->write(ADDR_INV_PWR_LIM + iv->id * 2,iv->powerLimit[0]); - mEep->write(ADDR_INV_PWR_LIM_CON + iv->id * 2,iv->powerLimit[1]); - updateCrc(); - mEep->commit(); - DPRINTLN(DBG_INFO, F("Inverter ") + String(iv->id) + F(" has accepted power limit set point ") + String(iv->powerLimit[0]) + F(" with PowerLimitControl ") + String(iv->powerLimit[1]) + F(", written to dtu eeprom")); - } else { - DPRINTLN(DBG_INFO, F("Inverter ") + String(iv->id) + F(" has accepted power limit set point ") + String(iv->powerLimit[0]) + F(" with PowerLimitControl ") + String(iv->powerLimit[1])); + iv->devControlRequest = false; + switch (p->packet[12]) { + case ActivePowerContr: + if (iv->devControlCmd >= ActivePowerContr && iv->devControlCmd <= PFSet) { // ok inverter accepted the set point copy it to dtu eeprom + if ((iv->powerLimit[1] & 0xff00) > 0) { // User want to have it persistent + mEep->write(ADDR_INV_PWR_LIM + iv->id * 2, iv->powerLimit[0]); + mEep->write(ADDR_INV_PWR_LIM_CON + iv->id * 2, iv->powerLimit[1]); + updateCrc(); + mEep->commit(); + DPRINTLN(DBG_INFO, F("Inverter ") + String(iv->id) + F(" has accepted power limit set point ") + String(iv->powerLimit[0]) + F(" with PowerLimitControl ") + String(iv->powerLimit[1]) + F(", written to dtu eeprom")); + } else + DPRINTLN(DBG_INFO, F("Inverter ") + String(iv->id) + F(" has accepted power limit set point ") + String(iv->powerLimit[0]) + F(" with PowerLimitControl ") + String(iv->powerLimit[1])); + iv->devControlCmd = Init; + } + break; + + default: + if (iv->devControlCmd == ActivePowerContr) { + //case inverter did not accept the sent limit; set back to last stored limit + mEep->read(ADDR_INV_PWR_LIM + iv->id * 2, (uint16_t *)&(iv->powerLimit[0])); + mEep->read(ADDR_INV_PWR_LIM_CON + iv->id * 2, (uint16_t *)&(iv->powerLimit[1])); + DPRINTLN(DBG_INFO, F("Inverter has not accepted power limit set point")); } iv->devControlCmd = Init; - } - break; - default: - if (iv->devControlCmd == ActivePowerContr){ - //case inverter did not accept the sent limit; set back to last stored limit - mEep->read(ADDR_INV_PWR_LIM + iv->id * 2, (uint16_t *)&(iv->powerLimit[0])); - mEep->read(ADDR_INV_PWR_LIM_CON + iv->id * 2, (uint16_t *)&(iv->powerLimit[1])); - DPRINTLN(DBG_INFO, F("Inverter has not accepted power limit set point")); - } - iv->devControlCmd = Init; - break; + break; } } } @@ -160,22 +160,6 @@ void app::loop(void) { if((++mMqttTicker >= mMqttInterval) && (mMqttInterval != 0xffff) && mMqttActive) { mMqttTicker = 0; mMqtt.isConnected(true); // really needed? See comment from HorstG-57 #176 - /* - char topic[30], val[10]; - for(uint8_t id = 0; id < mSys->getNumInverters(); id++) { - Inverter<> *iv = mSys->getInverterByPos(id); - if(NULL != iv) { - if(iv->isAvailable(mTimestamp)) { - for(uint8_t i = 0; i < iv->listLen; i++) { - snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, fields[iv->assign[i].fieldId]); - snprintf(val, 10, "%.3f", iv->getValue(i)); - mMqtt.sendMsg(topic, val); - yield(); - } - } - } - } - */ char val[10]; snprintf(val, 10, "%ld", millis()/1000); @@ -256,12 +240,12 @@ void app::loop(void) { yield(); if(mConfig.serialDebug) - DPRINTLN(DBG_DEBUG, F("app:loop WiFi WiFi.status ") + String(WiFi.status()) ); - DPRINTLN(DBG_INFO, F("Requesting Inverter SN ") + String(iv->serial.u64, HEX)); - if(iv->devControlRequest && iv->powerLimit[0] > 0){ // prevent to "switch off" + DPRINTLN(DBG_DEBUG, F("app:loop WiFi WiFi.status ") + String(WiFi.status())); + DPRINTLN(DBG_INFO, F("Requesting Inverter SN ") + String(iv->serial.u64, HEX)); + if(iv->devControlRequest && (iv->powerLimit[0] > 0) && (NoPowerLimit != iv->powerLimit[1])) { // prevent to "switch off" if(mConfig.serialDebug) DPRINTLN(DBG_INFO, F("Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0])); - mSys->Radio.sendControlPacket(iv->radioId.u64,iv->devControlCmd ,iv->powerLimit); + mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd ,iv->powerLimit); iv->enqueCommand(SystemConfigPara); } else { mSys->Radio.sendTimePacket(iv->radioId.u64,iv->getQueuedCmd(), mPayload[iv->id].ts,iv->alarmMesIndex); @@ -516,9 +500,10 @@ String app::getStatistics(void) { Inverter<> *iv; for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { iv = mSys->getInverterByPos(i); + content += F("Inverter #") + String(i) + F(": "); if(NULL != iv) { bool avail = true; - content += F("Inverter '") + String(iv->name) + F(" (FW-Version: ") + String(iv->fwVersion) +F(")") + F("' is "); + content += String(iv->name) + F(" (v") + String(iv->fwVersion) +F(")") + F(" is "); if(!iv->isAvailable(mTimestamp)) { content += F("not "); avail = false; @@ -533,9 +518,8 @@ String app::getStatistics(void) { content += F("-> last successful transmission: ") + getDateTimeStr(iv->getLastTs()) + "\n"; } } - else { - content += F("Inverter ") + String(i) + F(" not (correctly) configured\n"); - } + else + content += F("n/a\n"); } if(!mSys->Radio.isChipConnected()) @@ -556,113 +540,6 @@ String app::getStatistics(void) { } - -//----------------------------------------------------------------------------- -String app::getLiveData(void) -{ - String modHtml; - for (uint8_t id = 0; id < mSys->getNumInverters(); id++) - { - Inverter<> *iv = mSys->getInverterByPos(id); - if (NULL != iv) - { -#ifdef LIVEDATA_VISUALIZED - uint8_t modNum, pos; - switch (iv->type) - { - default: - case INV_TYPE_1CH: - modNum = 1; - break; - case INV_TYPE_2CH: - modNum = 2; - break; - case INV_TYPE_4CH: - modNum = 4; - break; - } - - modHtml += F("
" - "
") + - String(iv->name) + F(" Limit ") + String(iv->actPowerLimit) - + F("% | last Alarm: ") + iv->lastAlarmMsg + F(""); - - uint8_t list[] = {FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_PCT, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_PRA, FLD_ALARM_MES_ID}; - - for (uint8_t fld = 0; fld < 11; fld++) - { - pos = (iv->getPosByChFld(CH0, list[fld])); - if (0xff != pos) - { - modHtml += F("
"); - modHtml += F("") + String(iv->getValue(pos)); - modHtml += F("") + String(iv->getUnit(pos)) + F(""); - modHtml += F("") + String(iv->getFieldName(pos)) + F(""); - modHtml += F("
"); - } - } - modHtml += "
"; - - for (uint8_t ch = 1; ch <= modNum; ch++) - { - modHtml += F("
"); - if (iv->chName[ch - 1][0] == 0) - modHtml += F("CHANNEL ") + String(ch); - else - modHtml += String(iv->chName[ch - 1]); - modHtml += F(""); - for (uint8_t j = 0; j < 6; j++) - { - switch (j) - { - default: - pos = (iv->getPosByChFld(ch, FLD_UDC)); - break; - case 1: - pos = (iv->getPosByChFld(ch, FLD_IDC)); - break; - case 2: - pos = (iv->getPosByChFld(ch, FLD_PDC)); - break; - case 3: - pos = (iv->getPosByChFld(ch, FLD_YD)); - break; - case 4: - pos = (iv->getPosByChFld(ch, FLD_YT)); - break; - case 5: - pos = (iv->getPosByChFld(ch, FLD_IRR)); - break; - } - if (0xff != pos) - { - modHtml += F("") + String(iv->getValue(pos)); - modHtml += F("") + String(iv->getUnit(pos)) + F(""); - modHtml += F("") + String(iv->getFieldName(pos)) + F(""); - } - } - modHtml += "
"; - yield(); - } - modHtml += F("
Last received data requested at: ") + getDateTimeStr(iv->ts) + F("
"); - modHtml += F("
"); -#else - // dump all data to web frontend - modHtml = F("
");
-            char topic[30], val[10];
-            for (uint8_t i = 0; i < iv->listLen; i++)
-            {
-                snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, iv->getFieldName(i));
-                snprintf(val, 10, "%.3f %s", iv->getValue(i), iv->getUnit(i));
-                modHtml += String(topic) + ": " + String(val) + "\n";
-            }
-            modHtml += F("
"); -#endif - } - } - return modHtml; -} - //----------------------------------------------------------------------------- String app::getJson(void) { DPRINTLN(DBG_VERBOSE, F("app::showJson")); @@ -879,11 +756,16 @@ void app::loadEEpconfig(void) { // it is "doppelt-gemoppelt" because the inverter shall remember the setting if the dtu makes a power cycle / reboot if (iv->powerLimit[0] != 0xffff) { iv->devControlCmd = ActivePowerContr; // set active power limit - if (iv->powerLimit[1] & 0x0001){ - DPRINTLN(DBG_INFO, F("add inverter: ") + String(name) + ", SN: " + String(invSerial, HEX) + ", Power Limit: " + String(iv->powerLimit[0]) + " in %"); - } else { - DPRINTLN(DBG_INFO, F("add inverter: ") + String(name) + ", SN: " + String(invSerial, HEX) + ", Power Limit: " + String(iv->powerLimit[0]) + " in Watt"); + DPRINT(DBG_INFO, F("add inverter: ") + String(name) + ", SN: " + String(invSerial, HEX)); + if(iv->powerLimit[1] != NoPowerLimit) { + DBGPRINT(F(", Power Limit: ") + String(iv->powerLimit[0])); + if ((iv->powerLimit[1] & 0x0001) == 0x0001) + DBGPRINTLN(F(" in %")); + else + DBGPRINTLN(F(" in Watt")); } + else + DBGPRINTLN(F(" ")); } for(uint8_t j = 0; j < 4; j++) { mEep->read(ADDR_INV_CH_NAME + (i * 4 * MAX_NAME_LENGTH) + j * MAX_NAME_LENGTH, iv->chName[j], MAX_NAME_LENGTH); diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index 3f3686ab..0ccefe7f 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -71,7 +71,6 @@ class app { void saveValues(void); void resetPayload(Inverter<>* iv); String getStatistics(void); - String getLiveData(void); String getJson(void); bool getWifiApActive(void); diff --git a/tools/esp8266/defines.h b/tools/esp8266/defines.h index ef0ea40a..33732ff5 100644 --- a/tools/esp8266/defines.h +++ b/tools/esp8266/defines.h @@ -58,6 +58,7 @@ typedef enum { } DevControlCmdType; typedef enum { // ToDo: to be verified by field tests + NoPowerLimit = 0xffff, // ahoy internal value, no hoymiles value! AbsolutNonPersistent = 0UL, // 0x0000 RelativNonPersistent = 1UL, // 0x0001 AbsolutPersistent = 256UL, // 0x0100 diff --git a/tools/esp8266/hmInverter.h b/tools/esp8266/hmInverter.h index 6a8d2994..fd2eafee 100644 --- a/tools/esp8266/hmInverter.h +++ b/tools/esp8266/hmInverter.h @@ -121,10 +121,10 @@ class Inverter { Inverter() { ts = 0; powerLimit[0] = 0xffff; // 65535 W Limit -> unlimited - powerLimit[1] = 0x0000; // + powerLimit[1] = NoPowerLimit; // actPowerLimit = 0xffff; // init feedback from inverter to -1 devControlRequest = false; - devControlCmd = 0xff; + devControlCmd = InitDataState; initialized = false; fwVersion = 0; lastAlarmMsg = "nothing"; @@ -155,7 +155,7 @@ class Inverter { // Fill with default commands enqueCommand(RealTimeRunData_Debug); if (fwVersion == 0) - { // info needed maybe after "one nigth" (=> DC>0 to DC=0 and to DC>0) or reboot + { // info needed maybe after "one night" (=> DC>0 to DC=0 and to DC>0) or reboot enqueCommand(InverterDevInform_All); } if (actPowerLimit == 0xffff) @@ -325,26 +325,25 @@ class Inverter { assign = NULL; } - uint8_t cmd = getQueuedCmd(); - switch (cmd) - { - case RealTimeRunData_Debug: - // Do nothing will use default - break; - case InverterDevInform_All: - listLen = (uint8_t)(HMINFO_LIST_LEN); - assign = (byteAssign_t *)InfoAssignment; - break; - case SystemConfigPara: - listLen = (uint8_t)(HMSYSTEM_LIST_LEN); - assign = (byteAssign_t *)SystemConfigParaAssignment; - break; - case AlarmData: - listLen = (uint8_t)(HMALARMDATA_LIST_LEN); - assign = (byteAssign_t *)AlarmDataAssignment; - break; - default: - DPRINTLN(DBG_INFO, "Parser not implemented"); + switch (getQueuedCmd()) { + case RealTimeRunData_Debug: + // Do nothing will use default + break; + case InverterDevInform_All: + listLen = (uint8_t)(HMINFO_LIST_LEN); + assign = (byteAssign_t *)InfoAssignment; + break; + case SystemConfigPara: + listLen = (uint8_t)(HMSYSTEM_LIST_LEN); + assign = (byteAssign_t *)SystemConfigParaAssignment; + break; + case AlarmData: + listLen = (uint8_t)(HMALARMDATA_LIST_LEN); + assign = (byteAssign_t *)AlarmDataAssignment; + break; + default: + DPRINTLN(DBG_INFO, "Parser not implemented"); + break; } } String getAlarmStr(u_int16_t alarmCode) diff --git a/tools/esp8266/html/h/setup_html.h b/tools/esp8266/html/h/setup_html.h index 5ec006e5..6309ef25 100644 --- a/tools/esp8266/html/h/setup_html.h +++ b/tools/esp8266/html/h/setup_html.h @@ -1,4 +1,4 @@ #ifndef __SETUP_HTML_H__ #define __SETUP_HTML_H__ -const char setup_html[] PROGMEM = "Setup - {DEVICE}

Setup

ERASE SETTINGS (not WiFi)
Device Host Name
WiFi

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

Inverter{INVERTERS}

General

NTP Server
MQTT
System Config

Pinout (Wemos)

{PINOUT}

Radio (NRF24L01+)

Serial Console



"; +const char setup_html[] PROGMEM = "Setup - {DEVICE}

Setup

ERASE SETTINGS (not WiFi)
Device Host Name
WiFi

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

Inverter{INVERTERS}

General

NTP Server
MQTT
System Config

Pinout (Wemos)

{PINOUT}

Radio (NRF24L01+)

Serial Console



"; #endif /*__SETUP_HTML_H__*/ diff --git a/tools/esp8266/html/setup.html b/tools/esp8266/html/setup.html index 98a30680..d3f2ee39 100644 --- a/tools/esp8266/html/setup.html +++ b/tools/esp8266/html/setup.html @@ -128,7 +128,7 @@

Serial Console


- +
diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 535fac1f..0d933142 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -18,6 +18,7 @@ const uint16_t pwrLimitOptionValues[] { + NoPowerLimit, AbsolutNonPersistent, AbsolutPersistent, RelativNonPersistent, @@ -25,6 +26,7 @@ const uint16_t pwrLimitOptionValues[] { }; const char* const pwrLimitOptions[] { + "no power limit", "absolute in Watt non persistent", "absolute in Watt persistent", "relativ in percent non persistent", @@ -216,7 +218,7 @@ void web::showSetup(void) { inv += F(""); inv += F("
WiFi

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

Inverter{INVERTERS}

General

NTP Server
MQTT
System Config

Pinout (Wemos)

{PINOUT}

Radio (NRF24L01+)

Serial Console



"; -#endif /*__SETUP_HTML_H__*/ diff --git a/tools/esp8266/html/h/style_css.h b/tools/esp8266/html/h/style_css.h deleted file mode 100644 index 24f50e79..00000000 --- a/tools/esp8266/html/h/style_css.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __STYLE_CSS_H__ -#define __STYLE_CSS_H__ -const char style_css[] PROGMEM = "h1 {margin:0;padding:20pt;font-size:22pt;color:#fff;background-color:#006ec0;display:block;text-transform:uppercase;}html, body {font-family:Arial;margin:0;padding:0;}p {text-align:justify;font-size:13pt;}p.lic, p.lic a {font-size:8pt;color:#999;}.des {margin-top:20px;font-size:13pt;color:#006ec0;}.s_active, .s_collapsible:hover {background-color:#006ec0;}.s_content {display:none;overflow:hidden;}.s_collapsible {background-color:#044e86;color:white;cursor:pointer;padding:18px;width:100%;border:none;text-align:left;outline:none;font-size:15px;margin-bottom:4px;}.subdes {font-size:12pt;color:#006ec0;margin-left:7px;}.subsubdes {font-size:12pt;color:#006ec0;margin:0 0 7px 12px;}.hide {display:none;}a:link, a:visited {text-decoration:none;font-size:13pt;color:#006ec0;}a:hover, a:focus {color:#f00;}a.erase {background-color:#006ec0;color:#fff;padding:7px;display:inline-block;margin-top:30px;}#content {padding:15px 15px 60px 15px;}#footer {position:fixed;bottom:0px;height:45px;background-color:#006ec0;width:100%;border-top:5px solid #fff;}#footer p, #footer a {color:#fff;padding:0 7px 0 7px;font-size:10pt !important;}div.content {background-color:#fff;padding-bottom:65px;overflow:auto;}input, select {padding:7px;font-size:13pt;}input.text, select {width:70%;box-sizing:border-box;margin-bottom:10px;border:1px solid #ccc;}input.sh {max-width:150px !important;margin-right:10px;}input.btn {background-color:#006ec0;color:#fff;border:0px;float:right;margin:10px 0 30px;text-transform:uppercase;}input.cb {margin-bottom:20px;}label {width:20%;display:inline-block;font-size:12pt;padding-right:10px;margin:10px 0px 0px 15px;vertical-align:top;}fieldset {margin-bottom:15px;}.left {float:left;}.right {float:right;}div.ch-iv {width:100%;background-color:#32b004;display:inline-block;margin-bottom:15px;padding-bottom:20px;overflow:auto;}div.ch {width:220px;min-height:350px;background-color:#006ec0;display:inline-block;margin:0 10px 15px 10px;overflow:auto;padding-bottom:20px;}div.ch .value, div.ch .info, div.ch .head, div.ch-iv .value, div.ch-iv .info, div.ch-iv .head {color:#fff;display:block;width:100%;text-align:center;}.subgrp {float:left;width:220px;}div.ch .unit, div.ch-iv .unit {font-size:19px;margin-left:10px;}div.ch .value, div.ch-iv .value {margin-top:20px;font-size:24px;}div.ch .info, div.ch-iv .info {margin-top:3px;font-size:10px;}div.ch .head {background-color:#003c80;padding:10px 0 10px 0;}div.ch-iv .head {background-color:#1c6800;padding:10px 0 10px 0;}div.iv {max-width:960px;margin-bottom:40px;}div.ts {font-size:13px;background-color:#ddd;border-top:7px solid #999;padding:7px;}div.modpwr, div.modname {width:70%;display:inline-block;}#note {margin:50px 10px 10px 10px;padding-top:10px;width:100%;border-top:1px solid #bbb;}@media(max-width:500px) {div.ch .unit, div.ch-iv .unit {font-size:18px;}div.ch {width:170px;min-height:100px }.subgrp {width:180px;}}"; -#endif /*__STYLE_CSS_H__*/ diff --git a/tools/esp8266/html/h/visualization_html.h b/tools/esp8266/html/h/visualization_html.h deleted file mode 100644 index b70bc5b2..00000000 --- a/tools/esp8266/html/h/visualization_html.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __VISUALIZATION_HTML_H__ -#define __VISUALIZATION_HTML_H__ -const char visualization_html[] PROGMEM = "Index - {DEVICE}

AHOY - {DEVICE}

Every {TS}seconds the values are updated

© 2022

Home

AHOY :: {VERSION}

"; -#endif /*__VISUALIZATION_HTML_H__*/ diff --git a/tools/esp8266/html/setup.html b/tools/esp8266/html/setup.html index d3f2ee39..5be9e9d7 100644 --- a/tools/esp8266/html/setup.html +++ b/tools/esp8266/html/setup.html @@ -102,7 +102,7 @@
MQTT - + diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 0d933142..1bd12af5 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -384,7 +384,9 @@ void web::showSave(void) { // mqtt if(mWeb->arg("mqttAddr") != "") { - mWeb->arg("mqttAddr").toCharArray(mConfig->mqtt.broker, MQTT_ADDR_LEN); + String addr = mWeb->arg("mqttAddr"); + addr.trim(); + addr.toCharArray(mConfig->mqtt.broker, MQTT_ADDR_LEN); mWeb->arg("mqttUser").toCharArray(mConfig->mqtt.user, MQTT_USER_LEN); mWeb->arg("mqttPwd").toCharArray(mConfig->mqtt.pwd, MQTT_PWD_LEN); mWeb->arg("mqttTopic").toCharArray(mConfig->mqtt.topic, MQTT_TOPIC_LEN); From b67cd033d251746212dfef12a6222689cad8ddf6 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 30 Aug 2022 15:49:33 +0200 Subject: [PATCH 22/31] fix #209 --- tools/esp8266/app.cpp | 18 ++++++++---------- tools/esp8266/app.h | 1 + 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index f97a6b9d..be78d6a5 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -53,14 +53,11 @@ void app::loop(void) { mWebInst->loop(); if(checkTicker(&mUptimeTicker, mUptimeInterval)) { - mUptimeSecs++; - if(0 != mTimestamp) - mTimestamp++; - else { - if(!apActive) { - mTimestamp = mWifi->getNtpTime(); - DPRINTLN(DBG_INFO, "[NTP]: " + getDateTimeStr(mTimestamp)); - } + if(millis() - mPrevMillis >= 1000) { + mPrevMillis += 1000; + mUptimeSecs++; + if(0 != mTimestamp) + mTimestamp++; } } @@ -662,9 +659,10 @@ const char* app::getFieldStateClass(uint8_t fieldId) { void app::resetSystem(void) { mUptimeSecs = 0; mUptimeTicker = 0xffffffff; - mUptimeInterval = 1000; // [ms] + mUptimeInterval = 500; // [ms] + mPrevMillis = 0; - mNtpRefreshTicker = 0xffffffff; + mNtpRefreshTicker = 0; mNtpRefreshInterval = NTP_REFRESH_INTERVAL; // [ms] #ifdef AP_ONLY diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index 48dbc1ed..b7fd462b 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -224,6 +224,7 @@ class app { uint32_t mUptimeTicker; uint16_t mUptimeInterval; uint32_t mUptimeSecs; + uint32_t mPrevMillis; uint8_t mHeapStatCnt; uint32_t mNtpRefreshTicker; uint32_t mNtpRefreshInterval; From 11fdb4c8228ef9ebde440ea2ebb11840437cb671 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 30 Aug 2022 21:24:35 +0200 Subject: [PATCH 23/31] fix action (directory was missing - needs to be created automatically now) --- tools/esp8266/html/convert.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/esp8266/html/convert.py b/tools/esp8266/html/convert.py index 98027b2f..dadaf92d 100755 --- a/tools/esp8266/html/convert.py +++ b/tools/esp8266/html/convert.py @@ -2,6 +2,8 @@ import re import sys import os +from pathlib import Path + def convert2Header(inFile): fileType = inFile.split(".")[1] define = inFile.split(".")[0].upper() @@ -12,8 +14,10 @@ def convert2Header(inFile): print("ok") outName = "html/" + "h/" + inFileVarName + ".h" inFile = "html/" + inFile + Path("html/h").mkdir(exist_ok=True) else: outName = "h/" + inFileVarName + ".h" + Path("h").mkdir(exist_ok=True) f = open(inFile, "r") data = f.read().replace('\n', '') From 10d6fcc698a0e52168e242af04768b94ed45920b Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 30 Aug 2022 21:33:05 +0200 Subject: [PATCH 24/31] badge test --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2411a7f2..c7f2b4f0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +![actions/workflows/compile_esp8266.yml](../../actions/workflows/compile_esp8266.yml/badge.svg) ![actions/workflows/compile_development.yml](../../actions/workflows/compile_development.yml/badge.svg) + ![Logo](https://github.com/grindylow/ahoy/blob/main/doc/logo1_small.png?raw=true) # ahoy @@ -9,7 +11,7 @@ Click on the link below you are interested in. There you will find further explanations on how to proceed. (*Note: It is still under construction!*) ##### Most updated section -- [ESP8266](tools/esp8266/) that includes an web interface ![](../../actions/workflows/compile_esp8266.yml/badge.svg) +- [ESP8266](tools/esp8266/) that includes an web interface ##### will be updated as needed - [Arduino Nano](tools/nano/NRF24_SendRcv/) From 046450176b96f3e7f9390586b7892af9308288d0 Mon Sep 17 00:00:00 2001 From: thfcm <112399896+thfcm@users.noreply.github.com> Date: Wed, 31 Aug 2022 12:42:30 +0200 Subject: [PATCH 25/31] Update README.md Added Discord Link. --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index b28364bb..4e287236 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,8 @@ In particular: * An [implementation for Raspberry Pi](tools/rpi/) that polls an inverter and archives results as log files/stdout as well as posting them to an MQTT broker. Contributors are always welcome! + +## Contact +We run a Discord Server that can be used to get in touch with the Developers and Users. + +https://discord.gg/WzhxEY62mB From 6c8c94d997a5232c061b819531279a5f06bca446 Mon Sep 17 00:00:00 2001 From: Andreas Schiffler Date: Wed, 31 Aug 2022 14:44:40 +0200 Subject: [PATCH 26/31] change dir for cases --- .../DollaTek_NRF24L01_Case/case.scad | 0 .../DollaTek_NRF24L01_Case/case.stl | Bin .../DollaTek_NRF24L01_Case/case_photo.jpeg | Bin .../DollaTek_NRF24L01_Case/case_render.png | Bin .../WemosD1_NRF24_Case/ESP_NRF24_Case.stl | Bin .../WemosD1_NRF24_Case/ESP_NRF24_Case_F360.png | Bin .../WemosD1_NRF24_Case/ESP_NRF24_Case_cover.stl | Bin .../WemosD1_NRF24_Case/IMG_2135.png | Bin .../WemosD1_NRF24_Case/IMG_2136.png | Bin .../WemosD1_NRF24_Case/IMG_2137.png | Bin .../WemosD1_NRF24_Case/IMG_2140.png | Bin 11 files changed, 0 insertions(+), 0 deletions(-) rename tools/{esp8266 => cases}/DollaTek_NRF24L01_Case/case.scad (100%) rename tools/{esp8266 => cases}/DollaTek_NRF24L01_Case/case.stl (100%) rename tools/{esp8266 => cases}/DollaTek_NRF24L01_Case/case_photo.jpeg (100%) rename tools/{esp8266 => cases}/DollaTek_NRF24L01_Case/case_render.png (100%) rename tools/{esp8266 => cases}/WemosD1_NRF24_Case/ESP_NRF24_Case.stl (100%) rename tools/{esp8266 => cases}/WemosD1_NRF24_Case/ESP_NRF24_Case_F360.png (100%) rename tools/{esp8266 => cases}/WemosD1_NRF24_Case/ESP_NRF24_Case_cover.stl (100%) rename tools/{esp8266 => cases}/WemosD1_NRF24_Case/IMG_2135.png (100%) rename tools/{esp8266 => cases}/WemosD1_NRF24_Case/IMG_2136.png (100%) rename tools/{esp8266 => cases}/WemosD1_NRF24_Case/IMG_2137.png (100%) rename tools/{esp8266 => cases}/WemosD1_NRF24_Case/IMG_2140.png (100%) diff --git a/tools/esp8266/DollaTek_NRF24L01_Case/case.scad b/tools/cases/DollaTek_NRF24L01_Case/case.scad similarity index 100% rename from tools/esp8266/DollaTek_NRF24L01_Case/case.scad rename to tools/cases/DollaTek_NRF24L01_Case/case.scad diff --git a/tools/esp8266/DollaTek_NRF24L01_Case/case.stl b/tools/cases/DollaTek_NRF24L01_Case/case.stl similarity index 100% rename from tools/esp8266/DollaTek_NRF24L01_Case/case.stl rename to tools/cases/DollaTek_NRF24L01_Case/case.stl diff --git a/tools/esp8266/DollaTek_NRF24L01_Case/case_photo.jpeg b/tools/cases/DollaTek_NRF24L01_Case/case_photo.jpeg similarity index 100% rename from tools/esp8266/DollaTek_NRF24L01_Case/case_photo.jpeg rename to tools/cases/DollaTek_NRF24L01_Case/case_photo.jpeg diff --git a/tools/esp8266/DollaTek_NRF24L01_Case/case_render.png b/tools/cases/DollaTek_NRF24L01_Case/case_render.png similarity index 100% rename from tools/esp8266/DollaTek_NRF24L01_Case/case_render.png rename to tools/cases/DollaTek_NRF24L01_Case/case_render.png diff --git a/tools/esp8266/WemosD1_NRF24_Case/ESP_NRF24_Case.stl b/tools/cases/WemosD1_NRF24_Case/ESP_NRF24_Case.stl similarity index 100% rename from tools/esp8266/WemosD1_NRF24_Case/ESP_NRF24_Case.stl rename to tools/cases/WemosD1_NRF24_Case/ESP_NRF24_Case.stl diff --git a/tools/esp8266/WemosD1_NRF24_Case/ESP_NRF24_Case_F360.png b/tools/cases/WemosD1_NRF24_Case/ESP_NRF24_Case_F360.png similarity index 100% rename from tools/esp8266/WemosD1_NRF24_Case/ESP_NRF24_Case_F360.png rename to tools/cases/WemosD1_NRF24_Case/ESP_NRF24_Case_F360.png diff --git a/tools/esp8266/WemosD1_NRF24_Case/ESP_NRF24_Case_cover.stl b/tools/cases/WemosD1_NRF24_Case/ESP_NRF24_Case_cover.stl similarity index 100% rename from tools/esp8266/WemosD1_NRF24_Case/ESP_NRF24_Case_cover.stl rename to tools/cases/WemosD1_NRF24_Case/ESP_NRF24_Case_cover.stl diff --git a/tools/esp8266/WemosD1_NRF24_Case/IMG_2135.png b/tools/cases/WemosD1_NRF24_Case/IMG_2135.png similarity index 100% rename from tools/esp8266/WemosD1_NRF24_Case/IMG_2135.png rename to tools/cases/WemosD1_NRF24_Case/IMG_2135.png diff --git a/tools/esp8266/WemosD1_NRF24_Case/IMG_2136.png b/tools/cases/WemosD1_NRF24_Case/IMG_2136.png similarity index 100% rename from tools/esp8266/WemosD1_NRF24_Case/IMG_2136.png rename to tools/cases/WemosD1_NRF24_Case/IMG_2136.png diff --git a/tools/esp8266/WemosD1_NRF24_Case/IMG_2137.png b/tools/cases/WemosD1_NRF24_Case/IMG_2137.png similarity index 100% rename from tools/esp8266/WemosD1_NRF24_Case/IMG_2137.png rename to tools/cases/WemosD1_NRF24_Case/IMG_2137.png diff --git a/tools/esp8266/WemosD1_NRF24_Case/IMG_2140.png b/tools/cases/WemosD1_NRF24_Case/IMG_2140.png similarity index 100% rename from tools/esp8266/WemosD1_NRF24_Case/IMG_2140.png rename to tools/cases/WemosD1_NRF24_Case/IMG_2140.png From 616ca1600485bed4171f18558451cba235a25ee7 Mon Sep 17 00:00:00 2001 From: Andreas Schiffler Date: Wed, 31 Aug 2022 15:10:22 +0200 Subject: [PATCH 27/31] Update User_Manual.md --- tools/esp8266/User_Manual.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/esp8266/User_Manual.md b/tools/esp8266/User_Manual.md index 47879889..9dd38878 100644 --- a/tools/esp8266/User_Manual.md +++ b/tools/esp8266/User_Manual.md @@ -1,5 +1,5 @@ # User Manual Ahoy DTU (on ESP8266) -16.08.2022 +Version #{VERSION}# ## Introduction See the repository [here](https://github.com/grindylow/ahoy/blob/main/tools/esp8266/README.md) From 035557269248f192fa0c20458cb83132c1dc71b8 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 1 Sep 2022 07:25:30 +0200 Subject: [PATCH 28/31] corrected most of the review comments, except "maxlength" --- tools/esp8266/README.md | 11 ++--------- tools/esp8266/app.cpp | 14 +++++--------- tools/esp8266/app.h | 2 -- 3 files changed, 7 insertions(+), 20 deletions(-) diff --git a/tools/esp8266/README.md b/tools/esp8266/README.md index fdebe916..41fb0bb0 100644 --- a/tools/esp8266/README.md +++ b/tools/esp8266/README.md @@ -36,6 +36,7 @@ For now the following inverters should work out of the box: - HM600 - HM700 - HM800 +- HM1000? - HM1200 - HM1500 @@ -48,15 +49,7 @@ These pins can be changed in the http:///setup URL or with a click on ## Compile -This code can be compiled using Visual Studio Code and **PlatformIO** Addon. The settings were: - -- Board: Generic ESP8266 Module -- Flash-Size: 4MB -- Install libraries (not included in the Arduino IDE 1.8.19): - - `Time` 1.6.1 - - `RF24` 1.4.5 - - `PubSubClient` 2.8 - - `ArduinoJson` 6.19.4 +This code can be compiled using Visual Studio Code and **PlatformIO** Addon. ## Used Libraries diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index be78d6a5..1394876c 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -52,13 +52,11 @@ void app::loop(void) { bool apActive = mWifi->loop(); mWebInst->loop(); - if(checkTicker(&mUptimeTicker, mUptimeInterval)) { - if(millis() - mPrevMillis >= 1000) { - mPrevMillis += 1000; - mUptimeSecs++; - if(0 != mTimestamp) - mTimestamp++; - } + if(millis() - mPrevMillis >= 1000) { + mPrevMillis += 1000; + mUptimeSecs++; + if(0 != mTimestamp) + mTimestamp++; } if(checkTicker(&mNtpRefreshTicker, mNtpRefreshInterval)) { @@ -658,8 +656,6 @@ const char* app::getFieldStateClass(uint8_t fieldId) { //----------------------------------------------------------------------------- void app::resetSystem(void) { mUptimeSecs = 0; - mUptimeTicker = 0xffffffff; - mUptimeInterval = 500; // [ms] mPrevMillis = 0; mNtpRefreshTicker = 0; diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index b7fd462b..4accf7d0 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -221,8 +221,6 @@ class app { } - uint32_t mUptimeTicker; - uint16_t mUptimeInterval; uint32_t mUptimeSecs; uint32_t mPrevMillis; uint8_t mHeapStatCnt; From 365da355342ab0baad7b06df84e2603d1177dfc8 Mon Sep 17 00:00:00 2001 From: thfcm <112399896+thfcm@users.noreply.github.com> Date: Sat, 3 Sep 2022 22:16:57 +0200 Subject: [PATCH 29/31] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Überarbeitete Readme.md - Umstrukturierung der Themen - Aktualisierte Inhaltsliste - Ergänzungen --- tools/esp8266/README.md | 236 ++++++++++++++++++++++++++-------------- 1 file changed, 155 insertions(+), 81 deletions(-) diff --git a/tools/esp8266/README.md b/tools/esp8266/README.md index 41fb0bb0..a4871a6e 100644 --- a/tools/esp8266/README.md +++ b/tools/esp8266/README.md @@ -1,35 +1,34 @@ ## Table of Contents - [Overview](#overview) -- [Compile](#compile) - * [Optional Configuration before compilation](#optional-configuration-before-compilation) -- [Flash ESP with Firmware](#flash-esp-with-firmware) -- [Usage](#usage) - [Compatiblity](#compatiblity) +- [Things needed](#things-needed) +- [Wiring things up](#wiring-things-up) + + [ESP8266 wiring example](#esp8266-wiring-example) +- [Flash the Firmware on your Ahoy DTU Hardware](#flash-the-firmware-on-your-ahoy-dtu-hardware) + + [Compiling your own Version (the geek way)](#compiling-your-own-version) + - [Optional Configuration before compilation](#optional-configuration-before-compilation) + + [Using a ready-to-flash binary using nodemcu-pyflasher (the easy way)](#using-a-ready-to-flash-binary-using-nodemcu-pyflasher) +- [Connect to your Ahoy DTU](#connect-to-your-ahoy-dtu) + + [Your Ahoy DTO is very verbose using the Serial Console](#your-ahoy-dto-is-very-verbose-using-the-serial-console) + + [Connect to the Ahoy DTU Webinterface using your Browser](#connect-to-the-ahoy-dtu-webinterface-using-your-browser) + - [HTTP based Pages](#http-based-pages) +- [MQTT command to set the DTU without webinterface](#mqtt-command-to-set-the-dtu-without-webinterface) - [Used Libraries](#used-libraries) - [Contact](#contact) +- [ToDo's - remove when done](#todo) *** ## Overview -This page describes how the module of a Wemos D1 mini and ESP8266 is wired to the radio module, flashed and how the further steps are to communicate with the WR HM series. +This page describes how the module of a Wemos D1 mini and ESP8266 is wired to the radio module and is flashed with the latest Firmware.
+Further information will help you to communicate to the compatible converters. -The NRF24L01+ radio module is connected to the -standard SPI pins: -- SCLK (Signal Clock), -- MISO (Master In Slave Out) and -- MOSI (Master Out Slave In) +## Compatiblity +For now the following Inverters should work out of the box: -Additional there are 3 pins, which can be set individual: -- CS (Chip Select), -- CE (Chip Enable) and -- IRQ (Interrupt) - -These pins can be changed from the /setup URL - -#### Compatiblity -For now the following inverters should work out of the box: +Hoymiles Inverters - HM300 - HM350 - HM400 @@ -40,17 +39,143 @@ For now the following inverters should work out of the box: - HM1200 - HM1500 -The NRF24L01+ radio module is connected to the standard SPI pins. -Additional there are 3 pins, which can be set individual: CS, CE and IRQ -These pins can be changed in the http:///setup URL or with a click on the Setup link. +TSun Inverters: +- TSOL-350 +- TSOL-400 +- othery may work as well (need to be veryfied). -## ESP8266 electr. associate + +## Things needed +In order to build your own Ahoy DTU, you will need some things.
+This list is not closing as the Maker Community offers more Boards than we could cover in this Readme.

+ +We suggest to use a WEMOS D1 mini Board as well as a NRF24L01+ Breakout Board.
+Make sure it has the "+" in its name as we depend on some features provided with the plus-variant.
+Any other ESP8266 Board with at least 4MBytes of ROM could work as well, depending on your skills. + + +## Wiring things up + +The NRF24L01+ radio module is connected to the +standard SPI pins: +- SCLK (Signal Clock), +- MISO (Master In Slave Out) and +- MOSI (Master Out Slave In) + +*These pins need to be configured in the config.h.* + +Additional, there are 3 pins, which can be set individual: +- CS (Chip Select), +- CE (Chip Enable) and +- IRQ (Interrupt) + +*These pins can be changed from the /setup URL.* + +#### ESP8266 wiring example +ToDo: (this one needs to be reworked - also a generified one would be helpful) -## Compile -This code can be compiled using Visual Studio Code and **PlatformIO** Addon. + + +## Flash the Firmware on your Ahoy DTU Hardware +Once your Hardware is ready to run, you need to flash the Ahoy DTU Firmware to your Board. +You can either build your own using your own configuration or use one or our pre-compiled generic builds. + + +#### Compiling your own Version +This information suits you if you want to configure and build your own firmware. + +This code comes to you as a **PlatformIO** project and can be compiled using the **PlatformIO** Addon.
+Visual Studio Code, AtomIDE and other IDE's support the PlatformIO Addon.
+If you do not want to compile your own build, you can use one of our ready-to-flash binaries. + +##### Optional Configuration before compilation + +- number of supported inverters (set to 3 by default) `config.h` +- DTU radio id `config.h` (default = 1234567801) +- unformated list in webbrowser `/livedata` `config.h`, `LIVEDATA_VISUALIZED` + +Alternativly, instead of modifying `config.h`, `config_override_example.h` can be copied to `config_override.h` and customized. +config_override.h is excluded from version control and stays local. + + +#### Using a ready-to-flash binary using nodemcu-pyflasher +This information suits you if you just want to use an easy way. + +1. download the flash-tool [nodemcu-pyflasher](https://github.com/marcelstoer/nodemcu-pyflasher) +2. download latest release bin-file from [ahoy_](https://github.com/grindylow/ahoy/releases) +3. open flash-tool and connect the target device with your pc. +4. Set the correct serial port and select the correct *.bin file +5. click on "Flash NodeMCU" +6. flash the ESP with the compiled firmware using the UART pins or +7. repower the ESP +8. the ESP will start as access point (AP) if there is no network config stored in its eeprom +9. connect to the AP, you will be forwarded to the setup page +10. configure your WiFi settings, save, repower +11. check your router or serial console for the IP address of the module. You can try ping the configured device name as well. + +Once your Ahoy DTU is running, you can use the Over The Air (OTA) capabilities to update ypur firmware. + + +! ATTENTION: If you update from a very low version to the newest, please make sure to wipe all flash data! + + + + + + +## Connect to your Ahoy DTU +When everything is wired up and the firmware is flashed, it is time to connect to your Ahoy DTU. + + +#### Your Ahoy DTO is very verbose using the Serial Console + When connected to your computer, you can open a Serial Console to obtain additional information. + This might be useful in case of any troubles that might occur as well as to simply obtain information about the converted values which were read out of the inverter(s). + + +#### Connect to the Ahoy DTU Webinterface using your Browser + After you have sucessfully flashed and powered your Ahoy DTU, you can access it via your Browser. + If your Ahoy DTU was able to log into the configured WiFi Network, it will try to obtain an IP-Adress from your local DHCP Server (in most cases thats your Router). + In case it could not connect to your configured Network, it will provide its own WiFi Network that you can connect to for furter configuration. The WiFi SSID ("Name") and Passwort is configured in the config.h and defaults to the SSID "AHOY-DTU" with the Passwort "esp_8266". + The Ahox DTU will keep that Network open for a certain amount of time (also configurable in the config.h and defaults to 60secs). If nothing connects to it and that time runs up, it will retry to connect to the configured network an so on. + + If yonnected to your local Network, you just have to find out the used IP Address. In must cases your Router will give you a hint. + If you connect to the WiFi the Ahoy DTU opens in case it could not connect to any other Network, the IP-Address of your Ahoy DTU is 192.168.0.1. + Just open the IP-Address in your browser. + + The webinterface has the following abilities: +- OTA Update (Over The Air Update) +- Configuration (Wifi, inverter(s), NTP Server, Pinout, MQTT, Amplifier Power Level, Debug) +- visual display of the connected inverters / modules +- some statistics about communication (debug) + + +##### HTTP based Pages + To take control of your Ahoy DTU, you can directly call one of the following sub-pages (e.g. http://192.168.0.1/setup ). + +| page | use | output | +| ---- | ------ | ------ | +| /uptime | displays the uptime uf your Ahoy DTU | 0 Days, 01:37:34; now: 2022-08-21 11:13:53 | +| /reboot | reboots the Ahoy DTU | | +| /erase | erases the EEPROM | | +| /factory | resets to the factory defaults configured in config.h | | +| /setup | opens the setup page | | +| /save | | | +| /cmdstat | show stat from the home page | | +| /visualization | displays the information from your converter | | +| /livedata | displays the live data | | +| /json | gets live-data in JSON format | json output from the livedata | +| /api | | | + + + +## MQTT command to set the DTU without webinterface + [Read here](https://github.com/grindylow/ahoy/blob/development02/tools/esp8266/User_Manual.md) + + + ## Used Libraries - `ESP8266WiFi` 1.0 @@ -62,63 +187,17 @@ This code can be compiled using Visual Studio Code and **PlatformIO** Addon. - `PubSubClient` 2.8 - `ArduinoJson` 6.19.4 -### Optional Configuration before compilation -- number of supported inverters (set to 3 by default) `config.h` -- DTU radio id `config.h` (default = 1234567801) -- unformated list in webbrowser `/livedata` `config.h`, `LIVEDATA_VISUALIZED` +## Contact +We run a Discord Server that can be used to get in touch with the Developers and Users. -Alternativly, instead of modifying `config.h`, `config_override_example.h` can be copied to `config_override.h` and customized. -config_override.h is excluded from version control and stays local. +https://discord.gg/WzhxEY62mB -## Flash ESP with Firmware -#### nodemcu-pyflasher (easy way) -1. download the flash-tool [nodemcu-pyflasher](https://github.com/marcelstoer/nodemcu-pyflasher) -2. download latest release bin-file from [ahoy_](https://github.com/grindylow/ahoy/releases) -3. connect the target device with your pc. -4. Set the correct serial port and select the correct *.bin file -5. click now on "Flash NodeMCU" -1. flash the ESP with the compiled firmware using the UART pins or any preinstalled firmware with OTA capabilities -2. repower the ESP -3. the ESP will start as access point (AP) if there is no network config stored in its eeprom -4. connect to the AP, you will be forwarded to the setup page +## ToDo -X. configure your WiFi settings, save, repower -Y. check your router or serial console for the IP address of the module. You can try ping the configured device name as well. - -! ATTENTION: If you update from a very low version to the newest, please make sure to wipe all flash data! - -## pages -| page | output | -| ---- | ------ | -| /uptime | 0 Days, 01:37:34; now: 2022-08-21 11:13:53 | -| /reboot | reboot dtu device | -| /erase | | -| /factory | | -| /setup | | -| /save | open the setup site | -| /cmdstat | show stat from the home site | -| /visualization | | -| /livedata | | -| /json | json output from the livedata | -| /api | | - -## Usage - -The webinterface has the following abilities: -- OTA Update (over the air update) -- Configuration (Wifi, inverter(s), NTP Server, Pinout, MQTT, Amplifier Power Level, Debug) -- visual display of the connected inverters / modules -- some statistics about communication (debug) - -The serial console will print the converted values which were read out of the inverter(s) - -### MQTT command to set the DTU without webinterface - [Read here](https://github.com/grindylow/ahoy/blob/development02/tools/esp8266/User_Manual.md) - - ## Todo's [See this post](https://github.com/grindylow/ahoy/issues/142) +[See this post](https://github.com/grindylow/ahoy/issues/142) - [ ] Wechsel zu AsyncWebServer und ElegantOTA für Stabilität - [x] klarer Scheduler / Task manager, der ggf. den Receive Task priorisieren kann @@ -135,8 +214,3 @@ The serial console will print the converted values which were read out of the in - [ ] Debug Level im Setup änderbar -auch Livedata Visualisierung abschalten ? - [ ] MQTT Discovery (HomeAssistant) im Setup optional machen - [x] MQTT Subscribe nur beim Reconnect [Das subscribe in der Reconnect Procedure sollte doch nur nach einem conect ausgeführt werden und nicht bei jedem Duchlauf #139](https://github.com/grindylow/ahoy/issues/139) - -## Contact -We run a Discord Server that can be used to get in touch with the Developers and Users. - -https://discord.gg/WzhxEY62mB From 904c2fa43cc9d4e24c60dd6de3516b3e9a2c0f40 Mon Sep 17 00:00:00 2001 From: thfcm <112399896+thfcm@users.noreply.github.com> Date: Sun, 4 Sep 2022 08:49:11 +0200 Subject: [PATCH 30/31] Update README.md Implemented Change Request --- tools/esp8266/README.md | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/tools/esp8266/README.md b/tools/esp8266/README.md index a4871a6e..ddb94a36 100644 --- a/tools/esp8266/README.md +++ b/tools/esp8266/README.md @@ -23,7 +23,7 @@ ## Overview This page describes how the module of a Wemos D1 mini and ESP8266 is wired to the radio module and is flashed with the latest Firmware.
-Further information will help you to communicate to the compatible converters. +Further information will help you to communicate to the compatible inverters. ## Compatiblity For now the following Inverters should work out of the box: @@ -105,7 +105,7 @@ This information suits you if you just want to use an easy way. 1. download the flash-tool [nodemcu-pyflasher](https://github.com/marcelstoer/nodemcu-pyflasher) 2. download latest release bin-file from [ahoy_](https://github.com/grindylow/ahoy/releases) -3. open flash-tool and connect the target device with your pc. +3. open flash-tool and connect the target device to your computer. 4. Set the correct serial port and select the correct *.bin file 5. click on "Flash NodeMCU" 6. flash the ESP with the compiled firmware using the UART pins or @@ -116,7 +116,7 @@ This information suits you if you just want to use an easy way. 11. check your router or serial console for the IP address of the module. You can try ping the configured device name as well. -Once your Ahoy DTU is running, you can use the Over The Air (OTA) capabilities to update ypur firmware. +Once your Ahoy DTU is running, you can use the Over The Air (OTA) capabilities to update your firmware. ! ATTENTION: If you update from a very low version to the newest, please make sure to wipe all flash data! @@ -130,19 +130,19 @@ Once your Ahoy DTU is running, you can use the Over The Air (OTA) capabilities t When everything is wired up and the firmware is flashed, it is time to connect to your Ahoy DTU. -#### Your Ahoy DTO is very verbose using the Serial Console +#### Your Ahoy DTU is very verbose using the Serial Console When connected to your computer, you can open a Serial Console to obtain additional information. This might be useful in case of any troubles that might occur as well as to simply obtain information about the converted values which were read out of the inverter(s). #### Connect to the Ahoy DTU Webinterface using your Browser After you have sucessfully flashed and powered your Ahoy DTU, you can access it via your Browser. - If your Ahoy DTU was able to log into the configured WiFi Network, it will try to obtain an IP-Adress from your local DHCP Server (in most cases thats your Router). - In case it could not connect to your configured Network, it will provide its own WiFi Network that you can connect to for furter configuration. The WiFi SSID ("Name") and Passwort is configured in the config.h and defaults to the SSID "AHOY-DTU" with the Passwort "esp_8266". - The Ahox DTU will keep that Network open for a certain amount of time (also configurable in the config.h and defaults to 60secs). If nothing connects to it and that time runs up, it will retry to connect to the configured network an so on. + If your Ahoy DTU was able to log into the configured WiFi Network, it will try to obtain an IP-Address from your local DHCP Server (in most cases thats your Router). + In case it could not connect to your configured Network, it will provide its own WiFi Network that you can connect to for furter configuration. The WiFi SSID *(the WiFi Name)* and Passwort is configured in the config.h and defaults to the SSID "AHOY-DTU" with the Passwort "esp_8266". + The Ahoy DTU will keep that Network open for a certain amount of time (also configurable in the config.h and defaults to 60secs). If nothing connects to it and that time runs up, it will retry to connect to the configured network an so on. - If yonnected to your local Network, you just have to find out the used IP Address. In must cases your Router will give you a hint. - If you connect to the WiFi the Ahoy DTU opens in case it could not connect to any other Network, the IP-Address of your Ahoy DTU is 192.168.0.1. + If connected to your local Network, you just have to find out the used IP Address. In most cases your Router will give you a hint. + If you connect to the WiFi the Ahoy DTU opens in case it could not connect to any other Network, the IP-Address of your Ahoy DTU is 192.168.1.1. Just open the IP-Address in your browser. The webinterface has the following abilities: @@ -153,7 +153,7 @@ When everything is wired up and the firmware is flashed, it is time to connect t ##### HTTP based Pages - To take control of your Ahoy DTU, you can directly call one of the following sub-pages (e.g. http://192.168.0.1/setup ). + To take control of your Ahoy DTU, you can directly call one of the following sub-pages (e.g. http://192.168.1.1/setup ). | page | use | output | | ---- | ------ | ------ | @@ -198,19 +198,3 @@ https://discord.gg/WzhxEY62mB ## ToDo [See this post](https://github.com/grindylow/ahoy/issues/142) - -- [ ] Wechsel zu AsyncWebServer und ElegantOTA für Stabilität -- [x] klarer Scheduler / Task manager, der ggf. den Receive Task priorisieren kann -- [x] Device Info Kommandos (Firmware Version, etc.) über das Dashboard anzeigen [Device Information ( `0x15` `REQ_ARW_DAT_ALL` ) SubCmd Kommandos #145](https://github.com/grindylow/ahoy/issues/145) -- [ ] AlarmData & AlarmUpdate Parsen und auf eigener Seite darstellen ------------------- SWIM LANE --------------------------- -- [ ] Device Control Kommandos aus dem Setup ermöglichen (TurnOn, TurnOff, Restart, ActivePower Limit, ReactivePower Limit, SetPowerFactor, etc.) -- [ ] Settings exportieren / importieren (API/UI) -- [ ] Settings in settings.ini speichern (LittleFS statt EEPROM) [Settings in settings.ini speichern (LittleFS statt EEPROM) #164](https://github.com/grindylow/ahoy/issues/164) -- [ ] Homepage aufräumen nur ein Status (aktuell drei AJAX Calls /uptime, /time, /cmdstat) -- [ ] app.cpp aufräumen und in hmRadio / hmProtokollGen3 auslagern -- [ ] MI Wechselrichter unterstützen (miSystem, miInverter, miDefines, miProtokollGen2 etc.) -- [ ] nRF24 Interrupt Handling sinnvoll oder warum macht die nRF24 Bibliothek ständig `0x07` Statusabfragen [NRF24 polling trotz aktiviertem IRQ #83](https://github.com/grindylow/ahoy/issues/83) -- [ ] Debug Level im Setup änderbar -auch Livedata Visualisierung abschalten ? -- [ ] MQTT Discovery (HomeAssistant) im Setup optional machen -- [x] MQTT Subscribe nur beim Reconnect [Das subscribe in der Reconnect Procedure sollte doch nur nach einem conect ausgeführt werden und nicht bei jedem Duchlauf #139](https://github.com/grindylow/ahoy/issues/139) From 8b6185b02f7fe98b7a36f409584c0b35134a76eb Mon Sep 17 00:00:00 2001 From: Andreas Schiffler Date: Sun, 4 Sep 2022 12:18:37 +0200 Subject: [PATCH 31/31] Update Changes for release 0.5.16 --- tools/esp8266/CHANGES.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/esp8266/CHANGES.md b/tools/esp8266/CHANGES.md index 3e0714be..5b047ae9 100644 --- a/tools/esp8266/CHANGES.md +++ b/tools/esp8266/CHANGES.md @@ -1,5 +1,14 @@ # Changelog +- v0.5.16 + * Add alarm messages dictonary in the hminverter class + * show last alarm message in the overview after receiving the message id from the AlarmData command + * Added No-PowerLimit function/setting (thx @lumapu) + * Bug fix #195 trailing and leading spaces in setup parameters (thx @lumapu) + * Added parametric CAD model for a case (thx @cubinet-code) + * Code styling improvements (eg. dynamic creation of html code) (thx @stefan123t, @lumapu) + * Mqtt publish action is now after successful parse a payload, no own ticker + * Fixes/improvements #183, #184, #216, #213, #196, #176, #171 - v0.5.15 * Bug fix: mqtt payload handling (thx @klahus1, silverserver) * Bug fix: eeprom alignment fixed (thx @klahus1)