diff --git a/lib/Hoymiles/src/commands/ActivePowerControlCommand.cpp b/lib/Hoymiles/src/commands/ActivePowerControlCommand.cpp index 86da1a8a..a4f59e15 100644 --- a/lib/Hoymiles/src/commands/ActivePowerControlCommand.cpp +++ b/lib/Hoymiles/src/commands/ActivePowerControlCommand.cpp @@ -25,12 +25,17 @@ ID Target Addr Source Addr Cmd SCmd ? Limit Type CRC16 CRC8 #define CRC_SIZE 6 -const uint32_t _powerLimitControlTypeValue[] = { - 0x0000, - 0x0001, - 0x0100, - 0x0101, -}; +const std::array ActivePowerControlCommand::_powerLimitControlTypeValues = { { + { HmActivePowerControl, AbsolutNonPersistent, 0x0000 }, + { HmActivePowerControl, RelativNonPersistent, 0x0001 }, + { HmActivePowerControl, AbsolutPersistent, 0x0100 }, + { HmActivePowerControl, RelativPersistent, 0x0101 }, + + { HmsActivePowerControl, AbsolutNonPersistent, 0x0000 }, + { HmsActivePowerControl, RelativNonPersistent, 0x0001 }, + { HmsActivePowerControl, AbsolutPersistent, 0x0002 }, + { HmsActivePowerControl, RelativPersistent, 0x0003 }, +} }; ActivePowerControlCommand::ActivePowerControlCommand(InverterAbstract* inv, const uint64_t router_address) : DevControlCommand(inv, router_address) @@ -51,8 +56,9 @@ ActivePowerControlCommand::ActivePowerControlCommand(InverterAbstract* inv, cons String ActivePowerControlCommand::getCommandName() const { + const char* typeName = getDeviceType() == ActivePowerControlDeviceType::HmActivePowerControl ? "HM" : "HMS"; char buffer[30]; - snprintf(buffer, sizeof(buffer), "ActivePowerControl (%02X)", getType()); + snprintf(buffer, sizeof(buffer), "ActivePowerControl (%s, %02X)", typeName, getType()); return buffer; } @@ -71,7 +77,7 @@ void ActivePowerControlCommand::setActivePowerLimit(const float limit, const Pow _payload[13] = (l) & 0xff; // type - uint32_t type_value = _powerLimitControlTypeValue[type]; + uint32_t type_value = getControlTypeValue(_deviceType, type); _payload[14] = (type_value >> 8) & 0xff; _payload[15] = (type_value) & 0xff; @@ -112,13 +118,34 @@ PowerLimitControlType ActivePowerControlCommand::getType() const { uint32_t type_val = ((static_cast(_payload[14]) << 8) | _payload[15]); for (uint8_t i = 0; i < PowerLimitControl_Max; i++) { - if (type_val == _powerLimitControlTypeValue[i]) { + if (type_val == getControlTypeValue(_deviceType, static_cast(i))) { return static_cast(i); } } return PowerLimitControlType::RelativNonPersistent; } +void ActivePowerControlCommand::setDeviceType(ActivePowerControlDeviceType type) +{ + _deviceType = type; +} + +ActivePowerControlDeviceType ActivePowerControlCommand::getDeviceType() const +{ + return _deviceType; +} + +uint32_t ActivePowerControlCommand::getControlTypeValue(ActivePowerControlDeviceType deviceType, PowerLimitControlType limitType) +{ + for (auto& val : _powerLimitControlTypeValues) { + if (val.device == deviceType && val.controlType == limitType) { + return val.value; + } + } + + return 0; +} + void ActivePowerControlCommand::gotTimeout() { _inv->SystemConfigPara()->setLastLimitCommandSuccess(CMD_NOK); diff --git a/lib/Hoymiles/src/commands/ActivePowerControlCommand.h b/lib/Hoymiles/src/commands/ActivePowerControlCommand.h index cf60b8d6..523864aa 100644 --- a/lib/Hoymiles/src/commands/ActivePowerControlCommand.h +++ b/lib/Hoymiles/src/commands/ActivePowerControlCommand.h @@ -2,6 +2,7 @@ #pragma once #include "DevControlCommand.h" +#include typedef enum { AbsolutNonPersistent, @@ -11,6 +12,17 @@ typedef enum { PowerLimitControl_Max } PowerLimitControlType; +typedef enum { + HmActivePowerControl, + HmsActivePowerControl, +} ActivePowerControlDeviceType; + +typedef struct { + ActivePowerControlDeviceType device; + PowerLimitControlType controlType; + uint32_t value; +} ActivePowerControlValue_t; + class ActivePowerControlCommand : public DevControlCommand { public: explicit ActivePowerControlCommand(InverterAbstract* inv, const uint64_t router_address = 0); @@ -25,4 +37,13 @@ public: void setActivePowerLimit(const float limit, const PowerLimitControlType type = RelativNonPersistent); float getLimit() const; PowerLimitControlType getType() const; + + void setDeviceType(ActivePowerControlDeviceType type); + ActivePowerControlDeviceType getDeviceType() const; + +private: + static uint32_t getControlTypeValue(ActivePowerControlDeviceType deviceType, PowerLimitControlType limitType); + + ActivePowerControlDeviceType _deviceType = ActivePowerControlDeviceType::HmActivePowerControl; + static const std::array _powerLimitControlTypeValues; }; diff --git a/lib/Hoymiles/src/inverters/HMS_Abstract.cpp b/lib/Hoymiles/src/inverters/HMS_Abstract.cpp index 4fc64b03..ca937da2 100644 --- a/lib/Hoymiles/src/inverters/HMS_Abstract.cpp +++ b/lib/Hoymiles/src/inverters/HMS_Abstract.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2023-2024 Thomas Basler and others + * Copyright (C) 2023-2025 Thomas Basler and others */ #include "HMS_Abstract.h" #include "Hoymiles.h" @@ -25,3 +25,25 @@ bool HMS_Abstract::sendChangeChannelRequest() return true; }; + +bool HMS_Abstract::sendActivePowerControlRequest(float limit, const PowerLimitControlType type) +{ + if (!getEnableCommands()) { + return false; + } + + if (type == PowerLimitControlType::RelativNonPersistent || type == PowerLimitControlType::RelativPersistent) { + limit = min(100, limit); + } + + _activePowerControlLimit = limit; + _activePowerControlType = type; + + auto cmd = _radio->prepareCommand(this); + cmd->setDeviceType(ActivePowerControlDeviceType::HmsActivePowerControl); + cmd->setActivePowerLimit(limit, type); + SystemConfigPara()->setLastLimitCommandSuccess(CMD_PENDING); + _radio->enqueCommand(cmd); + + return true; +} diff --git a/lib/Hoymiles/src/inverters/HMS_Abstract.h b/lib/Hoymiles/src/inverters/HMS_Abstract.h index c4026a53..77f2d103 100644 --- a/lib/Hoymiles/src/inverters/HMS_Abstract.h +++ b/lib/Hoymiles/src/inverters/HMS_Abstract.h @@ -8,4 +8,5 @@ public: explicit HMS_Abstract(HoymilesRadio* radio, const uint64_t serial); virtual bool sendChangeChannelRequest(); -}; \ No newline at end of file + bool sendActivePowerControlRequest(float limit, const PowerLimitControlType type); +}; diff --git a/lib/Hoymiles/src/inverters/HM_Abstract.h b/lib/Hoymiles/src/inverters/HM_Abstract.h index 9f5c4b31..96b720d6 100644 --- a/lib/Hoymiles/src/inverters/HM_Abstract.h +++ b/lib/Hoymiles/src/inverters/HM_Abstract.h @@ -18,10 +18,11 @@ public: bool sendGridOnProFileParaRequest(); bool supportsPowerDistributionLogic() override; -private: - uint8_t _lastAlarmLogCnt = 0; +protected: float _activePowerControlLimit = 0; PowerLimitControlType _activePowerControlType = PowerLimitControlType::AbsolutNonPersistent; +private: + uint8_t _lastAlarmLogCnt = 0; uint8_t _powerState = 1; };