Refactor button platform to use indevolt-api 1.4.2#169063
Conversation
There was a problem hiding this comment.
Pull request overview
Refactors the Indevolt button implementation to use the updated indevolt-api (v1.4.2) real-time action methods, aligning button behavior and tests with the new API surface.
Changes:
- Switch button press handling from writing the real-time action key to calling the API’s
stop()real-time action. - Replace coordinator real-time action execution with
charge() / discharge() / stop()calls. - Update Indevolt button tests and test fixtures to match the new API behavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
homeassistant/components/indevolt/coordinator.py |
Replaces old real-time action push logic with IndevoltRealtimeAction and API action methods. |
homeassistant/components/indevolt/button.py |
Updates button press to invoke coordinator real-time STOP action. |
homeassistant/components/indevolt/const.py |
Removes the no-longer-used real-time action write key constant. |
tests/components/indevolt/test_button.py |
Updates tests to assert mode switch + stop() behavior instead of writing action data. |
tests/components/indevolt/conftest.py |
Extends the IndevoltAPI mock with stop/charge/discharge return values. |
Comments suppressed due to low confidence (2)
tests/components/indevolt/test_button.py:122
- Add/restore a test case covering stop() raising a timeout/connection exception (previously covered via set_data TimeOutException) so the new real-time action path’s error mapping stays verified.
# Simulate stop() returning False (e.g. device rejected the command)
mock_indevolt.stop.return_value = False
# Mock call to pause (dis)charging
with pytest.raises(HomeAssistantError):
await hass.services.async_call(
BUTTON_DOMAIN,
SERVICE_PRESS,
{ATTR_ENTITY_ID: ENTITY_ID_GEN2},
blocking=True,
)
homeassistant/components/indevolt/coordinator.py:169
- Wrap the Indevolt API real-time action calls in exception handling (or reuse async_push_data) so TimeOutException/connection errors are translated into a HomeAssistantError with the intended translation key instead of bubbling raw exceptions.
await self.async_switch_energy_mode(REALTIME_ACTION_MODE, refresh=False)
match action_code:
case IndevoltRealtimeAction.CHARGE:
success = await self.api.charge(power, target_soc)
case IndevoltRealtimeAction.DISCHARGE:
success = await self.api.discharge(power, target_soc)
case _:
success = await self.api.stop()
if not success:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="failed_to_execute_realtime_action",
)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
tests/components/indevolt/test_button.py:121
- Add coverage for stop() raising TimeOutException/connection errors (in addition to returning False) once coordinator wraps these into HomeAssistantError, since the previous timeout test was removed and this is user-facing error behavior.
@pytest.mark.parametrize("generation", [2], indirect=True)
async def test_button_press_standby_rejected_command(
hass: HomeAssistant,
mock_indevolt: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test pressing standby raises HomeAssistantError when the device rejects the command."""
with patch("homeassistant.components.indevolt.PLATFORMS", [Platform.BUTTON]):
await setup_integration(hass, mock_config_entry)
# Simulate stop() returning False (device rejected the command)
mock_indevolt.stop.return_value = False
# Mock call to pause (dis)charging
with pytest.raises(HomeAssistantError):
await hass.services.async_call(
BUTTON_DOMAIN,
SERVICE_PRESS,
{ATTR_ENTITY_ID: ENTITY_ID_GEN2},
blocking=True,
)
| ) from err | ||
| match action_code: | ||
| case IndevoltRealtimeAction.STOP: | ||
| success = await self.api.stop() |
There was a problem hiding this comment.
Ensure async_realtime_action always defines success by handling all IndevoltRealtimeAction values (e.g., CHARGE/DISCHARGE) or adding a default case that raises a clear error; otherwise non-STOP actions will crash with an unbound local error.
| success = await self.api.stop() | |
| success = await self.api.stop() | |
| case _: | |
| raise HomeAssistantError( | |
| f"Unsupported real-time action: {action_code}" | |
| ) |
There was a problem hiding this comment.
There is currently only one caller of this function which only uses IndevoltRealtimeAction.STOP - there are thus no uncovered edge cases. Other cases will be added in subsequent PRs in which we can be exhaustive.
abmantis
left a comment
There was a problem hiding this comment.
The new api is looking nice! Thanks for the effort!
Proposed change
Updated the existing integration to utilize the updated Indevolt API library. This prevent having changes to the buttons platform when the PR for actions (#163578) is merged. It is part of a bigger refactoring to move global magic constants into the API library. Changes:
Type of change
Additional information
Checklist
ruff format homeassistant tests)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest.requirements_all.txt.Updated by running
python3 -m script.gen_requirements_all.To help with the load of incoming pull requests: