Conversation
…ion API Co-authored-by: TimSoethout <593132+TimSoethout@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds EV charger (wallbox) entity support to the SEMS Home Assistant integration by extracting evCharge data from the existing power station getData() response and exposing it via new per-charger sensor entities (no additional API calls).
Changes:
- Extend the coordinator data model to include
SemsData.ev_chargerspopulated fromisEvCharge/evCharge. - Add EV charger device info + sensor definitions (status, power, current, charge energy, SOC) driven by the coordinator data.
- Add fixtures and integration-style tests to validate EV charger entity creation and absence when EV data is not present.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
custom_components/sems/__init__.py |
Extracts evCharge from the station payload and stores it in SemsData.ev_chargers. |
custom_components/sems/sensor.py |
Adds EV charger sensor types/entities and status mapping. |
custom_components/sems/device.py |
Adds device_info_for_ev_charger() to group EV charger entities under a device. |
custom_components/sems/const.py |
Documents the EV charger API misspelling for firmware (fireware). |
tests/fixtures.py |
Adds EV charger fixture payload + anonymized charger SN. |
tests/test_sensor_entities.py |
Adds tests asserting EV charger sensors are created (and not created when absent). |
| def native_value(self) -> Any: | ||
| """Return the current value, without string-cleaning for EV charger fields.""" | ||
|
|
||
| value = self._get_native_value_from_coordinator() | ||
|
|
||
| if value is None: | ||
| return None | ||
|
|
||
| if self._empty_value is not None and value == self._empty_value: | ||
| return None | ||
|
|
||
| try: | ||
| return self._data_type_converter(value) | ||
| except (TypeError, ValueError): | ||
| return value |
There was a problem hiding this comment.
SemsEVChargerSensor.native_value bypasses the base class string cleaning for all EV charger sensors. If the SEMS API returns numeric fields like power/current/soc as strings with units (similar to powerflow values like "2337(W)"), those values will no longer be parsed into numbers and may end up as raw strings in sensor state. Consider limiting the bypass to the status sensor only (e.g., a dedicated SemsEVChargerStatusSensor / flag on SemsSensorType), or reusing the base string-cleaning behavior for non-status EV sensors while still preserving non-numeric status strings.
| return DeviceInfo( | ||
| identifiers={(DOMAIN, serial_number)}, | ||
| name=f"EV Charger {name}", | ||
| manufacturer="GoodWe", | ||
| model=ev_charger_data.get("model") or "unknown", | ||
| sw_version=ev_charger_data.get(GOODWE_SPELLING.firmware) or "unknown", | ||
| ) |
There was a problem hiding this comment.
device_info_for_ev_charger() uses identifiers={(DOMAIN, serial_number)}, which is the same identifier scheme used for inverters. If an EV charger SN ever overlaps with an inverter SN, Home Assistant will merge them into a single device in the device registry. Consider namespacing the identifier (e.g., prefixing with ev- or using a distinct identifier tuple) to guarantee uniqueness across device types.
The SEMS power station API already returns
isEvCharge+evChargefields but the integration ignores them. This adds sensor entities for GoodWe EV chargers (wallboxes) using that existing data — no extra API calls required.Data flow
_async_update_data()now readsevChargefrom the power station response (handles both list and dict) and populates a newSemsData.ev_chargers: dict[str, dict]keyed by charger SN, mirroring the existinginverterspattern.New sensors (per charger SN)
{sn}-ev-status{sn}-ev-powerpowerfield{sn}-ev-currentcurrentfield{sn}-ev-charge-energychargeEnergyfield{sn}-ev-socsocfieldKey design notes
SemsEVChargerSensoroverridesnative_valueto skip the base-class string-cleaning regex (which strips non-numeric strings), needed because the status field is a raw API string like"EVDetail_Status_Title_Charging".convert_ev_charger_status()maps these to human-readable labels.GOODWE_SPELLING.firmware = "fireware"added toconst.pyto document the API's misspelling in EV charger responses, consistent with the existing convention.device_info_for_ev_charger()added todevice.pyfollowing the same pattern asdevice_info_for_inverter().When
isEvCharge=FalseorevChargeis null,ev_chargersisNoneand no EV charger entities are created.💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.