1
0
mirror of https://github.com/home-assistant/core.git synced 2026-07-11 16:47:52 +01:00

Refactor button platform to use indevolt-api 1.4.2 (#169063)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
A. Gideonse
2026-04-24 20:11:01 +02:00
committed by GitHub
parent 446d89aee2
commit ca70abe240
5 changed files with 27 additions and 32 deletions
+3 -2
View File
@@ -5,6 +5,8 @@ from __future__ import annotations
from dataclasses import dataclass, field
from typing import Final
from indevolt_api import IndevoltRealtimeAction
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -66,5 +68,4 @@ class IndevoltButtonEntity(IndevoltEntity, ButtonEntity):
async def async_press(self) -> None:
"""Handle the button press."""
await self.coordinator.async_execute_realtime_action([0, 0, 0])
await self.coordinator.async_realtime_action(IndevoltRealtimeAction.STOP)
+1 -2
View File
@@ -16,8 +16,7 @@ ENERGY_MODE_READ_KEY: Final = "7101"
ENERGY_MODE_WRITE_KEY: Final = "47005"
PORTABLE_MODE: Final = 0
# API write key and value for real-time control mode
REALTIME_ACTION_KEY: Final = "47015"
# Value for real-time control mode
REALTIME_ACTION_MODE: Final = 4
# API key fields
@@ -7,7 +7,7 @@ import logging
from typing import Any, Final
from aiohttp import ClientError
from indevolt_api import IndevoltAPI, TimeOutException
from indevolt_api import IndevoltAPI, IndevoltRealtimeAction, TimeOutException
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_MODEL
@@ -24,7 +24,6 @@ from .const import (
ENERGY_MODE_READ_KEY,
ENERGY_MODE_WRITE_KEY,
PORTABLE_MODE,
REALTIME_ACTION_KEY,
REALTIME_ACTION_MODE,
SENSOR_KEYS,
)
@@ -146,19 +145,16 @@ class IndevoltCoordinator(DataUpdateCoordinator[dict[str, Any]]):
if refresh:
await self.async_request_refresh()
async def async_execute_realtime_action(self, action: list[int]) -> None:
async def async_realtime_action(
self,
action_code: IndevoltRealtimeAction,
) -> None:
"""Switch mode, execute action, and refresh for real-time control."""
await self.async_switch_energy_mode(REALTIME_ACTION_MODE, refresh=False)
try:
success = await self.async_push_data(REALTIME_ACTION_KEY, action)
except (DeviceTimeoutError, DeviceConnectionError) as err:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="failed_to_execute_realtime_action",
) from err
match action_code:
case IndevoltRealtimeAction.STOP:
success = await self.api.stop()
if not success:
raise HomeAssistantError(
+3
View File
@@ -87,6 +87,9 @@ def mock_indevolt(generation: int) -> Generator[AsyncMock]:
client = mock_client.return_value
client.fetch_data.return_value = fixture_data
client.set_data.return_value = True
client.stop.return_value = True
client.charge.return_value = True
client.discharge.return_value = True
client.get_config.return_value = {
"device": {
"sn": device_info["sn"],
+12 -16
View File
@@ -1,8 +1,7 @@
"""Tests for the Indevolt button platform."""
from unittest.mock import AsyncMock, call, patch
from unittest.mock import AsyncMock, patch
from indevolt_api import TimeOutException
import pytest
from syrupy.assertion import SnapshotAssertion
@@ -11,7 +10,6 @@ from homeassistant.components.indevolt.const import (
ENERGY_MODE_READ_KEY,
ENERGY_MODE_WRITE_KEY,
PORTABLE_MODE,
REALTIME_ACTION_KEY,
REALTIME_ACTION_MODE,
)
from homeassistant.const import ATTR_ENTITY_ID, Platform
@@ -64,14 +62,11 @@ async def test_button_press_standby(
blocking=True,
)
# Verify set_data was called twice with correct parameters
assert mock_indevolt.set_data.call_count == 2
mock_indevolt.set_data.assert_has_calls(
[
call(ENERGY_MODE_WRITE_KEY, REALTIME_ACTION_MODE),
call(REALTIME_ACTION_KEY, [0, 0, 0]),
]
# Verify set_data was called for mode switch and stop() was called
mock_indevolt.set_data.assert_called_once_with(
ENERGY_MODE_WRITE_KEY, REALTIME_ACTION_MODE
)
mock_indevolt.stop.assert_called_once()
@pytest.mark.parametrize("generation", [2], indirect=True)
@@ -98,22 +93,23 @@ async def test_button_press_standby_already_in_realtime_mode(
blocking=True,
)
# Verify set_data was called once with correct parameters
mock_indevolt.set_data.assert_called_once_with(REALTIME_ACTION_KEY, [0, 0, 0])
# Verify stop() was called and no mode switch was needed
mock_indevolt.set_data.assert_not_called()
mock_indevolt.stop.assert_called_once()
@pytest.mark.parametrize("generation", [2], indirect=True)
async def test_button_press_standby_timeout_error(
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 times out."""
"""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 an API push failure
mock_indevolt.set_data.side_effect = TimeOutException("Timed out")
# Simulate stop() returning False (device rejected the command)
mock_indevolt.stop.return_value = False
# Mock call to pause (dis)charging
with pytest.raises(HomeAssistantError):