From cdc6fef292aefc8b433547380c19df271295bf9b Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 5 Mar 2023 09:00:59 +0100 Subject: [PATCH 01/55] Code cleanup: remove obsolete JSON_EP --- src/config/config_override_example.h | 3 --- src/web/web.h | 33 ---------------------------- 2 files changed, 36 deletions(-) diff --git a/src/config/config_override_example.h b/src/config/config_override_example.h index b56214c8..ed976ceb 100644 --- a/src/config/config_override_example.h +++ b/src/config/config_override_example.h @@ -30,9 +30,6 @@ #undef MIDNIGHTTICKER_OFFSET #define MIDNIGHTTICKER_OFFSET (mCalculatedTimezoneOffset + 1) -// To enable the json endpoint at /json -// #define ENABLE_JSON_EP - // To enable the endpoint for prometheus to scrape data from at /metrics // #define ENABLE_PROMETHEUS_EP diff --git a/src/web/web.h b/src/web/web.h index d79ace82..2c4f1ad8 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -75,9 +75,6 @@ class Web { mWeb.on("/live", HTTP_ANY, std::bind(&Web::onLive, this, std::placeholders::_1)); //mWeb.on("/api1", HTTP_POST, std::bind(&Web::showWebApi, this, std::placeholders::_1)); - #ifdef ENABLE_JSON_EP - mWeb.on("/json", HTTP_ANY, std::bind(&Web::showJson, this, std::placeholders::_1)); - #endif #ifdef ENABLE_PROMETHEUS_EP mWeb.on("/metrics", HTTP_ANY, std::bind(&Web::showMetrics, this, std::placeholders::_1)); #endif @@ -730,36 +727,6 @@ class Web { request->send(response); } -#ifdef ENABLE_JSON_EP - void showJson(AsyncWebServerRequest *request) { - DPRINTLN(DBG_VERBOSE, F("web::showJson")); - String modJson; - Inverter<> *iv; - record_t<> *rec; - char topic[40], val[25]; - - modJson = F("{\n"); - for(uint8_t id = 0; id < mSys->getNumInverters(); id++) { - iv = mSys->getInverterByPos(id); - if(NULL == iv) - continue; - - rec = iv->getRecordStruct(RealTimeRunData_Debug); - snprintf(topic, 30, "\"%s\": {\n", iv->config->name); - modJson += String(topic); - for(uint8_t i = 0; i < rec->length; i++) { - snprintf(topic, 40, "\t\"ch%d/%s\"", rec->assign[i].ch, iv->getFieldName(i, rec)); - snprintf(val, 25, "[%.3f, \"%s\"]", iv->getValue(i, rec), iv->getUnit(i, rec)); - modJson += String(topic) + ": " + String(val) + F(",\n"); - } - modJson += F("\t\"last_msg\": \"") + ah::getDateTimeStr(rec->ts) + F("\"\n\t},\n"); - } - modJson += F("\"json_ts\": \"") + String(ah::getDateTimeStr(mApp->getTimestamp())) + F("\"\n}\n"); - - AsyncWebServerResponse *response = request->beginResponse(200, F("application/json"), modJson); - request->send(response); - } -#endif #ifdef ENABLE_PROMETHEUS_EP enum { From e2af1b5f3bb6f37bc06d4c51103fb203387d22e9 Mon Sep 17 00:00:00 2001 From: rori1977 <56794204+rori1977@users.noreply.github.com> Date: Tue, 28 Mar 2023 09:22:27 +0200 Subject: [PATCH 02/55] Update CHANGES.md correction of 2 spelling mistakes only --- src/CHANGES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index debcf40d..e0591a00 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -3,7 +3,7 @@ Changelog v0.6.0 ## General * improved night time calculation time to 1 minute after last communication pause #515 * refactored code for better readability -* improved Hoymiles commuinication (retransmits, immediate power limit transmission, timing at all) +* improved Hoymiles communication (retransmits, immediate power limit transmission, timing at all) * renamed firmware binaries * add login / logout to menu * add display support for `SH1106`, `SSD1306`, `Nokia` and `ePaper 1.54"` (ESP32 only) @@ -13,7 +13,7 @@ Changelog v0.6.0 * improved wifi connection and stability (connect to strongest AP) * addded Hoymiles alarm IDs to log * improved `System` information page (eg. radio statitistics) -* improved UI (repsonsive design, (optional) dark mode) +* improved UI (responsive design, (optional) dark mode) * improved system stability (reduced `heap-fragmentation`, don't break settings on failure) #644, #645 * added support for 2nd generation of Hoymiles inverters, MI series * improved JSON API for more stable WebUI From 3b4c727d5cc118f0a295799a36449661422a429b Mon Sep 17 00:00:00 2001 From: Argafal Date: Wed, 29 Mar 2023 09:09:13 +0200 Subject: [PATCH 03/55] Update Getting_Started.md --- Getting_Started.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Getting_Started.md b/Getting_Started.md index e73277f0..876a68ea 100644 --- a/Getting_Started.md +++ b/Getting_Started.md @@ -154,7 +154,7 @@ Example wiring for a 38pin ESP32 module ##### ESP32 GPIO settings -For this wiring, set the 3 individual GPIOs under the /setup URL: +CS, CE, IRQ must be set according to how they are wired up. For the diagram above, set the 3 individual GPIOs under the /setup URL as follows: ``` CS D1 (GPIO5) @@ -162,14 +162,14 @@ CE D2 (GPIO4) IRQ D0 (GPIO16 - no IRQ!) ``` -ATTENTION: From development version 108 onwards, also MISO, MOSI and SCLK -are configurable. Their defaults are correct for 'standard' ESP32 boards -and non-settable for ESP8266 (as this chip cannot move them elsewhere). -If you have an existing install though, you might see '0' in the web GUI. +IMPORTANT: From development version 108/release 0.6.0 onwards, also MISO, MOSI, and SCLK +are configurable. On new installations, their defaults are correct for most ESP32 boards. +These pins cannot be configured for ESP82xx boards, as this chip cannot move them elsewhere. -Set MISO=19, MOSI=23, SCLK=18 in GUI and save for existing installs, this is the old -correct default for most ESP32 boards, for ESP82xx, a simple settings save should suffice. -Reboot afterwards. +If you are upgrading an existing install though, you might see that these pins are set to '0' in the web GUI. +Communication with the NRF module wont work. For upgrading an existing installations, set MISO=19, MOSI=23, SCLK=18 in the settings. +This is the correct default for most ESP32 boards. On ESP82xx, simply saving the settings without changes should suffice. +Save and reboot. ## Flash the Firmware on your Ahoy DTU Hardware From 88f5120fc0d2cd2b1f7c40ca56bc49c52af7e79d Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Thu, 30 Mar 2023 13:58:22 +0200 Subject: [PATCH 04/55] MI - restructure priority handling - app differenciates between HM and MI type now (thx to beegee3 and AsZork) - review debug output (also for HM) --- src/app.h | 8 ++- src/hm/hmPayload.h | 29 +++++----- src/hm/miPayload.h | 138 +++++++++++++++++++++++++-------------------- 3 files changed, 98 insertions(+), 77 deletions(-) diff --git a/src/app.h b/src/app.h index cbf7e6a1..069f3c7d 100644 --- a/src/app.h +++ b/src/app.h @@ -141,8 +141,12 @@ class app : public IApp, public ah::Scheduler { } void ivSendHighPrio(Inverter<> *iv) { - if(mIVCommunicationOn) // only send commands if communcation is enabled - mPayload.ivSendHighPrio(iv); + if(mIVCommunicationOn) { // only send commands if communcation is enabled + if (iv->ivGen == IV_HM) + mPayload.ivSendHighPrio(iv); + else if (iv->ivGen == IV_MI) + mMiPayload.ivSendHighPrio(iv); + } } bool getMqttIsConnected() { diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index 0af8f466..ff555c33 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -64,7 +64,7 @@ class HmPayload { } void loop() { - if(NULL != mHighPrioIv) { + if ( NULL != mHighPrioIv && mHighPrioIv->ivGen == IV_HM ) { ivSend(mHighPrioIv, true); mHighPrioIv = NULL; } @@ -110,19 +110,22 @@ class HmPayload { process(false); // no retransmit if (!mPayload[iv->id].complete) { - if (MAX_PAYLOAD_ENTRIES == mPayload[iv->id].maxPackId) + if (mSerialDebug) + DPRINT_IVID(DBG_INFO, iv->id); + if (MAX_PAYLOAD_ENTRIES == mPayload[iv->id].maxPackId) { mStat->rxFailNoAnser++; // got nothing - else + if (mSerialDebug) + DBGPRINTLN(F("enqueued cmd failed/timeout")); + } + else { mStat->rxFail++; // got fragments but not complete response - - iv->setQueuedCmdFinished(); // command failed - if (mSerialDebug) { - DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); - DPRINT_IVID(DBG_INFO, iv->id); - DBGPRINT(F("no Payload received! (retransmits: ")); - DBGPRINT(String(mPayload[iv->id].retransmits)); - DBGPRINTLN(F(")")); + if (mSerialDebug) { + DBGPRINT(F("no complete Payload received! (retransmits: ")); + DBGPRINT(String(mPayload[iv->id].retransmits)); + DBGPRINTLN(F(")")); + } } + iv->setQueuedCmdFinished(); // command failed } } } @@ -390,8 +393,8 @@ class HmPayload { } void reset(uint8_t id) { - DPRINT(DBG_INFO, "resetPayload: id: "); - DBGPRINTLN(String(id)); + DPRINT_IVID(DBG_INFO, id); + DBGPRINTLN(F("resetPayload")); memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES); mPayload[id].txCmd = 0; mPayload[id].gotFragment = false; diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index dbe43c06..79bae081 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -25,7 +25,6 @@ typedef struct { uint8_t txId; uint8_t invId; uint8_t retransmits; - //uint8_t skipfirstrepeat; bool gotFragment; /* uint8_t data[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE]; @@ -70,8 +69,8 @@ class MiPayload { } void loop() { - if(NULL != mHighPrioIv) { // && mHighPrioIv->ivGen == IV_MI) { - ivSend(mHighPrioIv, true); // for devcontrol commands? + if ( NULL != mHighPrioIv && mHighPrioIv->ivGen == IV_MI ) { + ivSend(mHighPrioIv, true); // for e.g. devcontrol commands mHighPrioIv = NULL; } } @@ -87,21 +86,23 @@ class MiPayload { process(false); // no retransmit if (!mPayload[iv->id].complete) { - if (!mPayload[iv->id].gotFragment) - mStat->rxFailNoAnser++; // got nothing - else - mStat->rxFail++; // got fragments but not complete response - - iv->setQueuedCmdFinished(); // command failed if (mSerialDebug) DPRINT_IVID(DBG_INFO, iv->id); - DBGPRINTLN(F("enqueued cmd failed/timeout")); - if (mSerialDebug) { - DPRINT_IVID(DBG_INFO, iv->id); - DBGPRINT(F("no Payload received! (retransmits: ")); - DBGPRINT(String(mPayload[iv->id].retransmits)); - DBGPRINTLN(F(")")); + if (!mPayload[iv->id].gotFragment) { + mStat->rxFailNoAnser++; // got nothing + if (mSerialDebug) + DBGPRINTLN(F("enqueued cmd failed/timeout")); } + else { + mStat->rxFail++; // got "fragments" (part of the required messages) + // but no complete set of responses + if (mSerialDebug) { + DBGPRINT(F("no complete Payload received! (retransmits: ")); + DBGPRINT(String(mPayload[iv->id].retransmits)); + DBGPRINTLN(F(")")); + } + } + iv->setQueuedCmdFinished(); // command failed } } } @@ -232,42 +233,39 @@ const byteAssign_t InfoAssignment[] = { iv->setValue(i, rec, (float) ((p->packet[(12+2*i)] << 8) + p->packet[(13+2*i)])/1); } iv->isConnected = true; + mPayload[iv->id].gotFragment = true; if(mSerialDebug) { DPRINT_IVID(DBG_INFO, iv->id); DPRINT(DBG_INFO,F("HW_VER is ")); DBGPRINTLN(String((p->packet[24] << 8) + p->packet[25])); } - /*iv->setQueuedCmdFinished(); - mSys->Radio.sendCmdPacket(iv->radioId.u64, 0x0f, 0x01, false);*/ } else if ( p->packet[9] == 0x01 || p->packet[9] == 0x10 ) {//second frame for MI, 3rd gen. answers in 0x10 DPRINT_IVID(DBG_INFO, iv->id); if ( p->packet[9] == 0x01 ) { DBGPRINTLN(F("got 2nd frame (hw info)")); - } else { - DBGPRINTLN(F("3rd gen. inverter!")); // see table in OpenDTU code, DevInfoParser.cpp devInfo[] - } - // xlsx: HW_ECapValue is total energy?!? (data coll. inst. #154) - DPRINT(DBG_INFO,F("HW_PartNo ")); - DBGPRINTLN(String((uint32_t) (((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])); - //DBGPRINTLN(String((p->packet[12] << 8) + p->packet[13])); - if ( p->packet[9] == 0x01 ) { + DPRINT(DBG_INFO,F("HW_PartNo ")); + DBGPRINTLN(String((uint32_t) (((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])); + mPayload[iv->id].gotFragment = true; iv->setValue(iv->getPosByChFld(0, FLD_YT, rec), rec, (float) ((p->packet[20] << 8) + p->packet[21])/1); if(mSerialDebug) { - DPRINT(DBG_INFO,F("HW_ECapValue ")); - DBGPRINTLN(String((p->packet[20] << 8) + p->packet[21])); - DPRINT(DBG_INFO,F("HW_FB_TLmValue ")); DBGPRINTLN(String((p->packet[14] << 8) + p->packet[15])); DPRINT(DBG_INFO,F("HW_FB_ReSPRT ")); DBGPRINTLN(String((p->packet[16] << 8) + p->packet[17])); DPRINT(DBG_INFO,F("HW_GridSamp_ResValule ")); DBGPRINTLN(String((p->packet[18] << 8) + p->packet[19])); + DPRINT(DBG_INFO,F("HW_ECapValue ")); + DBGPRINTLN(String((p->packet[20] << 8) + p->packet[21])); } + } else { + DBGPRINTLN(F("3rd gen. inverter!")); // see table in OpenDTU code, DevInfoParser.cpp devInfo[] } + } else if ( p->packet[9] == 0x12 ) {//3rd frame DPRINT_IVID(DBG_INFO, iv->id); DBGPRINTLN(F("got 3rd frame (hw info)")); iv->setQueuedCmdFinished(); + mPayload[iv->id].complete = true; mStat->rxSuccess++; } @@ -347,7 +345,9 @@ const byteAssign_t InfoAssignment[] = { payloadLen -= 2; if (mSerialDebug) { - DPRINT(DBG_INFO, F("Payload (") + String(payloadLen) + "): "); + DPRINT(DBG_INFO, F("Payload (")); + DBGPRINT(String(payloadLen)); + DBGPRINT("): "); mSys->Radio.dumpBuf(payload, payloadLen); } @@ -448,8 +448,8 @@ const byteAssign_t InfoAssignment[] = { } else { bool change = false; if ( cmd >= 0x36 && cmd < 0x39 ) { // MI-1500 Data command - //cmd++; // just request the next channel - //change = true; + if (cmd > 0x36 && mPayload[iv->id].retransmits==1) // first request for the upper channels + change = true; } else if ( cmd == 0x09 ) {//MI single or dual channel device if ( mPayload[iv->id].dataAB[CH1] && iv->type == INV_TYPE_2CH ) { if (!mPayload[iv->id].stsAB[CH1] && mPayload[iv->id].retransmits<2) {} @@ -641,7 +641,6 @@ const byteAssign_t InfoAssignment[] = { ( p->packet[0] == 0x91 || p->packet[0] == (0x37 + ALL_FRAMES) ) ? CH2 : p->packet[0] == (0x38 + ALL_FRAMES) ? CH3 : CH4; - //DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") data msg 0x") + String(p->packet[0], HEX) + F(" channel ") + datachan); // count in RF_communication_protocol.xlsx is with offset = -1 iv->setValue(iv->getPosByChFld(datachan, FLD_UDC, rec), rec, (float)((p->packet[9] << 8) + p->packet[10])/10); yield(); @@ -656,7 +655,6 @@ const byteAssign_t InfoAssignment[] = { yield(); iv->setValue(iv->getPosByChFld(0, FLD_T, rec), rec, (float) ((int16_t)(p->packet[21] << 8) + p->packet[22])/10); iv->setValue(iv->getPosByChFld(0, FLD_IRR, rec), rec, (float) (calcIrradiation(iv, datachan))); - //AC Power is missing; we may have to calculate, as no respective data is in payload if ( datachan < 3 ) { mPayload[iv->id].dataAB[datachan] = true; @@ -687,17 +685,13 @@ const byteAssign_t InfoAssignment[] = { mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); mPayload[iv->id].txCmd = cmd;*/ mPayload[iv->id].txCmd++; - if (mPayload[iv->id].retransmits) - mPayload[iv->id].retransmits--; // reserve retransmissions for each response + mPayload[iv->id].retransmits = 0; // reserve retransmissions for each response mPayload[iv->id].complete = false; } - else if (p->packet[0] == (0x39 + ALL_FRAMES) ) { - /*uint8_t cmd = p->packet[0] - ALL_FRAMES + 1; - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); - mPayload[iv->id].txCmd = cmd;*/ + /*else if ( p->packet[0] == (0x39 + ALL_FRAMES) ) { mPayload[iv->id].complete = true; - } + }*/ /*if (iv->alarmMesIndex < rec->record[iv->getPosByChFld(0, FLD_EVT, rec)]){ iv->alarmMesIndex = rec->record[iv->getPosByChFld(0, FLD_EVT, rec)]; @@ -709,35 +703,34 @@ const byteAssign_t InfoAssignment[] = { } - if ( mPayload[iv->id].complete || //4ch device - (iv->type != INV_TYPE_4CH //other devices + /* + if(AlarmData == mPayload[iv->id].txCmd) { + uint8_t i = 0; + uint16_t code; + uint32_t start, end; + while(1) { + code = iv->parseAlarmLog(i++, payload, payloadLen, &start, &end); + if(0 == code) + break; + if (NULL != mCbMiAlarm) + (mCbAlarm)(code, start, end); + yield(); + } + }*/ + + //if ( mPayload[iv->id].complete || //4ch device + if ( p->packet[0] == (0x39 + ALL_FRAMES) || //4ch device - last message + (iv->type != INV_TYPE_4CH //other devices && mPayload[iv->id].dataAB[CH0] && mPayload[iv->id].stsAB[CH0])) { miComplete(iv); } - - - -/* - if(AlarmData == mPayload[iv->id].txCmd) { - uint8_t i = 0; - uint16_t code; - uint32_t start, end; - while(1) { - code = iv->parseAlarmLog(i++, payload, payloadLen, &start, &end); - if(0 == code) - break; - if (NULL != mCbMiAlarm) - (mCbAlarm)(code, start, end); - yield(); - } - }*/ } void miComplete(Inverter<> *iv) { - if (mPayload[iv->id].complete) - return; //if we got second message as well in repreated attempt - mPayload[iv->id].complete = true; // For 2 CH devices, this might be too short... + if ( mPayload[iv->id].complete ) // && iv->type != INV_TYPE_4CH) + return; // if we got second message as well in repreated attempt + mPayload[iv->id].complete = true; DPRINT_IVID(DBG_INFO, iv->id); DBGPRINTLN(F("got all msgs")); record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); @@ -778,6 +771,27 @@ const byteAssign_t InfoAssignment[] = { return true; } +/* uint16_t mParseAlarmLog(uint8_t id, uint8_t pyld[], uint8_t len, uint32_t *start, uint32_t *endTime) { + uint8_t startOff = 2 + id * ALARM_LOG_ENTRY_SIZE; + if((startOff + ALARM_LOG_ENTRY_SIZE) > len) + return 0; + + uint16_t wCode = ((uint16_t)pyld[startOff]) << 8 | pyld[startOff+1]; + uint32_t startTimeOffset = 0, endTimeOffset = 0; + + if (((wCode >> 13) & 0x01) == 1) // check if is AM or PM + startTimeOffset = 12 * 60 * 60; + if (((wCode >> 12) & 0x01) == 1) // check if is AM or PM + endTimeOffset = 12 * 60 * 60; + + *start = (((uint16_t)pyld[startOff + 4] << 8) | ((uint16_t)pyld[startOff + 5])) + startTimeOffset; + *endTime = (((uint16_t)pyld[startOff + 6] << 8) | ((uint16_t)pyld[startOff + 7])) + endTimeOffset; + + DPRINTLN(DBG_INFO, "Alarm #" + String(pyld[startOff+1]) + " '" + String(getAlarmStr(pyld[startOff+1])) + "' start: " + ah::getTimeStr(*start) + ", end: " + ah::getTimeStr(*endTime)); + return pyld[startOff+1]; + } +*/ + void reset(uint8_t id, bool clrSts = false) { DPRINT_IVID(DBG_INFO, id); DBGPRINTLN(F("resetPayload")); From f4accf1e373049778df6dbc7746d21a718453f52 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Thu, 30 Mar 2023 19:44:08 +0200 Subject: [PATCH 05/55] MI - find priority inverter remove unnecessary type checks --- src/hm/hmPayload.h | 2 +- src/hm/miPayload.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index ff555c33..de99d41b 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -64,7 +64,7 @@ class HmPayload { } void loop() { - if ( NULL != mHighPrioIv && mHighPrioIv->ivGen == IV_HM ) { + if (NULL != mHighPrioIv) { ivSend(mHighPrioIv, true); mHighPrioIv = NULL; } diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 79bae081..fd2665f8 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -69,7 +69,7 @@ class MiPayload { } void loop() { - if ( NULL != mHighPrioIv && mHighPrioIv->ivGen == IV_MI ) { + if (NULL != mHighPrioIv) { ivSend(mHighPrioIv, true); // for e.g. devcontrol commands mHighPrioIv = NULL; } From 1bc2d2551cc60f4b9cc005bb0efd4472e7f76be4 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 31 Mar 2023 00:08:40 +0200 Subject: [PATCH 06/55] improved phrasing of readme's --- Getting_Started.md | 16 +++++++--------- README.md | 6 ++---- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/Getting_Started.md b/Getting_Started.md index 876a68ea..3a031af0 100644 --- a/Getting_Started.md +++ b/Getting_Started.md @@ -1,13 +1,12 @@ ## 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 inverters. +On this page, you'll find detailed instructions on how to wire the module of a Wemos D1 mini or ESP32 to the radio module, as well as how to flash it with the latest firmware. This information will enable you to communicate with compatible inverters. You find the full [User_Manual here](User_Manual.md) ## Compatiblity -For now the following Inverters should work out of the box: +The following inverters are currently supported out of the box: Hoymiles Inverters @@ -55,12 +54,11 @@ Solenso Inverters: ## 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.

