ocpp icon indicating copy to clipboard operation
ocpp copied to clipboard

ABB Terra AC rejects the maximum current setting message due to stackLevel 3

Open leppanenmak opened this issue 7 months ago • 15 comments

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.

leppanenmak avatar Sep 19 '25 12:09 leppanenmak

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.

jthun avatar Sep 19 '25 13:09 jthun

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.

leppanenmak avatar Sep 19 '25 13:09 leppanenmak

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.

jthun avatar Sep 19 '25 14:09 jthun

Try clearing old profiles (the ocpp.clear_profile action). That might help.

jthun avatar Sep 19 '25 14:09 jthun

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"}]

leppanenmak avatar Sep 19 '25 14:09 leppanenmak

It will not make ChargePointMaxProfile work, but it will clear profiles that might have interfered with TxDefaultProfile changing your max current. No improvement there?

jthun avatar Sep 19 '25 14:09 jthun

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?

jthun avatar Sep 19 '25 14:09 jthun

Any progress with this issue?

jthun avatar Sep 23 '25 11:09 jthun

May it is possible that the automation is wrong ? Is the "{{ | int**}}" needed ?

"chargingSchedule": {
  "chargingRateUnit": "A",
  "chargingSchedulePeriod": [
    {"startPeriod": 0, "limit": {{ 8 | int }}}

MatthiasDahlke avatar Oct 03 '25 16:10 MatthiasDahlke

Do you see that in the logs from the integration? Or is it an automation you have made yourself?

jthun avatar Oct 03 '25 16:10 jthun

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}]}}}]

MatthiasDahlke avatar Oct 03 '25 16:10 MatthiasDahlke

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._maximum_current, the integration sends request using maximum stack level 3, which the charger has told. But at least Terra AC does not accept the max value and rejects the ChargePointMaxProfile request (see logs below).

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?

leppanenmak avatar Oct 08 '25 06:10 leppanenmak

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.

koopee avatar Oct 09 '25 08:10 koopee

Hi there, same issue in 0.10.5.

MatthiasDahlke avatar Oct 19 '25 14:10 MatthiasDahlke

Stale issue message

github-actions[bot] avatar Dec 19 '25 06:12 github-actions[bot]