From a7f571a5811f07378fad8ad10eb687a21d890086 Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Tue, 25 Oct 2022 00:08:27 +0200 Subject: [PATCH 01/12] HASS: Move create of device object so separate method --- include/MqttHassPublishing.h | 2 ++ src/MqttHassPublishing.cpp | 26 +++++++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/include/MqttHassPublishing.h b/include/MqttHassPublishing.h index 366f41c7..caa71e11 100644 --- a/include/MqttHassPublishing.h +++ b/include/MqttHassPublishing.h @@ -3,6 +3,7 @@ #include "Configuration.h" #include +#include #include #include @@ -59,6 +60,7 @@ public: private: void publishField(std::shared_ptr inv, uint8_t channel, byteAssign_fieldDeviceClass_t fieldType, bool clear = false); + void createDeviceInfo(JsonObject& object, std::shared_ptr inv); bool _wasConnected = false; bool _updateForced = false; diff --git a/src/MqttHassPublishing.cpp b/src/MqttHassPublishing.cpp index aaa50d9d..513f159f 100644 --- a/src/MqttHassPublishing.cpp +++ b/src/MqttHassPublishing.cpp @@ -3,7 +3,6 @@ * Copyright (C) 2022 Thomas Basler and others */ #include "MqttHassPublishing.h" -#include "ArduinoJson.h" #include "MqttPublishing.h" #include "MqttSettings.h" #include "NetworkSettings.h" @@ -102,13 +101,8 @@ void MqttHassPublishingClass::publishField(std::shared_ptr inv } DynamicJsonDocument deviceDoc(512); - deviceDoc[F("name")] = inv->name(); - deviceDoc[F("ids")] = String(serial); - deviceDoc[F("cu")] = String(F("http://")) + String(WiFi.localIP().toString()); - deviceDoc[F("mf")] = F("OpenDTU"); - deviceDoc[F("mdl")] = inv->typeName(); - deviceDoc[F("sw")] = AUTO_GIT_HASH; JsonObject deviceObj = deviceDoc.as(); + createDeviceInfo(deviceObj, inv); DynamicJsonDocument root(1024); root[F("name")] = name; @@ -129,8 +123,22 @@ void MqttHassPublishingClass::publishField(std::shared_ptr inv char buffer[512]; serializeJson(root, buffer); MqttSettings.publishHass(configTopic, buffer); - } - else { + } else { MqttSettings.publishHass(configTopic, ""); } +} + +void MqttHassPublishingClass::createDeviceInfo(JsonObject& object, std::shared_ptr inv) +{ + char serial[sizeof(uint64_t) * 8 + 1]; + snprintf(serial, sizeof(serial), "%0x%08x", + ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), + ((uint32_t)(inv->serial() & 0xFFFFFFFF))); + + object[F("name")] = inv->name(); + object[F("ids")] = String(serial); + object[F("cu")] = String(F("http://")) + String(WiFi.localIP().toString()); + object[F("mf")] = F("OpenDTU"); + object[F("mdl")] = inv->typeName(); + object[F("sw")] = AUTO_GIT_HASH; } \ No newline at end of file From 64e4656dbe6c7fe5b31c3e2f99a01ca68b06b4ea Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Wed, 26 Oct 2022 00:11:06 +0200 Subject: [PATCH 02/12] Simplify creation of HASS device info --- src/MqttHassPublishing.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/MqttHassPublishing.cpp b/src/MqttHassPublishing.cpp index 513f159f..e452419e 100644 --- a/src/MqttHassPublishing.cpp +++ b/src/MqttHassPublishing.cpp @@ -100,16 +100,15 @@ void MqttHassPublishingClass::publishField(std::shared_ptr inv name = String(inv->name()) + " CH" + String(channel) + " " + fieldName; } - DynamicJsonDocument deviceDoc(512); - JsonObject deviceObj = deviceDoc.as(); - createDeviceInfo(deviceObj, inv); - DynamicJsonDocument root(1024); root[F("name")] = name; root[F("stat_t")] = stateTopic; root[F("unit_of_meas")] = inv->Statistics()->getChannelFieldUnit(channel, fieldType.fieldId); root[F("uniq_id")] = String(serial) + "_ch" + String(channel) + "_" + fieldName; - root[F("dev")] = deviceObj; + + JsonObject deviceObj = root.createNestedObject("dev"); + createDeviceInfo(deviceObj, inv); + if (Configuration.get().Mqtt_Hass_Expire) { root[F("exp_aft")] = Hoymiles.getNumInverters() * Configuration.get().Mqtt_PublishInterval * 2; } @@ -137,7 +136,7 @@ void MqttHassPublishingClass::createDeviceInfo(JsonObject& object, std::shared_p object[F("name")] = inv->name(); object[F("ids")] = String(serial); - object[F("cu")] = String(F("http://")) + String(WiFi.localIP().toString()); + object[F("cu")] = String(F("http://")) + WiFi.localIP().toString(); object[F("mf")] = F("OpenDTU"); object[F("mdl")] = inv->typeName(); object[F("sw")] = AUTO_GIT_HASH; From 96170c08b84662b02a19046b6f18f49d0be300e7 Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Wed, 26 Oct 2022 19:59:05 +0200 Subject: [PATCH 03/12] HASS Auto Discovery: Publish buttons for on/off/restart --- include/MqttHassPublishing.h | 1 + src/MqttHassPublishing.cpp | 42 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/include/MqttHassPublishing.h b/include/MqttHassPublishing.h index caa71e11..660d27cc 100644 --- a/include/MqttHassPublishing.h +++ b/include/MqttHassPublishing.h @@ -60,6 +60,7 @@ public: private: void publishField(std::shared_ptr inv, uint8_t channel, byteAssign_fieldDeviceClass_t fieldType, bool clear = false); + void publishInverterButton(std::shared_ptr inv, const char* caption, const char* icon, const char* category, const char* deviceClass, const char* subTopic, const char* payload); void createDeviceInfo(JsonObject& object, std::shared_ptr inv); bool _wasConnected = false; diff --git a/src/MqttHassPublishing.cpp b/src/MqttHassPublishing.cpp index e452419e..e0fdf3db 100644 --- a/src/MqttHassPublishing.cpp +++ b/src/MqttHassPublishing.cpp @@ -51,6 +51,10 @@ void MqttHassPublishingClass::publishConfig() for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { auto inv = Hoymiles.getInverterByPos(i); + publishInverterButton(inv, "Turn Inverter Off", "mdi:power-plug-off", "config", "", "cmd/power", "0"); + publishInverterButton(inv, "Turn Inverter On", "mdi:power-plug", "config", "", "cmd/power", "1"); + publishInverterButton(inv, "Restart Inverter", "", "config", "restart", "cmd/restart", "1"); + // Loop all channels for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) { for (uint8_t f = 0; f < DEVICE_CLS_ASSIGN_LIST_LEN; f++) { @@ -127,6 +131,44 @@ void MqttHassPublishingClass::publishField(std::shared_ptr inv } } +void MqttHassPublishingClass::publishInverterButton(std::shared_ptr inv, const char* caption, const char* icon, const char* category, const char* deviceClass, const char* subTopic, const char* payload) +{ + char serial[sizeof(uint64_t) * 8 + 1]; + snprintf(serial, sizeof(serial), "%0x%08x", + ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), + ((uint32_t)(inv->serial() & 0xFFFFFFFF))); + + String buttonId = caption; + buttonId.replace(" ", "_"); + buttonId.toLowerCase(); + + String configTopic = "button/dtu_" + String(serial) + + "/" + buttonId + + "/config"; + + String cmdTopic = MqttSettings.getPrefix() + String(serial) + "/" + subTopic; + + DynamicJsonDocument root(1024); + root[F("name")] = caption; + root[F("uniq_id")] = String(serial) + "_" + buttonId; + if(strcmp(icon, "")) { + root[F("ic")] = icon; + } + if(strcmp(deviceClass, "")) { + root[F("dev_cla")] = deviceClass; + } + root[F("ent_cat")] = category; + root[F("cmd_t")] = cmdTopic; + root[F("payload_press")] = payload; + + JsonObject deviceObj = root.createNestedObject("dev"); + createDeviceInfo(deviceObj, inv); + + char buffer[512]; + serializeJson(root, buffer); + MqttSettings.publishHass(configTopic, buffer); +} + void MqttHassPublishingClass::createDeviceInfo(JsonObject& object, std::shared_ptr inv) { char serial[sizeof(uint64_t) * 8 + 1]; From 6403521e31a573411b4edd9fb7e20143fedd7cd0 Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Wed, 26 Oct 2022 22:05:00 +0200 Subject: [PATCH 04/12] HASS Auto Discovery: Publish numbers to set limit --- include/MqttHassPublishing.h | 1 + src/MqttHassPublishing.cpp | 52 ++++++++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/include/MqttHassPublishing.h b/include/MqttHassPublishing.h index 660d27cc..d2f732c9 100644 --- a/include/MqttHassPublishing.h +++ b/include/MqttHassPublishing.h @@ -61,6 +61,7 @@ public: private: void publishField(std::shared_ptr inv, uint8_t channel, byteAssign_fieldDeviceClass_t fieldType, bool clear = false); void publishInverterButton(std::shared_ptr inv, const char* caption, const char* icon, const char* category, const char* deviceClass, const char* subTopic, const char* payload); + void publishInverterNumber(std::shared_ptr inv, const char* caption, const char* icon, const char* category, const char* commandTopic, const char* stateTopic, const char* unitOfMeasure, int16_t min = 1, int16_t max = 100); void createDeviceInfo(JsonObject& object, std::shared_ptr inv); bool _wasConnected = false; diff --git a/src/MqttHassPublishing.cpp b/src/MqttHassPublishing.cpp index e0fdf3db..72754a16 100644 --- a/src/MqttHassPublishing.cpp +++ b/src/MqttHassPublishing.cpp @@ -55,6 +55,12 @@ void MqttHassPublishingClass::publishConfig() publishInverterButton(inv, "Turn Inverter On", "mdi:power-plug", "config", "", "cmd/power", "1"); publishInverterButton(inv, "Restart Inverter", "", "config", "restart", "cmd/restart", "1"); + publishInverterNumber(inv, "Limit NonPersistent Relative", "mdi:speedometer", "config", "cmd/limit_nonpersistent_relative", "status/limit_relative", "%"); + publishInverterNumber(inv, "Limit Persistent Relative", "mdi:speedometer", "config", "cmd/limit_persistent_relative", "status/limit_relative", "%"); + + publishInverterNumber(inv, "Limit NonPersistent Absolute", "mdi:speedometer", "config", "cmd/limit_nonpersistent_absolute", "status/limit_absolute", "W", 10, 1500); + publishInverterNumber(inv, "Limit Persistent Absolute", "mdi:speedometer", "config", "cmd/limit_persistent_absolute", "status/limit_absolute", "W", 10, 1500); + // Loop all channels for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) { for (uint8_t f = 0; f < DEVICE_CLS_ASSIGN_LIST_LEN; f++) { @@ -151,10 +157,10 @@ void MqttHassPublishingClass::publishInverterButton(std::shared_ptr inv, const char* caption, const char* icon, const char* category, + const char* commandTopic, const char* stateTopic, const char* unitOfMeasure, + int16_t min, int16_t max) +{ + char serial[sizeof(uint64_t) * 8 + 1]; + snprintf(serial, sizeof(serial), "%0x%08x", + ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), + ((uint32_t)(inv->serial() & 0xFFFFFFFF))); + + String buttonId = caption; + buttonId.replace(" ", "_"); + buttonId.toLowerCase(); + + String configTopic = "number/dtu_" + String(serial) + + "/" + buttonId + + "/config"; + + String cmdTopic = MqttSettings.getPrefix() + String(serial) + "/" + commandTopic; + String statTopic = MqttSettings.getPrefix() + String(serial) + "/" + stateTopic; + + DynamicJsonDocument root(1024); + root[F("name")] = caption; + root[F("uniq_id")] = String(serial) + "_" + buttonId; + if (strcmp(icon, "")) { + root[F("ic")] = icon; + } + root[F("ent_cat")] = category; + root[F("cmd_t")] = cmdTopic; + root[F("stat_t")] = statTopic; + root[F("unit_of_meas")] = unitOfMeasure; + root[F("min")] = min; + root[F("max")] = max; + + JsonObject deviceObj = root.createNestedObject("dev"); + createDeviceInfo(deviceObj, inv); + + char buffer[512]; + serializeJson(root, buffer); + MqttSettings.publishHass(configTopic, buffer); +} + void MqttHassPublishingClass::createDeviceInfo(JsonObject& object, std::shared_ptr inv) { char serial[sizeof(uint64_t) * 8 + 1]; From 3a0ba86c9c86fb98600083d2df4aa80cfd4c51ba Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Wed, 26 Oct 2022 22:37:23 +0200 Subject: [PATCH 05/12] HASS Auto Discovery: Publish binary sensor reachable and producing --- include/MqttHassPublishing.h | 1 + src/MqttHassPublishing.cpp | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/MqttHassPublishing.h b/include/MqttHassPublishing.h index d2f732c9..e5044746 100644 --- a/include/MqttHassPublishing.h +++ b/include/MqttHassPublishing.h @@ -62,6 +62,7 @@ private: void publishField(std::shared_ptr inv, uint8_t channel, byteAssign_fieldDeviceClass_t fieldType, bool clear = false); void publishInverterButton(std::shared_ptr inv, const char* caption, const char* icon, const char* category, const char* deviceClass, const char* subTopic, const char* payload); void publishInverterNumber(std::shared_ptr inv, const char* caption, const char* icon, const char* category, const char* commandTopic, const char* stateTopic, const char* unitOfMeasure, int16_t min = 1, int16_t max = 100); + void publishInverterBinarySensor(std::shared_ptr inv, const char* caption, const char* subTopic, const char* payload_on, const char* payload_off); void createDeviceInfo(JsonObject& object, std::shared_ptr inv); bool _wasConnected = false; diff --git a/src/MqttHassPublishing.cpp b/src/MqttHassPublishing.cpp index 72754a16..8b8f5073 100644 --- a/src/MqttHassPublishing.cpp +++ b/src/MqttHassPublishing.cpp @@ -61,6 +61,9 @@ void MqttHassPublishingClass::publishConfig() publishInverterNumber(inv, "Limit NonPersistent Absolute", "mdi:speedometer", "config", "cmd/limit_nonpersistent_absolute", "status/limit_absolute", "W", 10, 1500); publishInverterNumber(inv, "Limit Persistent Absolute", "mdi:speedometer", "config", "cmd/limit_persistent_absolute", "status/limit_absolute", "W", 10, 1500); + publishInverterBinarySensor(inv, "Reachable", "status/reachable", "1", "0"); + publishInverterBinarySensor(inv, "Producing", "status/producing", "1", "0"); + // Loop all channels for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) { for (uint8_t f = 0; f < DEVICE_CLS_ASSIGN_LIST_LEN; f++) { @@ -217,6 +220,38 @@ void MqttHassPublishingClass::publishInverterNumber( MqttSettings.publishHass(configTopic, buffer); } +void MqttHassPublishingClass::publishInverterBinarySensor(std::shared_ptr inv, const char* caption, const char* subTopic, const char* payload_on, const char* payload_off) +{ + char serial[sizeof(uint64_t) * 8 + 1]; + snprintf(serial, sizeof(serial), "%0x%08x", + ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), + ((uint32_t)(inv->serial() & 0xFFFFFFFF))); + + String sensorId = caption; + sensorId.replace(" ", "_"); + sensorId.toLowerCase(); + + String configTopic = "binary_sensor/dtu_" + String(serial) + + "/" + sensorId + + "/config"; + + String statTopic = MqttSettings.getPrefix() + String(serial) + "/" + subTopic; + + DynamicJsonDocument root(1024); + root[F("name")] = caption; + root[F("uniq_id")] = String(serial) + "_" + sensorId; + root[F("stat_t")] = statTopic; + root[F("pl_on")] = payload_on; + root[F("pl_off")] = payload_off; + + JsonObject deviceObj = root.createNestedObject("dev"); + createDeviceInfo(deviceObj, inv); + + char buffer[512]; + serializeJson(root, buffer); + MqttSettings.publishHass(configTopic, buffer); +} + void MqttHassPublishingClass::createDeviceInfo(JsonObject& object, std::shared_ptr inv) { char serial[sizeof(uint64_t) * 8 + 1]; From c999197dae3b1036f861a80dbbf980fb3cae2351 Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Fri, 28 Oct 2022 23:27:59 +0200 Subject: [PATCH 06/12] Optimize performance by passing strings as const reference --- include/MqttSettings.h | 4 ++-- src/MqttSettings.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/MqttSettings.h b/include/MqttSettings.h index 209a8ad6..afa3283c 100644 --- a/include/MqttSettings.h +++ b/include/MqttSettings.h @@ -13,8 +13,8 @@ public: void init(); void performReconnect(); bool getConnected(); - void publish(String subtopic, String payload); - void publishHass(String subtopic, String payload); + void publish(const String& subtopic, const String& payload); + void publishHass(const String& subtopic, const String& payload); String getPrefix(); diff --git a/src/MqttSettings.cpp b/src/MqttSettings.cpp index d7e7a655..516409bd 100644 --- a/src/MqttSettings.cpp +++ b/src/MqttSettings.cpp @@ -233,14 +233,14 @@ String MqttSettingsClass::getPrefix() return Configuration.get().Mqtt_Topic; } -void MqttSettingsClass::publish(String subtopic, String payload) +void MqttSettingsClass::publish(const String& subtopic, const String& payload) { String topic = getPrefix(); topic += subtopic; mqttClient->publish(topic.c_str(), 0, Configuration.get().Mqtt_Retain, payload.c_str()); } -void MqttSettingsClass::publishHass(String subtopic, String payload) +void MqttSettingsClass::publishHass(const String& subtopic, const String& payload) { String topic = Configuration.get().Mqtt_Hass_Topic; topic += subtopic; From f21dd351ef6ebc88248432048b8259a8ecc8030a Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Fri, 28 Oct 2022 23:39:32 +0200 Subject: [PATCH 07/12] Optimize performance by removing not required string constructors --- lib/Hoymiles/src/inverters/HM_1CH.cpp | 2 +- lib/Hoymiles/src/inverters/HM_2CH.cpp | 2 +- lib/Hoymiles/src/inverters/HM_4CH.cpp | 2 +- lib/Hoymiles/src/parser/AlarmLogParser.cpp | 140 ++++++++++----------- src/NetworkSettings.cpp | 2 +- 5 files changed, 74 insertions(+), 74 deletions(-) diff --git a/lib/Hoymiles/src/inverters/HM_1CH.cpp b/lib/Hoymiles/src/inverters/HM_1CH.cpp index 5de99138..2311330e 100644 --- a/lib/Hoymiles/src/inverters/HM_1CH.cpp +++ b/lib/Hoymiles/src/inverters/HM_1CH.cpp @@ -25,7 +25,7 @@ bool HM_1CH::isValidSerial(uint64_t serial) String HM_1CH::typeName() { - return String(F("HM-300, HM-350, HM-400")); + return F("HM-300, HM-350, HM-400"); } const byteAssign_t* HM_1CH::getByteAssignment() diff --git a/lib/Hoymiles/src/inverters/HM_2CH.cpp b/lib/Hoymiles/src/inverters/HM_2CH.cpp index aea62cb3..cf2c5536 100644 --- a/lib/Hoymiles/src/inverters/HM_2CH.cpp +++ b/lib/Hoymiles/src/inverters/HM_2CH.cpp @@ -25,7 +25,7 @@ bool HM_2CH::isValidSerial(uint64_t serial) String HM_2CH::typeName() { - return String(F("HM-600, HM-700, HM-800")); + return F("HM-600, HM-700, HM-800"); } const byteAssign_t* HM_2CH::getByteAssignment() diff --git a/lib/Hoymiles/src/inverters/HM_4CH.cpp b/lib/Hoymiles/src/inverters/HM_4CH.cpp index 908f163c..bda9592d 100644 --- a/lib/Hoymiles/src/inverters/HM_4CH.cpp +++ b/lib/Hoymiles/src/inverters/HM_4CH.cpp @@ -25,7 +25,7 @@ bool HM_4CH::isValidSerial(uint64_t serial) String HM_4CH::typeName() { - return String(F("HM-1000, HM-1200, HM-1500")); + return F("HM-1000, HM-1200, HM-1500"); } const byteAssign_t* HM_4CH::getByteAssignment() diff --git a/lib/Hoymiles/src/parser/AlarmLogParser.cpp b/lib/Hoymiles/src/parser/AlarmLogParser.cpp index a5d09366..4958b6a7 100644 --- a/lib/Hoymiles/src/parser/AlarmLogParser.cpp +++ b/lib/Hoymiles/src/parser/AlarmLogParser.cpp @@ -59,214 +59,214 @@ void AlarmLogParser::getLogEntry(uint8_t entryId, AlarmLogEntry_t* entry) switch (entry->MessageId) { case 1: - entry->Message = String(F("Inverter start")); + entry->Message = F("Inverter start"); break; case 2: - entry->Message = String(F("DTU command failed")); + entry->Message = F("DTU command failed"); break; case 121: - entry->Message = String(F("Over temperature protection")); + entry->Message = F("Over temperature protection"); break; case 124: - entry->Message = String(F("Shut down by remote control")); + entry->Message = F("Shut down by remote control"); break; case 125: - entry->Message = String(F("Grid configuration parameter error")); + entry->Message = F("Grid configuration parameter error"); break; case 126: - entry->Message = String(F("Software error code 126")); + entry->Message = F("Software error code 126"); break; case 127: - entry->Message = String(F("Firmware error")); + entry->Message = F("Firmware error"); break; case 128: - entry->Message = String(F("Software error code 128")); + entry->Message = F("Software error code 128"); break; case 129: - entry->Message = String(F("Abnormal bias")); + entry->Message = F("Abnormal bias"); break; case 130: - entry->Message = String(F("Offline")); + entry->Message = F("Offline"); break; case 141: - entry->Message = String(F("Grid: Grid overvoltage")); + entry->Message = F("Grid: Grid overvoltage"); break; case 142: - entry->Message = String(F("Grid: 10 min value grid overvoltage")); + entry->Message = F("Grid: 10 min value grid overvoltage"); break; case 143: - entry->Message = String(F("Grid: Grid undervoltage")); + entry->Message = F("Grid: Grid undervoltage"); break; case 144: - entry->Message = String(F("Grid: Grid overfrequency")); + entry->Message = F("Grid: Grid overfrequency"); break; case 145: - entry->Message = String(F("Grid: Grid underfrequency")); + entry->Message = F("Grid: Grid underfrequency"); break; case 146: - entry->Message = String(F("Grid: Rapid grid frequency change rate")); + entry->Message = F("Grid: Rapid grid frequency change rate"); break; case 147: - entry->Message = String(F("Grid: Power grid outage")); + entry->Message = F("Grid: Power grid outage"); break; case 148: - entry->Message = String(F("Grid: Grid disconnection")); + entry->Message = F("Grid: Grid disconnection"); break; case 149: - entry->Message = String(F("Grid: Island detected")); + entry->Message = F("Grid: Island detected"); break; case 205: - entry->Message = String(F("MPPT-A: Input overvoltage")); + entry->Message = F("MPPT-A: Input overvoltage"); break; case 206: - entry->Message = String(F("MPPT-B: Input overvoltage")); + entry->Message = F("MPPT-B: Input overvoltage"); break; case 207: - entry->Message = String(F("MPPT-A: Input undervoltage")); + entry->Message = F("MPPT-A: Input undervoltage"); break; case 208: - entry->Message = String(F("MPPT-B: Input undervoltage")); + entry->Message = F("MPPT-B: Input undervoltage"); break; case 209: - entry->Message = String(F("PV-1: No input")); + entry->Message = F("PV-1: No input"); break; case 210: - entry->Message = String(F("PV-2: No input")); + entry->Message = F("PV-2: No input"); break; case 211: - entry->Message = String(F("PV-3: No input")); + entry->Message = F("PV-3: No input"); break; case 212: - entry->Message = String(F("PV-4: No input")); + entry->Message = F("PV-4: No input"); break; case 213: - entry->Message = String(F("MPPT-A: PV-1 & PV-2 abnormal wiring")); + entry->Message = F("MPPT-A: PV-1 & PV-2 abnormal wiring"); break; case 214: - entry->Message = String(F("MPPT-B: PV-3 & PV-4 abnormal wiring")); + entry->Message = F("MPPT-B: PV-3 & PV-4 abnormal wiring"); break; case 215: - entry->Message = String(F("PV-1: Input overvoltage")); + entry->Message = F("PV-1: Input overvoltage"); break; case 216: - entry->Message = String(F("PV-1: Input undervoltage")); + entry->Message = F("PV-1: Input undervoltage"); break; case 217: - entry->Message = String(F("PV-2: Input overvoltage")); + entry->Message = F("PV-2: Input overvoltage"); break; case 218: - entry->Message = String(F("PV-2: Input undervoltage")); + entry->Message = F("PV-2: Input undervoltage"); break; case 219: - entry->Message = String(F("PV-3: Input overvoltage")); + entry->Message = F("PV-3: Input overvoltage"); break; case 220: - entry->Message = String(F("PV-3: Input undervoltage")); + entry->Message = F("PV-3: Input undervoltage"); break; case 221: - entry->Message = String(F("PV-4: Input overvoltage")); + entry->Message = F("PV-4: Input overvoltage"); break; case 222: - entry->Message = String(F("PV-4: Input undervoltage")); + entry->Message = F("PV-4: Input undervoltage"); break; case 301: - entry->Message = String(F("Hardware error code 301")); + entry->Message = F("Hardware error code 301"); break; case 302: - entry->Message = String(F("Hardware error code 302")); + entry->Message = F("Hardware error code 302"); break; case 303: - entry->Message = String(F("Hardware error code 303")); + entry->Message = F("Hardware error code 303"); break; case 304: - entry->Message = String(F("Hardware error code 304")); + entry->Message = F("Hardware error code 304"); break; case 305: - entry->Message = String(F("Hardware error code 305")); + entry->Message = F("Hardware error code 305"); break; case 306: - entry->Message = String(F("Hardware error code 306")); + entry->Message = F("Hardware error code 306"); break; case 307: - entry->Message = String(F("Hardware error code 307")); + entry->Message = F("Hardware error code 307"); break; case 308: - entry->Message = String(F("Hardware error code 308")); + entry->Message = F("Hardware error code 308"); break; case 309: - entry->Message = String(F("Hardware error code 309")); + entry->Message = F("Hardware error code 309"); break; case 310: - entry->Message = String(F("Hardware error code 310")); + entry->Message = F("Hardware error code 310"); break; case 311: - entry->Message = String(F("Hardware error code 311")); + entry->Message = F("Hardware error code 311"); break; case 312: - entry->Message = String(F("Hardware error code 312")); + entry->Message = F("Hardware error code 312"); break; case 313: - entry->Message = String(F("Hardware error code 313")); + entry->Message = F("Hardware error code 313"); break; case 314: - entry->Message = String(F("Hardware error code 314")); + entry->Message = F("Hardware error code 314"); break; case 5041: - entry->Message = String(F("Error code-04 Port 1")); + entry->Message = F("Error code-04 Port 1"); break; case 5042: - entry->Message = String(F("Error code-04 Port 2")); + entry->Message = F("Error code-04 Port 2"); break; case 5043: - entry->Message = String(F("Error code-04 Port 3")); + entry->Message = F("Error code-04 Port 3"); break; case 5044: - entry->Message = String(F("Error code-04 Port 4")); + entry->Message = F("Error code-04 Port 4"); break; case 5051: - entry->Message = String(F("PV Input 1 Overvoltage/Undervoltage")); + entry->Message = F("PV Input 1 Overvoltage/Undervoltage"); break; case 5052: - entry->Message = String(F("PV Input 2 Overvoltage/Undervoltage")); + entry->Message = F("PV Input 2 Overvoltage/Undervoltage"); break; case 5053: - entry->Message = String(F("PV Input 3 Overvoltage/Undervoltage")); + entry->Message = F("PV Input 3 Overvoltage/Undervoltage"); break; case 5054: - entry->Message = String(F("PV Input 4 Overvoltage/Undervoltage")); + entry->Message = F("PV Input 4 Overvoltage/Undervoltage"); break; case 5060: - entry->Message = String(F("Abnormal bias")); + entry->Message = F("Abnormal bias"); break; case 5070: - entry->Message = String(F("Over temperature protection")); + entry->Message = F("Over temperature protection"); break; case 5080: - entry->Message = String(F("Grid Overvoltage/Undervoltage")); + entry->Message = F("Grid Overvoltage/Undervoltage"); break; case 5090: - entry->Message = String(F("Grid Overfrequency/Underfrequency")); + entry->Message = F("Grid Overfrequency/Underfrequency"); break; case 5100: - entry->Message = String(F("Island detected")); + entry->Message = F("Island detected"); break; case 5120: - entry->Message = String(F("EEPROM reading and writing error")); + entry->Message = F("EEPROM reading and writing error"); break; case 5150: - entry->Message = String(F("10 min value grid overvoltage")); + entry->Message = F("10 min value grid overvoltage"); break; case 5200: - entry->Message = String(F("Firmware error")); + entry->Message = F("Firmware error"); break; case 8310: - entry->Message = String(F("Shut down")); + entry->Message = F("Shut down"); break; case 9000: - entry->Message = String(F("Microinverter is suspected of being stolen")); + entry->Message = F("Microinverter is suspected of being stolen"); break; default: - entry->Message = String(F("Unknown")); + entry->Message = F("Unknown"); break; } } diff --git a/src/NetworkSettings.cpp b/src/NetworkSettings.cpp index 732f3ec2..b975043c 100644 --- a/src/NetworkSettings.cpp +++ b/src/NetworkSettings.cpp @@ -375,7 +375,7 @@ String NetworkSettingsClass::macAddress() return WiFi.macAddress(); break; default: - return String(""); + return ""; } } From f741fea333d6527ea5d26f38d8ac8c15ed59c7d7 Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Sat, 29 Oct 2022 00:25:01 +0200 Subject: [PATCH 08/12] Move serial number formatting to inverter class --- .../src/inverters/InverterAbstract.cpp | 12 +++++ lib/Hoymiles/src/inverters/InverterAbstract.h | 2 + src/MqttHassPublishing.cpp | 51 +++++++------------ src/MqttPublishing.cpp | 14 +---- src/WebApi_devinfo.cpp | 8 +-- src/WebApi_eventlog.cpp | 10 ++-- src/WebApi_limit.cpp | 12 ++--- src/WebApi_power.cpp | 8 +-- src/WebApi_ws_live.cpp | 7 +-- 9 files changed, 43 insertions(+), 81 deletions(-) diff --git a/lib/Hoymiles/src/inverters/InverterAbstract.cpp b/lib/Hoymiles/src/inverters/InverterAbstract.cpp index adb3191e..bb7216d9 100644 --- a/lib/Hoymiles/src/inverters/InverterAbstract.cpp +++ b/lib/Hoymiles/src/inverters/InverterAbstract.cpp @@ -5,6 +5,13 @@ InverterAbstract::InverterAbstract(uint64_t serial) { _serial.u64 = serial; + + char serial_buff[sizeof(uint64_t) * 8 + 1]; + snprintf(serial_buff, sizeof(serial_buff), "%0x%08x", + ((uint32_t)((serial >> 32) & 0xFFFFFFFF)), + ((uint32_t)(serial & 0xFFFFFFFF))); + _serialString = serial_buff; + _alarmLogParser.reset(new AlarmLogParser()); _devInfoParser.reset(new DevInfoParser()); _powerCommandParser.reset(new PowerCommandParser()); @@ -26,6 +33,11 @@ uint64_t InverterAbstract::serial() return _serial.u64; } +const String& InverterAbstract::serialString() +{ + return _serialString; +} + void InverterAbstract::setName(const char* name) { uint8_t len = strlen(name); diff --git a/lib/Hoymiles/src/inverters/InverterAbstract.h b/lib/Hoymiles/src/inverters/InverterAbstract.h index 5d962706..5c9088b1 100644 --- a/lib/Hoymiles/src/inverters/InverterAbstract.h +++ b/lib/Hoymiles/src/inverters/InverterAbstract.h @@ -33,6 +33,7 @@ public: explicit InverterAbstract(uint64_t serial); void init(); uint64_t serial(); + const String& serialString(); void setName(const char* name); const char* name(); virtual String typeName() = 0; @@ -64,6 +65,7 @@ public: private: serial_u _serial; + String _serialString; char _name[MAX_NAME_LENGTH] = ""; fragment_t _rxFragmentBuffer[MAX_RF_FRAGMENT_COUNT]; uint8_t _rxFragmentMaxPacketId = 0; diff --git a/src/MqttHassPublishing.cpp b/src/MqttHassPublishing.cpp index 8b8f5073..60705b4a 100644 --- a/src/MqttHassPublishing.cpp +++ b/src/MqttHassPublishing.cpp @@ -85,10 +85,7 @@ void MqttHassPublishingClass::publishField(std::shared_ptr inv return; } - char serial[sizeof(uint64_t) * 8 + 1]; - snprintf(serial, sizeof(serial), "%0x%08x", - ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), - ((uint32_t)(inv->serial() & 0xFFFFFFFF))); + String serial = inv->serialString(); String fieldName; if (channel == CH0 && fieldType.fieldId == FLD_PDC) { @@ -97,7 +94,7 @@ void MqttHassPublishingClass::publishField(std::shared_ptr inv fieldName = inv->Statistics()->getChannelFieldName(channel, fieldType.fieldId); } - String configTopic = "sensor/dtu_" + String(serial) + String configTopic = "sensor/dtu_" + serial + "/" + "ch" + String(channel) + "_" + fieldName + "/config"; @@ -117,7 +114,7 @@ void MqttHassPublishingClass::publishField(std::shared_ptr inv root[F("name")] = name; root[F("stat_t")] = stateTopic; root[F("unit_of_meas")] = inv->Statistics()->getChannelFieldUnit(channel, fieldType.fieldId); - root[F("uniq_id")] = String(serial) + "_ch" + String(channel) + "_" + fieldName; + root[F("uniq_id")] = serial + "_ch" + String(channel) + "_" + fieldName; JsonObject deviceObj = root.createNestedObject("dev"); createDeviceInfo(deviceObj, inv); @@ -142,24 +139,21 @@ void MqttHassPublishingClass::publishField(std::shared_ptr inv void MqttHassPublishingClass::publishInverterButton(std::shared_ptr inv, const char* caption, const char* icon, const char* category, const char* deviceClass, const char* subTopic, const char* payload) { - char serial[sizeof(uint64_t) * 8 + 1]; - snprintf(serial, sizeof(serial), "%0x%08x", - ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), - ((uint32_t)(inv->serial() & 0xFFFFFFFF))); + String serial = inv->serialString(); String buttonId = caption; buttonId.replace(" ", "_"); buttonId.toLowerCase(); - String configTopic = "button/dtu_" + String(serial) + String configTopic = "button/dtu_" + serial + "/" + buttonId + "/config"; - String cmdTopic = MqttSettings.getPrefix() + String(serial) + "/" + subTopic; + String cmdTopic = MqttSettings.getPrefix() + serial + "/" + subTopic; DynamicJsonDocument root(1024); root[F("name")] = caption; - root[F("uniq_id")] = String(serial) + "_" + buttonId; + root[F("uniq_id")] = serial + "_" + buttonId; if (strcmp(icon, "")) { root[F("ic")] = icon; } @@ -183,25 +177,22 @@ void MqttHassPublishingClass::publishInverterNumber( const char* commandTopic, const char* stateTopic, const char* unitOfMeasure, int16_t min, int16_t max) { - char serial[sizeof(uint64_t) * 8 + 1]; - snprintf(serial, sizeof(serial), "%0x%08x", - ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), - ((uint32_t)(inv->serial() & 0xFFFFFFFF))); + String serial = inv->serialString(); String buttonId = caption; buttonId.replace(" ", "_"); buttonId.toLowerCase(); - String configTopic = "number/dtu_" + String(serial) + String configTopic = "number/dtu_" + serial + "/" + buttonId + "/config"; - String cmdTopic = MqttSettings.getPrefix() + String(serial) + "/" + commandTopic; - String statTopic = MqttSettings.getPrefix() + String(serial) + "/" + stateTopic; + String cmdTopic = MqttSettings.getPrefix() + serial + "/" + commandTopic; + String statTopic = MqttSettings.getPrefix() + serial + "/" + stateTopic; DynamicJsonDocument root(1024); root[F("name")] = caption; - root[F("uniq_id")] = String(serial) + "_" + buttonId; + root[F("uniq_id")] = serial + "_" + buttonId; if (strcmp(icon, "")) { root[F("ic")] = icon; } @@ -222,24 +213,21 @@ void MqttHassPublishingClass::publishInverterNumber( void MqttHassPublishingClass::publishInverterBinarySensor(std::shared_ptr inv, const char* caption, const char* subTopic, const char* payload_on, const char* payload_off) { - char serial[sizeof(uint64_t) * 8 + 1]; - snprintf(serial, sizeof(serial), "%0x%08x", - ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), - ((uint32_t)(inv->serial() & 0xFFFFFFFF))); + String serial = inv->serialString(); String sensorId = caption; sensorId.replace(" ", "_"); sensorId.toLowerCase(); - String configTopic = "binary_sensor/dtu_" + String(serial) + String configTopic = "binary_sensor/dtu_" + serial + "/" + sensorId + "/config"; - String statTopic = MqttSettings.getPrefix() + String(serial) + "/" + subTopic; + String statTopic = MqttSettings.getPrefix() + serial + "/" + subTopic; DynamicJsonDocument root(1024); root[F("name")] = caption; - root[F("uniq_id")] = String(serial) + "_" + sensorId; + root[F("uniq_id")] = serial + "_" + sensorId; root[F("stat_t")] = statTopic; root[F("pl_on")] = payload_on; root[F("pl_off")] = payload_off; @@ -254,13 +242,8 @@ void MqttHassPublishingClass::publishInverterBinarySensor(std::shared_ptr inv) { - char serial[sizeof(uint64_t) * 8 + 1]; - snprintf(serial, sizeof(serial), "%0x%08x", - ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), - ((uint32_t)(inv->serial() & 0xFFFFFFFF))); - object[F("name")] = inv->name(); - object[F("ids")] = String(serial); + object[F("ids")] = inv->serialString(); object[F("cu")] = String(F("http://")) + WiFi.localIP().toString(); object[F("mf")] = F("OpenDTU"); object[F("mdl")] = inv->typeName(); diff --git a/src/MqttPublishing.cpp b/src/MqttPublishing.cpp index fc74b785..46819bce 100644 --- a/src/MqttPublishing.cpp +++ b/src/MqttPublishing.cpp @@ -33,11 +33,7 @@ void MqttPublishingClass::loop() for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { auto inv = Hoymiles.getInverterByPos(i); - char buffer[sizeof(uint64_t) * 8 + 1]; - snprintf(buffer, sizeof(buffer), "%0x%08x", - ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), - ((uint32_t)(inv->serial() & 0xFFFFFFFF))); - String subtopic = String(buffer); + String subtopic = inv->serialString(); // Name MqttSettings.publish(subtopic + "/name", inv->name()); @@ -110,12 +106,6 @@ String MqttPublishingClass::getTopic(std::shared_ptr inv, uint return String(""); } - char buffer[sizeof(uint64_t) * 8 + 1]; - snprintf(buffer, sizeof(buffer), "%0x%08x", - ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), - ((uint32_t)(inv->serial() & 0xFFFFFFFF))); - String invSerial = String(buffer); - String chanName; if (channel == 0 && fieldId == FLD_PDC) { chanName = "powerdc"; @@ -124,5 +114,5 @@ String MqttPublishingClass::getTopic(std::shared_ptr inv, uint chanName.toLowerCase(); } - return invSerial + "/" + String(channel) + "/" + chanName; + return inv->serialString() + "/" + String(channel) + "/" + chanName; } \ No newline at end of file diff --git a/src/WebApi_devinfo.cpp b/src/WebApi_devinfo.cpp index 318b2f02..93f2fa75 100644 --- a/src/WebApi_devinfo.cpp +++ b/src/WebApi_devinfo.cpp @@ -29,13 +29,7 @@ void WebApiDevInfoClass::onDevInfoStatus(AsyncWebServerRequest* request) for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { auto inv = Hoymiles.getInverterByPos(i); - // Inverter Serial is read as HEX - char buffer[sizeof(uint64_t) * 8 + 1]; - snprintf(buffer, sizeof(buffer), "%0x%08x", - ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), - ((uint32_t)(inv->serial() & 0xFFFFFFFF))); - - JsonObject devInfoObj = root[buffer].createNestedObject(); + JsonObject devInfoObj = root[inv->serialString()].createNestedObject(); devInfoObj[F("valid_data")] = inv->DevInfo()->getLastUpdate() > 0; devInfoObj[F("fw_bootloader_version")] = inv->DevInfo()->getFwBootloaderVersion(); devInfoObj[F("fw_build_version")] = inv->DevInfo()->getFwBuildVersion(); diff --git a/src/WebApi_eventlog.cpp b/src/WebApi_eventlog.cpp index edff3bb6..9ba3c525 100644 --- a/src/WebApi_eventlog.cpp +++ b/src/WebApi_eventlog.cpp @@ -34,16 +34,12 @@ void WebApiEventlogClass::onEventlogStatus(AsyncWebServerRequest* request) auto inv = Hoymiles.getInverterBySerial(serial); if (inv != nullptr) { - // Inverter Serial is read as HEX - char buffer[sizeof(uint64_t) * 8 + 1]; - snprintf(buffer, sizeof(buffer), "%0x%08x", - ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), - ((uint32_t)(inv->serial() & 0xFFFFFFFF))); + String serial = inv->serialString(); uint8_t logEntryCount = inv->EventLog()->getEntryCount(); - root[buffer]["count"] = logEntryCount; - JsonArray eventsArray = root[buffer].createNestedArray(F("events")); + root[serial]["count"] = logEntryCount; + JsonArray eventsArray = root[serial].createNestedArray(F("events")); for (uint8_t logEntry = 0; logEntry < logEntryCount; logEntry++) { JsonObject eventsObject = eventsArray.createNestedObject(); diff --git a/src/WebApi_limit.cpp b/src/WebApi_limit.cpp index cfcb21e7..33bcd407 100644 --- a/src/WebApi_limit.cpp +++ b/src/WebApi_limit.cpp @@ -29,14 +29,10 @@ void WebApiLimitClass::onLimitStatus(AsyncWebServerRequest* request) for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { auto inv = Hoymiles.getInverterByPos(i); - // Inverter Serial is read as HEX - char buffer[sizeof(uint64_t) * 8 + 1]; - snprintf(buffer, sizeof(buffer), "%0x%08x", - ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), - ((uint32_t)(inv->serial() & 0xFFFFFFFF))); + String serial = inv->serialString(); - root[buffer]["limit_relative"] = inv->SystemConfigPara()->getLimitPercent(); - root[buffer]["max_power"] = inv->DevInfo()->getMaxPower(); + root[serial]["limit_relative"] = inv->SystemConfigPara()->getLimitPercent(); + root[serial]["max_power"] = inv->DevInfo()->getMaxPower(); LastCommandSuccess status = inv->SystemConfigPara()->getLastLimitCommandSuccess(); String limitStatus = "Unknown"; @@ -49,7 +45,7 @@ void WebApiLimitClass::onLimitStatus(AsyncWebServerRequest* request) else if (status == LastCommandSuccess::CMD_PENDING) { limitStatus = "Pending"; } - root[buffer]["limit_set_status"] = limitStatus; + root[serial]["limit_set_status"] = limitStatus; } response->setLength(); diff --git a/src/WebApi_power.cpp b/src/WebApi_power.cpp index 8ecda811..8e3c2bc8 100644 --- a/src/WebApi_power.cpp +++ b/src/WebApi_power.cpp @@ -29,12 +29,6 @@ void WebApiPowerClass::onPowerStatus(AsyncWebServerRequest* request) for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { auto inv = Hoymiles.getInverterByPos(i); - // Inverter Serial is read as HEX - char buffer[sizeof(uint64_t) * 8 + 1]; - snprintf(buffer, sizeof(buffer), "%0x%08x", - ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), - ((uint32_t)(inv->serial() & 0xFFFFFFFF))); - LastCommandSuccess status = inv->PowerCommand()->getLastPowerCommandSuccess(); String limitStatus = "Unknown"; if (status == LastCommandSuccess::CMD_OK) { @@ -44,7 +38,7 @@ void WebApiPowerClass::onPowerStatus(AsyncWebServerRequest* request) } else if (status == LastCommandSuccess::CMD_PENDING) { limitStatus = "Pending"; } - root[buffer]["power_set_status"] = limitStatus; + root[inv->serialString()]["power_set_status"] = limitStatus; } response->setLength(); diff --git a/src/WebApi_ws_live.cpp b/src/WebApi_ws_live.cpp index 032c9078..41ce2b5e 100644 --- a/src/WebApi_ws_live.cpp +++ b/src/WebApi_ws_live.cpp @@ -77,12 +77,7 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root) for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { auto inv = Hoymiles.getInverterByPos(i); - char buffer[sizeof(uint64_t) * 8 + 1]; - snprintf(buffer, sizeof(buffer), "%0x%08x", - ((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)), - ((uint32_t)(inv->serial() & 0xFFFFFFFF))); - - root[i][F("serial")] = String(buffer); + root[i][F("serial")] = inv->serialString(); root[i][F("name")] = inv->name(); root[i][F("data_age")] = (millis() - inv->Statistics()->getLastUpdate()) / 1000; root[i][F("reachable")] = inv->isReachable(); From 6a3fbc7a82e23e009b0122b10d3d4c9d9125c8ba Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Sun, 30 Oct 2022 17:47:52 +0100 Subject: [PATCH 09/12] Fix #283: Fix python error when building firmware --- auto_firmware_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto_firmware_version.py b/auto_firmware_version.py index 33d2e587..d2969b76 100644 --- a/auto_firmware_version.py +++ b/auto_firmware_version.py @@ -11,7 +11,7 @@ installed_pkgs = {pkg.key for pkg in pkg_resources.working_set} missing_pkgs = required_pkgs - installed_pkgs if missing_pkgs: - env.Execute('"$PYTHONEXE" -m pip install dulwich --global-option="--pure"') + env.Execute('"$PYTHONEXE" -m pip install dulwich"') from dulwich import porcelain From fefe0cd128235cedc242f73a22b65c73aba99772 Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Sun, 30 Oct 2022 17:52:30 +0100 Subject: [PATCH 10/12] Fix syntax error --- auto_firmware_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto_firmware_version.py b/auto_firmware_version.py index d2969b76..2f15cc95 100644 --- a/auto_firmware_version.py +++ b/auto_firmware_version.py @@ -11,7 +11,7 @@ installed_pkgs = {pkg.key for pkg in pkg_resources.working_set} missing_pkgs = required_pkgs - installed_pkgs if missing_pkgs: - env.Execute('"$PYTHONEXE" -m pip install dulwich"') + env.Execute('"$PYTHONEXE" -m pip install dulwich') from dulwich import porcelain From 03f79adad0dce9f8c2fe07d6f5c720cf3a26a12b Mon Sep 17 00:00:00 2001 From: descodess <87569405+descodess@users.noreply.github.com> Date: Sun, 30 Oct 2022 19:41:48 +0100 Subject: [PATCH 11/12] Fixes for README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fix microfarads (µF; see: https://en.wikipedia.org/wiki/Farad) - fix spaces between number and unit of measurement (see: https://en.wikipedia.org/wiki/Space_(punctuation)#Unit_symbols_and_numbers) - fix ellipsis (see: https://en.wikipedia.org/wiki/Ellipsis) - fix typo --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 116c33cb..6a520428 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ A heavily incomplete list of trusted hardware shops in germany is: This list is for your convenience only, the project is not related to any of these shops. ### Power supply -Use a power suppy with 5V and 1A. The USB cable connected to your PC/Notebook may be powerful enough or may be not. +Use a power suppy with 5 V and 1 A. The USB cable connected to your PC/Notebook may be powerful enough or may be not. ## Wiring up @@ -206,11 +206,11 @@ A documentation of all available MQTT Topics can be found here: [MQTT Documentat * First: When there is no light on the solar panels, the inverter completely turns off and does not answer to OpenDTU! So if you assembled your OpenDTU in the evening, wait until tomorrow. * When there is no data received from the inverter(s) - try to reduce the distance between the openDTU and the inverter (e.g. move it to the window towards the roof) * Under Settings -> DTU Settings you can increase the transmit power "PA level". Default is "minimum". -* The NRF24L01+ needs relatively much current. With bad power supply (and especially bad cables!) a 10uF capacitor soldered directly to the NRF24L01+ board connector brings more stability (pin 1+2 are the power supply). Note the polarity of the capacitor.... -* You can try to use an USB power supply with 1A or more instead of connecting the ESP32 to the computer. +* The NRF24L01+ needs relatively much current. With bad power supply (and especially bad cables!) a 10 µF capacitor soldered directly to the NRF24L01+ board connector brings more stability (pin 1+2 are the power supply). Note the polarity of the capacitor… +* You can try to use an USB power supply with 1 A or more instead of connecting the ESP32 to the computer. * Try a different USB cable. Once again, a stable power source is important. Some USB cables are made of much plastic and very little copper inside. -* Double-Check that you have a radio module NRF24L01+ with a plus sign at the end. NRF24L01 module without the plus are not compatible with this project. -* There is no possibility of auto-discovering the inverters. Double-Check you have entered the serial numbers of the inverters correctly. +* Double check that you have a radio module NRF24L01+ with a plus sign at the end. NRF24L01 module without the plus are not compatible with this project. +* There is no possibility of auto-discovering the inverters. Double check you have entered the serial numbers of the inverters correctly. * OpenDTU needs access to a working NTP server to get the current date & time. * If your problem persists, check the [Issues on Github](https://github.com/tbnobody/OpenDTU/issues). Please inspect not only the open issues, also the closed issues contain useful information. * Another source of information are the [Discussions](https://github.com/tbnobody/OpenDTU/discussions/) From e47c1603e1bbf9688d3b8914148d7cbfb043cb49 Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Sun, 30 Oct 2022 20:15:06 +0100 Subject: [PATCH 12/12] Add own youtube video showing the compilation process --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 116c33cb..38b58699 100644 --- a/README.md +++ b/README.md @@ -108,11 +108,14 @@ This can be achieved by editing the 'platformio.ini' file and add/change one or * Install git and enable git in vscode - [git download](https://git-scm.com/downloads/) - [Instructions](https://www.jcchouinard.com/install-git-in-vscode/) * Clone this repository (you really have to clone it, don't just download the ZIP file. During the build process the git hash gets embedded into the firmware. If you download the ZIP file a build error will occur): Inside vscode open the command palette by pressing `CTRL` + `SHIFT` + `P`. Enter `git clone`, add the repository-URL `https://github.com/tbnobody/OpenDTU`. Next you have to choose (or create) a target directory. * In vscode, choose File --> Open Folder and select the previously downloaded source code. (You have to select the folder which contains the "platformio.ini" file) -* There is a short [Video](https://youtu.be/9cA_esv3zeA) showing these steps. * Adjust the COM port in the file "platformio.ini" for your USB-serial-converter. It occurs twice: * upload_port * monitor_port * Select the arrow button in the status bar (PlatformIO: Upload) to compile and upload the firmware. During the compilation, all required libraries are downloaded automatically. +* There are two videos showing these steps: + * [Git Clone and compilation](https://youtu.be/9cA_esv3zeA) + * [Full installation and compilation](https://youtu.be/xs6TqHn7QWM) + ### on the commandline with PlatformIO Core * Install [PlatformIO Core](https://platformio.org/install/cli) * Clone this repository (you really have to clone it, don't just download the ZIP file. During the build process the git hash gets embedded into the firmware. If you download the ZIP file a build error will occur)