Feature: Allow setting of power limit on new firmware versions for HMS inverters

See #2784
This commit is contained in:
Thomas Basler
2025-08-26 17:03:40 +02:00
parent e4c95ab1e0
commit 9245cb8704
5 changed files with 85 additions and 13 deletions

View File

@@ -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<const ActivePowerControlValue_t, PowerLimitControlType::PowerLimitControl_Max * 2> 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<uint16_t>(_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<PowerLimitControlType>(i))) {
return static_cast<PowerLimitControlType>(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);

View File

@@ -2,6 +2,7 @@
#pragma once
#include "DevControlCommand.h"
#include <array>
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<const ActivePowerControlValue_t, PowerLimitControlType::PowerLimitControl_Max * 2> _powerLimitControlTypeValues;
};

View File

@@ -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<float>(100, limit);
}
_activePowerControlLimit = limit;
_activePowerControlType = type;
auto cmd = _radio->prepareCommand<ActivePowerControlCommand>(this);
cmd->setDeviceType(ActivePowerControlDeviceType::HmsActivePowerControl);
cmd->setActivePowerLimit(limit, type);
SystemConfigPara()->setLastLimitCommandSuccess(CMD_PENDING);
_radio->enqueCommand(cmd);
return true;
}

View File

@@ -8,4 +8,5 @@ public:
explicit HMS_Abstract(HoymilesRadio* radio, const uint64_t serial);
virtual bool sendChangeChannelRequest();
};
bool sendActivePowerControlRequest(float limit, const PowerLimitControlType type);
};

View File

@@ -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;
};