44 ocpp integration support#67
Conversation
|
just a quick update. |
|
Hi @kljakobsen, I've rewritten the set_current_limit function to set the number of maximum_current instead of using the ocpp service set max current. Could you test this latest commit? |
dirkgroenen
left a comment
There was a problem hiding this comment.
Thanks for helping along @juliusvaart! Unfortunately AI seems to have taken a little spin on the code which I feel made it enter the wrong rabbit hole.
I left some replies I would like to ask you to check to see whether we can make it work. For the set_current_limit implementation I left a suggest implementation in my comment, following the protocol implementation standards.
For the second one related to finding the entitiy by its key I think AI went on a little spin and made some complex changes, while the actual solution was just to change OcppEntityMap to:
class OcppEntityMap:
"""
Map OCPP entities to their respective attributes.
Based on the enums and measurands from the OCPP integration:
https://github.com/lbbrhzn/ocpp/blob/main/custom_components/ocpp/enums.py
"""
# Status entities from HAChargerStatuses
Status = "status"
StatusConnector = "status_connector"
# Current limit via number metric
# https://github.com/lbbrhzn/ocpp/blob/main/custom_components/ocpp/number.py
MaximumCurrent = "maximum_current"
TransactionId = "transaction_id"May I ask you to make these changes and test if it works? I can also push the changes myself to your branch if you prefer, such that you can test them, that's not a problem for me.
| min_current = min(limit.values()) | ||
|
|
||
| # Build the entity_id for the "Maximum current" number entity | ||
| entity_id = f"number.{self._get_ocpp_devid()}_maximum_current" |
There was a problem hiding this comment.
I was looking at the docs reviewing this PR when I stumbled upon this entry:
When the OCPP integration is added to your Home Assistant, you get a slider to control the maximum charge current named (or one per connector, if your charger has multiple connectors): number.<name_ocpp_charger>_maximum_current
While using this entity in your automation might seem logical, it could potentially lead to permanent damage to your charger in the long run. This entity controls the OCPP ChargePointMaxProfile, which configures the maximum power or current available for the entire charging station. This setting is typically written to non-volatile storage (like EEPROM or flash memory) to persist across reboots. Frequent writes to these types of memory can accelerate wear, potentially shortening the lifespan of your charger. Ten updates per day is no problem at all, 1 update per 10s could break your charger somewhere between 3 days and 3 years depending on the HW solution.
I therefore don't recommend going this approach, as we're basically changing the chargers "global max current" setting (which is what get_max_current_limit() should return) and risk breaking chargers.
There was a problem hiding this comment.
I suggest the following, leveraging ChargePointMaxProfile instead of TxProfile to set the entire Charge Points max (ampcontrol.io wrote a nice doc about OCPP)
async def set_current_limit(self, limit: dict[Phase, int]) -> None:
"""
Set the current limit for the charger.
OCPP chargers typically support setting current limits through
the set_charge_rate service or smart charging profiles.
As OCPP may not support per-phase limits, we'll use the minimum value.
"""
min_current = min(limit.values())
transaction_id = self._get_entity_id_by_key(OcppEntityMap.TransactionId)
try:
await self.hass.services.async_call(
domain=CHARGER_DOMAIN_OCPP,
service="set_charge_rate",
service_data={
"custom_profile": {
"transactionId": transaction_id,
"chargingProfileId": 1,
"stackLevel": 0,
"chargingProfilePurpose": "ChargePointMaxProfile",
"chargingProfileKind": "Relative",
"chargingSchedule": {
"chargingRateUnit": "A",
"chargingSchedulePeriod": [
{"startPeriod": 0, "limit": min_current}
]
}
},
"conn_id": 1
},
blocking=True,
)
except (ValueError, RuntimeError, TimeoutError) as e:
_LOGGER.warning(
"Failed to set current limit for OCPP charger %s: %s",
self.device_entry.id,
e,
)
There was a problem hiding this comment.
I'll try this! Totally missed this doc from the OCPP integration...
| def _get_ocpp_devid(self) -> str: | ||
| """Extract OCPP charge point identity (devid) from device identifiers.""" | ||
| for id_domain, ident in self.device_entry.identifiers: | ||
| if id_domain == CHARGER_DOMAIN_OCPP: | ||
| return ident | ||
| return getattr(self.device_entry, "name", None) or self.device_entry.id |
There was a problem hiding this comment.
I see this was used in combination with get_ocpp_device to compose an entity_id, but there's already a _get_entity_id_by_key() method which searches through the entities related to the device and grab the one ending with the provided key (maximum_current) for example.
There was a problem hiding this comment.
Ah ok! This can go. I'm not the best when it comes to RTFM...
| def _get_entity_id_by_key(self, entity_key: str) -> float | None: | ||
| """ | ||
| Get the entity ID for a given key. | ||
| def _get_entity_id_by_key(self, entity_key: str) -> str: |
There was a problem hiding this comment.
I see you rewrote this method, but are not using it in your (latest) changes in the actual OcppCharger class. The AI code also feels a bit like a shot in the dark, and makes me wonder if we're not just declaring the wrong OcppEntityMap for StatusConnector and Status).
Since there's a bunch of char replacement (_ for . eg) I feel like we can probably just fix this by changing the entity map. Unfortunately I don't have an OCPP setup myself, so I can't see how the device exposes the entities.
Can you check in your Developer Tools if entities aren't just exposed as sensor.{device_id}_status_connector for example?
If that's the case we don't need these changes in here, but simply just a change in the OcppEntittyMap.
There was a problem hiding this comment.
The default with one socket is: sensor.charger_status_connector and sensor.charger_status so yes: sensor.{device_id}_status_connector ('charger' is the default).
From the OCPP manual:
Your charger exposes a connector status sensor:
Single-connector: sensor.<charger_id>_status_connector
Multi-connector: sensor.<charger_id>_connector_<connector_number>_status_connector
See: https://home-assistant-ocpp.readthedocs.io/en/latest/user-guide.html#understanding-status
|
I made the changes as suggested but now "EVSE Load Balancer Load balancing state" is not "Monitoring loads" anymore but stays on "Awaiting charger". |
Your car is plugged in and ready to charge? If so what's the state and entitiy_id of |
|
|
I cant find where you committed this test? |
|
Because with the latest code in my fork i get this when calling the device_entities() in dev-tools: |
|
@dirkgroenen I don't really know how to continue testing/improving this PR. |
eb8440f to
ca27bb5
Compare
b30b3e9
into
dirkgroenen:44-ocpp-integration-support
|
@juliusvaart I've merged your branch in its latest state in the other one (#47) we have going on. Just to make things a bit easier and consolidate the different work streams. I'll go through that PR now, make sure specs are working, read through our history again and see where we are with things at the moment. I'll drop you a comment in #47 in a bit. |





I've changed the way ha_device finds the entity names and made fixes to the ocpp charger.