-
-
Notifications
You must be signed in to change notification settings - Fork 508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
added GridProfileParser from noone2k #1527
Conversation
@tbnobody thanks for implementing this next step on our path to a working DTU Pro replacement! I just compared the gist from noone2k and my PR to see that the following parts are missing:
Please see his or my latest gist for the profiles / tables with some comments. |
Sry. Didn't see your last comment. I will add it soon. Currently it's implemented here 06651f3 |
Congrats Thomas @tbnobody |
The latest values are added here: eac4794 |
@tbnobody I just found a small feature, which we forgot, the postive See the description from Hoymiles documentation here: |
@stefan123t I did only think 10 seconds about it so maybe I am wrong... Does it maybe make sense to cast the two bytes (in general for all values) to int16_t instead of uint16_t or will it generate any mistakes in the other values? Will doublecheck it tomorrow. |
I recall that most (all?) of the values in the original Hoymiles DTU Pro source code were defined as signed int16_t too. |
I've doublechecked it: https://godbolt.org/z/GWo3f8Wcb Casting to int16_t does exactly what it should. On the other hand it does not impact any other values. (My gridprofile is the same, with or without that modification) |
python has no explicit buildin signed/unsigned values. |
Great @tbnobody then lets cast it to signed int16_t ;) Should we give/translate the sign to positive |
@Fribur thanks for making some adjustments in your fork to the GridProfile parser matching the North American NA_IEEE1547_240V (2.0.0) Grid Profile. Also thanks for the pointer to the american diysolarforum thread which we should have a closer look into ;) Let me leave this pointer from the closed PR to merge the gist from noone2k into OpenDTU to your latest update. Would you mind checking the latest version of OpenDTU for your changes being still necessary but also to document the various NA GridProfiles / Versions in binary hex/bin format as available from the OpenDTU UI ? |
@stefan123t I have to make the following changes to the parser to match it with the following document: Which is also related to #1590 diff --git a/lib/Hoymiles/src/parser/GridProfileParser.cpp b/lib/Hoymiles/src/parser/GridProfileParser.cpp
index da1c806..9d38669 100644
--- a/lib/Hoymiles/src/parser/GridProfileParser.cpp
+++ b/lib/Hoymiles/src/parser/GridProfileParser.cpp
@@ -45,19 +45,19 @@ constexpr GridProfileItemDefinition_t make_value(frozen::string Name, frozen::st
return v;
}
-constexpr frozen::map<uint8_t, GridProfileItemDefinition_t, 0x39> itemDefinitions = {
+constexpr frozen::map<uint8_t, GridProfileItemDefinition_t, 0x3e> itemDefinitions = {
{ 0x01, make_value("Nominale Voltage (NV)", "V", 10) },
{ 0x02, make_value("Low Voltage 1 (LV1)", "V", 10) },
{ 0x03, make_value("LV1 Maximum Trip Time (MTT)", "s", 10) },
{ 0x04, make_value("High Voltage 1 (HV1)", "V", 10) },
{ 0x05, make_value("HV1 Maximum Trip Time (MTT)", "s", 10) },
{ 0x06, make_value("Low Voltage 2 (LV2)", "V", 10) },
- { 0x07, make_value("LV2 Maximum Trip Time (MTT)", "s", 10) },
+ { 0x07, make_value("LV2 Maximum Trip Time (MTT)", "s", 100) },
{ 0x08, make_value("High Voltage 2 (HV2)", "V", 10) },
- { 0x09, make_value("HV2 Maximum Trip Time (MTT)", "s", 10) },
+ { 0x09, make_value("HV2 Maximum Trip Time (MTT)", "s", 100) },
{ 0x0a, make_value("10mins Average High Voltage (AHV)", "V", 10) },
{ 0x0b, make_value("High Voltage 3 (HV3)", "V", 10) },
- { 0x0c, make_value("HV3 Maximum Trip Time (MTT)", "s", 10) },
+ { 0x0c, make_value("HV3 Maximum Trip Time (MTT)", "s", 100) },
{ 0x0d, make_value("Nominal Frequency", "Hz", 100) },
{ 0x0e, make_value("Low Frequency 1 (LF1)", "Hz", 100) },
{ 0x0f, make_value("LF1 Maximum Trip Time (MTT)", "s", 10) },
@@ -102,6 +102,11 @@ constexpr frozen::map<uint8_t, GridProfileItemDefinition_t, 0x39> itemDefinition
{ 0x36, make_value("WPF Function Activated", "bool", 1) },
{ 0x37, make_value("Start of Power of WPF (Pstart)", "%Pn", 10) },
{ 0x38, make_value("Power Factor ar Rated Power (PFRP)", "", 100) },
+ { 0x39, make_value("Low Voltage 3 (LV3)", "V", 10) },
+ { 0x3a, make_value("LV3 Maximum Trip Time (MTT)", "s", 100) },
+ { 0x3b, make_value("Momentary Cessition Low Voltage", "V", 10) },
+ { 0x3c, make_value("Momentary Cessition High Voltage", "V", 10) },
+ { 0x3d, make_value("FW Settling Time (Tr)", "s", 10) },
{ 0xff, make_value("Unkown Value", "", 1) },
};
@@ -178,10 +183,10 @@ const std::array<const GridProfileValue_t, SECTION_VALUE_COUNT> GridProfileParse
{ 0x00, 0x35, 0x07 },
{ 0x00, 0x35, 0x08 },
{ 0x00, 0x35, 0x09 },
- { 0x00, 0x35, 0xff },
- { 0x00, 0x35, 0xff },
- { 0x00, 0x35, 0xff },
- { 0x00, 0x35, 0xff },
+ { 0x00, 0x35, 0x39 },
+ { 0x00, 0x35, 0x3a },
+ { 0x00, 0x35, 0x3b },
+ { 0x00, 0x35, 0x3c },
// Frequency (H/LFRT)
// Version 0x00
@@ -255,7 +260,7 @@ const std::array<const GridProfileValue_t, SECTION_VALUE_COUNT> GridProfileParse
{ 0x50, 0x11, 0x1f },
{ 0x50, 0x11, 0x20 },
{ 0x50, 0x11, 0x21 },
- { 0x50, 0x11, 0x22 },
+ { 0x50, 0x11, 0x3d },
// Volt Watt (VW)
// Version 0x00 |
I just saw that a new grid profile on the wiki was posted (NL xxxx) and wanted to incorporate it. that said: I have no problem with someone merging this in their existing repo that there is a central, current version where changes can be pushed and discussed. sneaky view to tbnobody or stefan123t ;) since it is now also merged into opendtu, the chances are high, that more and more new grid profile are fed into the wiki. |
Yes tbnobody already added your changes to OpenDTU. @noone2k I would suggest that your original python code should be incorporated/ merged into some python library. I would suggest the actively maintained library by @rovo89 here https://github.com/rovo89/hoymiles_proto Also the original Raspberry Pi python code for the HM-600/800 inverters by @Sprinterfreak et al. which was archived under https://github.com/lumapu/ahoy/tree/main/tools/rpi or his own repo https://github.com/Sprinterfreak/ahoy should be good places for your code donation. |
After parsing the current grid profiles in the wiki I would also change this: diff --git a/lib/Hoymiles/src/parser/GridProfileParser.cpp b/lib/Hoymiles/src/parser/GridProfileParser.cpp
index da1c806..64ed5e0 100644
--- a/lib/Hoymiles/src/parser/GridProfileParser.cpp
+++ b/lib/Hoymiles/src/parser/GridProfileParser.cpp
@@ -9,12 +9,14 @@
#include <frozen/string.h>
const std::array<const ProfileType_t, PROFILE_TYPE_COUNT> GridProfileParser::_profileTypes = { {
- { 0x02, 0x00, "no data (yet)" },
+ { 0x02, 0x00, "US - IEEE 1547 240V (2018)" },
{ 0x03, 0x00, "Germany - DE_VDE4105_2018" },
+ { 0x03, 0x01, "no data (yet)" },
{ 0x0a, 0x00, "European - EN 50549-1:2019" },
{ 0x0c, 0x00, "AT Tor - EU_EN50438" },
{ 0x0d, 0x04, "France" },
{ 0x12, 0x00, "Poland - EU_EN50438" },
+ { 0x29, 0x00, "NL - NL_NEN-EN50549-1_2019" },
{ 0x37, 0x00, "Swiss - CH_NA EEA-NE7-CH2020" },
} }; |
the "0x02 0x00" - no data yet, meant : the inverter has not populated the internal buffer, f.ex after a fresh (re)start. i just tried to reproduce this behaviour, but failed ... the newer opendtu don't show the unitialized "0x02 0x00" ;) the new "0x03 x01" is an unknown grid profile name, hence i named it that way - unknown ;) |
@tbnobody i do agree to add the new / proper names to the grid profiles. However I would suggest to stick with the orignal Hoymiles naming convention and Names (if known). |
I agree too!! I tried to find several names in youtube videos, manuals and the demo account from the Hoymiles Installer app. Currently have the following list (only Gen3):
They are mostly from this video: https://www.youtube.com/watch?v=zvCC5wSRqr4 I am wondering how they are handling the different saved versions of an profile. (And maybe the aliases which can also be created?) And as you can see in the video, the possible selectable grid profiles depend on the country setting of the inverter. Therefor I would suggest to prepend the country (code?) in front of the original file name. The alpha-2-code could be used. |
i mostly agree to the new naming scheme, i start to adopt most of them.
and on the bottom of the wiki someone added a spain profile ... quick preview, for voltage table:
|
Thank you for sharing this! this is my latest patch to the grid profile parser: diff --git a/lib/Hoymiles/src/parser/GridProfileParser.cpp b/lib/Hoymiles/src/parser/GridProfileParser.cpp
index da1c806..b6c1573 100644
--- a/lib/Hoymiles/src/parser/GridProfileParser.cpp
+++ b/lib/Hoymiles/src/parser/GridProfileParser.cpp
@@ -9,13 +9,16 @@
#include <frozen/string.h>
const std::array<const ProfileType_t, PROFILE_TYPE_COUNT> GridProfileParser::_profileTypes = { {
- { 0x02, 0x00, "no data (yet)" },
- { 0x03, 0x00, "Germany - DE_VDE4105_2018" },
- { 0x0a, 0x00, "European - EN 50549-1:2019" },
- { 0x0c, 0x00, "AT Tor - EU_EN50438" },
- { 0x0d, 0x04, "France" },
- { 0x12, 0x00, "Poland - EU_EN50438" },
- { 0x37, 0x00, "Swiss - CH_NA EEA-NE7-CH2020" },
+ { 0x02, 0x00, "US - NA_IEEE1547_240V" },
+ { 0x03, 0x00, "DE - DE_VDE4105_2018" },
+ { 0x03, 0x01, "XX - unknown" },
+ { 0x0a, 0x00, "XX - EN 50549-1:2019" },
+ { 0x0c, 0x00, "AT - AT_TOR_Erzeuger_default" },
+ { 0x0d, 0x04, "FR -" },
+ { 0x10, 0x00, "ES - ES_RD1699" },
+ { 0x12, 0x00, "PL - EU_EN50438" },
+ { 0x29, 0x00, "NL - NL_NEN-EN50549-1_2019" },
+ { 0x37, 0x00, "CH - CH_NA EEA-NE7-CH2020" },
} };
constexpr frozen::map<uint8_t, frozen::string, 12> profileSection = {
@@ -45,19 +48,19 @@ constexpr GridProfileItemDefinition_t make_value(frozen::string Name, frozen::st
return v;
}
-constexpr frozen::map<uint8_t, GridProfileItemDefinition_t, 0x39> itemDefinitions = {
+constexpr frozen::map<uint8_t, GridProfileItemDefinition_t, 0x42> itemDefinitions = {
{ 0x01, make_value("Nominale Voltage (NV)", "V", 10) },
{ 0x02, make_value("Low Voltage 1 (LV1)", "V", 10) },
{ 0x03, make_value("LV1 Maximum Trip Time (MTT)", "s", 10) },
{ 0x04, make_value("High Voltage 1 (HV1)", "V", 10) },
{ 0x05, make_value("HV1 Maximum Trip Time (MTT)", "s", 10) },
{ 0x06, make_value("Low Voltage 2 (LV2)", "V", 10) },
- { 0x07, make_value("LV2 Maximum Trip Time (MTT)", "s", 10) },
+ { 0x07, make_value("LV2 Maximum Trip Time (MTT)", "s", 100) },
{ 0x08, make_value("High Voltage 2 (HV2)", "V", 10) },
- { 0x09, make_value("HV2 Maximum Trip Time (MTT)", "s", 10) },
+ { 0x09, make_value("HV2 Maximum Trip Time (MTT)", "s", 100) },
{ 0x0a, make_value("10mins Average High Voltage (AHV)", "V", 10) },
{ 0x0b, make_value("High Voltage 3 (HV3)", "V", 10) },
- { 0x0c, make_value("HV3 Maximum Trip Time (MTT)", "s", 10) },
+ { 0x0c, make_value("HV3 Maximum Trip Time (MTT)", "s", 100) },
{ 0x0d, make_value("Nominal Frequency", "Hz", 100) },
{ 0x0e, make_value("Low Frequency 1 (LF1)", "Hz", 100) },
{ 0x0f, make_value("LF1 Maximum Trip Time (MTT)", "s", 10) },
@@ -94,7 +97,7 @@ constexpr frozen::map<uint8_t, GridProfileItemDefinition_t, 0x39> itemDefinition
{ 0x2e, make_value("Voltage Set Point V3", "V", 10) },
{ 0x2f, make_value("Voltage Set Point V4", "V", 10) },
{ 0x30, make_value("Reactive Set Point Q4", "%Pn", 10) },
- { 0x31, make_value("Setting Time (Tr)", "s", 10) },
+ { 0x31, make_value("VV Setting Time (Tr)", "s", 10) },
{ 0x32, make_value("SPF Function Activated", "bool", 1) },
{ 0x33, make_value("Power Factor (PF)", "", 100) },
{ 0x34, make_value("RPC Function Activated", "bool", 1) },
@@ -102,6 +105,15 @@ constexpr frozen::map<uint8_t, GridProfileItemDefinition_t, 0x39> itemDefinition
{ 0x36, make_value("WPF Function Activated", "bool", 1) },
{ 0x37, make_value("Start of Power of WPF (Pstart)", "%Pn", 10) },
{ 0x38, make_value("Power Factor ar Rated Power (PFRP)", "", 100) },
+ { 0x39, make_value("Low Voltage 3 (LV3)", "V", 10) },
+ { 0x3a, make_value("LV3 Maximum Trip Time (MTT)", "s", 100) },
+ { 0x3b, make_value("Momentary Cessition Low Voltage", "V", 10) },
+ { 0x3c, make_value("Momentary Cessition High Voltage", "V", 10) },
+ { 0x3d, make_value("FW Settling Time (Tr)", "s", 10) },
+ { 0x3e, make_value("LF2 Maximum Trip Time (MTT)", "s", 100) },
+ { 0x3f, make_value("HF2 Maximum Trip time (MTT)", "s", 100) },
+ { 0x40, make_value("Short Interruption Reconnect Time (SRT)", "s", 10) },
+ { 0x41, make_value("Short Interruption Time (SIT)", "s", 10) },
{ 0xff, make_value("Unkown Value", "", 1) },
};
@@ -114,6 +126,24 @@ const std::array<const GridProfileValue_t, SECTION_VALUE_COUNT> GridProfileParse
{ 0x00, 0x00, 0x04 },
{ 0x00, 0x00, 0x05 },
+ // Version 0x01
+ { 0x00, 0x01, 0x01 },
+ { 0x00, 0x01, 0x02 },
+ { 0x00, 0x01, 0x03 },
+ { 0x00, 0x01, 0x04 },
+ { 0x00, 0x01, 0x05 },
+ { 0x00, 0x01, 0x08 },
+ { 0x00, 0x01, 0x09 },
+
+ // Version 0x02
+ { 0x00, 0x02, 0x01 },
+ { 0x00, 0x02, 0x02 },
+ { 0x00, 0x02, 0x03 },
+ { 0x00, 0x02, 0x04 },
+ { 0x00, 0x02, 0x05 },
+ { 0x00, 0x02, 0x06 },
+ { 0x00, 0x02, 0x07 },
+
// Version 0x03
{ 0x00, 0x03, 0x01 },
{ 0x00, 0x03, 0x02 },
@@ -178,10 +208,10 @@ const std::array<const GridProfileValue_t, SECTION_VALUE_COUNT> GridProfileParse
{ 0x00, 0x35, 0x07 },
{ 0x00, 0x35, 0x08 },
{ 0x00, 0x35, 0x09 },
- { 0x00, 0x35, 0xff },
- { 0x00, 0x35, 0xff },
- { 0x00, 0x35, 0xff },
- { 0x00, 0x35, 0xff },
+ { 0x00, 0x35, 0x39 },
+ { 0x00, 0x35, 0x3a },
+ { 0x00, 0x35, 0x3b },
+ { 0x00, 0x35, 0x3c },
// Frequency (H/LFRT)
// Version 0x00
@@ -198,9 +228,9 @@ const std::array<const GridProfileValue_t, SECTION_VALUE_COUNT> GridProfileParse
{ 0x10, 0x03, 0x10 },
{ 0x10, 0x03, 0x11 },
{ 0x10, 0x03, 0x12 },
- { 0x10, 0x03, 0x13 },
+ { 0x10, 0x03, 0x3e },
{ 0x10, 0x03, 0x14 },
- { 0x10, 0x03, 0x15 },
+ { 0x10, 0x03, 0x3f },
// Island Detection (ID)
// Version 0x00
@@ -220,8 +250,8 @@ const std::array<const GridProfileValue_t, SECTION_VALUE_COUNT> GridProfileParse
{ 0x30, 0x07, 0x19 },
{ 0x30, 0x07, 0x1a },
{ 0x30, 0x07, 0x1b },
- { 0x30, 0x07, 0xff },
- { 0x30, 0x07, 0xff },
+ { 0x30, 0x07, 0x40 },
+ { 0x30, 0x07, 0x41 },
// Ramp Rates (RR)
// Version 0x00
@@ -255,7 +285,7 @@ const std::array<const GridProfileValue_t, SECTION_VALUE_COUNT> GridProfileParse
{ 0x50, 0x11, 0x1f },
{ 0x50, 0x11, 0x20 },
{ 0x50, 0x11, 0x21 },
- { 0x50, 0x11, 0x22 },
+ { 0x50, 0x11, 0x3d },
// Volt Watt (VW)
// Version 0x00 Based on the spanish profile I found the |
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new discussion or issue for related concerns. |
Added a parseGridProfile method stub to the GridProfileParser.cpp/h based on work done by @noone2k here:
https://gist.github.com/noone2k/0b3a116a6f35286abef7199b62a0777a
This is capable of parsing data shown on https://github.com/tbnobody/OpenDTU/wiki/Grid-Profile-Parser
This PR will allow to address the reading parts of #256, #679, #707, #900, #987, #1369
VUE UI and some REST API glue code is missing.