+If you're interested in building your own AhoyDTU, you'll need a few things to get started. While we've provided a list of recommended boards below, keep in mind that the maker community is constantly developing new and innovative options that we may not have covered in this readme.. -We suggest to use a WEMOS D1 mini Board as well as a NRF24L01+ Breakout Board as a bare minimum.
-Any other ESP8266 Board with at least 4MBytes of ROM could work as well, depending on your skills and goals.
-Make sure the NRF24L01+ module has the "+" in its name as we depend on the 250kbps features provided only with the plus-variant. +For optimal performance, we recommend using a Wemos D1 mini or ESP32 along with a NRF24L01+ breakout board as a bare minimum. However, if you have experience working with other ESP boards, any board with at least 4MBytes of ROM may be suitable, depending on your skills. + +Just be sure that the NRF24L01+ module you choose includes the "+" in its name, as we rely on the 250kbps features that are only provided by the plus-variant. | **Parts** | **Price** | | --- | --- | @@ -70,7 +68,7 @@ Make sure the NRF24L01+ module has the "+" in its name as we depend on the 250kb | Jumper Wire Steckbrücken Steckbrett weiblich-weiblich | 2,49 Euro | | **Total costs** | **10,34 Euro** | -To also run our sister project OpenDTU and be upwards compatible for the future we would recommend to spend some more money on an ESP32 board which has two CPU cores and a NRF24L01+ module with external antenna. +If you're interested in using our sister project OpenDTU or you want to future-proof your setup, we recommend investing in an ESP32 board that features two CPU cores. As Radio you can also use a NRF24L01+ module with an external antenna. While this option may cost a bit more, it will provide superior performance and ensure compatibility with upcoming developments. | **Parts** | **Price** | | --- | --- | diff --git a/README.md b/README.md index 78094c78..73c4184f 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ This work is licensed under a # 🖐 Ahoy! ![Logo](https://github.com/grindylow/ahoy/blob/main/doc/logo1_small.png?raw=true) -**Communicate with Hoymiles inverters via radio**. Get actual values like power, current, daily energy and set parameters like the power limit via web interface or MQTT. In this repository you will find different approaches means Hardware / Software to realize the described functionalities. +This repository offers hardware and software solutions for communicating with Hoymiles inverters via radio. With our system, you can easily obtain real-time values such as power, current, and daily energy. Additionally, you can set parameters like the power limit of your inverter to achieve zero export. You can access these functionalities through our user-friendly web interface, MQTT, or JSON. Whether you're monitoring your solar panel system's performance or fine-tuning its settings, our solutions make it easy to achieve your goals. Table of approaches: @@ -43,9 +43,7 @@ Table of approaches: - [The root of development](https://www.mikrocontroller.net/topic/525778) ### Development -If you encounter issues use the issues here on github. - -Please try to describe your issues as precise as possible and think about if this is a issue with the software here in the repository or other software components. +If you run into any issues, please feel free to use the issue tracker here on Github. When describing your issue, please be as detailed and precise as possible, and take a moment to consider whether the issue is related to our software. This will help us to provide more effective solutions to your problem. **Contributors are always welcome!** From f6993fdc696780284353ecd27a010c38ac40269b Mon Sep 17 00:00:00 2001 From: Markus Krause Date: Fri, 31 Mar 2023 00:12:01 +0200 Subject: [PATCH 07/55] fix S3 bin distribution --- scripts/getVersion.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/getVersion.py b/scripts/getVersion.py index 0ebe1ec2..7fbe0e1b 100644 --- a/scripts/getVersion.py +++ b/scripts/getVersion.py @@ -50,6 +50,7 @@ def readVersion(path, infile): versionnumber += line[p+13:].rstrip() + "." os.mkdir(path + "firmware/") + os.mkdir(path + "firmware/s3/") sha = os.getenv("SHA",default="sha") versionout = version[:-1] + "_" + sha + "_esp8266.bin" @@ -80,7 +81,7 @@ def readVersion(path, infile): versionout = version[:-1] + "_" + sha + "_esp32s3.bin" src = path + ".pio/build/opendtufusionv1-release/firmware.bin" - dst = path + "firmware/" + versionout + dst = path + "firmware/s3/" + versionout os.rename(src, dst) # other ESP32 bin files @@ -89,6 +90,15 @@ def readVersion(path, infile): os.rename(src + "bootloader.bin", dst + "bootloader.bin") os.rename(src + "partitions.bin", dst + "partitions.bin") genOtaBin(path + "firmware/") + + # other ESP32S3 bin files + src = path + ".pio/build/opendtufusionv1-release/" + dst = path + "firmware/s3/" + os.rename(src + "bootloader.bin", dst + "bootloader.bin") + os.rename(src + "partitions.bin", dst + "partitions.bin") + os.rename("~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin", dst + "ota.bin") + genOtaBin(path + "firmware/s3/") + os.rename("../scripts/gh-action-dev-build-flash.html", path + "install.html") print("name=" + versionnumber[:-1] ) From 2eb845a9cb6e63df886d455fbe2375d6efb0f370 Mon Sep 17 00:00:00 2001 From: Markus Krause Date: Fri, 31 Mar 2023 00:21:16 +0200 Subject: [PATCH 08/55] remove redundant call --- scripts/getVersion.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/getVersion.py b/scripts/getVersion.py index 7fbe0e1b..e3927907 100644 --- a/scripts/getVersion.py +++ b/scripts/getVersion.py @@ -97,7 +97,6 @@ def readVersion(path, infile): os.rename(src + "bootloader.bin", dst + "bootloader.bin") os.rename(src + "partitions.bin", dst + "partitions.bin") os.rename("~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin", dst + "ota.bin") - genOtaBin(path + "firmware/s3/") os.rename("../scripts/gh-action-dev-build-flash.html", path + "install.html") From c9b6cc5f6f09dd7f79528ffbc54226a75123d16f Mon Sep 17 00:00:00 2001 From: Markus Krause Date: Fri, 31 Mar 2023 00:49:48 +0200 Subject: [PATCH 09/55] fix ota bin copy --- .github/workflows/compile_development.yml | 3 ++ .github/workflows/compile_release.yml | 3 ++ ahoy.code-workspace | 45 +++++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 ahoy.code-workspace diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index ffde2d21..768a522f 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -49,6 +49,9 @@ jobs: - name: Run PlatformIO run: pio run -d src --environment esp8266-release --environment esp8266-release-prometheus --environment esp8285-release --environment esp32-wroom32-release --environment esp32-wroom32-release-prometheus --environment opendtufusionv1-release + - name: Copy boot_app0.bin + run: cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin .pio/build/opendtufusionv1-release/ota.bin + - name: Rename Binary files id: rename-binary-files working-directory: src diff --git a/.github/workflows/compile_release.yml b/.github/workflows/compile_release.yml index 84ad5111..25f34fa6 100644 --- a/.github/workflows/compile_release.yml +++ b/.github/workflows/compile_release.yml @@ -53,6 +53,9 @@ jobs: - name: Run PlatformIO run: pio run -d src --environment esp8266-release --environment esp8266-release-prometheus --environment esp8285-release --environment esp32-wroom32-release --environment esp32-wroom32-release-prometheus --environment opendtufusionv1-release + - name: Copy boot_app0.bin + run: cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin .pio/build/opendtufusionv1-release/ota.bin + - name: Rename Binary files id: rename-binary-files working-directory: src diff --git a/ahoy.code-workspace b/ahoy.code-workspace new file mode 100644 index 00000000..20d5909e --- /dev/null +++ b/ahoy.code-workspace @@ -0,0 +1,45 @@ +{ + "folders": [ + { + "path": "." + }, + { + "path": "src" + } + ], + "settings": { + "files.associations": { + "algorithm": "cpp", + "array": "cpp", + "chrono": "cpp", + "deque": "cpp", + "format": "cpp", + "forward_list": "cpp", + "functional": "cpp", + "initializer_list": "cpp", + "iterator": "cpp", + "list": "cpp", + "memory": "cpp", + "queue": "cpp", + "random": "cpp", + "regex": "cpp", + "vector": "cpp", + "xhash": "cpp", + "xlocmon": "cpp", + "xlocnum": "cpp", + "xmemory": "cpp", + "xstring": "cpp", + "xtree": "cpp", + "xutility": "cpp", + "*.tcc": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "string_view": "cpp", + "sstream": "cpp", + "istream": "cpp", + "ostream": "cpp" + }, + "editor.formatOnSave": false + } +} \ No newline at end of file From 2eb0a6542db3693502f7d5f79b40202839d76f93 Mon Sep 17 00:00:00 2001 From: Markus Krause Date: Fri, 31 Mar 2023 00:53:59 +0200 Subject: [PATCH 10/55] take new ota.bin --- scripts/getVersion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/getVersion.py b/scripts/getVersion.py index e3927907..e8393ae1 100644 --- a/scripts/getVersion.py +++ b/scripts/getVersion.py @@ -96,7 +96,7 @@ def readVersion(path, infile): dst = path + "firmware/s3/" os.rename(src + "bootloader.bin", dst + "bootloader.bin") os.rename(src + "partitions.bin", dst + "partitions.bin") - os.rename("~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin", dst + "ota.bin") + os.rename(src + "ota.bin", dst + "ota.bin") os.rename("../scripts/gh-action-dev-build-flash.html", path + "install.html") From 3043eaca1f94ddc326e8cb1e17d4a174152255b1 Mon Sep 17 00:00:00 2001 From: Markus Krause Date: Fri, 31 Mar 2023 01:04:39 +0200 Subject: [PATCH 11/55] fix path --- .github/workflows/compile_development.yml | 2 +- .github/workflows/compile_release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index 768a522f..4913d726 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -50,7 +50,7 @@ jobs: run: pio run -d src --environment esp8266-release --environment esp8266-release-prometheus --environment esp8285-release --environment esp32-wroom32-release --environment esp32-wroom32-release-prometheus --environment opendtufusionv1-release - name: Copy boot_app0.bin - run: cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin .pio/build/opendtufusionv1-release/ota.bin + run: cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin src/.pio/build/opendtufusionv1-release/ota.bin - name: Rename Binary files id: rename-binary-files diff --git a/.github/workflows/compile_release.yml b/.github/workflows/compile_release.yml index 25f34fa6..a50ec355 100644 --- a/.github/workflows/compile_release.yml +++ b/.github/workflows/compile_release.yml @@ -54,7 +54,7 @@ jobs: run: pio run -d src --environment esp8266-release --environment esp8266-release-prometheus --environment esp8285-release --environment esp32-wroom32-release --environment esp32-wroom32-release-prometheus --environment opendtufusionv1-release - name: Copy boot_app0.bin - run: cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin .pio/build/opendtufusionv1-release/ota.bin + run: cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin src/.pio/build/opendtufusionv1-release/ota.bin - name: Rename Binary files id: rename-binary-files From ba996f56dd1b32c6d6beca5b9e085f1f5179ea9f Mon Sep 17 00:00:00 2001 From: Markus Krause Date: Fri, 31 Mar 2023 02:10:09 +0200 Subject: [PATCH 12/55] change build settings fpr S3 to address flash instability --- src/platformio.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/platformio.ini b/src/platformio.ini index 4e2e92fd..7cb7cbfe 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -137,6 +137,10 @@ monitor_filters = [env:opendtufusionv1-release] platform = espressif32 board = esp32-s3-devkitc-1 +upload_protocol = esp-builtin +upload_speed = 115200 +debug_tool = esp-builtin +debug_speed = 12000 build_flags = -D RELEASE -std=gnu++14 build_unflags = -std=gnu++11 monitor_filters = From 1f0f8b904a57ff162b67992c3090b295c8dddf26 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Fri, 31 Mar 2023 08:06:51 +0200 Subject: [PATCH 13/55] MI - use only crc8 for MI commands MI-600 at least sents answers as well... --- src/hm/hmRadio.h | 11 ++++++----- src/hm/miPayload.h | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index c37ab7d0..3917df8e 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -205,6 +205,7 @@ class HmRadio { } else { //MI 2nd gen. specific switch (cmd) { case TurnOn: + //mTxBuf[0] = 0x50; mTxBuf[9] = 0x55; mTxBuf[10] = 0xaa; break; @@ -223,7 +224,7 @@ class HmRadio { } cnt++; } - sendPacket(invId, cnt, isRetransmit, true); + sendPacket(invId, cnt, isRetransmit, isNoMI); } void prepareDevInformCmd(uint64_t invId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit, uint8_t reqfld=TX_REQ_INFO) { // might not be necessary to add additional arg. @@ -239,9 +240,9 @@ class HmRadio { sendPacket(invId, 24, isRetransmit, true); } - void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit) { + void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool isMI=false) { initPacket(invId, mid, pid); - sendPacket(invId, 10, isRetransmit, false); + sendPacket(invId, 10, isRetransmit, isMI); } void dumpBuf(uint8_t buf[], uint8_t len) { @@ -317,12 +318,12 @@ class HmRadio { mTxBuf[9] = pid; } - void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool clear=false) { + void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool appendCrc16=false) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendPacket")); //DPRINTLN(DBG_VERBOSE, "sent packet: #" + String(mSendCnt)); // append crc's - if (len > 10) { + if (appendCrc16 && len > 10) { // crc control data uint16_t crc = ah::crc16(&mTxBuf[10], len - 10); mTxBuf[len++] = (crc >> 8) & 0xff; diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index fd2665f8..d9f0b338 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -149,7 +149,7 @@ class MiPayload { if (cmd == 0x01 || cmd == SystemConfigPara ) { //0x1 and 0x05 for HM-types cmd = 0x0f; // for MI, these seem to make part of the Polling the device software and hardware version number command cmd2 = cmd == SystemConfigPara ? 0x01 : 0x00; //perhaps we can only try to get second frame? - mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd2, false); + mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, true); } else { mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd2, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); }; @@ -442,7 +442,7 @@ const byteAssign_t InfoAssignment[] = { mPayload[iv->id].retransmits = mMaxRetrans; } else if ( cmd == 0x0f ) { //hard/firmware request - mSys->Radio.sendCmdPacket(iv->radioId.u64, 0x0f, 0x00, true); + mSys->Radio.sendCmdPacket(iv->radioId.u64, 0x0f, 0x00, true, true); //iv->setQueuedCmdFinished(); //cmd = iv->getQueuedCmd(); } else { From 24bfb43b02c8b6b86d18838656307ec2741df2a7 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Fri, 31 Mar 2023 19:17:16 +0200 Subject: [PATCH 14/55] Radio changes, MQTT fixes * consolidated (?) proposals from beegee3 * timing now 410microsesonds --- src/app.cpp | 2 + src/hm/hmRadio.h | 82 ++++++++++++++++++----------------------- src/hm/miPayload.h | 4 +- src/publisher/pubMqtt.h | 11 +++++- 4 files changed, 50 insertions(+), 49 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index d3fba12a..7d9f75ba 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -51,6 +51,7 @@ void app::setup() { mMiPayload.setup(this, &mSys, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); mMiPayload.enableSerialDebug(mConfig->serial.debug); + mMiPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); // DBGPRINTLN("--- after payload"); // DBGPRINTLN(String(ESP.getFreeHeap())); @@ -67,6 +68,7 @@ void app::setup() { mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, &mSys, &mTimestamp); mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1)); mPayload.addAlarmListener(std::bind(&PubMqttType::alarmEventListener, &mMqtt, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + mMiPayload.addAlarmListener(std::bind(&PubMqttType::alarmEventListener, &mMqtt, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); } #endif setupLed(); diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 3917df8e..8a4f602e 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -101,19 +101,20 @@ class HmRadio { // change the byte order of the DTU serial number and append the required 0x01 at the end DTU_RADIO_ID = ((uint64_t)(((dtuSn >> 24) & 0xFF) | ((dtuSn >> 8) & 0xFF00) | ((dtuSn << 8) & 0xFF0000) | ((dtuSn << 24) & 0xFF000000)) << 8) | 0x01; + SPIClass* spi; #ifdef ESP32 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - mSpi = new SPIClass(FSPI); + spi = new SPIClass(FSPI); #else - mSpi = new SPIClass(VSPI); + spi = new SPIClass(VSPI); #endif - mSpi->begin(sclk, miso, mosi, cs); + spi->begin(sclk, miso, mosi, cs); #else //the old ESP82xx cannot freely place their SPI pins - mSpi = new SPIClass(); - mSpi->begin(); + spi = new SPIClass(); + spi->begin(); #endif - mNrf24.begin(mSpi, ce, cs); + mNrf24.begin(spi, ce, cs); mNrf24.setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms mNrf24.setChannel(mRfChLst[mRxChIdx]); @@ -123,7 +124,7 @@ class HmRadio { mNrf24.enableDynamicPayloads(); mNrf24.setCRCLength(RF24_CRC_16); mNrf24.setAddressWidth(5); - mNrf24.openReadingPipe(1, DTU_RADIO_ID); + mNrf24.openReadingPipe(1, reinterpret_cast(&DTU_RADIO_ID)); // enable all receiving interrupts mNrf24.maskIRQ(false, false, false); @@ -147,32 +148,31 @@ class HmRadio { bool tx_ok, tx_fail, rx_ready; mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH mNrf24.flush_tx(); // empty TX FIFO - //DBGPRINTLN("TX whatHappened Ch" + String(mRfChLst[mTxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); - // start listening on the default RX channel - mRxChIdx = 0; + // start listening mNrf24.setChannel(mRfChLst[mRxChIdx]); mNrf24.startListening(); - //uint32_t debug_ms = millis(); - uint16_t cnt = 300; // that is 60 times 5 channels - while (0 < cnt--) { - uint32_t startMillis = millis(); - while (millis()-startMillis < 4) { // listen 4ms to each channel + uint32_t startMicros = micros(); + uint32_t loopMillis = millis(); + while (millis()-loopMillis < 410) { + while (micros()-startMicros < 5110) { // listen 5110us to each channel if (mIrqRcvd) { mIrqRcvd = false; if (getReceived()) { // everything received - //DBGPRINTLN("RX finished Cnt: " + String(300-cnt) + " time used: " + String(millis()-debug_ms)+ " ms"); return true; } } yield(); } - switchRxCh(); // switch to next RX channel + // switch to next RX channel + startMicros = micros(); + if(++mRxChIdx >= RF_CHANNELS) + mRxChIdx = 0; + mNrf24.setChannel(mRfChLst[mRxChIdx]); yield(); } // not finished but time is over - //DBGPRINTLN("RX not finished: 300 time used: " + String(millis()-debug_ms)+ " ms"); return true; } @@ -240,9 +240,9 @@ class HmRadio { sendPacket(invId, 24, isRetransmit, true); } - void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool isMI=false) { + void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool appendCrc16=true) { initPacket(invId, mid, pid); - sendPacket(invId, 10, isRetransmit, isMI); + sendPacket(invId, 10, isRetransmit, appendCrc16); } void dumpBuf(uint8_t buf[], uint8_t len) { @@ -275,7 +275,6 @@ class HmRadio { bool getReceived(void) { bool tx_ok, tx_fail, rx_ready; mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH - //DBGPRINTLN("RX whatHappened Ch" + String(mRfChLst[mRxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); bool isLastPackage = false; while(mNrf24.available()) { @@ -286,29 +285,21 @@ class HmRadio { p.ch = mRfChLst[mRxChIdx]; p.len = len; mNrf24.read(p.packet, len); - mBufCtrl.push(p); - if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command - isLastPackage = (p.packet[9] > 0x81); // > 0x81 indicates last packet received - else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command - isLastPackage = (p.packet[9] > 0x11); // > 0x11 indicates last packet received - else if (p.packet[0] != 0x00 && p.packet[0] != 0x88 && p.packet[0] != 0x92) - // ignore fragment number zero and MI status messages - isLastPackage = true; // response from dev control command - yield(); + if (p.packet[0] != 0x00) { + mBufCtrl.push(p); + if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command + isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received + else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command + isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received + else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore fragment number zero and MI status messages //#0 was p.packet[0] != 0x00 && + isLastPackage = true; // response from dev control command + } } + yield(); } return isLastPackage; } - void switchRxCh() { - mNrf24.stopListening(); - // get next channel index - if(++mRxChIdx >= RF_CHANNELS) - mRxChIdx = 0; - mNrf24.setChannel(mRfChLst[mRxChIdx]); - mNrf24.startListening(); - } - void initPacket(uint64_t invId, uint8_t mid, uint8_t pid) { DPRINTLN(DBG_VERBOSE, F("initPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX)); memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); @@ -318,12 +309,12 @@ class HmRadio { mTxBuf[9] = pid; } - void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool appendCrc16=false) { + void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool appendCrc16=true) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendPacket")); //DPRINTLN(DBG_VERBOSE, "sent packet: #" + String(mSendCnt)); // append crc's - if (appendCrc16 && len > 10) { + if (appendCrc16 && (len > 10)) { // crc control data uint16_t crc = ah::crc16(&mTxBuf[10], len - 10); mTxBuf[len++] = (crc >> 8) & 0xff; @@ -333,6 +324,10 @@ class HmRadio { mTxBuf[len] = ah::crc8(mTxBuf, len); len++; + // set TX and RX channels + mTxChIdx = (mTxChIdx + 1) % RF_CHANNELS; + mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; + if(mSerialDebug) { DPRINT(DBG_INFO, F("TX ")); DBGPRINT(String(len)); @@ -347,10 +342,6 @@ class HmRadio { mNrf24.openWritingPipe(reinterpret_cast(&invId)); mNrf24.startWrite(mTxBuf, len, false); // false = request ACK response - // switch TX channel for next packet - if(++mTxChIdx >= RF_CHANNELS) - mTxChIdx = 0; - if(isRetransmit) mRetransmits++; else @@ -364,7 +355,6 @@ class HmRadio { uint8_t mTxChIdx; uint8_t mRxChIdx; - SPIClass* mSpi; RF24 mNrf24; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; }; diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index d9f0b338..92020b51 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -149,7 +149,7 @@ class MiPayload { if (cmd == 0x01 || cmd == SystemConfigPara ) { //0x1 and 0x05 for HM-types cmd = 0x0f; // for MI, these seem to make part of the Polling the device software and hardware version number command cmd2 = cmd == SystemConfigPara ? 0x01 : 0x00; //perhaps we can only try to get second frame? - mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, true); + mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, false); } else { mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd2, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); }; @@ -442,7 +442,7 @@ const byteAssign_t InfoAssignment[] = { mPayload[iv->id].retransmits = mMaxRetrans; } else if ( cmd == 0x0f ) { //hard/firmware request - mSys->Radio.sendCmdPacket(iv->radioId.u64, 0x0f, 0x00, true, true); + mSys->Radio.sendCmdPacket(iv->radioId.u64, 0x0f, 0x00, true, false); //iv->setQueuedCmdFinished(); //cmd = iv->getQueuedCmd(); } else { diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index b008d8d2..f75c4068 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -49,6 +49,8 @@ class PubMqtt { mTxCnt = 0; mSubscriptionCb = NULL; memset(mLastIvState, MQTT_STATUS_NOT_AVAIL_NOT_PROD, MAX_NUM_INVERTERS); + memset(mIvLastRTRpub, 0, MAX_NUM_INVERTERS * 4); + mLastAnyAvail = false; } @@ -522,7 +524,13 @@ class PubMqtt { void sendData(Inverter<> *iv, uint8_t curInfoCmd) { record_t<> *rec = iv->getRecordStruct(curInfoCmd); - if (iv->getLastTs(rec) > 0) { + uint32_t lastTs = iv->getLastTs(rec); + bool pubData = (lastTs > 0); + if (curInfoCmd == RealTimeRunData_Debug) + pubData &= (lastTs != mIvLastRTRpub[iv->id]); + + if (pubData) { + mIvLastRTRpub[iv->id] = lastTs; for (uint8_t i = 0; i < rec->length; i++) { bool retained = false; if (curInfoCmd == RealTimeRunData_Debug) { @@ -653,6 +661,7 @@ class PubMqtt { subscriptionCb mSubscriptionCb; bool mLastAnyAvail; uint8_t mLastIvState[MAX_NUM_INVERTERS]; + uint32_t mIvLastRTRpub[MAX_NUM_INVERTERS]; uint16_t mIntervalTimeout; // last will topic and payload must be available trough lifetime of 'espMqttClient' From 33264cc776b1c8501b2894a8f2f8ebfee9cd93a4 Mon Sep 17 00:00:00 2001 From: Markus Krause Date: Fri, 31 Mar 2023 22:51:01 +0200 Subject: [PATCH 15/55] make LED polarity selectable --- src/app.cpp | 28 +++++++++++++++------------- src/app.h | 4 ++-- src/config/settings.h | 4 ++++ src/web/RestApi.h | 1 + src/web/html/setup.html | 12 ++++++++++++ src/web/web.h | 3 ++- 6 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index d3fba12a..088454f6 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -69,7 +69,7 @@ void app::setup() { mPayload.addAlarmListener(std::bind(&PubMqttType::alarmEventListener, &mMqtt, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); } #endif - setupLed(); + setupLed(mConfig->led.led_high_active); mWeb.setup(this, &mSys, mConfig); mWeb.setProtection(strlen(mConfig->sys.adminPwd) != 0); @@ -353,7 +353,7 @@ void app::tickSend(void) { } yield(); - updateLed(); + updateLed(mConfig->led.led_high_active); } //----------------------------------------------------------------------------- @@ -386,31 +386,33 @@ void app::mqttSubRxCb(JsonObject obj) { } //----------------------------------------------------------------------------- -void app::setupLed(void) { - /** LED connection diagram - * \\ - * PIN ---- |<----- 3.3V - * - * */ +void app::setupLed(uint8_t is_high_active) { + + uint8_t led_off = (is_high_active != 0) ? LOW : HIGH; + if (mConfig->led.led0 != 0xff) { pinMode(mConfig->led.led0, OUTPUT); - digitalWrite(mConfig->led.led0, HIGH); // LED off + digitalWrite(mConfig->led.led0, led_off); } if (mConfig->led.led1 != 0xff) { pinMode(mConfig->led.led1, OUTPUT); - digitalWrite(mConfig->led.led1, HIGH); // LED off + digitalWrite(mConfig->led.led1, led_off); } } //----------------------------------------------------------------------------- -void app::updateLed(void) { +void app::updateLed(uint8_t is_high_active) { + + uint8_t led_off = (is_high_active != 0) ? LOW : HIGH; + uint8_t led_on = (is_high_active != 0) ? HIGH : LOW; + if (mConfig->led.led0 != 0xff) { Inverter<> *iv = mSys.getInverterByPos(0); if (NULL != iv) { if (iv->isProducing(mTimestamp)) - digitalWrite(mConfig->led.led0, LOW); // LED on + digitalWrite(mConfig->led.led0, led_on); else - digitalWrite(mConfig->led.led0, HIGH); // LED off + digitalWrite(mConfig->led.led0, led_off); } } } diff --git a/src/app.h b/src/app.h index cbf7e6a1..252434ae 100644 --- a/src/app.h +++ b/src/app.h @@ -213,8 +213,8 @@ class app : public IApp, public ah::Scheduler { void mqttSubRxCb(JsonObject obj); - void setupLed(void); - void updateLed(void); + void setupLed(uint8_t is_high_active); + void updateLed(uint8_t is_high_active); void tickReboot(void) { DPRINTLN(DBG_INFO, F("Rebooting...")); diff --git a/src/config/settings.h b/src/config/settings.h index 6d58b406..7449a0b6 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -100,6 +100,7 @@ typedef struct { typedef struct { uint8_t led0; // first LED pin uint8_t led1; // second LED pin + uint8_t led_high_active; // determines if LEDs are high or low active } cfgLed_t; typedef struct { @@ -378,6 +379,7 @@ class settings { mCfg.led.led0 = DEF_PIN_OFF; mCfg.led.led1 = DEF_PIN_OFF; + mCfg.led.led_high_active = LOW; memset(&mCfg.inst, 0, sizeof(cfgInst_t)); @@ -517,9 +519,11 @@ class settings { if(set) { obj[F("0")] = mCfg.led.led0; obj[F("1")] = mCfg.led.led1; + obj[F("2")] = mCfg.led.led_high_active; } else { mCfg.led.led0 = obj[F("0")]; mCfg.led.led1 = obj[F("1")]; + mCfg.led.led_high_active = obj[F("2")]; } } diff --git a/src/web/RestApi.h b/src/web/RestApi.h index b224f239..8c193e28 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -391,6 +391,7 @@ class RestApi { obj[F("miso")] = mConfig->nrf.pinMiso; obj[F("led0")] = mConfig->led.led0; obj[F("led1")] = mConfig->led.led1; + obj[F("led_high_active")] = mConfig->led.led_high_active; } void getRadio(JsonObject obj) { diff --git a/src/web/html/setup.html b/src/web/html/setup.html index bfbda402..fbe29010 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -411,6 +411,10 @@ [47, "GPIO47"], [48, "GPIO48"], ]; + var led_high_active = [ + [0, "low active"], + [1, "high active"], + ]; const re = /11[2,4,6]1.*/; @@ -670,6 +674,14 @@ ]) ); } + e.append( + ml("div", { class: "row mb-3" }, [ + ml("div", { class: "col-12 col-sm-3 my-2" }, "LED polarity"), + ml("div", { class: "col-12 col-sm-9" }, + sel('pinLedHighActive', led_high_active, obj["led_high_active"]) + ) + ]) + ); } function parseRadio(obj) { diff --git a/src/web/web.h b/src/web/web.h index c141e013..94f6ece7 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -33,7 +33,7 @@ #define WEB_SERIAL_BUF_SIZE 2048 -const char *const pinArgNames[] = {"pinCs", "pinCe", "pinIrq", "pinSclk", "pinMosi", "pinMiso", "pinLed0", "pinLed1"}; +const char *const pinArgNames[] = {"pinCs", "pinCe", "pinIrq", "pinSclk", "pinMosi", "pinMiso", "pinLed0", "pinLed1", "pinLedHighActive"}; template class Web { @@ -532,6 +532,7 @@ class Web { case 5: mConfig->nrf.pinMiso = ((pin != 0xff) ? pin : DEF_MISO_PIN); break; case 6: mConfig->led.led0 = pin; break; case 7: mConfig->led.led1 = pin; break; + case 8: mConfig->led.led_high_active = pin; break; // this is not really a pin but a polarity, but handling it close to here makes sense } } From 48a6bf021cf11f79ca71a25fa9eae571779d3748 Mon Sep 17 00:00:00 2001 From: Markus Krause Date: Sat, 1 Apr 2023 13:00:38 +0200 Subject: [PATCH 16/55] add MQTT status to LED update, try to fix settings save for led polarity --- src/app.cpp | 22 +++++++++++++++------- src/app.h | 4 ++-- src/config/settings.h | 4 ++-- src/web/html/setup.html | 2 +- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 088454f6..9ec6ff26 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -69,7 +69,7 @@ void app::setup() { mPayload.addAlarmListener(std::bind(&PubMqttType::alarmEventListener, &mMqtt, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); } #endif - setupLed(mConfig->led.led_high_active); + setupLed(); mWeb.setup(this, &mSys, mConfig); mWeb.setProtection(strlen(mConfig->sys.adminPwd) != 0); @@ -353,7 +353,7 @@ void app::tickSend(void) { } yield(); - updateLed(mConfig->led.led_high_active); + updateLed(); } //----------------------------------------------------------------------------- @@ -386,9 +386,9 @@ void app::mqttSubRxCb(JsonObject obj) { } //----------------------------------------------------------------------------- -void app::setupLed(uint8_t is_high_active) { +void app::setupLed(void) { - uint8_t led_off = (is_high_active != 0) ? LOW : HIGH; + uint8_t led_off = (mConfig->led.led_high_active != 0) ? LOW : HIGH; if (mConfig->led.led0 != 0xff) { pinMode(mConfig->led.led0, OUTPUT); @@ -401,10 +401,10 @@ void app::setupLed(uint8_t is_high_active) { } //----------------------------------------------------------------------------- -void app::updateLed(uint8_t is_high_active) { +void app::updateLed(void) { - uint8_t led_off = (is_high_active != 0) ? LOW : HIGH; - uint8_t led_on = (is_high_active != 0) ? HIGH : LOW; + uint8_t led_off = (mConfig->led.led_high_active != 0) ? LOW : HIGH; + uint8_t led_on = (mConfig->led.led_high_active != 0) ? HIGH : LOW; if (mConfig->led.led0 != 0xff) { Inverter<> *iv = mSys.getInverterByPos(0); @@ -415,4 +415,12 @@ void app::updateLed(uint8_t is_high_active) { digitalWrite(mConfig->led.led0, led_off); } } + + if (mConfig->led.led1 != 0xff) { + if (getMqttIsConnected()) { + digitalWrite(mConfig->led.led1, led_on); + } else { + digitalWrite(mConfig->led.led1, led_off); + } + } } diff --git a/src/app.h b/src/app.h index 252434ae..6dfc404c 100644 --- a/src/app.h +++ b/src/app.h @@ -213,8 +213,8 @@ class app : public IApp, public ah::Scheduler { void mqttSubRxCb(JsonObject obj); - void setupLed(uint8_t is_high_active); - void updateLed(uint8_t is_high_active); + void setupLed(); + void updateLed(); void tickReboot(void) { DPRINTLN(DBG_INFO, F("Rebooting...")); diff --git a/src/config/settings.h b/src/config/settings.h index 7449a0b6..e895a8a9 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -519,11 +519,11 @@ class settings { if(set) { obj[F("0")] = mCfg.led.led0; obj[F("1")] = mCfg.led.led1; - obj[F("2")] = mCfg.led.led_high_active; + obj[F("led_high_active")] = mCfg.led.led_high_active; } else { mCfg.led.led0 = obj[F("0")]; mCfg.led.led1 = obj[F("1")]; - mCfg.led.led_high_active = obj[F("2")]; + mCfg.led.led_high_active = obj[F("led_high_active")]; } } diff --git a/src/web/html/setup.html b/src/web/html/setup.html index fbe29010..97bf5608 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -678,7 +678,7 @@ ml("div", { class: "row mb-3" }, [ ml("div", { class: "col-12 col-sm-3 my-2" }, "LED polarity"), ml("div", { class: "col-12 col-sm-9" }, - sel('pinLedHighActive', led_high_active, obj["led_high_active"]) + sel('pinLedHighActive', led_high_active, obj['led_high_active']) ) ]) ); From e8e216cd6998c06f9d2315c6a64ff30cb8b1f99c Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Sat, 1 Apr 2023 19:04:47 +0200 Subject: [PATCH 17/55] MI - fix MQTT version + changed rx/tx logic (times + debug output) --- src/hm/hmRadio.h | 9 +++++++-- src/hm/miPayload.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 8a4f602e..c1152e32 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -155,10 +155,14 @@ class HmRadio { uint32_t startMicros = micros(); uint32_t loopMillis = millis(); - while (millis()-loopMillis < 410) { - while (micros()-startMicros < 5110) { // listen 5110us to each channel + + uint32_t timeslot = 4088;//5110; //3066; //6132;//4088; + uint64_t tsCnt = 0; + while (millis()-loopMillis < 200) { + while (micros()-startMicros < timeslot) { // listen timeslot us to each channel if (mIrqRcvd) { mIrqRcvd = false; + DBGPRINTLN("*** time: " + String(tsCnt*(uint64_t)timeslot + (uint64_t)(micros()-startMicros)) + " ***"); if (getReceived()) { // everything received return true; } @@ -170,6 +174,7 @@ class HmRadio { if(++mRxChIdx >= RF_CHANNELS) mRxChIdx = 0; mNrf24.setChannel(mRfChLst[mRxChIdx]); + tsCnt++; yield(); } // not finished but time is over diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 92020b51..17d26fe8 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -751,7 +751,7 @@ const byteAssign_t InfoAssignment[] = { iv->setQueuedCmdFinished(); mStat->rxSuccess++; yield(); - notify(mPayload[iv->id].txCmd); + notify(RealTimeRunData_Debug); //iv->type == INV_TYPE_4CH ? 0x36 : 0x09 ); } bool build(uint8_t id, bool *complete) { From 574f6aed99866a33418806eec10ffa41a9dd62d9 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Sat, 1 Apr 2023 21:06:48 +0200 Subject: [PATCH 18/55] MI - fix comletion for 1ch MI --- src/hm/miPayload.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 17d26fe8..02d49c53 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -659,7 +659,7 @@ const byteAssign_t InfoAssignment[] = { if ( datachan < 3 ) { mPayload[iv->id].dataAB[datachan] = true; } - if ( !mPayload[iv->id].dataAB[CH0] && mPayload[iv->id].dataAB[CH2] && mPayload[iv->id].dataAB[CH2] ) { + if ( !mPayload[iv->id].dataAB[CH0] && mPayload[iv->id].dataAB[CH1] && mPayload[iv->id].dataAB[CH2] ) { mPayload[iv->id].dataAB[CH0] = true; } From 7050a3486813e6e066c2252f4e40f112f67b0e47 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 1 Apr 2023 23:34:48 +0200 Subject: [PATCH 19/55] 0.6.1 * merge LED fix - LED1 shows MqTT state, LED configureable active high/low #839 --- src/CHANGES.md | 35 +++-------------------------------- src/defines.h | 2 +- 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index e0591a00..cbaa465a 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,33 +1,4 @@ -Changelog v0.6.0 +# Development Changes -## General -* improved night time calculation time to 1 minute after last communication pause #515 -* refactored code for better readability -* improved Hoymiles communication (retransmits, immediate power limit transmission, timing at all) -* renamed firmware binaries -* add login / logout to menu -* add display support for `SH1106`, `SSD1306`, `Nokia` and `ePaper 1.54"` (ESP32 only) -* add yield total correction - move your yield to a new inverter or correct an already used inverter -* added import / export feature -* added `Prometheus` endpoints -* improved wifi connection and stability (connect to strongest AP) -* addded Hoymiles alarm IDs to log -* improved `System` information page (eg. radio statitistics) -* improved UI (responsive design, (optional) dark mode) -* improved system stability (reduced `heap-fragmentation`, don't break settings on failure) #644, #645 -* added support for 2nd generation of Hoymiles inverters, MI series -* improved JSON API for more stable WebUI -* added option to disable input display in `/live` (`max-power` has to be set to `0`) -* updated documentation -* improved settings on ESP32 devices while setting SPI pins (for `NRF24` radio) - -## MqTT -* added `comm_disabled` #529 -* added fixed interval option #542, #523 -* improved communication, only required publishes -* improved retained flags -* added `set_power_limit` acknowledge MQTT publish #553 -* added feature to reset values on midnight, communication pause or if the inverters are not available -* partially added Hoymiles alarm ID -* improved autodiscover (added total values on multi-inverter setup) -* improved `clientID` a part of the MAC address is added to have an unique name +## 0.6.1 - 2023-04-01 +* merge LED fix - LED1 shows MqTT state, LED configureable active high/low #839 diff --git a/src/defines.h b/src/defines.h index 1be438ff..28275eff 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 0 +#define VERSION_PATCH 1 //------------------------------------- typedef struct { From db8b17502e043d6b957e8e4e8ee80611a936f1e4 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 1 Apr 2023 23:47:51 +0200 Subject: [PATCH 20/55] 0.6.1 * only publish new inverter data #826 --- src/CHANGES.md | 1 + src/publisher/pubMqtt.h | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index cbaa465a..9df7d29c 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,3 +2,4 @@ ## 0.6.1 - 2023-04-01 * merge LED fix - LED1 shows MqTT state, LED configureable active high/low #839 +* only publish new inverter data #826 diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index b008d8d2..e717ee7c 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -49,6 +49,7 @@ class PubMqtt { mTxCnt = 0; mSubscriptionCb = NULL; memset(mLastIvState, MQTT_STATUS_NOT_AVAIL_NOT_PROD, MAX_NUM_INVERTERS); + memset(mIvLastRTRpub, 0, MAX_NUM_INVERTERS * 4); mLastAnyAvail = false; } @@ -522,7 +523,13 @@ class PubMqtt { void sendData(Inverter<> *iv, uint8_t curInfoCmd) { record_t<> *rec = iv->getRecordStruct(curInfoCmd); - if (iv->getLastTs(rec) > 0) { + uint32_t lastTs = iv->getLastTs(rec); + bool pubData = (lastTs > 0); + if (curInfoCmd == RealTimeRunData_Debug) + pubData &= (lastTs != mIvLastRTRpub[iv->id]); + + if (pubData) { + mIvLastRTRpub[iv->id] = lastTs; for (uint8_t i = 0; i < rec->length; i++) { bool retained = false; if (curInfoCmd == RealTimeRunData_Debug) { @@ -653,6 +660,7 @@ class PubMqtt { subscriptionCb mSubscriptionCb; bool mLastAnyAvail; uint8_t mLastIvState[MAX_NUM_INVERTERS]; + uint32_t mIvLastRTRpub[MAX_NUM_INVERTERS]; uint16_t mIntervalTimeout; // last will topic and payload must be available trough lifetime of 'espMqttClient' From 521c7ca3071f1e2adec98c2fdaa6614b7c627efb Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 2 Apr 2023 00:08:06 +0200 Subject: [PATCH 21/55] 0.6.1 * potential fix of WiFi hostname during boot up #752 --- src/CHANGES.md | 1 + src/wifi/ahoywifi.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 9df7d29c..0a2613ae 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -3,3 +3,4 @@ ## 0.6.1 - 2023-04-01 * merge LED fix - LED1 shows MqTT state, LED configureable active high/low #839 * only publish new inverter data #826 +* potential fix of WiFi hostname during boot up #752 diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 0acdf9e2..9677e7ee 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- -// 2023 Ahoy, https://www.mikrocontroller.net/topic/525778 -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +// 2023 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- #if defined(ESP32) && defined(F) @@ -160,6 +160,9 @@ void ahoywifi::setupAp(void) { DBGPRINTLN(mApIp.toString()); DBGPRINTLN(F("---------\n")); + if(String(mConfig->sys.deviceName) != "") + WiFi.hostname(mConfig->sys.deviceName); + WiFi.mode(WIFI_AP_STA); WiFi.softAPConfig(mApIp, mApIp, IPAddress(255, 255, 255, 0)); WiFi.softAP(WIFI_AP_SSID, WIFI_AP_PWD); From 26ec95d61e72d882d088eed702a2867f90287abf Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Sun, 2 Apr 2023 13:45:18 +0200 Subject: [PATCH 22/55] MI - fixes to MQTT; uses classic hmRadio.h --- src/hm/hmRadio.h | 90 ++++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 42 deletions(-) diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index c1152e32..99867982 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -101,20 +101,19 @@ class HmRadio { // change the byte order of the DTU serial number and append the required 0x01 at the end DTU_RADIO_ID = ((uint64_t)(((dtuSn >> 24) & 0xFF) | ((dtuSn >> 8) & 0xFF00) | ((dtuSn << 8) & 0xFF0000) | ((dtuSn << 24) & 0xFF000000)) << 8) | 0x01; - SPIClass* spi; #ifdef ESP32 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - spi = new SPIClass(FSPI); + mSpi = new SPIClass(FSPI); #else - spi = new SPIClass(VSPI); + mSpi = new SPIClass(VSPI); #endif - spi->begin(sclk, miso, mosi, cs); + mSpi->begin(sclk, miso, mosi, cs); #else //the old ESP82xx cannot freely place their SPI pins - spi = new SPIClass(); - spi->begin(); + mSpi = new SPIClass(); + mSpi->begin(); #endif - mNrf24.begin(spi, ce, cs); + mNrf24.begin(mSpi, ce, cs); mNrf24.setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms mNrf24.setChannel(mRfChLst[mRxChIdx]); @@ -124,7 +123,7 @@ class HmRadio { mNrf24.enableDynamicPayloads(); mNrf24.setCRCLength(RF24_CRC_16); mNrf24.setAddressWidth(5); - mNrf24.openReadingPipe(1, reinterpret_cast(&DTU_RADIO_ID)); + mNrf24.openReadingPipe(1, DTU_RADIO_ID); // enable all receiving interrupts mNrf24.maskIRQ(false, false, false); @@ -148,36 +147,32 @@ class HmRadio { bool tx_ok, tx_fail, rx_ready; mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH mNrf24.flush_tx(); // empty TX FIFO + //DBGPRINTLN("TX whatHappened Ch" + String(mRfChLst[mTxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); - // start listening + // start listening on the default RX channel + mRxChIdx = 0; mNrf24.setChannel(mRfChLst[mRxChIdx]); mNrf24.startListening(); - uint32_t startMicros = micros(); - uint32_t loopMillis = millis(); - - uint32_t timeslot = 4088;//5110; //3066; //6132;//4088; - uint64_t tsCnt = 0; - while (millis()-loopMillis < 200) { - while (micros()-startMicros < timeslot) { // listen timeslot us to each channel + //uint32_t debug_ms = millis(); + uint16_t cnt = 300; // that is 60 times 5 channels + while (0 < cnt--) { + uint32_t startMillis = millis(); + while (millis()-startMillis < 4) { // listen 4ms to each channel if (mIrqRcvd) { mIrqRcvd = false; - DBGPRINTLN("*** time: " + String(tsCnt*(uint64_t)timeslot + (uint64_t)(micros()-startMicros)) + " ***"); if (getReceived()) { // everything received + //DBGPRINTLN("RX finished Cnt: " + String(300-cnt) + " time used: " + String(millis()-debug_ms)+ " ms"); return true; } } yield(); } - // switch to next RX channel - startMicros = micros(); - if(++mRxChIdx >= RF_CHANNELS) - mRxChIdx = 0; - mNrf24.setChannel(mRfChLst[mRxChIdx]); - tsCnt++; + switchRxCh(); // switch to next RX channel yield(); } // not finished but time is over + //DBGPRINTLN("RX not finished: 300 time used: " + String(millis()-debug_ms)+ " ms"); return true; } @@ -233,7 +228,8 @@ class HmRadio { } void prepareDevInformCmd(uint64_t invId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit, uint8_t reqfld=TX_REQ_INFO) { // might not be necessary to add additional arg. - DPRINTLN(DBG_DEBUG, F("prepareDevInformCmd 0x") + String(cmd, HEX)); + DPRINT(DBG_DEBUG, F("prepareDevInformCmd 0x")); + DPRINTLN(DBG_DEBUG, String(cmd, HEX)); initPacket(invId, reqfld, ALL_FRAMES); mTxBuf[10] = cmd; // cid mTxBuf[11] = 0x00; @@ -245,9 +241,9 @@ class HmRadio { sendPacket(invId, 24, isRetransmit, true); } - void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool appendCrc16=true) { + void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool isMI=false) { initPacket(invId, mid, pid); - sendPacket(invId, 10, isRetransmit, appendCrc16); + sendPacket(invId, 10, isRetransmit, isMI); } void dumpBuf(uint8_t buf[], uint8_t len) { @@ -280,6 +276,7 @@ class HmRadio { bool getReceived(void) { bool tx_ok, tx_fail, rx_ready; mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH + //DBGPRINTLN("RX whatHappened Ch" + String(mRfChLst[mRxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); bool isLastPackage = false; while(mNrf24.available()) { @@ -290,21 +287,29 @@ class HmRadio { p.ch = mRfChLst[mRxChIdx]; p.len = len; mNrf24.read(p.packet, len); - if (p.packet[0] != 0x00) { - mBufCtrl.push(p); - if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command - isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received - else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command - isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received - else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore fragment number zero and MI status messages //#0 was p.packet[0] != 0x00 && - isLastPackage = true; // response from dev control command - } + mBufCtrl.push(p); + if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command + isLastPackage = (p.packet[9] > 0x81); // > 0x81 indicates last packet received + else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command + isLastPackage = (p.packet[9] > 0x11); // > 0x11 indicates last packet received + else if (p.packet[0] != 0x00 && p.packet[0] != 0x88 && p.packet[0] != 0x92) + // ignore fragment number zero and MI status messages + isLastPackage = true; // response from dev control command + yield(); } - yield(); } return isLastPackage; } + void switchRxCh() { + mNrf24.stopListening(); + // get next channel index + if(++mRxChIdx >= RF_CHANNELS) + mRxChIdx = 0; + mNrf24.setChannel(mRfChLst[mRxChIdx]); + mNrf24.startListening(); + } + void initPacket(uint64_t invId, uint8_t mid, uint8_t pid) { DPRINTLN(DBG_VERBOSE, F("initPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX)); memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); @@ -314,12 +319,12 @@ class HmRadio { mTxBuf[9] = pid; } - void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool appendCrc16=true) { + void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool appendCrc16=false) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendPacket")); //DPRINTLN(DBG_VERBOSE, "sent packet: #" + String(mSendCnt)); // append crc's - if (appendCrc16 && (len > 10)) { + if (appendCrc16 && len > 10) { // crc control data uint16_t crc = ah::crc16(&mTxBuf[10], len - 10); mTxBuf[len++] = (crc >> 8) & 0xff; @@ -329,10 +334,6 @@ class HmRadio { mTxBuf[len] = ah::crc8(mTxBuf, len); len++; - // set TX and RX channels - mTxChIdx = (mTxChIdx + 1) % RF_CHANNELS; - mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; - if(mSerialDebug) { DPRINT(DBG_INFO, F("TX ")); DBGPRINT(String(len)); @@ -347,6 +348,10 @@ class HmRadio { mNrf24.openWritingPipe(reinterpret_cast(&invId)); mNrf24.startWrite(mTxBuf, len, false); // false = request ACK response + // switch TX channel for next packet + if(++mTxChIdx >= RF_CHANNELS) + mTxChIdx = 0; + if(isRetransmit) mRetransmits++; else @@ -360,6 +365,7 @@ class HmRadio { uint8_t mTxChIdx; uint8_t mRxChIdx; + SPIClass* mSpi; RF24 mNrf24; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; }; From 1e6a06b5805a3f398b2e2d78f480f0ba3a5e0f4e Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Sun, 2 Apr 2023 19:23:57 +0200 Subject: [PATCH 23/55] hmRadio.h - change rx/tx channel hopping logic (#7) * hmRadio.h - change rx/tx channel hopping logic - patch originally provided by beegee3 - timings look very good for 3rd gen., and ok for MI in my environment over several restarts - runs stable on ESP32 - not sure wheather this also has any (negative or positive) impact to reboot problem with ESP8266 --- src/hm/hmRadio.h | 88 ++++++++++++++++++++-------------------------- src/hm/miPayload.h | 10 +++--- 2 files changed, 45 insertions(+), 53 deletions(-) diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 99867982..98fbb299 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -101,19 +101,20 @@ class HmRadio { // change the byte order of the DTU serial number and append the required 0x01 at the end DTU_RADIO_ID = ((uint64_t)(((dtuSn >> 24) & 0xFF) | ((dtuSn >> 8) & 0xFF00) | ((dtuSn << 8) & 0xFF0000) | ((dtuSn << 24) & 0xFF000000)) << 8) | 0x01; + SPIClass* spi; #ifdef ESP32 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - mSpi = new SPIClass(FSPI); + spi = new SPIClass(FSPI); #else - mSpi = new SPIClass(VSPI); + spi = new SPIClass(VSPI); #endif - mSpi->begin(sclk, miso, mosi, cs); + spi->begin(sclk, miso, mosi, cs); #else //the old ESP82xx cannot freely place their SPI pins - mSpi = new SPIClass(); - mSpi->begin(); + spi = new SPIClass(); + spi->begin(); #endif - mNrf24.begin(mSpi, ce, cs); + mNrf24.begin(spi, ce, cs); mNrf24.setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms mNrf24.setChannel(mRfChLst[mRxChIdx]); @@ -123,7 +124,7 @@ class HmRadio { mNrf24.enableDynamicPayloads(); mNrf24.setCRCLength(RF24_CRC_16); mNrf24.setAddressWidth(5); - mNrf24.openReadingPipe(1, DTU_RADIO_ID); + mNrf24.openReadingPipe(1, reinterpret_cast(&DTU_RADIO_ID)); // enable all receiving interrupts mNrf24.maskIRQ(false, false, false); @@ -147,32 +148,32 @@ class HmRadio { bool tx_ok, tx_fail, rx_ready; mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH mNrf24.flush_tx(); // empty TX FIFO - //DBGPRINTLN("TX whatHappened Ch" + String(mRfChLst[mTxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); - // start listening on the default RX channel - mRxChIdx = 0; + // start listening mNrf24.setChannel(mRfChLst[mRxChIdx]); mNrf24.startListening(); - //uint32_t debug_ms = millis(); - uint16_t cnt = 300; // that is 60 times 5 channels - while (0 < cnt--) { - uint32_t startMillis = millis(); - while (millis()-startMillis < 4) { // listen 4ms to each channel + uint32_t startMicros = micros(); + uint32_t loopMillis = millis(); + while (millis()-loopMillis < 400) { + while (micros()-startMicros < 5110) { // listen (4088us or?) 5110us to each channel if (mIrqRcvd) { mIrqRcvd = false; if (getReceived()) { // everything received - //DBGPRINTLN("RX finished Cnt: " + String(300-cnt) + " time used: " + String(millis()-debug_ms)+ " ms"); return true; } } - yield(); + //yield(); } - switchRxCh(); // switch to next RX channel - yield(); + // switch to next RX channel + startMicros = micros(); + if(++mRxChIdx >= RF_CHANNELS) + mRxChIdx = 0; + mNrf24.setChannel(mRfChLst[mRxChIdx]); + //yield(); } + yield(); // not finished but time is over - //DBGPRINTLN("RX not finished: 300 time used: " + String(millis()-debug_ms)+ " ms"); return true; } @@ -205,7 +206,6 @@ class HmRadio { } else { //MI 2nd gen. specific switch (cmd) { case TurnOn: - //mTxBuf[0] = 0x50; mTxBuf[9] = 0x55; mTxBuf[10] = 0xaa; break; @@ -241,9 +241,9 @@ class HmRadio { sendPacket(invId, 24, isRetransmit, true); } - void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool isMI=false) { + void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool appendCrc16=true) { initPacket(invId, mid, pid); - sendPacket(invId, 10, isRetransmit, isMI); + sendPacket(invId, 10, isRetransmit, appendCrc16); } void dumpBuf(uint8_t buf[], uint8_t len) { @@ -276,7 +276,6 @@ class HmRadio { bool getReceived(void) { bool tx_ok, tx_fail, rx_ready; mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH - //DBGPRINTLN("RX whatHappened Ch" + String(mRfChLst[mRxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); bool isLastPackage = false; while(mNrf24.available()) { @@ -287,29 +286,21 @@ class HmRadio { p.ch = mRfChLst[mRxChIdx]; p.len = len; mNrf24.read(p.packet, len); - mBufCtrl.push(p); - if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command - isLastPackage = (p.packet[9] > 0x81); // > 0x81 indicates last packet received - else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command - isLastPackage = (p.packet[9] > 0x11); // > 0x11 indicates last packet received - else if (p.packet[0] != 0x00 && p.packet[0] != 0x88 && p.packet[0] != 0x92) - // ignore fragment number zero and MI status messages - isLastPackage = true; // response from dev control command - yield(); + if (p.packet[0] != 0x00) { + mBufCtrl.push(p); + if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command + isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received + else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command + isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received + else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore fragment number zero and MI status messages //#0 was p.packet[0] != 0x00 && + isLastPackage = true; // response from dev control command + } } + yield(); } return isLastPackage; } - void switchRxCh() { - mNrf24.stopListening(); - // get next channel index - if(++mRxChIdx >= RF_CHANNELS) - mRxChIdx = 0; - mNrf24.setChannel(mRfChLst[mRxChIdx]); - mNrf24.startListening(); - } - void initPacket(uint64_t invId, uint8_t mid, uint8_t pid) { DPRINTLN(DBG_VERBOSE, F("initPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX)); memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); @@ -319,12 +310,12 @@ class HmRadio { mTxBuf[9] = pid; } - void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool appendCrc16=false) { + void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool appendCrc16=true) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendPacket")); //DPRINTLN(DBG_VERBOSE, "sent packet: #" + String(mSendCnt)); // append crc's - if (appendCrc16 && len > 10) { + if (appendCrc16 && (len > 10)) { // crc control data uint16_t crc = ah::crc16(&mTxBuf[10], len - 10); mTxBuf[len++] = (crc >> 8) & 0xff; @@ -334,6 +325,10 @@ class HmRadio { mTxBuf[len] = ah::crc8(mTxBuf, len); len++; + // set TX and RX channels + mTxChIdx = (mTxChIdx + 1) % RF_CHANNELS; + mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; + if(mSerialDebug) { DPRINT(DBG_INFO, F("TX ")); DBGPRINT(String(len)); @@ -348,10 +343,6 @@ class HmRadio { mNrf24.openWritingPipe(reinterpret_cast(&invId)); mNrf24.startWrite(mTxBuf, len, false); // false = request ACK response - // switch TX channel for next packet - if(++mTxChIdx >= RF_CHANNELS) - mTxChIdx = 0; - if(isRetransmit) mRetransmits++; else @@ -365,7 +356,6 @@ class HmRadio { uint8_t mTxChIdx; uint8_t mRxChIdx; - SPIClass* mSpi; RF24 mNrf24; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; }; diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 02d49c53..6d2a5d1a 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -151,7 +151,8 @@ class MiPayload { cmd2 = cmd == SystemConfigPara ? 0x01 : 0x00; //perhaps we can only try to get second frame? mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, false); } else { - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd2, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); + //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd2, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); + mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, false); }; mPayload[iv->id].txCmd = cmd; @@ -479,8 +480,8 @@ const byteAssign_t InfoAssignment[] = { } DBGPRINT(F(" 0x")); DBGHEXLN(cmd); - //mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd, true); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, true, cmd); + mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd, true, false); + //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, true, cmd); yield(); } } @@ -496,7 +497,8 @@ const byteAssign_t InfoAssignment[] = { DBGPRINT(F("prepareDevInformCmd 0x")); DBGHEXLN(mPayload[iv->id].txCmd); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); + //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); + mSys->Radio.sendCmdPacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].txCmd, false, false); } } /*else { // payload complete From 6533143e8019ebf5c7164b8e7c3038fe72bd745c Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 4 Apr 2023 13:51:11 +0200 Subject: [PATCH 24/55] 0.6.2 * fix login from multiple clients #819 * fix login screen on small displays --- src/CHANGES.md | 4 ++ src/app.h | 4 +- src/appInterface.h | 3 +- src/defines.h | 2 +- src/web/RestApi.h | 64 ++++++++++++------------ src/web/html/login.html | 4 +- src/web/html/style.css | 29 ++++++----- src/web/web.h | 107 +++++++++++++++------------------------- 8 files changed, 101 insertions(+), 116 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 0a2613ae..3702d0e6 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.6.2 - 2023-04-04 +* fix login from multiple clients #819 +* fix login screen on small displays + ## 0.6.1 - 2023-04-01 * merge LED fix - LED1 shows MqTT state, LED configureable active high/low #839 * only publish new inverter data #826 diff --git a/src/app.h b/src/app.h index 6dfc404c..5ea40968 100644 --- a/src/app.h +++ b/src/app.h @@ -157,8 +157,8 @@ class app : public IApp, public ah::Scheduler { return mMqtt.getRxCnt(); } - bool getProtection() { - return mWeb.getProtection(); + bool getProtection(AsyncWebServerRequest *request) { + return mWeb.isProtected(request); } uint8_t getIrqPin(void) { diff --git a/src/appInterface.h b/src/appInterface.h index a79dcdb1..44491d91 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -8,6 +8,7 @@ #include "defines.h" #include "hm/hmSystem.h" +#include "ESPAsyncWebServer.h" // abstract interface to App. Make members of App accessible from child class // like web or API without forward declaration @@ -47,7 +48,7 @@ class IApp { virtual uint32_t getMqttRxCnt() = 0; virtual uint32_t getMqttTxCnt() = 0; - virtual bool getProtection() = 0; + virtual bool getProtection(AsyncWebServerRequest *request) = 0; }; #endif /*__IAPP_H__*/ diff --git a/src/defines.h b/src/defines.h index 28275eff..5d01003b 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 1 +#define VERSION_PATCH 2 //------------------------------------- typedef struct { diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 8c193e28..2d617847 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -77,19 +77,19 @@ class RestApi { JsonObject root = response->getRoot(); String path = request->url().substring(5); - if(path == "html/system") getHtmlSystem(root); - else if(path == "html/logout") getHtmlLogout(root); - else if(path == "html/reboot") getHtmlReboot(root); - else if(path == "html/save") getHtmlSave(root); - else if(path == "system") getSysInfo(root); - else if(path == "generic") getGeneric(root); - else if(path == "reboot") getReboot(root); + if(path == "html/system") getHtmlSystem(request, root); + else if(path == "html/logout") getHtmlLogout(request, root); + else if(path == "html/reboot") getHtmlReboot(request, root); + else if(path == "html/save") getHtmlSave(request, root); + else if(path == "system") getSysInfo(request, root); + else if(path == "generic") getGeneric(request, root); + else if(path == "reboot") getReboot(request, root); else if(path == "statistics") getStatistics(root); else if(path == "inverter/list") getInverterList(root); - else if(path == "index") getIndex(root); - else if(path == "setup") getSetup(root); + else if(path == "index") getIndex(request, root); + else if(path == "setup") getSetup(request, root); else if(path == "setup/networks") getNetworks(root); - else if(path == "live") getLive(root); + else if(path == "live") getLive(request, root); else if(path == "record/info") getRecord(root, InverterDevInform_All); else if(path == "record/alarm") getRecord(root, AlarmData); else if(path == "record/config") getRecord(root, SystemConfigPara); @@ -189,10 +189,10 @@ class RestApi { fp.close(); } - void getGeneric(JsonObject obj) { + void getGeneric(AsyncWebServerRequest *request, JsonObject obj) { obj[F("wifi_rssi")] = (WiFi.status() != WL_CONNECTED) ? 0 : WiFi.RSSI(); obj[F("ts_uptime")] = mApp->getUptime(); - obj[F("menu_prot")] = mApp->getProtection(); + obj[F("menu_prot")] = mApp->getProtection(request); obj[F("menu_mask")] = (uint16_t)(mConfig->sys.protectionMask ); obj[F("menu_protEn")] = (bool) (strlen(mConfig->sys.adminPwd) > 0); @@ -203,7 +203,7 @@ class RestApi { #endif } - void getSysInfo(JsonObject obj) { + void getSysInfo(AsyncWebServerRequest *request, JsonObject obj) { obj[F("ssid")] = mConfig->sys.stationSsid; obj[F("device_name")] = mConfig->sys.deviceName; obj[F("dark_mode")] = (bool)mConfig->sys.darkMode; @@ -218,7 +218,7 @@ class RestApi { obj[F("heap_free")] = mHeapFree; obj[F("sketch_total")] = ESP.getFreeSketchSpace(); obj[F("sketch_used")] = ESP.getSketchSize() / 1024; // in kb - getGeneric(obj); + getGeneric(request, obj); getRadio(obj.createNestedObject(F("radio"))); getStatistics(obj.createNestedObject(F("statistics"))); @@ -252,34 +252,34 @@ class RestApi { obj[F("schMax")] = max; } - void getHtmlSystem(JsonObject obj) { - getSysInfo(obj.createNestedObject(F("system"))); - getGeneric(obj.createNestedObject(F("generic"))); + void getHtmlSystem(AsyncWebServerRequest *request, JsonObject obj) { + getSysInfo(request, obj.createNestedObject(F("system"))); + getGeneric(request, obj.createNestedObject(F("generic"))); obj[F("html")] = F("Factory Reset

Reboot"); } - void getHtmlLogout(JsonObject obj) { - getGeneric(obj.createNestedObject(F("generic"))); + void getHtmlLogout(AsyncWebServerRequest *request, JsonObject obj) { + getGeneric(request, obj.createNestedObject(F("generic"))); obj[F("refresh")] = 3; obj[F("refresh_url")] = "/"; obj[F("html")] = F("succesfully logged out"); } - void getHtmlReboot(JsonObject obj) { - getGeneric(obj.createNestedObject(F("generic"))); + void getHtmlReboot(AsyncWebServerRequest *request, JsonObject obj) { + getGeneric(request, obj.createNestedObject(F("generic"))); obj[F("refresh")] = 20; obj[F("refresh_url")] = "/"; obj[F("html")] = F("rebooting ..."); } - void getHtmlSave(JsonObject obj) { - getGeneric(obj.createNestedObject(F("generic"))); + void getHtmlSave(AsyncWebServerRequest *request, JsonObject obj) { + getGeneric(request, obj.createNestedObject(F("generic"))); obj["pending"] = (bool)mApp->getSavePending(); obj["success"] = (bool)mApp->getLastSaveSucceed(); } - void getReboot(JsonObject obj) { - getGeneric(obj.createNestedObject(F("generic"))); + void getReboot(AsyncWebServerRequest *request, JsonObject obj) { + getGeneric(request, obj.createNestedObject(F("generic"))); obj[F("refresh")] = 10; obj[F("refresh_url")] = "/"; obj[F("html")] = F("reboot. Autoreload after 10 seconds"); @@ -430,8 +430,8 @@ class RestApi { obj[F("disp_bsy")] = (mConfig->plugin.display.type < 10) ? DEF_PIN_OFF : mConfig->plugin.display.disp_busy; } - void getIndex(JsonObject obj) { - getGeneric(obj.createNestedObject(F("generic"))); + void getIndex(AsyncWebServerRequest *request, JsonObject obj) { + getGeneric(request, obj.createNestedObject(F("generic"))); obj[F("ts_now")] = mApp->getTimestamp(); obj[F("ts_sunrise")] = mApp->getSunrise(); obj[F("ts_sunset")] = mApp->getSunset(); @@ -479,9 +479,9 @@ class RestApi { info.add(F("MQTT publishes in a fixed interval of ") + String(mConfig->mqtt.interval) + F(" seconds")); } - void getSetup(JsonObject obj) { - getGeneric(obj.createNestedObject(F("generic"))); - getSysInfo(obj.createNestedObject(F("system"))); + void getSetup(AsyncWebServerRequest *request, JsonObject obj) { + getGeneric(request, obj.createNestedObject(F("generic"))); + getSysInfo(request, obj.createNestedObject(F("system"))); //getInverterList(obj.createNestedObject(F("inverter"))); getMqtt(obj.createNestedObject(F("mqtt"))); getNtp(obj.createNestedObject(F("ntp"))); @@ -497,8 +497,8 @@ class RestApi { mApp->getAvailNetworks(obj); } - void getLive(JsonObject obj) { - getGeneric(obj.createNestedObject(F("generic"))); + void getLive(AsyncWebServerRequest *request, JsonObject obj) { + getGeneric(request, obj.createNestedObject(F("generic"))); obj[F("refresh")] = mConfig->nrf.sendInterval; for (uint8_t fld = 0; fld < sizeof(acList); fld++) { diff --git a/src/web/html/login.html b/src/web/html/login.html index e790f6a4..001e0453 100644 --- a/src/web/html/login.html +++ b/src/web/html/login.html @@ -11,8 +11,8 @@

AhoyDTU

-
-
+
+
diff --git a/src/web/html/style.css b/src/web/html/style.css index ca4b0c9a..415d5b40 100644 --- a/src/web/html/style.css +++ b/src/web/html/style.css @@ -546,6 +546,18 @@ div.hr { width: 100%; } +#login { + width: 450px; + height: 200px; + border: 1px solid #ccc; + background-color: var(--input-bg); + position: absolute; + top: 50%; + left: 50%; + margin-top: -160px; + margin-left: -225px; +} + @media(max-width: 500px) { div.ch .unit, div.ch-iv .unit { font-size: 18px; @@ -559,6 +571,11 @@ div.hr { .subgrp { width: 180px; } + + #login { + margin-left: -150px; + width: 300px; + } } #serial { @@ -578,18 +595,6 @@ div.hr { margin-top: 15px; } -#login { - width: 450px; - height: 200px; - border: 1px solid #ccc; - background-color: var(--input-bg); - position: absolute; - top: 50%; - left: 50%; - margin-top: -160px; - margin-left: -225px; -} - .head { background-color: var(--primary); diff --git a/src/web/web.h b/src/web/web.h index 4d322fac..6b7aaed1 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -126,8 +126,19 @@ class Web { mProtected = protect; } - bool getProtection() { - return mProtected; + bool isProtected(AsyncWebServerRequest *request) { + bool prot; + prot = mProtected; + if(!prot) { + uint8_t ip[4]; + ah::ip2Arr(ip, request->client()->remoteIP().toString().c_str()); + for(uint8_t i = 0; i < 4; i++) { + if(mLoginIp[i] != ip[i]) + prot = true; + } + } + + return prot; } void showUpdate2(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { @@ -216,7 +227,7 @@ class Web { } private: - void checkRedirect(AsyncWebServerRequest *request) { + inline void checkRedirect(AsyncWebServerRequest *request) { if ((mConfig->sys.protectionMask & PROT_MASK_INDEX) != PROT_MASK_INDEX) request->redirect(F("/index")); else if ((mConfig->sys.protectionMask & PROT_MASK_LIVE) != PROT_MASK_LIVE) @@ -229,15 +240,18 @@ class Web { request->redirect(F("/login")); } + void checkProtection(AsyncWebServerRequest *request) { + if(isProtected(request)) { + checkRedirect(request); + return; + } + } + void onUpdate(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("onUpdate")); - if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_UPDATE)) { - if (mProtected) { - checkRedirect(request); - return; - } - } + if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_UPDATE)) + checkProtection(request); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), update_html, update_html_len); response->addHeader(F("Content-Encoding"), "gzip"); @@ -290,12 +304,8 @@ class Web { void onIndex(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("onIndex")); - if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_INDEX)) { - if (mProtected) { - checkRedirect(request); - return; - } - } + if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_INDEX)) + checkProtection(request); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), index_html, index_html_len); response->addHeader(F("Content-Encoding"), "gzip"); @@ -308,6 +318,7 @@ class Web { if (request->args() > 0) { if (String(request->arg("pwd")) == String(mConfig->sys.adminPwd)) { mProtected = false; + ah::ip2Arr(mLoginIp, request->client()->remoteIP().toString().c_str()); request->redirect("/"); } } @@ -320,10 +331,7 @@ class Web { void onLogout(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("onLogout")); - if (mProtected) { - checkRedirect(request); - return; - } + checkProtection(request); mProtected = true; @@ -367,10 +375,8 @@ class Web { } void showNotFound(AsyncWebServerRequest *request) { - if (mProtected) - checkRedirect(request); - else - request->redirect("/setup"); + checkProtection(request); + request->redirect("/setup"); } void onReboot(AsyncWebServerRequest *request) { @@ -381,10 +387,7 @@ class Web { } void showErase(AsyncWebServerRequest *request) { - if (mProtected) { - checkRedirect(request); - return; - } + checkProtection(request); DPRINTLN(DBG_VERBOSE, F("showErase")); mApp->eraseSettings(false); @@ -392,10 +395,7 @@ class Web { } void showFactoryRst(AsyncWebServerRequest *request) { - if (mProtected) { - checkRedirect(request); - return; - } + checkProtection(request); DPRINTLN(DBG_VERBOSE, F("showFactoryRst")); String content = ""; @@ -424,12 +424,8 @@ class Web { void onSetup(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("onSetup")); - if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_SETUP)) { - if (mProtected) { - checkRedirect(request); - return; - } - } + if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_SETUP)) + checkProtection(request); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), setup_html, setup_html_len); response->addHeader(F("Content-Encoding"), "gzip"); @@ -439,10 +435,7 @@ class Web { void showSave(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("showSave")); - if (mProtected) { - checkRedirect(request); - return; - } + checkProtection(request); if (request->args() == 0) return; @@ -605,12 +598,8 @@ class Web { void onLive(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("onLive")); - if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_LIVE)) { - if (mProtected) { - checkRedirect(request); - return; - } - } + if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_LIVE)) + checkProtection(request); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), visualization_html, visualization_html_len); response->addHeader(F("Content-Encoding"), "gzip"); @@ -620,13 +609,6 @@ class Web { } void onAbout(AsyncWebServerRequest *request) { - if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_LIVE)) { - if (mProtected) { - checkRedirect(request); - return; - } - } - AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), about_html, about_html_len); response->addHeader(F("Content-Encoding"), "gzip"); response->addHeader(F("content-type"), "text/html; charset=UTF-8"); @@ -643,12 +625,8 @@ class Web { void onSerial(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("onSerial")); - if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_SERIAL)) { - if (mProtected) { - checkRedirect(request); - return; - } - } + if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_SERIAL)) + checkProtection(request); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), serial_html, serial_html_len); response->addHeader(F("Content-Encoding"), "gzip"); @@ -658,12 +636,8 @@ class Web { void onSystem(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("onSystem")); - if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_SYSTEM)) { - if (mProtected) { - checkRedirect(request); - return; - } - } + if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_SYSTEM)) + checkProtection(request); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), system_html, system_html_len); response->addHeader(F("Content-Encoding"), "gzip"); @@ -840,6 +814,7 @@ class Web { AsyncEventSource mEvts; bool mProtected; uint32_t mLogoutTimeout; + uint8_t mLoginIp[4]; IApp *mApp; HMSYSTEM *mSys; From 1e81a3e9634c3c51257d7f6872ed446ad776f340 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Tue, 4 Apr 2023 15:27:03 +0200 Subject: [PATCH 25/55] faster request after power limit and more yield() calls in while() loops (thx to beegee3) --- src/hm/hmPayload.h | 2 ++ src/hm/hmRadio.h | 34 ++++++++++++++++++++++------------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index de99d41b..e08dd909 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -210,6 +210,8 @@ class HmPayload { iv->clearCmdQueue(); iv->enqueCommand(SystemConfigPara); // read back power limit + if(mHighPrioIv == NULL) // do it immediately if possible + mHighPrioIv = iv; } iv->devControlCmd = Init; } diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 98fbb299..b848d377 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -52,12 +52,15 @@ template = RF_CHANNELS) mRxChIdx = 0; mNrf24.setChannel(mRfChLst[mRxChIdx]); - //yield(); + yield(); } - yield(); // not finished but time is over return true; } @@ -206,6 +208,7 @@ class HmRadio { } else { //MI 2nd gen. specific switch (cmd) { case TurnOn: + //mTxBuf[0] = 0x50; mTxBuf[9] = 0x55; mTxBuf[10] = 0xaa; break; @@ -228,8 +231,10 @@ class HmRadio { } void prepareDevInformCmd(uint64_t invId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit, uint8_t reqfld=TX_REQ_INFO) { // might not be necessary to add additional arg. - DPRINT(DBG_DEBUG, F("prepareDevInformCmd 0x")); - DPRINTLN(DBG_DEBUG, String(cmd, HEX)); + if(mSerialDebug) { + DPRINT(DBG_DEBUG, F("prepareDevInformCmd 0x")); + DPRINTLN(DBG_DEBUG,String(cmd, HEX)); + } initPacket(invId, reqfld, ALL_FRAMES); mTxBuf[10] = cmd; // cid mTxBuf[11] = 0x00; @@ -302,7 +307,12 @@ class HmRadio { } void initPacket(uint64_t invId, uint8_t mid, uint8_t pid) { - DPRINTLN(DBG_VERBOSE, F("initPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX)); + if(mSerialDebug) { + DPRINT(DBG_VERBOSE, F("initPacket, mid: ")); + DPRINT(DBG_VERBOSE, String(mid, HEX)); + DPRINT(DBG_VERBOSE,F(" pid: ")); + DPRINTLN(DBG_VERBOSE,String(pid, HEX)); + } memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); mTxBuf[0] = mid; // message id CP_U32_BigEndian(&mTxBuf[1], (invId >> 8)); From df1e1c2418e381c900f0d72fc0357abf06945582 Mon Sep 17 00:00:00 2001 From: tastendruecker123 <111116980+tastendruecker123@users.noreply.github.com> Date: Tue, 4 Apr 2023 17:06:56 +0200 Subject: [PATCH 26/55] Fixed issue #828. Browser caching, versioned URLs. --- src/web/html/includes/header.html | 6 +++--- src/web/html/includes/nav.html | 14 +++++++------- src/web/web.h | 31 +++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/web/html/includes/header.html b/src/web/html/includes/header.html index f38a30f7..d591eb42 100644 --- a/src/web/html/includes/header.html +++ b/src/web/html/includes/header.html @@ -1,5 +1,5 @@ - - + - + + \ No newline at end of file diff --git a/src/web/html/includes/nav.html b/src/web/html/includes/nav.html index 3dac1590..9d6b822c 100644 --- a/src/web/html/includes/nav.html +++ b/src/web/html/includes/nav.html @@ -1,21 +1,21 @@
- AhoyDTU + AhoyDTU
- Live - Serial / Control - Settings + Live + Serial / Control + Settings - Update - System + Update + System REST API Documentation - About + About Login Logout diff --git a/src/web/web.h b/src/web/web.h index 6b7aaed1..68174c8b 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -255,6 +255,9 @@ class Web { AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), update_html, update_html_len); response->addHeader(F("Content-Encoding"), "gzip"); + if(request->hasParam("v")) { + response->addHeader(F("Cache-Control"), F("max-age=604800")); + } request->send(response); } @@ -309,11 +312,15 @@ class Web { AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), index_html, index_html_len); response->addHeader(F("Content-Encoding"), "gzip"); + if(request->hasParam("v")) { + response->addHeader(F("Cache-Control"), F("max-age=604800")); + } request->send(response); } void onLogin(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("onLogin")); + DPRINTLN(DBG_WARN, String(mConfig->sys.adminPwd)); if (request->args() > 0) { if (String(request->arg("pwd")) == String(mConfig->sys.adminPwd)) { @@ -348,6 +355,9 @@ class Web { else response = request->beginResponse_P(200, F("text/css"), colorBright_css, colorBright_css_len); response->addHeader(F("Content-Encoding"), "gzip"); + if(request->hasParam("v")) { + response->addHeader(F("Cache-Control"), F("max-age=604800")); + } request->send(response); } @@ -356,6 +366,9 @@ class Web { mLogoutTimeout = LOGOUT_TIMEOUT; AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/css"), style_css, style_css_len); response->addHeader(F("Content-Encoding"), "gzip"); + if(request->hasParam("v")) { + response->addHeader(F("Cache-Control"), F("max-age=604800")); + } request->send(response); } @@ -364,6 +377,9 @@ class Web { AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/javascript"), api_js, api_js_len); response->addHeader(F("Content-Encoding"), "gzip"); + if(request->hasParam("v")) { + response->addHeader(F("Cache-Control"), F("max-age=604800")); + } request->send(response); } @@ -429,6 +445,9 @@ class Web { AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), setup_html, setup_html_len); response->addHeader(F("Content-Encoding"), "gzip"); + if(request->hasParam("v")) { + response->addHeader(F("Cache-Control"), F("max-age=604800")); + } request->send(response); } @@ -604,6 +623,9 @@ class Web { AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), visualization_html, visualization_html_len); response->addHeader(F("Content-Encoding"), "gzip"); response->addHeader(F("content-type"), "text/html; charset=UTF-8"); + if(request->hasParam("v")) { + response->addHeader(F("Cache-Control"), F("max-age=604800")); + } request->send(response); } @@ -612,6 +634,9 @@ class Web { AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), about_html, about_html_len); response->addHeader(F("Content-Encoding"), "gzip"); response->addHeader(F("content-type"), "text/html; charset=UTF-8"); + if(request->hasParam("v")) { + response->addHeader(F("Cache-Control"), F("max-age=604800")); + } request->send(response); } @@ -630,6 +655,9 @@ class Web { AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), serial_html, serial_html_len); response->addHeader(F("Content-Encoding"), "gzip"); + if(request->hasParam("v")) { + response->addHeader(F("Cache-Control"), F("max-age=604800")); + } request->send(response); } @@ -641,6 +669,9 @@ class Web { AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), system_html, system_html_len); response->addHeader(F("Content-Encoding"), "gzip"); + if(request->hasParam("v")) { + response->addHeader(F("Cache-Control"), F("max-age=604800")); + } request->send(response); } From e8aa1ba11b193391baff95987ce71a1271d306f8 Mon Sep 17 00:00:00 2001 From: tastendruecker123 <111116980+tastendruecker123@users.noreply.github.com> Date: Tue, 4 Apr 2023 17:13:46 +0200 Subject: [PATCH 27/55] removed debugging statement --- src/web/web.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/web/web.h b/src/web/web.h index 68174c8b..32424104 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -320,7 +320,6 @@ class Web { void onLogin(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("onLogin")); - DPRINTLN(DBG_WARN, String(mConfig->sys.adminPwd)); if (request->args() > 0) { if (String(request->arg("pwd")) == String(mConfig->sys.adminPwd)) { From c7060e40ff2d18a0387956c212a72b5ade5aa98a Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 4 Apr 2023 22:50:21 +0200 Subject: [PATCH 28/55] 0.6.3 * fix login, password length was not checked #852 --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/web/web.h | 12 +++++++----- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 3702d0e6..7af7279e 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.6.3 - 2023-04-04 +* fix login, password length was not checked #852 + ## 0.6.2 - 2023-04-04 * fix login from multiple clients #819 * fix login screen on small displays diff --git a/src/defines.h b/src/defines.h index 5d01003b..13799dbc 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 2 +#define VERSION_PATCH 3 //------------------------------------- typedef struct { diff --git a/src/web/web.h b/src/web/web.h index 6b7aaed1..0cafacf6 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -130,11 +130,13 @@ class Web { bool prot; prot = mProtected; if(!prot) { - uint8_t ip[4]; - ah::ip2Arr(ip, request->client()->remoteIP().toString().c_str()); - for(uint8_t i = 0; i < 4; i++) { - if(mLoginIp[i] != ip[i]) - prot = true; + if(strlen(mConfig->sys.adminPwd) > 0) { + uint8_t ip[4]; + ah::ip2Arr(ip, request->client()->remoteIP().toString().c_str()); + for(uint8_t i = 0; i < 4; i++) { + if(mLoginIp[i] != ip[i]) + prot = true; + } } } From 863254aecbe0c93f76630865ffd7733dad3d0966 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 4 Apr 2023 23:12:45 +0200 Subject: [PATCH 29/55] 0.6.3 * merge PR #854 optimize browser caching, thx @tastendruecker123 --- src/CHANGES.md | 1 + src/web/web.h | 81 ++++++++++---------------------------------------- 2 files changed, 16 insertions(+), 66 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 7af7279e..9ab4722e 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,7 @@ ## 0.6.3 - 2023-04-04 * fix login, password length was not checked #852 +* merge PR #854 optimize browser caching, thx @tastendruecker123 ## 0.6.2 - 2023-04-04 * fix login from multiple clients #819 diff --git a/src/web/web.h b/src/web/web.h index 4f816b38..f8abc0f7 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -249,20 +249,22 @@ class Web { } } - void onUpdate(AsyncWebServerRequest *request) { - DPRINTLN(DBG_VERBOSE, F("onUpdate")); - - if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_UPDATE)) + void getPage(AsyncWebServerRequest *request, uint8_t mask, const uint8_t *zippedHtml, uint32_t len) { + if (CHECK_MASK(mConfig->sys.protectionMask, mask)) checkProtection(request); - AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), update_html, update_html_len); + AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), zippedHtml, len); response->addHeader(F("Content-Encoding"), "gzip"); - if(request->hasParam("v")) { + response->addHeader(F("content-type"), "text/html; charset=UTF-8"); + if(request->hasParam("v")) response->addHeader(F("Cache-Control"), F("max-age=604800")); - } request->send(response); } + void onUpdate(AsyncWebServerRequest *request) { + getPage(request, PROT_MASK_UPDATE, update_html, update_html_len); + } + void showUpdate(AsyncWebServerRequest *request) { bool reboot = (!Update.hasError()); @@ -307,17 +309,7 @@ class Web { } void onIndex(AsyncWebServerRequest *request) { - DPRINTLN(DBG_VERBOSE, F("onIndex")); - - if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_INDEX)) - checkProtection(request); - - AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), index_html, index_html_len); - response->addHeader(F("Content-Encoding"), "gzip"); - if(request->hasParam("v")) { - response->addHeader(F("Cache-Control"), F("max-age=604800")); - } - request->send(response); + getPage(request, PROT_MASK_INDEX, index_html, index_html_len); } void onLogin(AsyncWebServerRequest *request) { @@ -378,9 +370,8 @@ class Web { AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/javascript"), api_js, api_js_len); response->addHeader(F("Content-Encoding"), "gzip"); - if(request->hasParam("v")) { + if(request->hasParam("v")) response->addHeader(F("Cache-Control"), F("max-age=604800")); - } request->send(response); } @@ -439,17 +430,7 @@ class Web { } void onSetup(AsyncWebServerRequest *request) { - DPRINTLN(DBG_VERBOSE, F("onSetup")); - - if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_SETUP)) - checkProtection(request); - - AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), setup_html, setup_html_len); - response->addHeader(F("Content-Encoding"), "gzip"); - if(request->hasParam("v")) { - response->addHeader(F("Cache-Control"), F("max-age=604800")); - } - request->send(response); + getPage(request, PROT_MASK_SETUP, setup_html, setup_html_len); } void showSave(AsyncWebServerRequest *request) { @@ -616,19 +597,7 @@ class Web { } void onLive(AsyncWebServerRequest *request) { - DPRINTLN(DBG_VERBOSE, F("onLive")); - - if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_LIVE)) - checkProtection(request); - - AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), visualization_html, visualization_html_len); - response->addHeader(F("Content-Encoding"), "gzip"); - response->addHeader(F("content-type"), "text/html; charset=UTF-8"); - if(request->hasParam("v")) { - response->addHeader(F("Cache-Control"), F("max-age=604800")); - } - - request->send(response); + getPage(request, PROT_MASK_LIVE, visualization_html, visualization_html_len); } void onAbout(AsyncWebServerRequest *request) { @@ -649,31 +618,11 @@ class Web { } void onSerial(AsyncWebServerRequest *request) { - DPRINTLN(DBG_VERBOSE, F("onSerial")); - - if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_SERIAL)) - checkProtection(request); - - AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), serial_html, serial_html_len); - response->addHeader(F("Content-Encoding"), "gzip"); - if(request->hasParam("v")) { - response->addHeader(F("Cache-Control"), F("max-age=604800")); - } - request->send(response); + getPage(request, PROT_MASK_SERIAL, serial_html, serial_html_len); } void onSystem(AsyncWebServerRequest *request) { - DPRINTLN(DBG_VERBOSE, F("onSystem")); - - if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_SYSTEM)) - checkProtection(request); - - AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), system_html, system_html_len); - response->addHeader(F("Content-Encoding"), "gzip"); - if(request->hasParam("v")) { - response->addHeader(F("Cache-Control"), F("max-age=604800")); - } - request->send(response); + getPage(request, PROT_MASK_SYSTEM, system_html, system_html_len); } From 8d8cab60993e970426084578b79564429e421f6a Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 4 Apr 2023 23:34:16 +0200 Subject: [PATCH 30/55] minor corrections --- src/hm/hmPayload.h | 3 +-- src/hm/hmRadio.h | 32 ++++++++++++++++---------------- src/hm/miPayload.h | 3 +-- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index e08dd909..b04ee8f3 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -116,8 +116,7 @@ class HmPayload { mStat->rxFailNoAnser++; // got nothing if (mSerialDebug) DBGPRINTLN(F("enqueued cmd failed/timeout")); - } - else { + } else { mStat->rxFail++; // got fragments but not complete response if (mSerialDebug) { DBGPRINT(F("no complete Payload received! (retransmits: ")); diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index b848d377..35993829 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -54,12 +54,12 @@ class HmRadio { HmRadio() : mNrf24(CE_PIN, CS_PIN, SPI_SPEED) { if(mSerialDebug) { DPRINT(DBG_VERBOSE, F("hmRadio.h : HmRadio():mNrf24(CE_PIN: ")); - DPRINT(DBG_VERBOSE, String(CE_PIN)); - DPRINT(DBG_VERBOSE, F(", CS_PIN: ")); - DPRINT(DBG_VERBOSE, String(CS_PIN)); - DPRINT(DBG_VERBOSE, F(", SPI_SPEED: ")); - DPRINT(DBG_VERBOSE, String(SPI_SPEED)); - DPRINTLN(DBG_VERBOSE, F(")")); + DBGPRINT(String(CE_PIN)); + DBGPRINT(F(", CS_PIN: ")); + DBGPRINT(String(CS_PIN)); + DBGPRINT(F(", SPI_SPEED: ")); + DBGPRINT(String(SPI_SPEED)); + DBGPRINTLN(F(")")); } // Depending on the program, the module can work on 2403, 2423, 2440, 2461 or 2475MHz. @@ -104,20 +104,19 @@ class HmRadio { // change the byte order of the DTU serial number and append the required 0x01 at the end DTU_RADIO_ID = ((uint64_t)(((dtuSn >> 24) & 0xFF) | ((dtuSn >> 8) & 0xFF00) | ((dtuSn << 8) & 0xFF0000) | ((dtuSn << 24) & 0xFF000000)) << 8) | 0x01; - SPIClass* spi; #ifdef ESP32 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - spi = new SPIClass(FSPI); + mSpi = new SPIClass(FSPI); #else - spi = new SPIClass(VSPI); + mSpi = new SPIClass(VSPI); #endif - spi->begin(sclk, miso, mosi, cs); + mSpi->begin(sclk, miso, mosi, cs); #else //the old ESP82xx cannot freely place their SPI pins - spi = new SPIClass(); - spi->begin(); + mSpi = new SPIClass(); + mSpi->begin(); #endif - mNrf24.begin(spi, ce, cs); + mNrf24.begin(mSpi, ce, cs); mNrf24.setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms mNrf24.setChannel(mRfChLst[mRxChIdx]); @@ -309,9 +308,9 @@ class HmRadio { void initPacket(uint64_t invId, uint8_t mid, uint8_t pid) { if(mSerialDebug) { DPRINT(DBG_VERBOSE, F("initPacket, mid: ")); - DPRINT(DBG_VERBOSE, String(mid, HEX)); - DPRINT(DBG_VERBOSE,F(" pid: ")); - DPRINTLN(DBG_VERBOSE,String(pid, HEX)); + DHEX(mid); + DBGPRINT(F(" pid: ")); + DBGHEXLN(pid); } memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); mTxBuf[0] = mid; // message id @@ -366,6 +365,7 @@ class HmRadio { uint8_t mTxChIdx; uint8_t mRxChIdx; + SPIClass* mSpi; RF24 mNrf24; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; }; diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 6d2a5d1a..fd922c8b 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -92,8 +92,7 @@ class MiPayload { mStat->rxFailNoAnser++; // got nothing if (mSerialDebug) DBGPRINTLN(F("enqueued cmd failed/timeout")); - } - else { + } else { mStat->rxFail++; // got "fragments" (part of the required messages) // but no complete set of responses if (mSerialDebug) { From 6e0ab50c1d1c5bce293e1c951c6b2b82f0f00581 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 5 Apr 2023 01:24:37 +0200 Subject: [PATCH 31/55] 0.6.3 * fix WiFi reconnect not working #851 * updated issue templates #822 --- .github/ISSUE_TEMPLATE/report-ahoy.md | 42 +------- .github/ISSUE_TEMPLATE/report.yaml | 132 +++++++------------------- src/CHANGES.md | 4 +- src/wifi/ahoywifi.cpp | 6 +- 4 files changed, 41 insertions(+), 143 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/report-ahoy.md b/.github/ISSUE_TEMPLATE/report-ahoy.md index 1f361271..f7d10494 100644 --- a/.github/ISSUE_TEMPLATE/report-ahoy.md +++ b/.github/ISSUE_TEMPLATE/report-ahoy.md @@ -22,58 +22,22 @@ Retailer URL: ______ ### Antenna: * [ ] circuit board -* [ ] external antenna +* [ ] external antenna (SMA) ### Power Stabilization: * [ ] 100uF Electrolytic Capacitor connected between +3.3V and GND (Pin 1 & 2) of the NRF Module * [ ] Voltage stabilizing motherboard -### Connection diagram: -* [ ] Image of the your wiring attached - -### Connection diagram I used: -| nRF24L01+ Pin | ESP8266 GPIO | -| ------------- | -------------- | -| Pin 1 GND [*] | GND | -| Pin 2 +3.3V | +3.3V | -| Pin 3 CE | GPIO2 CE D4 | -| Pin 4 CSN | GPIO15 CS D8 | -| Pin 5 SCK | GPIO14 SCLK D5 | -| Pin 6 MOSI | GPIO13 MOSI D7 | -| Pin 7 MISO | GPIO12 MISO D6 | -| Pin 8 IRQ | GPIO0 IRQ D3 | - -| nRF24L01+ Pin | ESP32 GPIO | -| ------------- | --------------- | -| Pin 1 GND [*] | GND | -| Pin 2 +3.3V | +3.3V | -| Pin 3 CE | GPIO4 CE D4 | -| Pin 4 CSN | GPIO5 CS D5 | -| Pin 5 SCK | GPIO18 SCLK D18 | -| Pin 6 MOSI | GPIO23 MOSI D23 | -| Pin 7 MISO | GPIO19 MISO D19 | -| Pin 8 IRQ | GPIO0 IRQ D0 | - -Note: [*] GND Pin 1 has a square mark on the nRF24L01+ module - -## Software -* [ ] AhoyDTU -* [ ] OpenDTU - ### Version / Git SHA: Version: _._.__ Github Hash: _______ ### Build & Flash Method: +* [ ] AhoyDTU Webinstaller +* [ ] VSCode - Platform IO * [ ] Arduino * [ ] ESP Tools -* [ ] Platform IO - -### Desktop OS: -* [ ] Linux -* [ ] Windows -* [ ] Mac OS ### Debugging: * [ ] USB Serial Log (attached) diff --git a/.github/ISSUE_TEMPLATE/report.yaml b/.github/ISSUE_TEMPLATE/report.yaml index 6c834480..bab0b3d4 100644 --- a/.github/ISSUE_TEMPLATE/report.yaml +++ b/.github/ISSUE_TEMPLATE/report.yaml @@ -1,18 +1,20 @@ name: "AhoyDTU bug" description: "File a bug report" -title: "[ESP8266/ESP32/RaspberryPi] Problem Description / Beschreibung" +title: "[Bug]" labels: ["bug", "needs-triage"] assignees: - - stefan123t + - lumapu body: - type: markdown attributes: value: | Bitte die Posting Guide lines lesen, Vorlage kopieren und ausfüllen und in Eurem Support Forum Eintrag posten. Wir lesen auch gerne Deutsch, bitte fülle die u.a. Fragen aus damit wir Dir bestmöglich helfen können Danke! + Bitte unser FAQ als Hilfestellung prüfen: https://ahoydtu.de/faq Please read, copy & fill in the template from our Posting Guide lines into your Support Forum post. We do enjoy the english language, but we need a couple of things to best support you in your goal, please fill in all / most of the details given below. Thanks! + Check our FAQ: https://ahoydtu.de/faq - type: markdown attributes: value: "## Hardware" @@ -35,11 +37,21 @@ body: placeholder: validations: required: false + - type: dropdown + id: assembly-type + attributes: + label: Assembly + description: + options: + - I did the assebly by myself + - the DTU was already assembled + validations: + required: true - type: dropdown id: nrf24l01-module attributes: label: nRF24L01+ Module - description: | + description: | What type of nRF24L01+ chip is on your nRF24L01+ module ? * you verified this is a **nRF24L01+ plus** model capable of the required 256kBit/s mode ? * **square dot** indicates original Nordic Semicon chip ? @@ -69,43 +81,11 @@ body: * special **voltage stabilizing board** * **nothing** (yet) options: - - ~100uF Elko + - Elko (~100uF) - board - nothing validations: required: true - - type: textarea - id: connection-diagram - attributes: - label: Connection diagram - description: Tell us which connection diagram you used? - value: | - ## Connection diagram I used: - | nRF24L01+ Pin | ESP8266 GPIO | - | ------------- | -------------- | - | Pin 1 GND [*] | GND | - | Pin 2 +3.3V | +3.3V | - | Pin 3 CE | GPIO2 CE D4 | - | Pin 4 CSN | GPIO15 CS D8 | - | Pin 5 SCK | GPIO14 SCLK D5 | - | Pin 6 MOSI | GPIO13 MOSI D7 | - | Pin 7 MISO | GPIO12 MISO D6 | - | Pin 8 IRQ | GPIO0 IRQ D3 | - - | nRF24L01+ Pin | ESP32 GPIO | - | ------------- | --------------- | - | Pin 1 GND [*] | GND | - | Pin 2 +3.3V | +3.3V | - | Pin 3 CE | GPIO4 CE D4 | - | Pin 4 CSN | GPIO5 CS D5 | - | Pin 5 SCK | GPIO18 SCLK D18 | - | Pin 6 MOSI | GPIO23 MOSI D23 | - | Pin 7 MISO | GPIO19 MISO D19 | - | Pin 8 IRQ | GPIO0 IRQ D0 | - - Note: [*] GND Pin 1 has a square mark on the nRF24L01+ module - validations: - required: true - type: checkboxes id: connection-picture attributes: @@ -123,7 +103,7 @@ body: attributes: label: Version description: What version of our software are you running ? - placeholder: 0.5.17 + placeholder: 0.6.0 validations: required: true - type: input @@ -131,7 +111,7 @@ body: attributes: label: Github Hash description: Which GitHub hash has the build of our software ? - placeholder: 5402e9b + placeholder: 0000000 validations: required: true - type: dropdown @@ -140,19 +120,11 @@ body: label: Build & Flash Method description: What software do you use to flash / build & flash our firmware images ? options: + - AhoyDTU Webinstaller + - VSCode - Platform IO (build & flash) - ESP Tools (flash) - - Platform IO (build & flash) - validations: - required: true - - type: dropdown - id: desktop-os - attributes: - label: Desktop - description: Which operating system are you using on your desktop to build & flash ? - options: - - Linux - - Mac OS - - Windows + - Arduino IDE + - was already installed validations: required: true - type: textarea @@ -160,49 +132,12 @@ body: attributes: label: Setup description: | - Which settings are configured under http://ahoy-dtu/setup ? - Document any relevant setup values correctly. - Copy and paste the Inverter Section if you have multiple Inverters. - value: | - ### Device Host Name - - Device Name: AHOY-DTU - ### WiFi - - SSID: YOUR_WIFI_SSID *don't paste here* - - Password: YOUR_WIFI_PWD *don't paste here* - ### Inverter - #### Inverter 0 - - Address: 1141752123456 - - Name: HM-600 - - Active Power Limit: 65535 - - Active Power Limit Control Type: no powerlimit - - Max Module Power (Wp): 375, 375 - - Module Name: link, rech - ### General - - Interval [s]: 30 - - Max retries per Payload: 5 - ### NTP Server - - NTP Server / IP: pool.ntp.org - - NTP Port: 123 - ### MQTT - - Broker / Server IP: - - Port: 1883 - - Username (optional): - - Password (optional): - - Topic: inverter - ### System Config - #### Pinout (Wemos) - - CS: D8 (GPIO15) - - CE: D4 (GPIO2) - - IRQ: D3 (GPIO0) - #### Radio (NRF24L01+) - - Amplifier Power Level: LOW - #### Serial Console - - print inverter data: [x] - - Serial Debug: [x] - - Interval [s]: 5 - - - Reboot device after successful save: [x] - - SAVE + Which settings were modified to which values? Check this page on your DTU: http://ahoy-dtu/setup + Do not post private data here (SSID / passwords / serial numbers)! + placeholder: | + Some examples: + - MqTT: only broker was added + - Inverter: set intervall to 5 seconds .. validations: required: true - type: textarea @@ -219,12 +154,9 @@ body: attributes: label: Error description description: Please describe what you expected and what happened instead. - value: | - 1) Go to http://ahoy-dtu/setup - 2) configure above settings - 3) Reboot - 4) I did this - 5) I expected that - 6) and something completely differen happened + placeholder: | + 1) I went to https://ahoy-dtu.de/web_install and installed latest release + 2) I did some configurations, especially ... + ... validations: required: true diff --git a/src/CHANGES.md b/src/CHANGES.md index 9ab4722e..36063f46 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,7 +2,9 @@ ## 0.6.3 - 2023-04-04 * fix login, password length was not checked #852 -* merge PR #854 optimize browser caching, thx @tastendruecker123 +* merge PR #854 optimize browser caching, thx @tastendruecker123 #828 +* fix WiFi reconnect not working #851 +* updated issue templates #822 ## 0.6.2 - 2023-04-04 * fix login from multiple clients #819 diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 9677e7ee..08c19070 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -25,6 +25,7 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb) { mStaConn = DISCONNECTED; mCnt = 0; mScanActive = false; + mScanCnt = 0; #if defined(ESP8266) wifiConnectHandler = WiFi.onStationModeConnected(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); @@ -109,7 +110,7 @@ void ahoywifi::tickWifiLoop() { DBGPRINTLN(F(" seconds")); if(mScanActive) { getBSSIDs(); - if(!mScanActive) // scan completed + if((!mScanActive) && (!mBSSIDList.empty())) // scan completed if ((mCnt % timeout) < timeout - 2) mCnt = timeout - 2; } @@ -297,8 +298,7 @@ void ahoywifi::getAvailNetworks(JsonObject obj) { void ahoywifi::getBSSIDs() { int n = WiFi.scanComplete(); if (n < 0) { - mScanCnt++; - if (mScanCnt < 20) + if (++mScanCnt < 20) return; } if(n > 0) { From 597f8a089d1a85d46f4044951d0ca4eecff70ec7 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 5 Apr 2023 01:27:26 +0200 Subject: [PATCH 32/55] update issue templates --- .github/ISSUE_TEMPLATE/report-ahoy.md | 42 +------- .github/ISSUE_TEMPLATE/report.yaml | 132 +++++++------------------- 2 files changed, 35 insertions(+), 139 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/report-ahoy.md b/.github/ISSUE_TEMPLATE/report-ahoy.md index 1f361271..f7d10494 100644 --- a/.github/ISSUE_TEMPLATE/report-ahoy.md +++ b/.github/ISSUE_TEMPLATE/report-ahoy.md @@ -22,58 +22,22 @@ Retailer URL: ______ ### Antenna: * [ ] circuit board -* [ ] external antenna +* [ ] external antenna (SMA) ### Power Stabilization: * [ ] 100uF Electrolytic Capacitor connected between +3.3V and GND (Pin 1 & 2) of the NRF Module * [ ] Voltage stabilizing motherboard -### Connection diagram: -* [ ] Image of the your wiring attached - -### Connection diagram I used: -| nRF24L01+ Pin | ESP8266 GPIO | -| ------------- | -------------- | -| Pin 1 GND [*] | GND | -| Pin 2 +3.3V | +3.3V | -| Pin 3 CE | GPIO2 CE D4 | -| Pin 4 CSN | GPIO15 CS D8 | -| Pin 5 SCK | GPIO14 SCLK D5 | -| Pin 6 MOSI | GPIO13 MOSI D7 | -| Pin 7 MISO | GPIO12 MISO D6 | -| Pin 8 IRQ | GPIO0 IRQ D3 | - -| nRF24L01+ Pin | ESP32 GPIO | -| ------------- | --------------- | -| Pin 1 GND [*] | GND | -| Pin 2 +3.3V | +3.3V | -| Pin 3 CE | GPIO4 CE D4 | -| Pin 4 CSN | GPIO5 CS D5 | -| Pin 5 SCK | GPIO18 SCLK D18 | -| Pin 6 MOSI | GPIO23 MOSI D23 | -| Pin 7 MISO | GPIO19 MISO D19 | -| Pin 8 IRQ | GPIO0 IRQ D0 | - -Note: [*] GND Pin 1 has a square mark on the nRF24L01+ module - -## Software -* [ ] AhoyDTU -* [ ] OpenDTU - ### Version / Git SHA: Version: _._.__ Github Hash: _______ ### Build & Flash Method: +* [ ] AhoyDTU Webinstaller +* [ ] VSCode - Platform IO * [ ] Arduino * [ ] ESP Tools -* [ ] Platform IO - -### Desktop OS: -* [ ] Linux -* [ ] Windows -* [ ] Mac OS ### Debugging: * [ ] USB Serial Log (attached) diff --git a/.github/ISSUE_TEMPLATE/report.yaml b/.github/ISSUE_TEMPLATE/report.yaml index 6c834480..bab0b3d4 100644 --- a/.github/ISSUE_TEMPLATE/report.yaml +++ b/.github/ISSUE_TEMPLATE/report.yaml @@ -1,18 +1,20 @@ name: "AhoyDTU bug" description: "File a bug report" -title: "[ESP8266/ESP32/RaspberryPi] Problem Description / Beschreibung" +title: "[Bug]" labels: ["bug", "needs-triage"] assignees: - - stefan123t + - lumapu body: - type: markdown attributes: value: | Bitte die Posting Guide lines lesen, Vorlage kopieren und ausfüllen und in Eurem Support Forum Eintrag posten. Wir lesen auch gerne Deutsch, bitte fülle die u.a. Fragen aus damit wir Dir bestmöglich helfen können Danke! + Bitte unser FAQ als Hilfestellung prüfen: https://ahoydtu.de/faq Please read, copy & fill in the template from our Posting Guide lines into your Support Forum post. We do enjoy the english language, but we need a couple of things to best support you in your goal, please fill in all / most of the details given below. Thanks! + Check our FAQ: https://ahoydtu.de/faq - type: markdown attributes: value: "## Hardware" @@ -35,11 +37,21 @@ body: placeholder: validations: required: false + - type: dropdown + id: assembly-type + attributes: + label: Assembly + description: + options: + - I did the assebly by myself + - the DTU was already assembled + validations: + required: true - type: dropdown id: nrf24l01-module attributes: label: nRF24L01+ Module - description: | + description: | What type of nRF24L01+ chip is on your nRF24L01+ module ? * you verified this is a **nRF24L01+ plus** model capable of the required 256kBit/s mode ? * **square dot** indicates original Nordic Semicon chip ? @@ -69,43 +81,11 @@ body: * special **voltage stabilizing board** * **nothing** (yet) options: - - ~100uF Elko + - Elko (~100uF) - board - nothing validations: required: true - - type: textarea - id: connection-diagram - attributes: - label: Connection diagram - description: Tell us which connection diagram you used? - value: | - ## Connection diagram I used: - | nRF24L01+ Pin | ESP8266 GPIO | - | ------------- | -------------- | - | Pin 1 GND [*] | GND | - | Pin 2 +3.3V | +3.3V | - | Pin 3 CE | GPIO2 CE D4 | - | Pin 4 CSN | GPIO15 CS D8 | - | Pin 5 SCK | GPIO14 SCLK D5 | - | Pin 6 MOSI | GPIO13 MOSI D7 | - | Pin 7 MISO | GPIO12 MISO D6 | - | Pin 8 IRQ | GPIO0 IRQ D3 | - - | nRF24L01+ Pin | ESP32 GPIO | - | ------------- | --------------- | - | Pin 1 GND [*] | GND | - | Pin 2 +3.3V | +3.3V | - | Pin 3 CE | GPIO4 CE D4 | - | Pin 4 CSN | GPIO5 CS D5 | - | Pin 5 SCK | GPIO18 SCLK D18 | - | Pin 6 MOSI | GPIO23 MOSI D23 | - | Pin 7 MISO | GPIO19 MISO D19 | - | Pin 8 IRQ | GPIO0 IRQ D0 | - - Note: [*] GND Pin 1 has a square mark on the nRF24L01+ module - validations: - required: true - type: checkboxes id: connection-picture attributes: @@ -123,7 +103,7 @@ body: attributes: label: Version description: What version of our software are you running ? - placeholder: 0.5.17 + placeholder: 0.6.0 validations: required: true - type: input @@ -131,7 +111,7 @@ body: attributes: label: Github Hash description: Which GitHub hash has the build of our software ? - placeholder: 5402e9b + placeholder: 0000000 validations: required: true - type: dropdown @@ -140,19 +120,11 @@ body: label: Build & Flash Method description: What software do you use to flash / build & flash our firmware images ? options: + - AhoyDTU Webinstaller + - VSCode - Platform IO (build & flash) - ESP Tools (flash) - - Platform IO (build & flash) - validations: - required: true - - type: dropdown - id: desktop-os - attributes: - label: Desktop - description: Which operating system are you using on your desktop to build & flash ? - options: - - Linux - - Mac OS - - Windows + - Arduino IDE + - was already installed validations: required: true - type: textarea @@ -160,49 +132,12 @@ body: attributes: label: Setup description: | - Which settings are configured under http://ahoy-dtu/setup ? - Document any relevant setup values correctly. - Copy and paste the Inverter Section if you have multiple Inverters. - value: | - ### Device Host Name - - Device Name: AHOY-DTU - ### WiFi - - SSID: YOUR_WIFI_SSID *don't paste here* - - Password: YOUR_WIFI_PWD *don't paste here* - ### Inverter - #### Inverter 0 - - Address: 1141752123456 - - Name: HM-600 - - Active Power Limit: 65535 - - Active Power Limit Control Type: no powerlimit - - Max Module Power (Wp): 375, 375 - - Module Name: link, rech - ### General - - Interval [s]: 30 - - Max retries per Payload: 5 - ### NTP Server - - NTP Server / IP: pool.ntp.org - - NTP Port: 123 - ### MQTT - - Broker / Server IP: - - Port: 1883 - - Username (optional): - - Password (optional): - - Topic: inverter - ### System Config - #### Pinout (Wemos) - - CS: D8 (GPIO15) - - CE: D4 (GPIO2) - - IRQ: D3 (GPIO0) - #### Radio (NRF24L01+) - - Amplifier Power Level: LOW - #### Serial Console - - print inverter data: [x] - - Serial Debug: [x] - - Interval [s]: 5 - - - Reboot device after successful save: [x] - - SAVE + Which settings were modified to which values? Check this page on your DTU: http://ahoy-dtu/setup + Do not post private data here (SSID / passwords / serial numbers)! + placeholder: | + Some examples: + - MqTT: only broker was added + - Inverter: set intervall to 5 seconds .. validations: required: true - type: textarea @@ -219,12 +154,9 @@ body: attributes: label: Error description description: Please describe what you expected and what happened instead. - value: | - 1) Go to http://ahoy-dtu/setup - 2) configure above settings - 3) Reboot - 4) I did this - 5) I expected that - 6) and something completely differen happened + placeholder: | + 1) I went to https://ahoy-dtu.de/web_install and installed latest release + 2) I did some configurations, especially ... + ... validations: required: true From 31ea117a66c3a56d08280488490d4a8d06f3d050 Mon Sep 17 00:00:00 2001 From: Lukas Pusch Date: Wed, 5 Apr 2023 01:36:26 +0200 Subject: [PATCH 33/55] Update report.yaml --- .github/ISSUE_TEMPLATE/report.yaml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/report.yaml b/.github/ISSUE_TEMPLATE/report.yaml index bab0b3d4..de5cb077 100644 --- a/.github/ISSUE_TEMPLATE/report.yaml +++ b/.github/ISSUE_TEMPLATE/report.yaml @@ -29,14 +29,6 @@ body: - RaspberryPi validations: required: true - - type: input - id: model - attributes: - label: Model name - description: Please give us a precise description of your hardware and/or a link to the vendor - placeholder: - validations: - required: false - type: dropdown id: assembly-type attributes: From bf1e77e33ecdebc9ba2273c7ca65aab7ef026444 Mon Sep 17 00:00:00 2001 From: Lukas Pusch Date: Wed, 5 Apr 2023 01:38:40 +0200 Subject: [PATCH 34/55] Update report.yaml --- .github/ISSUE_TEMPLATE/report.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/report.yaml b/.github/ISSUE_TEMPLATE/report.yaml index de5cb077..9a2824c4 100644 --- a/.github/ISSUE_TEMPLATE/report.yaml +++ b/.github/ISSUE_TEMPLATE/report.yaml @@ -103,7 +103,7 @@ body: attributes: label: Github Hash description: Which GitHub hash has the build of our software ? - placeholder: 0000000 + placeholder: abc1234 validations: required: true - type: dropdown From c69b3e0110336e6f37ccef77566c56bc6a3b58d0 Mon Sep 17 00:00:00 2001 From: Thomas Pohl Date: Thu, 6 Apr 2023 16:58:50 +0200 Subject: [PATCH 35/55] Fix padding of title in mobile view --- src/web/html/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/html/style.css b/src/web/html/style.css index ca4b0c9a..f9ac25a1 100644 --- a/src/web/html/style.css +++ b/src/web/html/style.css @@ -92,7 +92,7 @@ svg.icon { .title { background-color: var(--primary); color: #fff !important; - padding-left: 80px !important + padding: 15px 14px 16px 80px !important } .topnav .icon span { From ef020dcc08e22d7ca774a1971d8586431a87b29a Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 6 Apr 2023 23:23:06 +0200 Subject: [PATCH 36/55] 0.6.4 * merge PR #846, improved NRF24 communication and MI, thx @beegee3 & @rejoe2 --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 36063f46..b35f099e 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.6.4 - 2023-04-06 +* merge PR #846, improved NRF24 communication and MI, thx @beegee3 & @rejoe2 + ## 0.6.3 - 2023-04-04 * fix login, password length was not checked #852 * merge PR #854 optimize browser caching, thx @tastendruecker123 #828 diff --git a/src/defines.h b/src/defines.h index 13799dbc..1ff3e1b7 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 3 +#define VERSION_PATCH 4 //------------------------------------- typedef struct { From d114fd67433ed20685701b7bd3859a9ff68d4c96 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 6 Apr 2023 23:29:00 +0200 Subject: [PATCH 37/55] 0.6.4 * merge PR #859, fix burger menu height, thx @ThomasPohl --- src/CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CHANGES.md b/src/CHANGES.md index b35f099e..c9b426b9 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,7 @@ ## 0.6.4 - 2023-04-06 * merge PR #846, improved NRF24 communication and MI, thx @beegee3 & @rejoe2 +* merge PR #859, fix burger menu height, thx @ThomasPohl ## 0.6.3 - 2023-04-04 * fix login, password length was not checked #852 From 0334898e3d038c2c14c70bd722e7b831d70f3b8e Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 7 Apr 2023 09:15:55 +0200 Subject: [PATCH 38/55] Do not send prometheus metric if channel is disabled in configuration --- doc/prometheus_ep_description.md | 2 +- src/web/web.h | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/doc/prometheus_ep_description.md b/doc/prometheus_ep_description.md index 8fb9e002..755fd1e4 100644 --- a/doc/prometheus_ep_description.md +++ b/doc/prometheus_ep_description.md @@ -12,7 +12,7 @@ Prometheus metrics provided at `/metrics`. | name | Inverter name from setup | | serial | Serial number of inverter | | inverter | Inverter name from setup | -| channel | Channel name from setup | +| channel | Channel (Module) name from setup. Label only available if max power level of module is set to non-zero. Be sure to have a cannel name set in configuration. | ## Exported Metrics | Metric name | Type | Description | Labels | diff --git a/src/web/web.h b/src/web/web.h index f8abc0f7..4b7cbb39 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -719,15 +719,20 @@ class Web { rec = iv->getRecordStruct(RealTimeRunData_Debug); if (metricsChannelId < rec->length) { uint8_t channel = rec->assign[metricsChannelId].ch; - std::tie(promUnit, promType) = convertToPromUnits(iv->getUnit(metricsChannelId, rec)); - snprintf(type, sizeof(type), "# TYPE ahoy_solar_%s%s %s", iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), promType.c_str()); - if (0 == channel) { - snprintf(topic, sizeof(topic), "ahoy_solar_%s%s{inverter=\"%s\"}", iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), iv->config->name); + // Skip entry if maxPwr is 0 and it's not the inverter channel (channel 0) + if (0 == channel || 0 != iv->config->chMaxPwr[channel-1]) { + std::tie(promUnit, promType) = convertToPromUnits(iv->getUnit(metricsChannelId, rec)); + snprintf(type, sizeof(type), "# TYPE ahoy_solar_%s%s %s", iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), promType.c_str()); + if (0 == channel) { + snprintf(topic, sizeof(topic), "ahoy_solar_%s%s{inverter=\"%s\"}", iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), iv->config->name); + } else { + snprintf(topic, sizeof(topic), "ahoy_solar_%s%s{inverter=\"%s\",channel=\"%s\"}", iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), iv->config->name,iv->config->chName[channel-1]); + } + snprintf(val, sizeof(val), "%.3f", iv->getValue(metricsChannelId, rec)); + len = snprintf((char*)buffer,maxLen,"%s\n%s %s\n",type,topic,val); } else { - snprintf(topic, sizeof(topic), "ahoy_solar_%s%s{inverter=\"%s\",channel=\"%s\"}", iv->getFieldName(metricsChannelId, rec), promUnit.c_str(), iv->config->name,iv->config->chName[channel-1]); + len = snprintf((char*)buffer,maxLen,"#\n"); // At least one char to send otherwise the transmission ends. } - snprintf(val, sizeof(val), "%.3f", iv->getValue(metricsChannelId, rec)); - len = snprintf((char*)buffer,maxLen,"%s\n%s %s\n",type,topic,val); metricsChannelId++; } else { From e17f6afc8621a33857800c5a82f5024de1ee5447 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 7 Apr 2023 17:13:44 +0200 Subject: [PATCH 39/55] Removed /json endpoint availablity from documentation --- Getting_Started.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Getting_Started.md b/Getting_Started.md index 3a031af0..4d35903c 100644 --- a/Getting_Started.md +++ b/Getting_Started.md @@ -264,9 +264,8 @@ When everything is wired up and the firmware is flashed, it is time to connect t | /cmdstat | show stat from the home page | | yes | | /visualization | displays the information from your converter | | yes | | /livedata | displays the live data | | yes | -| /json | gets live-data in JSON format | json output from the livedata | no - enable via config_override.h | | /metrics | gets live-data for prometheus | prometheus metrics from the livedata | no - enable via config_override.h | -| /api | | | yes | +| /api | gets configuration and live-data in JSON format | json output from the configuration or livedata | yes | ## MQTT command to set the DTU without webinterface From e8e1fd768133e2d3fde9d8cf0f1561ba24b66c63 Mon Sep 17 00:00:00 2001 From: tastendruecker123 <111116980+tastendruecker123@users.noreply.github.com> Date: Mon, 10 Apr 2023 14:17:05 +0200 Subject: [PATCH 40/55] Don't load JSON settings that don't exist --- src/config/settings.h | 136 +++++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/src/config/settings.h b/src/config/settings.h index e895a8a9..5f254bcf 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -245,15 +245,15 @@ class settings { root.shrinkToFit(); if(!err && (root.size() > 0)) { mCfg.valid = true; - jsonWifi(root[F("wifi")]); - jsonNrf(root[F("nrf")]); - jsonNtp(root[F("ntp")]); - jsonSun(root[F("sun")]); - jsonSerial(root[F("serial")]); - jsonMqtt(root[F("mqtt")]); - jsonLed(root[F("led")]); - jsonPlugin(root[F("plugin")]); - jsonInst(root[F("inst")]); + if(root.containsKey(F("wifi"))) jsonWifi(root[F("wifi")]); + if(root.containsKey(F("nrf"))) jsonNrf(root[F("nrf")]); + if(root.containsKey(F("ntp"))) jsonNtp(root[F("ntp")]); + if(root.containsKey(F("sun"))) jsonSun(root[F("sun")]); + if(root.containsKey(F("serial"))) jsonSerial(root[F("serial")]); + if(root.containsKey(F("mqtt"))) jsonMqtt(root[F("mqtt")]); + if(root.containsKey(F("led"))) jsonLed(root[F("led")]); + if(root.containsKey(F("plugin"))) jsonPlugin(root[F("plugin")]); + if(root.containsKey(F("inst"))) jsonInst(root[F("inst")]); } else { Serial.println(F("failed to parse json, using default config")); @@ -410,17 +410,17 @@ class settings { ah::ip2Char(mCfg.sys.ip.dns2, buf); obj[F("dns2")] = String(buf); ah::ip2Char(mCfg.sys.ip.gateway, buf); obj[F("gtwy")] = String(buf); } else { - snprintf(mCfg.sys.stationSsid, SSID_LEN, "%s", obj[F("ssid")].as()); - snprintf(mCfg.sys.stationPwd, PWD_LEN, "%s", obj[F("pwd")].as()); - snprintf(mCfg.sys.deviceName, DEVNAME_LEN, "%s", obj[F("dev")].as()); - snprintf(mCfg.sys.adminPwd, PWD_LEN, "%s", obj[F("adm")].as()); - mCfg.sys.protectionMask = obj[F("prot_mask")]; - mCfg.sys.darkMode = obj[F("dark")]; - ah::ip2Arr(mCfg.sys.ip.ip, obj[F("ip")].as()); - ah::ip2Arr(mCfg.sys.ip.mask, obj[F("mask")].as()); - ah::ip2Arr(mCfg.sys.ip.dns1, obj[F("dns1")].as()); - ah::ip2Arr(mCfg.sys.ip.dns2, obj[F("dns2")].as()); - ah::ip2Arr(mCfg.sys.ip.gateway, obj[F("gtwy")].as()); + if(obj.containsKey(F("ssid"))) snprintf(mCfg.sys.stationSsid, SSID_LEN, "%s", obj[F("ssid")].as()); + if(obj.containsKey(F("pwd"))) snprintf(mCfg.sys.stationPwd, PWD_LEN, "%s", obj[F("pwd")].as()); + if(obj.containsKey(F("dev"))) snprintf(mCfg.sys.deviceName, DEVNAME_LEN, "%s", obj[F("dev")].as()); + if(obj.containsKey(F("adm"))) snprintf(mCfg.sys.adminPwd, PWD_LEN, "%s", obj[F("adm")].as()); + if(obj.containsKey(F("prot_mask"))) mCfg.sys.protectionMask = obj[F("prot_mask")]; + if(obj.containsKey(F("dark"))) mCfg.sys.darkMode = obj[F("dark")]; + if(obj.containsKey(F("ip"))) ah::ip2Arr(mCfg.sys.ip.ip, obj[F("ip")].as()); + if(obj.containsKey(F("mask"))) ah::ip2Arr(mCfg.sys.ip.mask, obj[F("mask")].as()); + if(obj.containsKey(F("dns1"))) ah::ip2Arr(mCfg.sys.ip.dns1, obj[F("dns1")].as()); + if(obj.containsKey(F("dns2"))) ah::ip2Arr(mCfg.sys.ip.dns2, obj[F("dns2")].as()); + if(obj.containsKey(F("gtwy"))) ah::ip2Arr(mCfg.sys.ip.gateway, obj[F("gtwy")].as()); if(mCfg.sys.protectionMask == 0) mCfg.sys.protectionMask = DEF_PROT_INDEX | DEF_PROT_LIVE | DEF_PROT_SERIAL | DEF_PROT_SETUP @@ -440,15 +440,15 @@ class settings { obj[F("miso")] = mCfg.nrf.pinMiso; obj[F("pwr")] = mCfg.nrf.amplifierPower; } else { - mCfg.nrf.sendInterval = obj[F("intvl")]; - mCfg.nrf.maxRetransPerPyld = obj[F("maxRetry")]; - mCfg.nrf.pinCs = obj[F("cs")]; - mCfg.nrf.pinCe = obj[F("ce")]; - mCfg.nrf.pinIrq = obj[F("irq")]; - mCfg.nrf.pinSclk = obj[F("sclk")]; - mCfg.nrf.pinMosi = obj[F("mosi")]; - mCfg.nrf.pinMiso = obj[F("miso")]; - mCfg.nrf.amplifierPower = obj[F("pwr")]; + if(obj.containsKey(F("ssid"))) mCfg.nrf.sendInterval = obj[F("intvl")]; + if(obj.containsKey(F("maxRetry"))) mCfg.nrf.maxRetransPerPyld = obj[F("maxRetry")]; + if(obj.containsKey(F("cs"))) mCfg.nrf.pinCs = obj[F("cs")]; + if(obj.containsKey(F("ce"))) mCfg.nrf.pinCe = obj[F("ce")]; + if(obj.containsKey(F("irq"))) mCfg.nrf.pinIrq = obj[F("irq")]; + if(obj.containsKey(F("sclk"))) mCfg.nrf.pinSclk = obj[F("sclk")]; + if(obj.containsKey(F("mosi"))) mCfg.nrf.pinMosi = obj[F("mosi")]; + if(obj.containsKey(F("miso"))) mCfg.nrf.pinMiso = obj[F("miso")]; + if(obj.containsKey(F("pwr"))) mCfg.nrf.amplifierPower = obj[F("pwr")]; if((obj[F("cs")] == obj[F("ce")])) { mCfg.nrf.pinCs = DEF_CS_PIN; mCfg.nrf.pinCe = DEF_CE_PIN; @@ -465,8 +465,8 @@ class settings { obj[F("addr")] = mCfg.ntp.addr; obj[F("port")] = mCfg.ntp.port; } else { - snprintf(mCfg.ntp.addr, NTP_ADDR_LEN, "%s", obj[F("addr")].as()); - mCfg.ntp.port = obj[F("port")]; + if(obj.containsKey(F("addr"))) snprintf(mCfg.ntp.addr, NTP_ADDR_LEN, "%s", obj[F("addr")].as()); + if(obj.containsKey(F("port"))) mCfg.ntp.port = obj[F("port")]; } } @@ -477,10 +477,10 @@ class settings { obj[F("dis")] = mCfg.sun.disNightCom; obj[F("offs")] = mCfg.sun.offsetSec; } else { - mCfg.sun.lat = obj[F("lat")]; - mCfg.sun.lon = obj[F("lon")]; - mCfg.sun.disNightCom = obj[F("dis")]; - mCfg.sun.offsetSec = obj[F("offs")]; + if(obj.containsKey(F("lat"))) mCfg.sun.lat = obj[F("lat")]; + if(obj.containsKey(F("lon"))) mCfg.sun.lon = obj[F("lon")]; + if(obj.containsKey(F("dis"))) mCfg.sun.disNightCom = obj[F("dis")]; + if(obj.containsKey(F("offs"))) mCfg.sun.offsetSec = obj[F("offs")]; } } @@ -490,9 +490,9 @@ class settings { obj[F("show")] = mCfg.serial.showIv; obj[F("debug")] = mCfg.serial.debug; } else { - mCfg.serial.interval = obj[F("intvl")]; - mCfg.serial.showIv = obj[F("show")]; - mCfg.serial.debug = obj[F("debug")]; + if(obj.containsKey(F("intvl"))) mCfg.serial.interval = obj[F("intvl")]; + if(obj.containsKey(F("show"))) mCfg.serial.showIv = obj[F("show")]; + if(obj.containsKey(F("debug"))) mCfg.serial.debug = obj[F("debug")]; } } @@ -506,12 +506,12 @@ class settings { obj[F("intvl")] = mCfg.mqtt.interval; } else { - mCfg.mqtt.port = obj[F("port")]; - mCfg.mqtt.interval = obj[F("intvl")]; - snprintf(mCfg.mqtt.broker, MQTT_ADDR_LEN, "%s", obj[F("broker")].as()); - snprintf(mCfg.mqtt.user, MQTT_USER_LEN, "%s", obj[F("user")].as()); - snprintf(mCfg.mqtt.pwd, MQTT_PWD_LEN, "%s", obj[F("pwd")].as()); - snprintf(mCfg.mqtt.topic, MQTT_TOPIC_LEN, "%s", obj[F("topic")].as()); + if(obj.containsKey(F("port"))) mCfg.mqtt.port = obj[F("port")]; + if(obj.containsKey(F("intvl"))) mCfg.mqtt.interval = obj[F("intvl")]; + if(obj.containsKey(F("broker"))) snprintf(mCfg.mqtt.broker, MQTT_ADDR_LEN, "%s", obj[F("broker")].as()); + if(obj.containsKey(F("user"))) snprintf(mCfg.mqtt.user, MQTT_USER_LEN, "%s", obj[F("user")].as()); + if(obj.containsKey(F("pwd"))) snprintf(mCfg.mqtt.pwd, MQTT_PWD_LEN, "%s", obj[F("pwd")].as()); + if(obj.containsKey(F("topic"))) snprintf(mCfg.mqtt.topic, MQTT_TOPIC_LEN, "%s", obj[F("topic")].as()); } } @@ -521,9 +521,9 @@ class settings { obj[F("1")] = mCfg.led.led1; obj[F("led_high_active")] = mCfg.led.led_high_active; } else { - mCfg.led.led0 = obj[F("0")]; - mCfg.led.led1 = obj[F("1")]; - mCfg.led.led_high_active = obj[F("led_high_active")]; + if(obj.containsKey(F("0"))) mCfg.led.led0 = obj[F("0")]; + if(obj.containsKey(F("1"))) mCfg.led.led1 = obj[F("1")]; + if(obj.containsKey(F("led_high_active"))) mCfg.led.led_high_active = obj[F("led_high_active")]; } } @@ -545,19 +545,19 @@ class settings { disp[F("dc")] = mCfg.plugin.display.disp_dc; } else { JsonObject disp = obj["disp"]; - mCfg.plugin.display.type = disp[F("type")]; - mCfg.plugin.display.pwrSaveAtIvOffline = (bool)disp[F("pwrSafe")]; - mCfg.plugin.display.pxShift = (bool)disp[F("pxShift")]; - mCfg.plugin.display.rot = disp[F("rotation")]; + if(disp.containsKey(F("type"))) mCfg.plugin.display.type = disp[F("type")]; + if(disp.containsKey(F("pwrSafe"))) mCfg.plugin.display.pwrSaveAtIvOffline = (bool)disp[F("pwrSafe")]; + if(disp.containsKey(F("pxShift"))) mCfg.plugin.display.pxShift = (bool)disp[F("pxShift")]; + if(disp.containsKey(F("rotation"))) mCfg.plugin.display.rot = disp[F("rotation")]; //mCfg.plugin.display.wakeUp = disp[F("wake")]; //mCfg.plugin.display.sleepAt = disp[F("sleep")]; - mCfg.plugin.display.contrast = disp[F("contrast")]; - mCfg.plugin.display.disp_data = disp[F("data")]; - mCfg.plugin.display.disp_clk = disp[F("clock")]; - mCfg.plugin.display.disp_cs = disp[F("cs")]; - mCfg.plugin.display.disp_reset = disp[F("reset")]; - mCfg.plugin.display.disp_busy = disp[F("busy")]; - mCfg.plugin.display.disp_dc = disp[F("dc")]; + if(disp.containsKey(F("contrast"))) mCfg.plugin.display.contrast = disp[F("contrast")]; + if(disp.containsKey(F("data"))) mCfg.plugin.display.disp_data = disp[F("data")]; + if(disp.containsKey(F("clock"))) mCfg.plugin.display.disp_clk = disp[F("clock")]; + if(disp.containsKey(F("cs"))) mCfg.plugin.display.disp_cs = disp[F("cs")]; + if(disp.containsKey(F("reset"))) mCfg.plugin.display.disp_reset = disp[F("reset")]; + if(disp.containsKey(F("busy"))) mCfg.plugin.display.disp_busy = disp[F("busy")]; + if(disp.containsKey(F("dc"))) mCfg.plugin.display.disp_dc = disp[F("dc")]; } } @@ -569,10 +569,10 @@ class settings { obj[F("rstComStop")] = (bool)mCfg.inst.rstValsCommStop; } else { - mCfg.inst.enabled = (bool)obj[F("en")]; - mCfg.inst.rstYieldMidNight = (bool)obj["rstMidNight"]; - mCfg.inst.rstValsNotAvail = (bool)obj["rstNotAvail"]; - mCfg.inst.rstValsCommStop = (bool)obj["rstComStop"]; + if(obj.containsKey(F("en"))) mCfg.inst.enabled = (bool)obj[F("en")]; + if(obj.containsKey(F("rstMidNight"))) mCfg.inst.rstYieldMidNight = (bool)obj["rstMidNight"]; + if(obj.containsKey(F("rstNotAvail"))) mCfg.inst.rstValsNotAvail = (bool)obj["rstNotAvail"]; + if(obj.containsKey(F("rstComStop"))) mCfg.inst.rstValsCommStop = (bool)obj["rstComStop"]; } JsonArray ivArr; @@ -601,13 +601,13 @@ class settings { obj[F("chName")][i] = cfg->chName[i]; } } else { - cfg->enabled = (bool)obj[F("en")]; - snprintf(cfg->name, MAX_NAME_LENGTH, "%s", obj[F("name")].as()); - cfg->serial.u64 = obj[F("sn")]; + if(obj.containsKey(F("en"))) cfg->enabled = (bool)obj[F("en")]; + if(obj.containsKey(F("name"))) snprintf(cfg->name, MAX_NAME_LENGTH, "%s", obj[F("name")].as()); + if(obj.containsKey(F("sn"))) cfg->serial.u64 = obj[F("sn")]; for(uint8_t i = 0; i < 4; i++) { - cfg->yieldCor[i] = obj[F("yield")][i]; - cfg->chMaxPwr[i] = obj[F("pwr")][i]; - snprintf(cfg->chName[i], MAX_NAME_LENGTH, "%s", obj[F("chName")][i].as()); + if(obj.containsKey(F("yield"))) cfg->yieldCor[i] = obj[F("yield")][i]; + if(obj.containsKey(F("pwr"))) cfg->chMaxPwr[i] = obj[F("pwr")][i]; + if(obj.containsKey(F("chName"))) snprintf(cfg->chName[i], MAX_NAME_LENGTH, "%s", obj[F("chName")][i].as()); } } } From f946b35d062ba6c3b6ec6b35d8c21d23981803a1 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 11 Apr 2023 20:54:33 +0200 Subject: [PATCH 41/55] 0.6.5 * fix #845 MqTT subscription for `ctrl/power/[IV-ID]` was missing --- src/CHANGES.md | 3 +++ src/publisher/pubMqtt.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/CHANGES.md b/src/CHANGES.md index c9b426b9..cc9d8a4b 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.6.5 - 2023-04-11 +* fix #845 MqTT subscription for `ctrl/power/[IV-ID]` was missing + ## 0.6.4 - 2023-04-06 * merge PR #846, improved NRF24 communication and MI, thx @beegee3 & @rejoe2 * merge PR #859, fix burger menu height, thx @ThomasPohl diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index e717ee7c..f9bf6f4d 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -247,6 +247,8 @@ class PubMqtt { subscribe(mVal); snprintf(mVal, 20, "ctrl/restart/%d", i); subscribe(mVal); + snprintf(mVal, 20, "ctrl/power/%d", i); + subscribe(mVal); } subscribe(subscr[MQTT_SUBS_SET_TIME]); } From 33186a9833a307a97347de7a52c19372ff2457aa Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 11 Apr 2023 22:39:08 +0200 Subject: [PATCH 42/55] 0.6.5 - 2023-04-11 * merge PR #876, check JSON settings during read for existance * **NOTE:** incompatible change: renamed `led_high_active` to `act_high`, maybe setting must be changed after update --- src/CHANGES.md | 2 + src/config/settings.h | 146 +++++++++++++++++++++++++----------------- src/utils/dbg.h | 2 +- 3 files changed, 89 insertions(+), 61 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index cc9d8a4b..69de48ff 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,8 @@ ## 0.6.5 - 2023-04-11 * fix #845 MqTT subscription for `ctrl/power/[IV-ID]` was missing +* merge PR #876, check JSON settings during read for existance +* **NOTE:** incompatible change: renamed `led_high_active` to `act_high`, maybe setting must be changed after update ## 0.6.4 - 2023-04-06 * merge PR #846, improved NRF24 communication and MI, thx @beegee3 & @rejoe2 diff --git a/src/config/settings.h b/src/config/settings.h index 5f254bcf..2f20510b 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -6,6 +6,11 @@ #ifndef __SETTINGS_H__ #define __SETTINGS_H__ +#if defined(F) && defined(ESP32) + #undef F + #define F(sl) (sl) +#endif + #include #include #include @@ -410,12 +415,12 @@ class settings { ah::ip2Char(mCfg.sys.ip.dns2, buf); obj[F("dns2")] = String(buf); ah::ip2Char(mCfg.sys.ip.gateway, buf); obj[F("gtwy")] = String(buf); } else { - if(obj.containsKey(F("ssid"))) snprintf(mCfg.sys.stationSsid, SSID_LEN, "%s", obj[F("ssid")].as()); - if(obj.containsKey(F("pwd"))) snprintf(mCfg.sys.stationPwd, PWD_LEN, "%s", obj[F("pwd")].as()); - if(obj.containsKey(F("dev"))) snprintf(mCfg.sys.deviceName, DEVNAME_LEN, "%s", obj[F("dev")].as()); - if(obj.containsKey(F("adm"))) snprintf(mCfg.sys.adminPwd, PWD_LEN, "%s", obj[F("adm")].as()); - if(obj.containsKey(F("prot_mask"))) mCfg.sys.protectionMask = obj[F("prot_mask")]; - if(obj.containsKey(F("dark"))) mCfg.sys.darkMode = obj[F("dark")]; + getChar(obj, F("ssid"), mCfg.sys.stationSsid, SSID_LEN); + getChar(obj, F("pwd"), mCfg.sys.stationPwd, PWD_LEN); + getChar(obj, F("adm"), mCfg.sys.deviceName, DEVNAME_LEN); + getChar(obj, F("dev"), mCfg.sys.adminPwd, PWD_LEN); + getVal(obj, F("prot_mask"), &mCfg.sys.protectionMask); + getVal(obj, F("dark"), &mCfg.sys.darkMode); if(obj.containsKey(F("ip"))) ah::ip2Arr(mCfg.sys.ip.ip, obj[F("ip")].as()); if(obj.containsKey(F("mask"))) ah::ip2Arr(mCfg.sys.ip.mask, obj[F("mask")].as()); if(obj.containsKey(F("dns1"))) ah::ip2Arr(mCfg.sys.ip.dns1, obj[F("dns1")].as()); @@ -440,15 +445,15 @@ class settings { obj[F("miso")] = mCfg.nrf.pinMiso; obj[F("pwr")] = mCfg.nrf.amplifierPower; } else { - if(obj.containsKey(F("ssid"))) mCfg.nrf.sendInterval = obj[F("intvl")]; - if(obj.containsKey(F("maxRetry"))) mCfg.nrf.maxRetransPerPyld = obj[F("maxRetry")]; - if(obj.containsKey(F("cs"))) mCfg.nrf.pinCs = obj[F("cs")]; - if(obj.containsKey(F("ce"))) mCfg.nrf.pinCe = obj[F("ce")]; - if(obj.containsKey(F("irq"))) mCfg.nrf.pinIrq = obj[F("irq")]; - if(obj.containsKey(F("sclk"))) mCfg.nrf.pinSclk = obj[F("sclk")]; - if(obj.containsKey(F("mosi"))) mCfg.nrf.pinMosi = obj[F("mosi")]; - if(obj.containsKey(F("miso"))) mCfg.nrf.pinMiso = obj[F("miso")]; - if(obj.containsKey(F("pwr"))) mCfg.nrf.amplifierPower = obj[F("pwr")]; + getVal(obj, F("intvl"), &mCfg.nrf.sendInterval); + getVal(obj, F("maxRetry"), &mCfg.nrf.maxRetransPerPyld); + getVal(obj, F("cs"), &mCfg.nrf.pinCs); + getVal(obj, F("ce"), &mCfg.nrf.pinCe); + getVal(obj, F("irq"), &mCfg.nrf.pinIrq); + getVal(obj, F("sclk"), &mCfg.nrf.pinSclk); + getVal(obj, F("mosi"), &mCfg.nrf.pinMosi); + getVal(obj, F("miso"), &mCfg.nrf.pinMiso); + getVal(obj, F("pwr"), &mCfg.nrf.amplifierPower); if((obj[F("cs")] == obj[F("ce")])) { mCfg.nrf.pinCs = DEF_CS_PIN; mCfg.nrf.pinCe = DEF_CE_PIN; @@ -465,8 +470,8 @@ class settings { obj[F("addr")] = mCfg.ntp.addr; obj[F("port")] = mCfg.ntp.port; } else { - if(obj.containsKey(F("addr"))) snprintf(mCfg.ntp.addr, NTP_ADDR_LEN, "%s", obj[F("addr")].as()); - if(obj.containsKey(F("port"))) mCfg.ntp.port = obj[F("port")]; + getChar(obj, F("addr"), mCfg.ntp.addr, NTP_ADDR_LEN); + getVal(obj, F("port"), &mCfg.ntp.port); } } @@ -477,10 +482,10 @@ class settings { obj[F("dis")] = mCfg.sun.disNightCom; obj[F("offs")] = mCfg.sun.offsetSec; } else { - if(obj.containsKey(F("lat"))) mCfg.sun.lat = obj[F("lat")]; - if(obj.containsKey(F("lon"))) mCfg.sun.lon = obj[F("lon")]; - if(obj.containsKey(F("dis"))) mCfg.sun.disNightCom = obj[F("dis")]; - if(obj.containsKey(F("offs"))) mCfg.sun.offsetSec = obj[F("offs")]; + getVal(obj, F("lat"), &mCfg.sun.lat); + getVal(obj, F("lon"), &mCfg.sun.lon); + getVal(obj, F("dis"), &mCfg.sun.disNightCom); + getVal(obj, F("offs"), &mCfg.sun.offsetSec); } } @@ -490,9 +495,9 @@ class settings { obj[F("show")] = mCfg.serial.showIv; obj[F("debug")] = mCfg.serial.debug; } else { - if(obj.containsKey(F("intvl"))) mCfg.serial.interval = obj[F("intvl")]; - if(obj.containsKey(F("show"))) mCfg.serial.showIv = obj[F("show")]; - if(obj.containsKey(F("debug"))) mCfg.serial.debug = obj[F("debug")]; + getVal(obj, F("intvl"), &mCfg.serial.interval); + getVal(obj, F("show"), &mCfg.serial.showIv); + getVal(obj, F("debug"), &mCfg.serial.debug); } } @@ -506,12 +511,12 @@ class settings { obj[F("intvl")] = mCfg.mqtt.interval; } else { - if(obj.containsKey(F("port"))) mCfg.mqtt.port = obj[F("port")]; - if(obj.containsKey(F("intvl"))) mCfg.mqtt.interval = obj[F("intvl")]; - if(obj.containsKey(F("broker"))) snprintf(mCfg.mqtt.broker, MQTT_ADDR_LEN, "%s", obj[F("broker")].as()); - if(obj.containsKey(F("user"))) snprintf(mCfg.mqtt.user, MQTT_USER_LEN, "%s", obj[F("user")].as()); - if(obj.containsKey(F("pwd"))) snprintf(mCfg.mqtt.pwd, MQTT_PWD_LEN, "%s", obj[F("pwd")].as()); - if(obj.containsKey(F("topic"))) snprintf(mCfg.mqtt.topic, MQTT_TOPIC_LEN, "%s", obj[F("topic")].as()); + getVal(obj, F("port"), &mCfg.mqtt.port); + getVal(obj, F("intvl"), &mCfg.mqtt.interval); + getChar(obj, F("broker"), mCfg.mqtt.broker, MQTT_ADDR_LEN); + getChar(obj, F("user"), mCfg.mqtt.user, MQTT_USER_LEN); + getChar(obj, F("pwd"), mCfg.mqtt.pwd, MQTT_PWD_LEN); + getChar(obj, F("topic"), mCfg.mqtt.topic, MQTT_TOPIC_LEN); } } @@ -519,11 +524,11 @@ class settings { if(set) { obj[F("0")] = mCfg.led.led0; obj[F("1")] = mCfg.led.led1; - obj[F("led_high_active")] = mCfg.led.led_high_active; + obj[F("act_high")] = mCfg.led.led_high_active; } else { - if(obj.containsKey(F("0"))) mCfg.led.led0 = obj[F("0")]; - if(obj.containsKey(F("1"))) mCfg.led.led1 = obj[F("1")]; - if(obj.containsKey(F("led_high_active"))) mCfg.led.led_high_active = obj[F("led_high_active")]; + getVal(obj, F("0"), &mCfg.led.led0); + getVal(obj, F("1"), &mCfg.led.led1); + getVal(obj, F("act_high"), &mCfg.led.led_high_active); } } @@ -545,19 +550,19 @@ class settings { disp[F("dc")] = mCfg.plugin.display.disp_dc; } else { JsonObject disp = obj["disp"]; - if(disp.containsKey(F("type"))) mCfg.plugin.display.type = disp[F("type")]; - if(disp.containsKey(F("pwrSafe"))) mCfg.plugin.display.pwrSaveAtIvOffline = (bool)disp[F("pwrSafe")]; - if(disp.containsKey(F("pxShift"))) mCfg.plugin.display.pxShift = (bool)disp[F("pxShift")]; - if(disp.containsKey(F("rotation"))) mCfg.plugin.display.rot = disp[F("rotation")]; + getVal(disp, F("type"), &mCfg.plugin.display.type); + getVal(disp, F("pwrSafe"), &mCfg.plugin.display.pwrSaveAtIvOffline); + getVal(disp, F("pxShift"), &mCfg.plugin.display.pxShift); + getVal(disp, F("rotation"), &mCfg.plugin.display.rot); //mCfg.plugin.display.wakeUp = disp[F("wake")]; //mCfg.plugin.display.sleepAt = disp[F("sleep")]; - if(disp.containsKey(F("contrast"))) mCfg.plugin.display.contrast = disp[F("contrast")]; - if(disp.containsKey(F("data"))) mCfg.plugin.display.disp_data = disp[F("data")]; - if(disp.containsKey(F("clock"))) mCfg.plugin.display.disp_clk = disp[F("clock")]; - if(disp.containsKey(F("cs"))) mCfg.plugin.display.disp_cs = disp[F("cs")]; - if(disp.containsKey(F("reset"))) mCfg.plugin.display.disp_reset = disp[F("reset")]; - if(disp.containsKey(F("busy"))) mCfg.plugin.display.disp_busy = disp[F("busy")]; - if(disp.containsKey(F("dc"))) mCfg.plugin.display.disp_dc = disp[F("dc")]; + getVal(disp, F("contrast"), &mCfg.plugin.display.contrast); + getVal(disp, F("data"), &mCfg.plugin.display.disp_data); + getVal(disp, F("clock"), &mCfg.plugin.display.disp_clk); + getVal(disp, F("cs"), &mCfg.plugin.display.disp_cs); + getVal(disp, F("reset"), &mCfg.plugin.display.disp_reset); + getVal(disp, F("busy"), &mCfg.plugin.display.disp_busy); + getVal(disp, F("dc"), &mCfg.plugin.display.disp_dc); } } @@ -569,10 +574,10 @@ class settings { obj[F("rstComStop")] = (bool)mCfg.inst.rstValsCommStop; } else { - if(obj.containsKey(F("en"))) mCfg.inst.enabled = (bool)obj[F("en")]; - if(obj.containsKey(F("rstMidNight"))) mCfg.inst.rstYieldMidNight = (bool)obj["rstMidNight"]; - if(obj.containsKey(F("rstNotAvail"))) mCfg.inst.rstValsNotAvail = (bool)obj["rstNotAvail"]; - if(obj.containsKey(F("rstComStop"))) mCfg.inst.rstValsCommStop = (bool)obj["rstComStop"]; + getVal(obj, F("en"), &mCfg.inst.enabled); + getVal(obj, F("rstMidNight"), &mCfg.inst.rstYieldMidNight); + getVal(obj, F("rstNotAvail"), &mCfg.inst.rstValsNotAvail); + getVal(obj, F("rstComStop"), &mCfg.inst.rstValsCommStop); } JsonArray ivArr; @@ -582,11 +587,8 @@ class settings { if(set) { if(mCfg.inst.iv[i].serial.u64 != 0ULL) jsonIv(ivArr.createNestedObject(), &mCfg.inst.iv[i], true); - } - else { - if(!obj[F("iv")][i].isNull()) - jsonIv(obj[F("iv")][i], &mCfg.inst.iv[i]); - } + } else if(!obj[F("iv")][i].isNull()) + jsonIv(obj[F("iv")][i], &mCfg.inst.iv[i]); } } @@ -601,17 +603,41 @@ class settings { obj[F("chName")][i] = cfg->chName[i]; } } else { - if(obj.containsKey(F("en"))) cfg->enabled = (bool)obj[F("en")]; - if(obj.containsKey(F("name"))) snprintf(cfg->name, MAX_NAME_LENGTH, "%s", obj[F("name")].as()); - if(obj.containsKey(F("sn"))) cfg->serial.u64 = obj[F("sn")]; + getVal(obj, F("en"), &cfg->enabled); + getChar(obj, F("name"), cfg->name, MAX_NAME_LENGTH); + getVal(obj, F("sn"), &cfg->serial.u64); for(uint8_t i = 0; i < 4; i++) { - if(obj.containsKey(F("yield"))) cfg->yieldCor[i] = obj[F("yield")][i]; - if(obj.containsKey(F("pwr"))) cfg->chMaxPwr[i] = obj[F("pwr")][i]; - if(obj.containsKey(F("chName"))) snprintf(cfg->chName[i], MAX_NAME_LENGTH, "%s", obj[F("chName")][i].as()); + getVal(obj, F("yield"), &cfg->yieldCor[i]); + getVal(obj, F("pwr"), &cfg->chMaxPwr[i]); + getChar(obj, F("chName"), cfg->chName[i], MAX_NAME_LENGTH); } } } + #if defined(ESP32) + void getChar(JsonObject obj, const char *key, char *dst, int maxLen) { + if(obj.containsKey(key)) + snprintf(dst, maxLen, "%s", obj[key].as()); + } + + template + void getVal(JsonObject obj, const char *key, T *dst) { + if(obj.containsKey(key)) + *dst = obj[key]; + } + #else + void getChar(JsonObject obj, const __FlashStringHelper *key, char *dst, int maxLen) { + if(obj.containsKey(key)) + snprintf(dst, maxLen, "%s", obj[key].as()); + } + + template + void getVal(JsonObject obj, const __FlashStringHelper *key, T *dst) { + if(obj.containsKey(key)) + *dst = obj[key]; + } + #endif + settings_t mCfg; bool mLastSaveSucceed; }; diff --git a/src/utils/dbg.h b/src/utils/dbg.h index 4716d7ae..a18d2f77 100644 --- a/src/utils/dbg.h +++ b/src/utils/dbg.h @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // 2023 Ahoy, https://www.mikrocontroller.net/topic/525778 -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- #ifndef __DBG_H__ From 563550d42cc3e74ca77c374a52ec05b3f767e62d Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 11 Apr 2023 22:44:05 +0200 Subject: [PATCH 43/55] 0.6.5 * merge PR #861 do not send channel metric if channel is disabled --- src/CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CHANGES.md b/src/CHANGES.md index 69de48ff..bfe6eb31 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -4,6 +4,7 @@ * fix #845 MqTT subscription for `ctrl/power/[IV-ID]` was missing * merge PR #876, check JSON settings during read for existance * **NOTE:** incompatible change: renamed `led_high_active` to `act_high`, maybe setting must be changed after update +* merge PR #861 do not send channel metric if channel is disabled ## 0.6.4 - 2023-04-06 * merge PR #846, improved NRF24 communication and MI, thx @beegee3 & @rejoe2 From d953dbfa37433c05ebcd500f326333f002de86b4 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 11 Apr 2023 23:38:27 +0200 Subject: [PATCH 44/55] 0.6.5 * fix small issue during loading settings --- src/config/settings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/settings.h b/src/config/settings.h index 2f20510b..078c88c3 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -609,7 +609,7 @@ class settings { for(uint8_t i = 0; i < 4; i++) { getVal(obj, F("yield"), &cfg->yieldCor[i]); getVal(obj, F("pwr"), &cfg->chMaxPwr[i]); - getChar(obj, F("chName"), cfg->chName[i], MAX_NAME_LENGTH); + if(obj.containsKey(F("chName"))) snprintf(cfg->chName[i], MAX_NAME_LENGTH, "%s", obj[F("chName")][i].as()); } } } From f38bee88a163ebb535acd3aa341f3c755be9fddf Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 11 Apr 2023 23:44:34 +0200 Subject: [PATCH 45/55] another fix --- src/config/settings.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/settings.h b/src/config/settings.h index 078c88c3..7d924c4e 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -417,8 +417,8 @@ class settings { } else { getChar(obj, F("ssid"), mCfg.sys.stationSsid, SSID_LEN); getChar(obj, F("pwd"), mCfg.sys.stationPwd, PWD_LEN); - getChar(obj, F("adm"), mCfg.sys.deviceName, DEVNAME_LEN); - getChar(obj, F("dev"), mCfg.sys.adminPwd, PWD_LEN); + getChar(obj, F("dev"), mCfg.sys.deviceName, DEVNAME_LEN); + getChar(obj, F("adm"), mCfg.sys.adminPwd, PWD_LEN); getVal(obj, F("prot_mask"), &mCfg.sys.protectionMask); getVal(obj, F("dark"), &mCfg.sys.darkMode); if(obj.containsKey(F("ip"))) ah::ip2Arr(mCfg.sys.ip.ip, obj[F("ip")].as()); From a0659968cecba561f334d7c1f2e300bba03a5cbd Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 11 Apr 2023 23:47:32 +0200 Subject: [PATCH 46/55] 0.6.5 Version number increase --- src/defines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/defines.h b/src/defines.h index 1ff3e1b7..f4adc55e 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 4 +#define VERSION_PATCH 5 //------------------------------------- typedef struct { From 1e1696ca15c0d6777856d9e800da6ba73c92309b Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 11 Apr 2023 23:52:54 +0200 Subject: [PATCH 47/55] 0.6.5 fix max module power read --- src/config/settings.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/settings.h b/src/config/settings.h index 7d924c4e..dc5a4408 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -607,8 +607,8 @@ class settings { getChar(obj, F("name"), cfg->name, MAX_NAME_LENGTH); getVal(obj, F("sn"), &cfg->serial.u64); for(uint8_t i = 0; i < 4; i++) { - getVal(obj, F("yield"), &cfg->yieldCor[i]); - getVal(obj, F("pwr"), &cfg->chMaxPwr[i]); + if(obj.containsKey(F("yield"))) cfg->yieldCor[i] = obj[F("yield")][i]; + if(obj.containsKey(F("pwr"))) cfg->chMaxPwr[i] = obj[F("pwr")][i]; if(obj.containsKey(F("chName"))) snprintf(cfg->chName[i], MAX_NAME_LENGTH, "%s", obj[F("chName")][i].as()); } } From 48ce948ede2c657680ea60a0acfadc668abc159a Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 12 Apr 2023 22:50:37 +0200 Subject: [PATCH 48/55] 0.6.6 * increased distance for `import` button in mobile view #879 * changed `led_high_active` to `bool` #879 --- src/CHANGES.md | 4 ++++ src/app.cpp | 8 +++----- src/config/settings.h | 6 +++--- src/defines.h | 2 +- src/web/html/includes/header.html | 3 ++- src/web/html/setup.html | 2 +- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index bfe6eb31..4e5900ad 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.6.6 - 2023-04-12 +* increased distance for `import` button in mobile view #879 +* changed `led_high_active` to `bool` #879 + ## 0.6.5 - 2023-04-11 * fix #845 MqTT subscription for `ctrl/power/[IV-ID]` was missing * merge PR #876, check JSON settings during read for existance diff --git a/src/app.cpp b/src/app.cpp index 7a0e5f2a..d2d87f50 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -389,8 +389,7 @@ void app::mqttSubRxCb(JsonObject obj) { //----------------------------------------------------------------------------- void app::setupLed(void) { - - uint8_t led_off = (mConfig->led.led_high_active != 0) ? LOW : HIGH; + uint8_t led_off = (mConfig->led.led_high_active) ? LOW : HIGH; if (mConfig->led.led0 != 0xff) { pinMode(mConfig->led.led0, OUTPUT); @@ -404,9 +403,8 @@ void app::setupLed(void) { //----------------------------------------------------------------------------- void app::updateLed(void) { - - uint8_t led_off = (mConfig->led.led_high_active != 0) ? LOW : HIGH; - uint8_t led_on = (mConfig->led.led_high_active != 0) ? HIGH : LOW; + uint8_t led_off = (mConfig->led.led_high_active) ? LOW : HIGH; + uint8_t led_on = (mConfig->led.led_high_active) ? HIGH : LOW; if (mConfig->led.led0 != 0xff) { Inverter<> *iv = mSys.getInverterByPos(0); diff --git a/src/config/settings.h b/src/config/settings.h index dc5a4408..d04fdce5 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -105,7 +105,7 @@ typedef struct { typedef struct { uint8_t led0; // first LED pin uint8_t led1; // second LED pin - uint8_t led_high_active; // determines if LEDs are high or low active + bool led_high_active; // determines if LEDs are high or low active } cfgLed_t; typedef struct { @@ -384,7 +384,7 @@ class settings { mCfg.led.led0 = DEF_PIN_OFF; mCfg.led.led1 = DEF_PIN_OFF; - mCfg.led.led_high_active = LOW; + mCfg.led.led_high_active = false; memset(&mCfg.inst, 0, sizeof(cfgInst_t)); @@ -528,7 +528,7 @@ class settings { } else { getVal(obj, F("0"), &mCfg.led.led0); getVal(obj, F("1"), &mCfg.led.led1); - getVal(obj, F("act_high"), &mCfg.led.led_high_active); + getVal(obj, F("act_high"), &mCfg.led.led_high_active); } } diff --git a/src/defines.h b/src/defines.h index f4adc55e..b3a961a1 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 5 +#define VERSION_PATCH 6 //------------------------------------- typedef struct { diff --git a/src/web/html/includes/header.html b/src/web/html/includes/header.html index d591eb42..ab3b0545 100644 --- a/src/web/html/includes/header.html +++ b/src/web/html/includes/header.html @@ -2,4 +2,5 @@ - \ No newline at end of file + + diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 97bf5608..32484308 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -292,7 +292,7 @@ Import / Export JSON Settings
Import
-
+
From 2c0e1bbe57af18da6b980d6a1ca6fd2e6678f6eb Mon Sep 17 00:00:00 2001 From: tastendruecker123 <111116980+tastendruecker123@users.noreply.github.com> Date: Thu, 13 Apr 2023 17:42:54 +0200 Subject: [PATCH 49/55] Bugfixes around saving settings --- src/app.h | 4 ++++ src/appInterface.h | 1 + src/web/RestApi.h | 1 + src/web/html/api.js | 8 +++++--- src/web/html/save.html | 39 +++++++++++++++++++++++++-------------- src/web/html/setup.html | 1 + src/web/web.h | 2 +- 7 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/app.h b/src/app.h index 52f5591d..b5f30346 100644 --- a/src/app.h +++ b/src/app.h @@ -92,6 +92,10 @@ class app : public IApp, public ah::Scheduler { return mSettings.getLastSaveSucceed(); } + bool getShouldReboot() { + return mSaveReboot; + } + statistics_t *getStatistics() { return &mStat; } diff --git a/src/appInterface.h b/src/appInterface.h index 44491d91..0c67415e 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -20,6 +20,7 @@ class IApp { virtual bool eraseSettings(bool eraseWifi) = 0; virtual bool getSavePending() = 0; virtual bool getLastSaveSucceed() = 0; + virtual bool getShouldReboot() = 0; virtual void setOnUpdate() = 0; virtual void setRebootFlag() = 0; virtual const char *getVersion() = 0; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 2d617847..fde8c7a4 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -276,6 +276,7 @@ class RestApi { getGeneric(request, obj.createNestedObject(F("generic"))); obj["pending"] = (bool)mApp->getSavePending(); obj["success"] = (bool)mApp->getLastSaveSucceed(); + obj["reboot"] = (bool)mApp->getShouldReboot(); } void getReboot(AsyncWebServerRequest *request, JsonObject obj) { diff --git a/src/web/html/api.js b/src/web/html/api.js index 5ccb0e15..cdc9e748 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -103,9 +103,11 @@ function parseVersion(obj) { } function parseESP(obj) { - document.getElementById("esp_type").append( - document.createTextNode("Board: " + obj["esp_type"]) - ); + if(document.getElementById("esp_type").childNodes.length < 1) { + document.getElementById("esp_type").append( + document.createTextNode("Board: " + obj["esp_type"]) + ); + } } function parseRssi(obj) { diff --git a/src/web/html/save.html b/src/web/html/save.html index 54d43d7f..f3b1896d 100644 --- a/src/web/html/save.html +++ b/src/web/html/save.html @@ -8,11 +8,14 @@ {#HTML_NAV}
-
+
Saving settings...
{#HTML_FOOTER} diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 32484308..00ea8101 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -31,6 +31,7 @@
Dark Mode
+
(empty browser cache or use Shift + F5 after reboot to apply this setting)
diff --git a/src/web/web.h b/src/web/web.h index 4b7cbb39..056b9e7c 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -515,7 +515,7 @@ class Web { // pinout uint8_t pin; - for (uint8_t i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 9; i++) { pin = request->arg(String(pinArgNames[i])).toInt(); switch(i) { default: mConfig->nrf.pinCs = ((pin != 0xff) ? pin : DEF_CS_PIN); break; From 492cc5a8aa50ed3e62b41008eadd7ea123bfbc2b Mon Sep 17 00:00:00 2001 From: tastendruecker123 <111116980+tastendruecker123@users.noreply.github.com> Date: Thu, 13 Apr 2023 20:59:12 +0200 Subject: [PATCH 50/55] fixed typo --- src/web/html/setup.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 00ea8101..77769fdd 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -31,7 +31,7 @@
Dark Mode
-
(empty browser cache or use Shift + F5 after reboot to apply this setting)
+
(empty browser cache or use CTRL + F5 after reboot to apply this setting)
From 12a3d503c8328be21339650a5c7287949f0b46b8 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 13 Apr 2023 22:58:59 +0200 Subject: [PATCH 51/55] 0.6.7 * merge PR #883, improved store of settings and javascript, thx @tastendruecker123 * support `.` and `,` as floating point seperator in setup #881 --- src/CHANGES.md | 4 +++ src/defines.h | 2 +- src/web/html/api.js | 8 ++---- src/web/html/save.html | 11 ++------ src/web/html/serial.html | 2 +- src/web/html/setup.html | 61 ++++++++++++++++++++++------------------ 6 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 4e5900ad..f4c89d23 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.6.7 - 2023-04-13 +* merge PR #883, improved store of settings and javascript, thx @tastendruecker123 +* support `.` and `,` as floating point seperator in setup #881 + ## 0.6.6 - 2023-04-12 * increased distance for `import` button in mobile view #879 * changed `led_high_active` to `bool` #879 diff --git a/src/defines.h b/src/defines.h index b3a961a1..1ace50df 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 6 +#define VERSION_PATCH 7 //------------------------------------- typedef struct { diff --git a/src/web/html/api.js b/src/web/html/api.js index cdc9e748..13ca50b5 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -103,11 +103,9 @@ function parseVersion(obj) { } function parseESP(obj) { - if(document.getElementById("esp_type").childNodes.length < 1) { - document.getElementById("esp_type").append( - document.createTextNode("Board: " + obj["esp_type"]) - ); - } + document.getElementById("esp_type").replaceChildren( + document.createTextNode("Board: " + obj["esp_type"]) + ); } function parseRssi(obj) { diff --git a/src/web/html/save.html b/src/web/html/save.html index f3b1896d..4c924c40 100644 --- a/src/web/html/save.html +++ b/src/web/html/save.html @@ -13,7 +13,6 @@
{#HTML_FOOTER} - + {#HTML_NAV}
- +
@@ -147,11 +136,11 @@
Interval [s]
-
+
Max retries per Payload
-
+
Reset values and YieldDay at midnight
@@ -178,7 +167,7 @@
NTP Port
-
+
set system time
@@ -195,15 +184,13 @@
Sunrise & Sunset -

Use a decimal separator: '.' (dot) for Latitude and Longitude

-
Latitude (decimal)
-
+
Longitude (decimal)
-
+
Offset (pre sunrise, post sunset)
@@ -226,7 +213,7 @@
Port
-
+
Username (optional)
@@ -243,7 +230,7 @@

Send Inverter data in a fixed interval, even if there is no change. A value of '0' disables the fixed interval. The data is published once it was successfully received from inverter. (default: 0)

Interval [s]
-
+
Discovery Config (homeassistant)
@@ -292,11 +279,13 @@
Import / Export JSON Settings
-
Import
-
+
Import
+
- - +
+
+
+
@@ -419,6 +408,24 @@ const re = /11[2,4,6]1.*/; + window.onload = function() { + for(it of document.getElementsByClassName("s_collapsible")) { + it.addEventListener("click", function() { + this.classList.toggle("active"); + var content = this.nextElementSibling; + content.style.display = (content.style.display === "block") ? "none" : "block"; + }); + } + + document.getElementById("settings").addEventListener("submit", function() { + var inputs = document.querySelectorAll("input[type='number']"); + for (var i = 0; i < inputs.length; i++) { + if (inputs[i].value.indexOf(",") != -1) + inputs[i].value = inputs[i].value.replace(",", "."); + } + }); + } + document.getElementById("btnAdd").addEventListener("click", function() { if(highestId <= (maxInv-1)) { ivHtml(JSON.parse('{"enabled":true,"name":"","serial":"","channels":4,"ch_max_pwr":[0,0,0,0],"ch_name":["","","",""],"ch_yield_cor":[0,0,0,0]}'), highestId); From b6531180df6bea425fe0da0ea70fea13a055ffa3 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 19 Apr 2023 21:56:25 +0200 Subject: [PATCH 52/55] 0.6.8 * fix #892 `zeroYieldDay` loop was not applied to all channels --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/hm/hmPayload.h | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index f4c89d23..0b0d3676 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.6.8 - 2023-04-19 +* fix #892 `zeroYieldDay` loop was not applied to all channels + ## 0.6.7 - 2023-04-13 * merge PR #883, improved store of settings and javascript, thx @tastendruecker123 * support `.` and `,` as floating point seperator in setup #881 diff --git a/src/defines.h b/src/defines.h index 1ace50df..4313ee71 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 7 +#define VERSION_PATCH 8 //------------------------------------- typedef struct { diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index b04ee8f3..29f380fa 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -74,8 +74,8 @@ class HmPayload { DPRINTLN(DBG_DEBUG, F("zeroYieldDay")); record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); uint8_t pos; - for(uint8_t ch = 0; ch < iv->channels; ch++) { - pos = iv->getPosByChFld(CH0, FLD_YD, rec); + for(uint8_t ch = 0; ch <= iv->channels; ch++) { + pos = iv->getPosByChFld(ch, FLD_YD, rec); iv->setValue(pos, rec, 0.0f); } } From 7e1f1cece4ba1fc4aee4698f7ac448f1ebaa5225 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 19 Apr 2023 23:00:24 +0200 Subject: [PATCH 53/55] 0.6.9 release --- src/CHANGES.md | 52 +++++++++++++--------------------------------- src/defines.h | 2 +- src/platformio.ini | 4 ++-- 3 files changed, 18 insertions(+), 40 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 0b0d3676..ba8f2d25 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,37 +1,15 @@ -# Development Changes - -## 0.6.8 - 2023-04-19 -* fix #892 `zeroYieldDay` loop was not applied to all channels - -## 0.6.7 - 2023-04-13 -* merge PR #883, improved store of settings and javascript, thx @tastendruecker123 -* support `.` and `,` as floating point seperator in setup #881 - -## 0.6.6 - 2023-04-12 -* increased distance for `import` button in mobile view #879 -* changed `led_high_active` to `bool` #879 - -## 0.6.5 - 2023-04-11 -* fix #845 MqTT subscription for `ctrl/power/[IV-ID]` was missing -* merge PR #876, check JSON settings during read for existance -* **NOTE:** incompatible change: renamed `led_high_active` to `act_high`, maybe setting must be changed after update -* merge PR #861 do not send channel metric if channel is disabled - -## 0.6.4 - 2023-04-06 -* merge PR #846, improved NRF24 communication and MI, thx @beegee3 & @rejoe2 -* merge PR #859, fix burger menu height, thx @ThomasPohl - -## 0.6.3 - 2023-04-04 -* fix login, password length was not checked #852 -* merge PR #854 optimize browser caching, thx @tastendruecker123 #828 -* fix WiFi reconnect not working #851 -* updated issue templates #822 - -## 0.6.2 - 2023-04-04 -* fix login from multiple clients #819 -* fix login screen on small displays - -## 0.6.1 - 2023-04-01 -* merge LED fix - LED1 shows MqTT state, LED configureable active high/low #839 -* only publish new inverter data #826 -* potential fix of WiFi hostname during boot up #752 +Changelog v0.6.9 + +* LEDs are now configurable to show if 1st inverter is available and if MqTT is connected +* LED are configurable to active high or low +* improved MqTT +* fix WiFi hostname during boot up +* improved login: only one session at the same time is possible +* fix UI: login screen for small displays; burger menu height; small modifications for import button (in setup) +* improved WiFi reconnect +* optimized performance: browser caching was improved to reduce requests from ESP +* improved NRF24 communication for more stable data transmission +* added / fixed MqTT subscription `ctrl/power/[IV-ID]` +* improved save settings +* improved UI in setup: now `.` and `,` are allowed as floating point seperator +* fix zero yield day functionality diff --git a/src/defines.h b/src/defines.h index 4313ee71..93722b6c 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 8 +#define VERSION_PATCH 9 //------------------------------------- typedef struct { diff --git a/src/platformio.ini b/src/platformio.ini index 5d4c655d..7b627f73 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -38,9 +38,9 @@ lib_deps = nrf24/RF24 @ ^1.4.5 paulstoffregen/Time @ ^1.6.1 https://github.com/bertmelis/espMqttClient#v1.4.2 - bblanchon/ArduinoJson @ ^6.21.0 + bblanchon/ArduinoJson @ ^6.21.2 https://github.com/JChristensen/Timezone @ ^1.2.4 - olikraus/U8g2 @ ^2.34.16 + olikraus/U8g2 @ ^2.34.17 zinggjm/GxEPD2 @ ^1.5.0 From 05d1eb607e1d54906ecd8287e088b0829014de61 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 19 Apr 2023 23:06:02 +0200 Subject: [PATCH 54/55] 0.6.8 try to fix esp32s3 build --- src/platformio.ini | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/platformio.ini b/src/platformio.ini index 5d4c655d..087efad3 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -16,17 +16,6 @@ include_dir = . framework = arduino board_build.filesystem = littlefs upload_speed = 921600 - -;build_flags = -; ;;;;; Possible Debug options ;;;;;; -; https://docs.platformio.org/en/latest/platforms/espressif8266.html#debug-level - ;-DDEBUG_ESP_PORT=Serial - ;-DDEBUG_ESP_CORE - ;-DDEBUG_ESP_WIFI - ;-DDEBUG_ESP_HTTP_CLIENT - ;-DDEBUG_ESP_HTTP_SERVER - ;-DDEBUG_ESP_OOM - monitor_speed = 115200 extra_scripts = @@ -95,7 +84,13 @@ platform = espressif8266 board = esp8285 board_build.ldscript = eagle.flash.1m64.ld board_build.f_cpu = 80000000L -build_flags = -DDEBUG_LEVEL=DBG_DEBUG -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_OOM -DDEBUG_ESP_PORT=Serial +build_flags = -DDEBUG_LEVEL=DBG_DEBUG + -DDEBUG_ESP_CORE + -DDEBUG_ESP_WIFI + -DDEBUG_ESP_HTTP_CLIENT + -DDEBUG_ESP_HTTP_SERVER + -DDEBUG_ESP_OOM + -DDEBUG_ESP_PORT=Serial build_type = debug monitor_filters = ;default ; Remove typical terminal control codes from input @@ -103,7 +98,7 @@ monitor_filters = log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory [env:esp32-wroom32-release] -platform = espressif32 +platform = espressif32@>=6.1.0 board = lolin_d32 build_flags = -D RELEASE -std=gnu++14 build_unflags = -std=gnu++11 @@ -114,9 +109,11 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32-release-prometheus] -platform = espressif32 +platform = espressif32@>=6.1.0 board = lolin_d32 -build_flags = -D RELEASE -std=gnu++14 -DENABLE_PROMETHEUS_EP +build_flags = -D RELEASE + -std=gnu++14 + -DENABLE_PROMETHEUS_EP build_unflags = -std=gnu++11 monitor_filters = ;default ; Remove typical terminal control codes from input @@ -125,9 +122,16 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32-debug] -platform = espressif32 +platform = espressif32@>=6.1.0 board = lolin_d32 -build_flags = -DDEBUG_LEVEL=DBG_DEBUG -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_OOM -DDEBUG_ESP_PORT=Serial -std=gnu++14 +build_flags = -DDEBUG_LEVEL=DBG_DEBUG + -DDEBUG_ESP_CORE + -DDEBUG_ESP_WIFI + -DDEBUG_ESP_HTTP_CLIENT + -DDEBUG_ESP_HTTP_SERVER + -DDEBUG_ESP_OOM + -DDEBUG_ESP_PORT=Serial + -std=gnu++14 build_unflags = -std=gnu++11 build_type = debug monitor_filters = @@ -136,7 +140,7 @@ monitor_filters = log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory [env:opendtufusionv1-release] -platform = espressif32 +platform = espressif32@>=6.1.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin upload_speed = 115200 From 15ec6a0608dd1ad7e754b7b291c99cc0f15c4e67 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 19 Apr 2023 23:21:42 +0200 Subject: [PATCH 55/55] 0.6.9 release --- src/CHANGES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index ba8f2d25..281dc784 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,7 +1,5 @@ Changelog v0.6.9 -* LEDs are now configurable to show if 1st inverter is available and if MqTT is connected -* LED are configurable to active high or low * improved MqTT * fix WiFi hostname during boot up * improved login: only one session at the same time is possible @@ -13,3 +11,5 @@ Changelog v0.6.9 * improved save settings * improved UI in setup: now `.` and `,` are allowed as floating point seperator * fix zero yield day functionality +* LEDs are now configurable to show if 1st inverter is available and if MqTT is connected +* LED are configurable to active high or low