ABB Terra AC rejects the maximum current setting message due to stackLevel 3
Hi all;
I have ABB Terra AC TAC-W11-G5-R0 11 kW charger connected to HA and OCPP integration v. 0.10.3. When I try to adjust the charger's max current via the sensor number.<my_charger>_maximum_current, the charger does not accept the change (verified via the TerraConfig app). For this reason, I can't use the OCPP integration, because I currently have no way to limit the maximum current via the HA.
The log shows that the charger rejects the ChargePointMaxProfile setting message sent by the OCPP integration:
2025-09-18 22:50:07.559 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"9f746209-ed39-4fa4-8b3f-80c3a6734947","GetConfiguration",{"key":["ChargingScheduleAllowedChargingRateUnit"]}] 2025-09-18 22:50:07.580 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "9f746209-ed39-4fa4-8b3f-80c3a6734947", {"configurationKey": [{"key": "ChargingScheduleAllowedChargingRateUnit", "readonly": true, "value": "Current,Power"}], "unknownKey": []}] 2025-09-18 22:50:07.582 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"21be57f5-1b9f-41cb-be5a-8f6c5583894c","GetConfiguration",{"key":["ChargeProfileMaxStackLevel"]}] 2025-09-18 22:50:07.680 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "21be57f5-1b9f-41cb-be5a-8f6c5583894c", {"configurationKey": [{"key": "ChargeProfileMaxStackLevel", "readonly": true, "value": "3"}], "unknownKey": []}] 2025-09-18 22:50:07.682 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"c32fc00b-46a6-404b-a3d1-21ab808828e7","SetChargingProfile",{"connectorId":0,"csChargingProfiles":{"chargingProfileId":1000,"stackLevel":3,"chargingProfileKind":"Relative","chargingProfilePurpose":"ChargePointMaxProfile","chargingSchedule":{"chargingRateUnit":"A","chargingSchedulePeriod":[{"startPeriod":0,"limit":8.0}]}}}] 2025-09-18 22:50:07.819 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "c32fc00b-46a6-404b-a3d1-21ab808828e7", {"status": "Rejected"}] 2025-09-18 22:50:07.823 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"4ee7d787-22c3-457b-87f1-cb953291d892","SetChargingProfile",{"connectorId":1,"csChargingProfiles":{"chargingProfileId":2001,"stackLevel":2,"chargingProfileKind":"Relative","chargingProfilePurpose":"TxDefaultProfile","chargingSchedule":{"chargingRateUnit":"A","chargingSchedulePeriod":[{"startPeriod":0,"limit":8.0}]}}}] 2025-09-18 22:50:07.918 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "4ee7d787-22c3-457b-87f1-cb953291d892", {"status": "Accepted"}]
However, the charger accepts the TxDefaultProfile setting message sent right after the rejected message. The relevant difference between them is the stackLevel parameter. The charger does not accept stackLevel parameter with value 3.
When I manually send corresponding ChargePointMaxProfile message with stackLevel 2, the charger accepts it according to log:
2025-09-18 22:54:24.244 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"32ec0779-c885-4530-96d5-0d27925a22f9","SetChargingProfile",{"connectorId":0,"csChargingProfiles":{"chargingProfileId":10 00,"stackLevel":2,"chargingProfileKind":"Relative","chargingProfilePurpose":"ChargePointMaxProfile","chargingSchedule":{"chargingRateUnit":"A","chargingSchedulePeriod":[{"startPeriod":0,"limit":9} ]}}}] 2025-09-18 22:54:24.246 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "32ec0779-c885-4530-96d5-0d27925a22f9", {"status": "Accepted"}]
Before adjusting the maximum level, the integration queries the station for the maximum stackLevel value using the ChargeProfileMaxStackLevel message and it receives a response of 3. However, the value 3 is not accepted in the setting message, so could this be an off-by-one issue, and the valid range is actually 0–2, at least for this ABB charger?
To Reproduce Adjust the maximum current by changing value of the sensor number.<my_charger>_maximum_current.
Expected behavior The charger accepts the OCPP message and stores the new value to its volatile memory and it limits the current during charging according it.
As you say, the integration queries the charger for the ChargeProfileMaxStackLevel and then uses that.
If your charger rejects that stack level, I would recommend that you use the ocpp.set_charge_rate action with a custom profile, as described in the Charge Automation section in the docs.
Thanks for prompt answer. I have used the OCPP integration successfully for years up to version 0.8 and all my logic is currently based on adjusting that sensor.
I can consider that workaround, but I'd still prefer to get the integration working like in previous versions.
Since the TxDefaultProfile sent after the ChargePointMaxProfile is accepted, that will be the max current of any future charging session. Or is that not the case with your charger? And if you have an ongoing charging session, a TxProfile will be sent before TxDefaultProfile to adjust the max current for that session.
Try clearing old profiles (the ocpp.clear_profile action). That might help.
Unfortunately clear_profile has no effect:
2025-09-19 16:02:56.191 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"083bec81-0356-456f-96e0-11927931c4e0","ClearChargingProfile",{}] 2025-09-19 16:02:56.193 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "083bec81-0356-456f-96e0-11927931c4e0", {"status": "Accepted"}] 2025-09-19 16:03:15.242 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"15ad9048-baa0-43ff-8b05-ff63feedb5ad","GetConfiguration",{"key":["ChargingScheduleAllowedChargingRateUnit"]}] 2025-09-19 16:03:15.252 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "15ad9048-baa0-43ff-8b05-ff63feedb5ad", {"configurationKey": [{"key": "ChargingScheduleAllowedChargingRateUni t", "readonly": true, "value": "Current,Power"}], "unknownKey": []}] 2025-09-19 16:03:15.253 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"9531cccc-289f-4c4b-b74b-6632c732b0e6","GetConfiguration",{"key":["ChargeProfileMaxStackLevel"]}] 2025-09-19 16:03:15.351 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "9531cccc-289f-4c4b-b74b-6632c732b0e6", {"configurationKey": [{"key": "ChargeProfileMaxStackLevel", "readonly ": true, "value": "3"}], "unknownKey": []}] 2025-09-19 16:03:15.353 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"ad353781-7b43-4d3c-9e46-44ffb5c0cc67","SetChargingProfile",{"connectorId":0,"csChargingProfiles":{"chargingProfileId":10 00,"stackLevel":3,"chargingProfileKind":"Relative","chargingProfilePurpose":"ChargePointMaxProfile","chargingSchedule":{"chargingRateUnit":"A","chargingSchedulePeriod":[{"startPeriod":0,"limit":9. 0}]}}}] 2025-09-19 16:03:15.489 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "ad353781-7b43-4d3c-9e46-44ffb5c0cc67", {"status": "Rejected"}]
It will not make ChargePointMaxProfile work, but it will clear profiles that might have interfered with TxDefaultProfile changing your max current. No improvement there?
I've looked at the older code, and this has not changed for a very long time. ChargePointMaxProfile has been sent with a stack level of ChargeProfileMaxStackLevel in for example 0.8.
What does a debug log for a "working" integration version for you look like?
Any progress with this issue?
May it is possible that the automation is wrong ? Is the "{{ | int**}}" needed ?
"chargingSchedule": {
"chargingRateUnit": "A",
"chargingSchedulePeriod": [
{"startPeriod": 0, "limit": {{ 8 | int }}}
Do you see that in the logs from the integration? Or is it an automation you have made yourself?
The code snippet is from the documentation https://github.com/lbbrhzn/ocpp/wiki/Charge_automation at the point TXProfile. I only insert the limit {{ 8 | int }}}
The Logs here from leppanenmak shown this:
- A","chargingSchedulePeriod":[{"startPeriod":0,"limit":8.0}]}}}]
- A","chargingSchedulePeriod":[{"startPeriod":0,"limit":9}
- "A","chargingSchedulePeriod":[{"startPeriod":0,"limit":9.0}]}}}]
I can no longer test the older version of the integration, because I've already modified my own logic to adjust current mainly by TxProfile. I use now the latest version 0.10.4.
If I manually adjust sensor number.
As a result of the rejection, the integration tries next to change TxProfile and TxDefaultProfile to one step lower stack_level value 2, and those requests are accepted. This logic is not what I intended — I would prefer the ChargePointMaxProfile request to succeed and that's all.
2025-10-07 23:02:41.949 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"1a950898-cdac-430b-9715-bbeb8bd85905","GetConfiguration",{"key":["ChargingScheduleAllowedChargingRateUnit"]}] 2025-10-07 23:02:41.951 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "1a950898-cdac-430b-9715-bbeb8bd85905", {"configurationKey": [{"key": "ChargingScheduleAllowedChargingRateUnit", "readonly": true, "value": "Current,Power"}], "unknownKey": []}] 2025-10-07 23:02:41.953 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"b27fa6e4-f00a-40c5-ae54-fe1a3ddeb531","GetConfiguration",{"key":["ChargeProfileMaxStackLevel"]}] 2025-10-07 23:02:42.069 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "b27fa6e4-f00a-40c5-ae54-fe1a3ddeb531", {"configurationKey": [{"key": "ChargeProfileMaxStackLevel", "readonly": true, "value": "3"}], "unknownKey": []}] 2025-10-07 23:02:42.071 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"f8d5dc3e-c1a3-4d71-b9a5-230bfc8884ad","SetChargingProfile",{"connectorId":0,"csChargingProfiles":{"chargingProfileId":1000,"stackLevel":3,"chargingProfileKind":"Relative","chargingProfilePurpose":"ChargePointMaxProfile","chargingSchedule":{"chargingRateUnit":"A","chargingSchedulePeriod":[{"startPeriod":0,"limit":10.0}]}}}] 2025-10-07 23:02:42.169 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "f8d5dc3e-c1a3-4d71-b9a5-230bfc8884ad", {"status": "Rejected"}] 2025-10-07 23:02:42.170 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"08aea718-d995-4356-aa78-4f681690a9fd","SetChargingProfile",{"connectorId":1,"csChargingProfiles":{"chargingProfileId":3001,"stackLevel":3,"chargingProfileKind":"Relative","chargingProfilePurpose":"TxProfile","chargingSchedule":{"chargingRateUnit":"A","chargingSchedulePeriod":[{"startPeriod":0,"limit":10.0}]},"transactionId":1759863912}}] 2025-10-07 23:02:42.307 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "08aea718-d995-4356-aa78-4f681690a9fd", {"status": "Rejected"}] 2025-10-07 23:02:42.309 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"e61f1080-47e8-4e06-8cb4-cf1fcfcd6f97","SetChargingProfile",{"connectorId":1,"csChargingProfiles":{"chargingProfileId":2001,"stackLevel":2,"chargingProfileKind":"Relative","chargingProfilePurpose":"TxDefaultProfile","chargingSchedule":{"chargingRateUnit":"A","chargingSchedulePeriod":[{"startPeriod":0,"limit":10.0}]}}}] 2025-10-07 23:02:42.407 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "e61f1080-47e8-4e06-8cb4-cf1fcfcd6f97", {"status": "Accepted"}]
I modified the integration code in file ocppv16.py as follows:
req = call.SetChargingProfile(
connector_id=0,
cs_charging_profiles={
om.charging_profile_id.value: _profile_id(
ChargingProfilePurposeType.charge_point_max_profile.value, 0
),
_# Decreased stack_level by one below_
om.stack_level.value: **max(1, stack_level - 1),**
om.charging_profile_kind.value: ChargingProfileKindType.relative.value,
om.charging_profile_purpose.value: ChargingProfilePurposeType.charge_point_max_profile.value,
om.charging_schedule.value: _mk_schedule(units_value, limit_value),
},
)
After that the SetChargingProfile request is accepted by Terra and the integration does not try to modify other profile values. Similarly, the stack_level of other requests needs to be lowered so that SetChargingProfile always uses the highest value allowed by the charger
2025-10-07 23:06:51.660 INFO (MainThread) [ocpp] TACW1142521G1487: send [2,"5dafdbab-102f-4796-882c-0cd17d622618","SetChargingProfile",{"connectorId":0,"csChargingProfiles":{"chargingProfileId":1000,"stackLevel":2,"chargingProfileKind":"Relative","chargingProfilePurpose":"ChargePointMaxProfile","chargingSchedule":{"chargingRateUnit":"A","chargingSchedulePeriod":[{"startPeriod":0,"limit":10}]}}}] 2025-10-07 23:06:51.663 INFO (MainThread) [ocpp] TACW1142521G1487: receive message [3, "5dafdbab-102f-4796-882c-0cd17d622618", {"status": "Accepted"}]
This is how I expect the integration should work. Does this off-by-one problem only occur with ABB Terra AC chargers?
Noticed this while wondering whether to upgrade ocpp (currently running 0.10.2) using same type of Terra AC charger. Maybe postponing the upgrade, because I also use the max current slider to control charging power.
I could help debugging and take some logs using this older SW if needed.
Hi there, same issue in 0.10.5.
Stale issue message