Skip to content

Commit

Permalink
Merge pull request #778 from helgeerbe/upstream-v24.3.15
Browse files Browse the repository at this point in the history
merges upstream v24.3.15
  • Loading branch information
schlimmchen committed Mar 20, 2024
2 parents cd339a3 + 5259fc1 commit cffc5b1
Show file tree
Hide file tree
Showing 44 changed files with 683 additions and 398 deletions.
1 change: 0 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"DavidAnson.vscode-markdownlint",
"EditorConfig.EditorConfig",
"Vue.volar",
"Vue.vscode-typescript-vue-plugin",
"platformio.platformio-ide"
],
"unwantedRecommendations": [
Expand Down
1 change: 1 addition & 0 deletions include/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ class ConfigurationClass {

INVERTER_CONFIG_T* getFreeInverterSlot();
INVERTER_CONFIG_T* getInverterConfig(const uint64_t serial);
void deleteInverterById(const uint8_t id);
};

extern ConfigurationClass Configuration;
8 changes: 7 additions & 1 deletion lib/Hoymiles/src/Hoymiles.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2022-2023 Thomas Basler and others
* Copyright (C) 2022-2024 Thomas Basler and others
*/
#include "Hoymiles.h"
#include "Utils.h"
#include "inverters/HERF_2CH.h"
#include "inverters/HERF_4CH.h"
#include "inverters/HMS_1CH.h"
#include "inverters/HMS_1CHv2.h"
#include "inverters/HMS_2CH.h"
Expand Down Expand Up @@ -168,6 +170,10 @@ std::shared_ptr<InverterAbstract> HoymilesClass::addInverter(const char* name, c
i = std::make_shared<HM_2CH>(_radioNrf.get(), serial);
} else if (HM_1CH::isValidSerial(serial)) {
i = std::make_shared<HM_1CH>(_radioNrf.get(), serial);
} else if (HERF_2CH::isValidSerial(serial)) {
i = std::make_shared<HERF_2CH>(_radioNrf.get(), serial);
} else if (HERF_4CH::isValidSerial(serial)) {
i = std::make_shared<HERF_4CH>(_radioNrf.get(), serial);
}

if (i) {
Expand Down
62 changes: 62 additions & 0 deletions lib/Hoymiles/src/inverters/HERF_2CH.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2022-2024 Thomas Basler and others
*/
#include "HERF_2CH.h"

static const byteAssign_t byteAssignment[] = {
{ TYPE_DC, CH0, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 },
{ TYPE_DC, CH0, FLD_IDC, UNIT_A, 6, 2, 100, false, 2 },
{ TYPE_DC, CH0, FLD_PDC, UNIT_W, 10, 2, 10, false, 1 },
{ TYPE_DC, CH0, FLD_YD, UNIT_WH, 22, 2, 1, false, 0 },
{ TYPE_DC, CH0, FLD_YT, UNIT_KWH, 14, 4, 1000, false, 3 },
{ TYPE_DC, CH0, FLD_IRR, UNIT_PCT, CALC_CH_IRR, CH0, CMD_CALC, false, 3 },

{ TYPE_DC, CH1, FLD_UDC, UNIT_V, 4, 2, 10, false, 1 },
{ TYPE_DC, CH1, FLD_IDC, UNIT_A, 8, 2, 100, false, 2 },
{ TYPE_DC, CH1, FLD_PDC, UNIT_W, 12, 2, 10, false, 1 },
{ TYPE_DC, CH1, FLD_YD, UNIT_WH, 24, 2, 1, false, 0 },
{ TYPE_DC, CH1, FLD_YT, UNIT_KWH, 18, 4, 1000, false, 3 },
{ TYPE_DC, CH1, FLD_IRR, UNIT_PCT, CALC_CH_IRR, CH1, CMD_CALC, false, 3 },

{ TYPE_AC, CH0, FLD_UAC, UNIT_V, 26, 2, 10, false, 1 },
{ TYPE_AC, CH0, FLD_IAC, UNIT_A, 34, 2, 100, false, 2 },
{ TYPE_AC, CH0, FLD_PAC, UNIT_W, 30, 2, 10, false, 1 },
{ TYPE_AC, CH0, FLD_Q, UNIT_VAR, 32, 2, 10, false, 1 },
{ TYPE_AC, CH0, FLD_F, UNIT_HZ, 28, 2, 100, false, 2 },
{ TYPE_AC, CH0, FLD_PF, UNIT_NONE, 36, 2, 1000, false, 3 },

{ TYPE_INV, CH0, FLD_T, UNIT_C, 38, 2, 10, true, 1 },
{ TYPE_INV, CH0, FLD_EVT_LOG, UNIT_NONE, 40, 2, 1, false, 0 },

{ TYPE_INV, CH0, FLD_YD, UNIT_WH, CALC_TOTAL_YD, 0, CMD_CALC, false, 0 },
{ TYPE_INV, CH0, FLD_YT, UNIT_KWH, CALC_TOTAL_YT, 0, CMD_CALC, false, 3 },
{ TYPE_INV, CH0, FLD_PDC, UNIT_W, CALC_TOTAL_PDC, 0, CMD_CALC, false, 1 },
{ TYPE_INV, CH0, FLD_EFF, UNIT_PCT, CALC_TOTAL_EFF, 0, CMD_CALC, false, 3 }
};

HERF_2CH::HERF_2CH(HoymilesRadio* radio, const uint64_t serial)
: HM_Abstract(radio, serial) {};

bool HERF_2CH::isValidSerial(const uint64_t serial)
{
// serial >= 0x282100000000 && serial <= 0x2821ffffffff
uint16_t preSerial = (serial >> 32) & 0xffff;
return preSerial == 0x2821;
}

String HERF_2CH::typeName() const
{
return "HERF-800-2T";
}

const byteAssign_t* HERF_2CH::getByteAssignment() const
{
return byteAssignment;
}

uint8_t HERF_2CH::getByteAssignmentSize() const
{
return sizeof(byteAssignment) / sizeof(byteAssignment[0]);
}
13 changes: 13 additions & 0 deletions lib/Hoymiles/src/inverters/HERF_2CH.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#include "HM_Abstract.h"

class HERF_2CH : public HM_Abstract {
public:
explicit HERF_2CH(HoymilesRadio* radio, const uint64_t serial);
static bool isValidSerial(const uint64_t serial);
String typeName() const;
const byteAssign_t* getByteAssignment() const;
uint8_t getByteAssignmentSize() const;
};
20 changes: 20 additions & 0 deletions lib/Hoymiles/src/inverters/HERF_4CH.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2022-2024 Thomas Basler and others
*/
#include "HERF_4CH.h"

HERF_4CH::HERF_4CH(HoymilesRadio* radio, const uint64_t serial)
: HM_4CH(radio, serial) {};

bool HERF_4CH::isValidSerial(const uint64_t serial)
{
// serial >= 0x280100000000 && serial <= 0x2801ffffffff
uint16_t preSerial = (serial >> 32) & 0xffff;
return preSerial == 0x2801;
}

String HERF_4CH::typeName() const
{
return "HERF-1600/1800-4T";
}
11 changes: 11 additions & 0 deletions lib/Hoymiles/src/inverters/HERF_4CH.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#include "HM_4CH.h"

class HERF_4CH : public HM_4CH {
public:
explicit HERF_4CH(HoymilesRadio* radio, const uint64_t serial);
static bool isValidSerial(const uint64_t serial);
String typeName() const;
};
2 changes: 1 addition & 1 deletion lib/Hoymiles/src/inverters/HMS_1CH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ HMS_1CH::HMS_1CH(HoymilesRadio* radio, const uint64_t serial)

bool HMS_1CH::isValidSerial(const uint64_t serial)
{
// serial >= 0x112400000000 && serial <= 0x112499999999
// serial >= 0x112400000000 && serial <= 0x1124ffffffff
uint16_t preSerial = (serial >> 32) & 0xffff;
return preSerial == 0x1124;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Hoymiles/src/inverters/HMS_1CHv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ HMS_1CHv2::HMS_1CHv2(HoymilesRadio* radio, const uint64_t serial)

bool HMS_1CHv2::isValidSerial(const uint64_t serial)
{
// serial >= 0x112500000000 && serial <= 0x112599999999
// serial >= 0x112500000000 && serial <= 0x1125ffffffff
uint16_t preSerial = (serial >> 32) & 0xffff;
return preSerial == 0x1125;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Hoymiles/src/inverters/HMS_2CH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ HMS_2CH::HMS_2CH(HoymilesRadio* radio, const uint64_t serial)

bool HMS_2CH::isValidSerial(const uint64_t serial)
{
// serial >= 0x114400000000 && serial <= 0x114499999999
// serial >= 0x114400000000 && serial <= 0x1144ffffffff
uint16_t preSerial = (serial >> 32) & 0xffff;
return preSerial == 0x1144;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Hoymiles/src/inverters/HMS_4CH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ HMS_4CH::HMS_4CH(HoymilesRadio* radio, const uint64_t serial)

bool HMS_4CH::isValidSerial(const uint64_t serial)
{
// serial >= 0x116400000000 && serial <= 0x116499999999
// serial >= 0x116400000000 && serial <= 0x1164ffffffff
uint16_t preSerial = (serial >> 32) & 0xffff;
return preSerial == 0x1164;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Hoymiles/src/inverters/HMT_4CH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ HMT_4CH::HMT_4CH(HoymilesRadio* radio, const uint64_t serial)

bool HMT_4CH::isValidSerial(const uint64_t serial)
{
// serial >= 0x136100000000 && serial <= 0x136199999999
// serial >= 0x136100000000 && serial <= 0x1361ffffffff
uint16_t preSerial = (serial >> 32) & 0xffff;
return preSerial == 0x1361;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Hoymiles/src/inverters/HMT_6CH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ HMT_6CH::HMT_6CH(HoymilesRadio* radio, const uint64_t serial)

bool HMT_6CH::isValidSerial(const uint64_t serial)
{
// serial >= 0x138200000000 && serial <= 0x138299999999
// serial >= 0x138200000000 && serial <= 0x1382ffffffff
uint16_t preSerial = (serial >> 32) & 0xffff;
return preSerial == 0x1382;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Hoymiles/src/inverters/HM_1CH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ HM_1CH::HM_1CH(HoymilesRadio* radio, const uint64_t serial)

bool HM_1CH::isValidSerial(const uint64_t serial)
{
// serial >= 0x112100000000 && serial <= 0x112199999999
// serial >= 0x112100000000 && serial <= 0x1121ffffffff

uint8_t preId[2];
preId[0] = (uint8_t)(serial >> 40);
Expand Down
2 changes: 1 addition & 1 deletion lib/Hoymiles/src/inverters/HM_2CH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ HM_2CH::HM_2CH(HoymilesRadio* radio, const uint64_t serial)

bool HM_2CH::isValidSerial(const uint64_t serial)
{
// serial >= 0x114100000000 && serial <= 0x114199999999
// serial >= 0x114100000000 && serial <= 0x1141ffffffff

uint8_t preId[2];
preId[0] = (uint8_t)(serial >> 40);
Expand Down
2 changes: 1 addition & 1 deletion lib/Hoymiles/src/inverters/HM_4CH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ HM_4CH::HM_4CH(HoymilesRadio* radio, const uint64_t serial)

bool HM_4CH::isValidSerial(const uint64_t serial)
{
// serial >= 0x116100000000 && serial <= 0x116199999999
// serial >= 0x116100000000 && serial <= 0x1161ffffffff

uint8_t preId[2];
preId[0] = (uint8_t)(serial >> 40);
Expand Down
2 changes: 2 additions & 0 deletions lib/Hoymiles/src/inverters/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@
| HMS_4CH | HMS-1600/1800/2000-4T | 1164 |
| HMT_4CH | HMT-1600/1800/2000-4T | 1361 |
| HMT_6CH | HMT-1800/2250-6T | 1382 |
| HERF_2CH | HERF 800 | 2821 |
| HERF_4CH | HERF 1800 | 2801 |
5 changes: 3 additions & 2 deletions lib/Hoymiles/src/parser/AlarmLogParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,12 @@ const std::array<const AlarmMessage_t, ALARM_MSG_COUNT> AlarmLogParser::_alarmMe
{ AlarmMessageType_t::ALL, 144, "Grid: Grid overfrequency", "Netz: Netzüberfrequenz", "Réseau: Surfréquence du réseau" },
{ AlarmMessageType_t::ALL, 145, "Grid: Grid underfrequency", "Netz: Netzunterfrequenz", "Réseau: Sous-fréquence du réseau" },
{ AlarmMessageType_t::ALL, 146, "Grid: Rapid grid frequency change rate", "Netz: Schnelle Wechselrate der Netzfrequenz", "Réseau: Taux de fluctuation rapide de la fréquence du réseau" },
{ AlarmMessageType_t::ALL, 147, "Grid: Power grid outage", "Netz: Eletrizitätsnetzausfall", "Réseau: Panne du réseau électrique" },
{ AlarmMessageType_t::ALL, 147, "Grid: Power grid outage", "Netz: Elektrizitätsnetzausfall", "Réseau: Panne du réseau électrique" },
{ AlarmMessageType_t::ALL, 148, "Grid: Grid disconnection", "Netz: Netztrennung", "Réseau: Déconnexion du réseau" },
{ AlarmMessageType_t::ALL, 149, "Grid: Island detected", "Netz: Inselbetrieb festgestellt", "Réseau: Détection d’îlots" },

{ AlarmMessageType_t::ALL, 150, "DCI exceeded", "", "" },
{ AlarmMessageType_t::ALL, 152, "Grid: Phase angle difference between two phases exceeded 5° >10 times", "", "" },
{ AlarmMessageType_t::HMT, 171, "Grid: Abnormal phase difference between phase to phase", "", "" },
{ AlarmMessageType_t::ALL, 181, "Abnormal insulation impedance", "", "" },
{ AlarmMessageType_t::ALL, 182, "Abnormal grounding", "", "" },
Expand Down Expand Up @@ -294,4 +295,4 @@ int AlarmLogParser::getTimezoneOffset()
gmt = mktime(ptm);

return static_cast<int>(difftime(rawtime, gmt));
}
}
4 changes: 2 additions & 2 deletions lib/Hoymiles/src/parser/AlarmLogParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#define ALARM_LOG_ENTRY_SIZE 12
#define ALARM_LOG_PAYLOAD_SIZE (ALARM_LOG_ENTRY_COUNT * ALARM_LOG_ENTRY_SIZE + 4)

#define ALARM_MSG_COUNT 130
#define ALARM_MSG_COUNT 131

struct AlarmLogEntry_t {
uint16_t MessageId;
Expand Down Expand Up @@ -62,4 +62,4 @@ class AlarmLogParser : public Parser {
AlarmMessageType_t _messageType = AlarmMessageType_t::ALL;

static const std::array<const AlarmMessage_t, ALARM_MSG_COUNT> _alarmMessages;
};
};
8 changes: 6 additions & 2 deletions lib/Hoymiles/src/parser/DevInfoParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ const devInfo_t devInfo[] = {
{ { 0x10, 0x32, 0x71, ALL }, 2000, "HMT-2000-4T" }, // 0

{ { 0x10, 0x33, 0x11, ALL }, 1800, "HMT-1800-6T" }, // 01
{ { 0x10, 0x33, 0x31, ALL }, 2250, "HMT-2250-6T" } // 01
{ { 0x10, 0x33, 0x31, ALL }, 2250, "HMT-2250-6T" }, // 01

{ { 0xF1, 0x01, 0x14, ALL }, 800, "HERF-800" }, // 00
{ { 0xF1, 0x01, 0x24, ALL }, 1600, "HERF-1600" }, // 00
{ { 0xF1, 0x01, 0x22, ALL }, 1800, "HERF-1800" }, // 00
};

DevInfoParser::DevInfoParser()
Expand Down Expand Up @@ -200,7 +204,7 @@ bool DevInfoParser::containsValidData() const
struct tm info;
localtime_r(&t, &info);

return info.tm_year > (2016 - 1900);
return info.tm_year > (2016 - 1900) || getHwPartNumber() == 124097;
}

uint8_t DevInfoParser::getDevIdx() const
Expand Down
4 changes: 2 additions & 2 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ build_unflags =
-std=gnu++11

lib_deps =
mathieucarbou/ESP Async WebServer @ 2.7.0
mathieucarbou/ESP Async WebServer @ 2.8.1
bblanchon/ArduinoJson @ ^6.21.5
https://github.com/bertmelis/espMqttClient.git#v1.6.0
nrf24/RF24 @ ^1.4.8
olikraus/U8g2 @ ^2.35.9
olikraus/U8g2 @ ^2.35.14
buelowp/sunset @ ^1.1.7
https://github.com/arkhipenko/TaskScheduler#testing
https://github.com/coryjfowler/MCP_CAN_lib
Expand Down
22 changes: 22 additions & 0 deletions src/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,4 +563,26 @@ INVERTER_CONFIG_T* ConfigurationClass::getInverterConfig(const uint64_t serial)
return nullptr;
}

void ConfigurationClass::deleteInverterById(const uint8_t id)
{
config.Inverter[id].Serial = 0ULL;
strlcpy(config.Inverter[id].Name, "", sizeof(config.Inverter[id].Name));
config.Inverter[id].Order = 0;

config.Inverter[id].Poll_Enable = true;
config.Inverter[id].Poll_Enable_Night = true;
config.Inverter[id].Command_Enable = true;
config.Inverter[id].Command_Enable_Night = true;
config.Inverter[id].ReachableThreshold = REACHABLE_THRESHOLD;
config.Inverter[id].ZeroRuntimeDataIfUnrechable = false;
config.Inverter[id].ZeroYieldDayOnMidnight = false;
config.Inverter[id].YieldDayCorrection = false;

for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
config.Inverter[id].channel[c].MaxChannelPower = 0;
config.Inverter[id].channel[c].YieldTotalOffset = 0.0f;
strlcpy(config.Inverter[id].channel[c].Name, "", sizeof(config.Inverter[id].channel[c].Name));
}
}

ConfigurationClass Configuration;
27 changes: 21 additions & 6 deletions src/Display_Graphic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,19 @@ const uint8_t languages[] = {
};

static const char* const i18n_offline[] = { "Offline", "Offline", "Offline" };

static const char* const i18n_current_power_w[] = { "%.0f W", "%.0f W", "%.0f W" };
static const char* const i18n_current_power_kw[] = { "%.1f kW", "%.1f kW", "%.1f kW" };

static const char* const i18n_meter_power_w[] = { "grid: %.0f W", "Netz: %.0f W", "reseau: %.0f W" };
static const char* const i18n_meter_power_kw[] = { "grid: %.1f kW", "Netz: %.1f kW", "reseau: %.1f kW" };

static const char* const i18n_yield_today_wh[] = { "today: %4.0f Wh", "Heute: %4.0f Wh", "auj.: %4.0f Wh" };
static const char* const i18n_yield_today_kwh[] = { "today: %.1f kWh", "Heute: %.1f kWh", "auj.: %.1f kWh" };

static const char* const i18n_yield_total_kwh[] = { "total: %.1f kWh", "Ges.: %.1f kWh", "total: %.1f kWh" };
static const char* const i18n_yield_total_mwh[] = { "total: %.0f kWh", "Ges.: %.0f kWh", "total: %.0f kWh" };

static const char* const i18n_date_format[] = { "%m/%d/%Y %H:%M", "%d.%m.%Y %H:%M", "%d/%m/%Y %H:%M" };

DisplayGraphicClass::DisplayGraphicClass()
Expand Down Expand Up @@ -133,6 +139,10 @@ void DisplayGraphicClass::printText(const char* text, const uint8_t line)
offset -= (_isLarge ? 5 : 0); // oscillate around center on large screens
dispX += offset;
}

if (dispX > _display->getDisplayWidth()) {
dispX = 0;
}
_display->drawStr(dispX, _lineOffsets[line], text);
}

Expand Down Expand Up @@ -241,15 +251,20 @@ void DisplayGraphicClass::loop()
//<=======================

if (showText) {
//=====> Today & Total Production =======
snprintf(_fmtText, sizeof(_fmtText), i18n_yield_today_wh[_display_language], Datastore.getTotalAcYieldDayEnabled());
// Daily production
float wattsToday = Datastore.getTotalAcYieldDayEnabled();
if (wattsToday >= 10000) {
snprintf(_fmtText, sizeof(_fmtText), i18n_yield_today_kwh[_display_language], wattsToday / 1000);
} else {
snprintf(_fmtText, sizeof(_fmtText), i18n_yield_today_wh[_display_language], wattsToday);
}
printText(_fmtText, 1);

const float watts = Datastore.getTotalAcYieldTotalEnabled();
auto const format = (watts >= 1000) ? i18n_yield_total_mwh : i18n_yield_total_kwh;
snprintf(_fmtText, sizeof(_fmtText), format[_display_language], watts);
// Total production
const float wattsTotal = Datastore.getTotalAcYieldTotalEnabled();
auto const format = (wattsTotal >= 1000) ? i18n_yield_total_mwh : i18n_yield_total_kwh;
snprintf(_fmtText, sizeof(_fmtText), format[_display_language], wattsTotal);
printText(_fmtText, 2);
//<=======================

//=====> IP or Date-Time ========
// Change every 3 seconds
Expand Down
Loading

0 comments on commit cffc5b1

Please sign in to comment.