BREAKING CHANGE: WebAPI endpoint /api/limit/config requires different parameters

Due to the fact that different inverters require different type identifiers in the backend the `limit_type` parameter was changed to numbers from 0 to 3.
* AbsolutNonPersistent = 0
* RelativNonPersistent = 1
* AbsolutPersistent = 2
* RelativPersistent = 3
This commit is contained in:
Thomas Basler
2025-08-07 20:44:45 +02:00
parent 32ef10e082
commit 8cab3335f3
5 changed files with 54 additions and 23 deletions

View File

@@ -25,6 +25,13 @@ ID Target Addr Source Addr Cmd SCmd ? Limit Type CRC16 CRC8
#define CRC_SIZE 6
const uint32_t _powerLimitControlTypeValue[] = {
0x0000,
0x0001,
0x0100,
0x0101,
};
ActivePowerControlCommand::ActivePowerControlCommand(InverterAbstract* inv, const uint64_t router_address)
: DevControlCommand(inv, router_address)
{
@@ -64,8 +71,9 @@ void ActivePowerControlCommand::setActivePowerLimit(const float limit, const Pow
_payload[13] = (l) & 0xff;
// type
_payload[14] = (type >> 8) & 0xff;
_payload[15] = (type) & 0xff;
uint32_t type_value = _powerLimitControlTypeValue[type];
_payload[14] = (type_value >> 8) & 0xff;
_payload[15] = (type_value) & 0xff;
udpateCRC(CRC_SIZE);
}
@@ -102,7 +110,13 @@ float ActivePowerControlCommand::getLimit() const
PowerLimitControlType ActivePowerControlCommand::getType() const
{
return (PowerLimitControlType)((static_cast<uint16_t>(_payload[14]) << 8) | _payload[15]);
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]) {
return static_cast<PowerLimitControlType>(i);
}
}
return PowerLimitControlType::RelativNonPersistent;
}
void ActivePowerControlCommand::gotTimeout()

View File

@@ -4,10 +4,11 @@
#include "DevControlCommand.h"
typedef enum { // ToDo: to be verified by field tests
AbsolutNonPersistent = 0x0000, // 0
RelativNonPersistent = 0x0001, // 1
AbsolutPersistent = 0x0100, // 256
RelativPersistent = 0x0101 // 257
AbsolutNonPersistent,
RelativNonPersistent,
AbsolutPersistent,
RelativPersistent,
PowerLimitControl_Max
} PowerLimitControlType;
class ActivePowerControlCommand : public DevControlCommand {

View File

@@ -91,11 +91,7 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
return;
}
if (!((root["limit_type"].as<uint16_t>() == PowerLimitControlType::AbsolutNonPersistent)
|| (root["limit_type"].as<uint16_t>() == PowerLimitControlType::AbsolutPersistent)
|| (root["limit_type"].as<uint16_t>() == PowerLimitControlType::RelativNonPersistent)
|| (root["limit_type"].as<uint16_t>() == PowerLimitControlType::RelativPersistent))) {
if (!(root["limit_type"].as<uint16_t>() < PowerLimitControlType::PowerLimitControl_Max)) {
retMsg["message"] = "Invalid type specified!";
retMsg["code"] = WebApiError::LimitInvalidType;
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);

View File

@@ -1,5 +1,13 @@
export enum LimitType {
AbsolutNonPersistent,
RelativNonPersistent,
AbsolutPersistent,
RelativPersistent,
PowerLimitControl_Max,
}
export interface LimitConfig {
serial: string;
limit_value: number;
limit_type: number;
limit_type: LimitType;
}

View File

@@ -434,15 +434,15 @@
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li>
<a class="dropdown-item" @click="onSelectType(1)" href="#">{{ $t('home.Relative') }}</a>
<a class="dropdown-item" @click="onSelectType(true)" href="#">{{ $t('home.Relative') }}</a>
</li>
<li>
<a class="dropdown-item" @click="onSelectType(0)" href="#">{{ $t('home.Absolute') }}</a>
<a class="dropdown-item" @click="onSelectType(false)" href="#">{{ $t('home.Absolute') }}</a>
</li>
</ul>
</div>
<div
v-if="targetLimitType == 0"
v-if="!targetLimitRelative"
class="alert alert-secondary mt-3"
role="alert"
v-html="$t('home.LimitHint')"
@@ -507,6 +507,7 @@ import GridProfile from '@/components/GridProfile.vue';
import HintView from '@/components/HintView.vue';
import InverterChannelInfo from '@/components/InverterChannelInfo.vue';
import InverterTotalInfo from '@/components/InverterTotalInfo.vue';
import { LimitType } from '@/types/LimitConfig';
import ModalDialog from '@/components/ModalDialog.vue';
import type { DevInfoStatus } from '@/types/DevInfoStatus';
import type { EventlogItems } from '@/types/EventlogStatus';
@@ -584,7 +585,7 @@ export default defineComponent({
targetLimitMin: 0,
targetLimitMax: 100,
targetLimitTypeText: this.$t('home.Relative'),
targetLimitType: 1,
targetLimitRelative: true,
alertMessageLimit: '',
alertTypeLimit: 'info',
@@ -823,8 +824,7 @@ export default defineComponent({
this.showAlertLimit = false;
this.targetLimitList.serial = '';
this.targetLimitList.limit_value = 0;
this.targetLimitType = 1;
this.targetLimitTypeText = this.$t('home.Relative');
this.onSelectType(true);
this.limitSettingLoading = true;
fetch('/api/limit/status', { headers: authHeader() })
@@ -846,7 +846,19 @@ export default defineComponent({
});
},
onSetLimitSettings(setPersistent: boolean) {
this.targetLimitList.limit_type = (setPersistent ? 256 : 0) + this.targetLimitType;
if (setPersistent) {
if (this.targetLimitRelative) {
this.targetLimitList.limit_type = LimitType.RelativPersistent;
} else {
this.targetLimitList.limit_type = LimitType.AbsolutPersistent;
}
} else {
if (this.targetLimitRelative) {
this.targetLimitList.limit_type = LimitType.RelativNonPersistent;
} else {
this.targetLimitList.limit_type = LimitType.AbsolutNonPersistent;
}
}
const formData = new FormData();
formData.append('data', JSON.stringify(this.targetLimitList));
@@ -868,8 +880,8 @@ export default defineComponent({
}
});
},
onSelectType(type: number) {
if (type == 1) {
onSelectType(isRelative: boolean) {
if (isRelative) {
this.targetLimitTypeText = this.$t('home.Relative');
this.targetLimitMin = 0;
this.targetLimitMax = 100;
@@ -878,7 +890,7 @@ export default defineComponent({
this.targetLimitMin = 0;
this.targetLimitMax = this.currentLimitList.max_power > 0 ? this.currentLimitList.max_power : 2250;
}
this.targetLimitType = type;
this.targetLimitRelative = isRelative;
},
onShowPowerSettings(serial: string) {