v0.8.0 - support sub-entries and many QOL improvements#225
Conversation
|
Migrations from 0.7.6 -> 0.8.0 have been confirmed working. w/ multiple tests |
…t for next poll to update it)
There was a problem hiding this comment.
Pull request overview
This PR bumps the AlphaESS Home Assistant integration to v0.8.0, introducing a v2 config entry model that uses sub-entries per inverter (and EV charger), plus new controllable entities and improved local-data fallback behavior.
Changes:
- Add config entry v2 with inverter sub-entries, inverter bind/reconfigure flows, and EV-charger sub-entry auto-creation/migration support.
- Add new platforms/entities: grid charge & discharge control switches, charge/discharge time slot time entities, and new “Today’s Generation/Income” sensors.
- Add per-inverter local IP mapping and independent local fallback fetch when the cloud API is unavailable; bump minimum Home Assistant version to 2026.1.0.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 17 comments.
Show a summary per file
| File | Description |
|---|---|
| hacs.json | Declares HA minimum version requirement (2026.1.0). |
| custom_components/alphaess/manifest.json | Bumps integration version to 0.8.0. |
| custom_components/alphaess/const.py | Adds subentry types/keys and registers new platforms (switch/time). |
| custom_components/alphaess/config_flow.py | Implements v2 config flow + inverter subentry flow (bind/reconfigure/unbind). |
| custom_components/alphaess/init.py | Builds coordinator using subentries, handles v1→v2 migration, and cleans up devices/entities. |
| custom_components/alphaess/coordinator.py | Adds per-inverter IP handling, local fallback improvements, and new summary fields. |
| custom_components/alphaess/sensor.py | Refactors sensor setup to be subentry-based and adds device-info builders. |
| custom_components/alphaess/sensorlist.py | Adds new sensor/switch/time/number descriptions (today stats, EV current, switches, time slots). |
| custom_components/alphaess/number.py | Adds EV charger current number + pushes inverter cap changes to the API on change. |
| custom_components/alphaess/button.py | Refactors button setup for subentries and adds per-subentry notification preference. |
| custom_components/alphaess/switch.py | New switch platform for gridCharge/ctrDis toggles. |
| custom_components/alphaess/time.py | New time platform for charge/discharge slot start/end times. |
| custom_components/alphaess/enums.py | Adds enum keys for new entities (times, today stats, switches). |
| custom_components/alphaess/entity.py | Adds Switch/Time entity description dataclasses. |
| custom_components/alphaess/strings.json | Adds/updates UI strings for subentries and new entities. |
| custom_components/alphaess/translations/en.json | Updates EN translations for subentries and removed global IP option. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 12 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if user_input: | ||
|
|
||
| try: | ||
| await validate_input(self.hass, user_input) | ||
|
|
||
| result = await validate_input(self.hass, user_input) | ||
| except CannotConnect: | ||
| errors["base"] = "cannot_connect" |
There was a problem hiding this comment.
Config flow doesn’t set a unique_id / abort if the same account is already configured. This can create duplicate config entries for the same AppID and duplicate polling/entities. Consider async_set_unique_id(AppID) + async_abort_if_unique_id_configured() (or another stable identifier).
| f"Reset Charge and Discharge configuration - " | ||
| f"Charge: {results['charge']}, Discharge: {results['discharge']}" | ||
| ) | ||
| # Optimistically update so switches reflect the change immediately | ||
| if serial in self.data: |
There was a problem hiding this comment.
reset_config() reads bat_use_cap / bat_high_cap using AlphaESSNames.batUseCap / AlphaESSNames.batHighCap as dict keys (a few lines above). Those enum values are human-readable strings and won’t match the values saved by the number entities (which use keys like "batUseCap"/"batHighCap"), so reset may always fall back to defaults. Use the same keying scheme as update_charge/update_discharge (or read from self.data).
| async def async_set_native_value(self, value: float) -> None: | ||
| self._attr_native_value = value | ||
| await self.save_value(value) | ||
| self.async_write_ha_state() | ||
|
|
There was a problem hiding this comment.
async_set_native_value() persists and publishes the new number value before performing the API write. If the API call fails, HA will show/restore a value that never applied. Only persist/update state after a successful API call, or revert on exception.
| if self.key is AlphaESSNames.batHighCap: | ||
| grid_charge = data.get("gridCharge", 1) | ||
| result = await self._coordinator.api.updateChargeConfigInfo( | ||
| self._serial, | ||
| value, |
There was a problem hiding this comment.
The new API push in async_set_native_value() isn’t wrapped in try/except. If updateChargeConfigInfo/updateDisChargeConfigInfo raises, the exception will propagate and the entity will stay at the optimistic value. Handle exceptions and revert/log appropriately.
| ): bool, | ||
| } | ||
|
|
||
| return self.async_show_form(step_id="init", data_schema=vol.Schema(schema), errors=errors) | ||
| return self.async_show_form(step_id="init", data_schema=vol.Schema(schema)) |
There was a problem hiding this comment.
Options flow still includes the "Disable Notifications On Charge/Discharge Confirmation" option in the schema, but the UI translations were removed and the runtime behavior now appears to be per-inverter (CONF_DISABLE_NOTIFICATIONS). Either remove this option here or wire it up to update all inverter subentries and restore its translation.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
CharlesGillanders
left a comment
There was a problem hiding this comment.
That's an enormous amount of work. I'm in awe. Thanks for flagging the breaking changes. That's going to be important that it's clearly called out.
Breaking Changes
entries are auto-migrated
assignments) are reset during migration
New Features:
epvtoday and todayIncome from getSumDataForCustomer
immediately push to API on change instead of only
saving locally
platform with toggles for gridCharge and ctrDis,
preserves all existing config when toggling
now a separate subentry under the main integration
entry
controllable number entity (6-32A), calls setEvChargerCurrentsBySn API
with their own IP address
with parent inverter association
own local IP address configured
the API during setup; EV chargers are auto-discovered
on first data fetch
unavailable, each inverter with a configured IP gets
its own local data independently
Migration (v1 → v2)
and assigned to the first inverter's subentry
migration to avoid "devices that don't belong to a
sub-entry" duplicates
continue to work