mirror of
https://github.com/tbnobody/OpenDTU.git
synced 2025-12-10 16:59:52 +01:00
Feature: Allow setting of power limit on new firmware versions for HMS inverters
See #2784
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -8,4 +8,5 @@ public:
|
||||
explicit HMS_Abstract(HoymilesRadio* radio, const uint64_t serial);
|
||||
|
||||
virtual bool sendChangeChannelRequest();
|
||||
};
|
||||
bool sendActivePowerControlRequest(float limit, const PowerLimitControlType type);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user