From c24579bfb2e27dca837c86f35ed30ca68e8a2762 Mon Sep 17 00:00:00 2001 From: YogevBokobza Date: Mon, 28 Oct 2024 17:57:24 +0200 Subject: [PATCH] Add switcher s12 support (#127277) Co-authored-by: Joostlek Co-authored-by: Shay Levy --- .../components/switcher_kis/cover.py | 67 +++++++++--- .../components/switcher_kis/light.py | 74 +++++++++---- .../components/switcher_kis/strings.json | 5 + tests/components/switcher_kis/consts.py | 24 +++++ .../switcher_kis/test_config_flow.py | 3 + tests/components/switcher_kis/test_cover.py | 101 ++++++++++++++---- tests/components/switcher_kis/test_light.py | 30 +++--- 7 files changed, 233 insertions(+), 71 deletions(-) diff --git a/homeassistant/components/switcher_kis/cover.py b/homeassistant/components/switcher_kis/cover.py index 6f71a27c72a..c56fa7442fb 100644 --- a/homeassistant/components/switcher_kis/cover.py +++ b/homeassistant/components/switcher_kis/cover.py @@ -40,21 +40,27 @@ async def async_setup_entry( @callback def async_add_cover(coordinator: SwitcherDataUpdateCoordinator) -> None: """Add cover from Switcher device.""" + entities: list[CoverEntity] = [] if coordinator.data.device_type.category in ( DeviceCategory.SHUTTER, DeviceCategory.SINGLE_SHUTTER_DUAL_LIGHT, ): - async_add_entities([SwitcherCoverEntity(coordinator, 0)]) + entities.append(SwitcherSingleCoverEntity(coordinator, 0)) + if ( + coordinator.data.device_type.category + == DeviceCategory.DUAL_SHUTTER_SINGLE_LIGHT + ): + entities.extend(SwitcherDualCoverEntity(coordinator, i) for i in range(2)) + async_add_entities(entities) config_entry.async_on_unload( async_dispatcher_connect(hass, SIGNAL_DEVICE_ADD, async_add_cover) ) -class SwitcherCoverEntity(SwitcherEntity, CoverEntity): +class SwitcherBaseCoverEntity(SwitcherEntity, CoverEntity): """Representation of a Switcher cover entity.""" - _attr_name = None _attr_device_class = CoverDeviceClass.SHUTTER _attr_supported_features = ( CoverEntityFeature.OPEN @@ -62,19 +68,7 @@ class SwitcherCoverEntity(SwitcherEntity, CoverEntity): | CoverEntityFeature.SET_POSITION | CoverEntityFeature.STOP ) - - def __init__( - self, - coordinator: SwitcherDataUpdateCoordinator, - cover_id: int, - ) -> None: - """Initialize the entity.""" - super().__init__(coordinator) - self._cover_id = cover_id - - self._attr_unique_id = f"{coordinator.device_id}-{coordinator.mac_address}" - - self._update_data() + _cover_id: int @callback def _handle_coordinator_update(self) -> None: @@ -137,3 +131,44 @@ class SwitcherCoverEntity(SwitcherEntity, CoverEntity): async def async_stop_cover(self, **kwargs: Any) -> None: """Stop the cover.""" await self._async_call_api(API_STOP, self._cover_id) + + +class SwitcherSingleCoverEntity(SwitcherBaseCoverEntity): + """Representation of a Switcher single cover entity.""" + + _attr_name = None + + def __init__( + self, + coordinator: SwitcherDataUpdateCoordinator, + cover_id: int, + ) -> None: + """Initialize the entity.""" + super().__init__(coordinator) + self._cover_id = cover_id + + self._attr_unique_id = f"{coordinator.device_id}-{coordinator.mac_address}" + + self._update_data() + + +class SwitcherDualCoverEntity(SwitcherBaseCoverEntity): + """Representation of a Switcher dual cover entity.""" + + _attr_translation_key = "cover" + + def __init__( + self, + coordinator: SwitcherDataUpdateCoordinator, + cover_id: int, + ) -> None: + """Initialize the entity.""" + super().__init__(coordinator) + self._cover_id = cover_id + + self._attr_translation_placeholders = {"cover_id": str(cover_id + 1)} + self._attr_unique_id = ( + f"{coordinator.device_id}-{coordinator.mac_address}-{cover_id}" + ) + + self._update_data() diff --git a/homeassistant/components/switcher_kis/light.py b/homeassistant/components/switcher_kis/light.py index f5125c616da..4b6df6db6ed 100644 --- a/homeassistant/components/switcher_kis/light.py +++ b/homeassistant/components/switcher_kis/light.py @@ -34,42 +34,31 @@ async def async_setup_entry( @callback def async_add_light(coordinator: SwitcherDataUpdateCoordinator) -> None: """Add light from Switcher device.""" + entities: list[LightEntity] = [] if ( coordinator.data.device_type.category == DeviceCategory.SINGLE_SHUTTER_DUAL_LIGHT ): - async_add_entities( - [ - SwitcherLightEntity(coordinator, 0), - SwitcherLightEntity(coordinator, 1), - ] - ) + entities.extend(SwitcherDualLightEntity(coordinator, i) for i in range(2)) + if ( + coordinator.data.device_type.category + == DeviceCategory.DUAL_SHUTTER_SINGLE_LIGHT + ): + entities.append(SwitcherSingleLightEntity(coordinator, 0)) + async_add_entities(entities) config_entry.async_on_unload( async_dispatcher_connect(hass, SIGNAL_DEVICE_ADD, async_add_light) ) -class SwitcherLightEntity(SwitcherEntity, LightEntity): +class SwitcherBaseLightEntity(SwitcherEntity, LightEntity): """Representation of a Switcher light entity.""" _attr_color_mode = ColorMode.ONOFF _attr_supported_color_modes = {ColorMode.ONOFF} - _attr_translation_key = "light" - - def __init__( - self, coordinator: SwitcherDataUpdateCoordinator, light_id: int - ) -> None: - """Initialize the entity.""" - super().__init__(coordinator) - self._light_id = light_id - self.control_result: bool | None = None - - # Entity class attributes - self._attr_translation_placeholders = {"light_id": str(light_id + 1)} - self._attr_unique_id = ( - f"{coordinator.device_id}-{coordinator.mac_address}-{light_id}" - ) + control_result: bool | None = None + _light_id: int @callback def _handle_coordinator_update(self) -> None: @@ -123,3 +112,44 @@ class SwitcherLightEntity(SwitcherEntity, LightEntity): await self._async_call_api(API_SET_LIGHT, DeviceState.OFF, self._light_id) self.control_result = False self.async_write_ha_state() + + +class SwitcherSingleLightEntity(SwitcherBaseLightEntity): + """Representation of a Switcher single light entity.""" + + _attr_name = None + + def __init__( + self, + coordinator: SwitcherDataUpdateCoordinator, + light_id: int, + ) -> None: + """Initialize the entity.""" + super().__init__(coordinator) + self._light_id = light_id + self.control_result: bool | None = None + + # Entity class attributes + self._attr_unique_id = f"{coordinator.device_id}-{coordinator.mac_address}" + + +class SwitcherDualLightEntity(SwitcherBaseLightEntity): + """Representation of a Switcher dual light entity.""" + + _attr_translation_key = "light" + + def __init__( + self, + coordinator: SwitcherDataUpdateCoordinator, + light_id: int, + ) -> None: + """Initialize the entity.""" + super().__init__(coordinator) + self._light_id = light_id + self.control_result: bool | None = None + + # Entity class attributes + self._attr_translation_placeholders = {"light_id": str(light_id + 1)} + self._attr_unique_id = ( + f"{coordinator.device_id}-{coordinator.mac_address}-{light_id}" + ) diff --git a/homeassistant/components/switcher_kis/strings.json b/homeassistant/components/switcher_kis/strings.json index 68f9f9d590c..798a43c981c 100644 --- a/homeassistant/components/switcher_kis/strings.json +++ b/homeassistant/components/switcher_kis/strings.json @@ -43,6 +43,11 @@ "name": "Vertical swing off" } }, + "cover": { + "cover": { + "name": "Cover {cover_id}" + } + }, "light": { "light": { "name": "Light {light_id}" diff --git a/tests/components/switcher_kis/consts.py b/tests/components/switcher_kis/consts.py index fc2becbb4d5..ab0bef4e335 100644 --- a/tests/components/switcher_kis/consts.py +++ b/tests/components/switcher_kis/consts.py @@ -4,6 +4,7 @@ from aioswitcher.device import ( DeviceState, DeviceType, ShutterDirection, + SwitcherDualShutterSingleLight, SwitcherPowerPlug, SwitcherShutter, SwitcherSingleShutterDualLight, @@ -21,16 +22,19 @@ DUMMY_DEVICE_ID2 = "cafe12" DUMMY_DEVICE_ID3 = "bada77" DUMMY_DEVICE_ID4 = "bbd164" DUMMY_DEVICE_ID5 = "bcdb64" +DUMMY_DEVICE_ID6 = "bcdc64" DUMMY_DEVICE_KEY1 = "18" DUMMY_DEVICE_KEY2 = "01" DUMMY_DEVICE_KEY3 = "12" DUMMY_DEVICE_KEY4 = "07" DUMMY_DEVICE_KEY5 = "15" +DUMMY_DEVICE_KEY6 = "16" DUMMY_DEVICE_NAME1 = "Plug 23BC" DUMMY_DEVICE_NAME2 = "Heater FE12" DUMMY_DEVICE_NAME3 = "Breeze AB39" DUMMY_DEVICE_NAME4 = "Runner DD77" DUMMY_DEVICE_NAME5 = "RunnerS11 6CF5" +DUMMY_DEVICE_NAME6 = "RunnerS12 A9BE" DUMMY_DEVICE_PASSWORD = "12345678" DUMMY_ELECTRIC_CURRENT1 = 0.5 DUMMY_ELECTRIC_CURRENT2 = 12.8 @@ -39,16 +43,19 @@ DUMMY_IP_ADDRESS2 = "192.168.100.158" DUMMY_IP_ADDRESS3 = "192.168.100.159" DUMMY_IP_ADDRESS4 = "192.168.100.160" DUMMY_IP_ADDRESS5 = "192.168.100.161" +DUMMY_IP_ADDRESS6 = "192.168.100.162" DUMMY_MAC_ADDRESS1 = "A1:B2:C3:45:67:D8" DUMMY_MAC_ADDRESS2 = "A1:B2:C3:45:67:D9" DUMMY_MAC_ADDRESS3 = "A1:B2:C3:45:67:DA" DUMMY_MAC_ADDRESS4 = "A1:B2:C3:45:67:DB" DUMMY_MAC_ADDRESS5 = "A1:B2:C3:45:67:DC" +DUMMY_MAC_ADDRESS6 = "A1:B2:C3:45:67:DD" DUMMY_TOKEN_NEEDED1 = False DUMMY_TOKEN_NEEDED2 = False DUMMY_TOKEN_NEEDED3 = False DUMMY_TOKEN_NEEDED4 = False DUMMY_TOKEN_NEEDED5 = True +DUMMY_TOKEN_NEEDED6 = True DUMMY_PHONE_ID = "1234" DUMMY_POWER_CONSUMPTION1 = 100 DUMMY_POWER_CONSUMPTION2 = 2780 @@ -61,9 +68,12 @@ DUMMY_FAN_LEVEL = ThermostatFanLevel.LOW DUMMY_SWING = ThermostatSwing.OFF DUMMY_REMOTE_ID = "ELEC7001" DUMMY_POSITION = [54] +DUMMY_POSITION_2 = [54, 54] DUMMY_DIRECTION = [ShutterDirection.SHUTTER_STOP] +DUMMY_DIRECTION_2 = [ShutterDirection.SHUTTER_STOP, ShutterDirection.SHUTTER_STOP] DUMMY_USERNAME = "email" DUMMY_TOKEN = "zvVvd7JxtN7CgvkD1Psujw==" +DUMMY_LIGHT = [DeviceState.ON] DUMMY_LIGHT_2 = [DeviceState.ON, DeviceState.ON] DUMMY_PLUG_DEVICE = SwitcherPowerPlug( @@ -121,6 +131,20 @@ DUMMY_SINGLE_SHUTTER_DUAL_LIGHT_DEVICE = SwitcherSingleShutterDualLight( DUMMY_LIGHT_2, ) +DUMMY_DUAL_SHUTTER_SINGLE_LIGHT_DEVICE = SwitcherDualShutterSingleLight( + DeviceType.RUNNER_S12, + DeviceState.ON, + DUMMY_DEVICE_ID6, + DUMMY_DEVICE_KEY6, + DUMMY_IP_ADDRESS6, + DUMMY_MAC_ADDRESS6, + DUMMY_DEVICE_NAME6, + DUMMY_TOKEN_NEEDED6, + DUMMY_POSITION_2, + DUMMY_DIRECTION_2, + DUMMY_LIGHT, +) + DUMMY_THERMOSTAT_DEVICE = SwitcherThermostat( DeviceType.BREEZE, DeviceState.ON, diff --git a/tests/components/switcher_kis/test_config_flow.py b/tests/components/switcher_kis/test_config_flow.py index e1c017b2b96..48cc0beacb8 100644 --- a/tests/components/switcher_kis/test_config_flow.py +++ b/tests/components/switcher_kis/test_config_flow.py @@ -11,6 +11,7 @@ from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType from .consts import ( + DUMMY_DUAL_SHUTTER_SINGLE_LIGHT_DEVICE, DUMMY_PLUG_DEVICE, DUMMY_SINGLE_SHUTTER_DUAL_LIGHT_DEVICE, DUMMY_TOKEN, @@ -62,6 +63,7 @@ async def test_user_setup( [ [ DUMMY_SINGLE_SHUTTER_DUAL_LIGHT_DEVICE, + DUMMY_DUAL_SHUTTER_SINGLE_LIGHT_DEVICE, ] ], indirect=True, @@ -106,6 +108,7 @@ async def test_user_setup_found_token_device_valid_token( [ [ DUMMY_SINGLE_SHUTTER_DUAL_LIGHT_DEVICE, + DUMMY_DUAL_SHUTTER_SINGLE_LIGHT_DEVICE, ] ], indirect=True, diff --git a/tests/components/switcher_kis/test_cover.py b/tests/components/switcher_kis/test_cover.py index c4b613ed2c1..d26fff8754c 100644 --- a/tests/components/switcher_kis/test_cover.py +++ b/tests/components/switcher_kis/test_cover.py @@ -23,6 +23,7 @@ from homeassistant.util import slugify from . import init_integration from .consts import ( + DUMMY_DUAL_SHUTTER_SINGLE_LIGHT_DEVICE as DEVICE3, DUMMY_SHUTTER_DEVICE as DEVICE, DUMMY_SINGLE_SHUTTER_DUAL_LIGHT_DEVICE as DEVICE2, DUMMY_TOKEN as TOKEN, @@ -31,16 +32,65 @@ from .consts import ( ENTITY_ID = f"{COVER_DOMAIN}.{slugify(DEVICE.name)}" ENTITY_ID2 = f"{COVER_DOMAIN}.{slugify(DEVICE2.name)}" +ENTITY_ID3 = f"{COVER_DOMAIN}.{slugify(DEVICE3.name)}_cover_1" +ENTITY_ID3_2 = f"{COVER_DOMAIN}.{slugify(DEVICE3.name)}_cover_2" @pytest.mark.parametrize( - ("device", "entity_id"), + ( + "device", + "entity_id", + "cover_id", + "position_open", + "position_close", + "direction_open", + "direction_close", + "direction_stop", + ), [ - (DEVICE, ENTITY_ID), - (DEVICE2, ENTITY_ID2), + ( + DEVICE, + ENTITY_ID, + 0, + [77], + [0], + [ShutterDirection.SHUTTER_UP], + [ShutterDirection.SHUTTER_DOWN], + [ShutterDirection.SHUTTER_STOP], + ), + ( + DEVICE2, + ENTITY_ID2, + 0, + [77], + [0], + [ShutterDirection.SHUTTER_UP], + [ShutterDirection.SHUTTER_DOWN], + [ShutterDirection.SHUTTER_STOP], + ), + ( + DEVICE3, + ENTITY_ID3, + 0, + [77, 0], + [0, 0], + [ShutterDirection.SHUTTER_UP, ShutterDirection.SHUTTER_STOP], + [ShutterDirection.SHUTTER_DOWN, ShutterDirection.SHUTTER_STOP], + [ShutterDirection.SHUTTER_STOP, ShutterDirection.SHUTTER_STOP], + ), + ( + DEVICE3, + ENTITY_ID3_2, + 1, + [0, 77], + [0, 0], + [ShutterDirection.SHUTTER_STOP, ShutterDirection.SHUTTER_UP], + [ShutterDirection.SHUTTER_STOP, ShutterDirection.SHUTTER_DOWN], + [ShutterDirection.SHUTTER_STOP, ShutterDirection.SHUTTER_STOP], + ), ], ) -@pytest.mark.parametrize("mock_bridge", [[DEVICE, DEVICE2]], indirect=True) +@pytest.mark.parametrize("mock_bridge", [[DEVICE, DEVICE2, DEVICE3]], indirect=True) async def test_cover( hass: HomeAssistant, mock_bridge, @@ -48,6 +98,12 @@ async def test_cover( monkeypatch: pytest.MonkeyPatch, device, entity_id: str, + cover_id: int, + position_open: list[int], + position_close: list[int], + direction_open: list[ShutterDirection], + direction_close: list[ShutterDirection], + direction_stop: list[ShutterDirection], ) -> None: """Test cover services.""" await init_integration(hass, USERNAME, TOKEN) @@ -68,12 +124,12 @@ async def test_cover( blocking=True, ) - monkeypatch.setattr(device, "position", [77]) + monkeypatch.setattr(device, "position", position_open) mock_bridge.mock_callbacks([device]) await hass.async_block_till_done() assert mock_api.call_count == 2 - mock_control_device.assert_called_once_with(77, 0) + mock_control_device.assert_called_once_with(77, cover_id) state = hass.states.get(entity_id) assert state.state == CoverState.OPEN assert state.attributes[ATTR_CURRENT_POSITION] == 77 @@ -89,12 +145,12 @@ async def test_cover( blocking=True, ) - monkeypatch.setattr(device, "direction", [ShutterDirection.SHUTTER_UP]) + monkeypatch.setattr(device, "direction", direction_open) mock_bridge.mock_callbacks([device]) await hass.async_block_till_done() assert mock_api.call_count == 4 - mock_control_device.assert_called_once_with(100, 0) + mock_control_device.assert_called_once_with(100, cover_id) state = hass.states.get(entity_id) assert state.state == CoverState.OPENING @@ -109,12 +165,12 @@ async def test_cover( blocking=True, ) - monkeypatch.setattr(device, "direction", [ShutterDirection.SHUTTER_DOWN]) + monkeypatch.setattr(device, "direction", direction_close) mock_bridge.mock_callbacks([device]) await hass.async_block_till_done() assert mock_api.call_count == 6 - mock_control_device.assert_called_once_with(0, 0) + mock_control_device.assert_called_once_with(0, cover_id) state = hass.states.get(entity_id) assert state.state == CoverState.CLOSING @@ -129,17 +185,17 @@ async def test_cover( blocking=True, ) - monkeypatch.setattr(device, "direction", [ShutterDirection.SHUTTER_STOP]) + monkeypatch.setattr(device, "direction", direction_stop) mock_bridge.mock_callbacks([device]) await hass.async_block_till_done() assert mock_api.call_count == 8 - mock_control_device.assert_called_once_with(0) + mock_control_device.assert_called_once_with(cover_id) state = hass.states.get(entity_id) assert state.state == CoverState.OPEN # Test closed on position == 0 - monkeypatch.setattr(device, "position", [0]) + monkeypatch.setattr(device, "position", position_close) mock_bridge.mock_callbacks([device]) await hass.async_block_till_done() @@ -149,19 +205,22 @@ async def test_cover( @pytest.mark.parametrize( - ("device", "entity_id"), + ("device", "entity_id", "cover_id"), [ - (DEVICE, ENTITY_ID), - (DEVICE2, ENTITY_ID2), + (DEVICE, ENTITY_ID, 0), + (DEVICE2, ENTITY_ID2, 0), + (DEVICE3, ENTITY_ID3, 0), + (DEVICE3, ENTITY_ID3_2, 1), ], ) -@pytest.mark.parametrize("mock_bridge", [[DEVICE, DEVICE2]], indirect=True) +@pytest.mark.parametrize("mock_bridge", [[DEVICE, DEVICE2, DEVICE3]], indirect=True) async def test_cover_control_fail( hass: HomeAssistant, mock_bridge, mock_api, device, entity_id: str, + cover_id: int, ) -> None: """Test cover control fail.""" await init_integration(hass, USERNAME, TOKEN) @@ -185,7 +244,7 @@ async def test_cover_control_fail( ) assert mock_api.call_count == 2 - mock_control_device.assert_called_once_with(44, 0) + mock_control_device.assert_called_once_with(44, cover_id) state = hass.states.get(entity_id) assert state.state == STATE_UNAVAILABLE @@ -210,16 +269,16 @@ async def test_cover_control_fail( ) assert mock_api.call_count == 4 - mock_control_device.assert_called_once_with(27, 0) + mock_control_device.assert_called_once_with(27, cover_id) state = hass.states.get(entity_id) assert state.state == STATE_UNAVAILABLE -@pytest.mark.parametrize("mock_bridge", [[DEVICE2]], indirect=True) +@pytest.mark.parametrize("mock_bridge", [[DEVICE2, DEVICE3]], indirect=True) async def test_cover2_no_token( hass: HomeAssistant, mock_bridge, mock_api, monkeypatch: pytest.MonkeyPatch ) -> None: - """Test single cover dual light without token services.""" + """Test cover with token needed without token specified.""" await init_integration(hass) assert mock_bridge diff --git a/tests/components/switcher_kis/test_light.py b/tests/components/switcher_kis/test_light.py index 8a37174cf58..d360cb11291 100644 --- a/tests/components/switcher_kis/test_light.py +++ b/tests/components/switcher_kis/test_light.py @@ -21,6 +21,7 @@ from homeassistant.util import slugify from . import init_integration from .consts import ( + DUMMY_DUAL_SHUTTER_SINGLE_LIGHT_DEVICE as DEVICE2, DUMMY_SINGLE_SHUTTER_DUAL_LIGHT_DEVICE as DEVICE, DUMMY_TOKEN as TOKEN, DUMMY_USERNAME as USERNAME, @@ -28,21 +29,24 @@ from .consts import ( ENTITY_ID = f"{LIGHT_DOMAIN}.{slugify(DEVICE.name)}_light_1" ENTITY_ID2 = f"{LIGHT_DOMAIN}.{slugify(DEVICE.name)}_light_2" +ENTITY_ID3 = f"{LIGHT_DOMAIN}.{slugify(DEVICE2.name)}" @pytest.mark.parametrize( - ("entity_id", "light_id", "device_state"), + ("device", "entity_id", "light_id", "device_state"), [ - (ENTITY_ID, 0, [DeviceState.OFF, DeviceState.ON]), - (ENTITY_ID2, 1, [DeviceState.ON, DeviceState.OFF]), + (DEVICE, ENTITY_ID, 0, [DeviceState.OFF, DeviceState.ON]), + (DEVICE, ENTITY_ID2, 1, [DeviceState.ON, DeviceState.OFF]), + (DEVICE2, ENTITY_ID3, 0, [DeviceState.OFF]), ], ) -@pytest.mark.parametrize("mock_bridge", [[DEVICE]], indirect=True) +@pytest.mark.parametrize("mock_bridge", [[DEVICE, DEVICE2]], indirect=True) async def test_light( hass: HomeAssistant, mock_bridge, mock_api, monkeypatch: pytest.MonkeyPatch, + device, entity_id: str, light_id: int, device_state: list[DeviceState], @@ -56,8 +60,8 @@ async def test_light( assert state.state == STATE_ON # Test state change on --> off for light - monkeypatch.setattr(DEVICE, "light", device_state) - mock_bridge.mock_callbacks([DEVICE]) + monkeypatch.setattr(device, "light", device_state) + mock_bridge.mock_callbacks([device]) await hass.async_block_till_done() state = hass.states.get(entity_id) @@ -91,10 +95,11 @@ async def test_light( @pytest.mark.parametrize( - ("entity_id", "light_id", "device_state"), + ("device", "entity_id", "light_id", "device_state"), [ - (ENTITY_ID, 0, [DeviceState.OFF, DeviceState.ON]), - (ENTITY_ID2, 1, [DeviceState.ON, DeviceState.OFF]), + (DEVICE, ENTITY_ID, 0, [DeviceState.OFF, DeviceState.ON]), + (DEVICE, ENTITY_ID2, 1, [DeviceState.ON, DeviceState.OFF]), + (DEVICE2, ENTITY_ID3, 0, [DeviceState.OFF]), ], ) @pytest.mark.parametrize("mock_bridge", [[DEVICE]], indirect=True) @@ -104,6 +109,7 @@ async def test_light_control_fail( mock_api, monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture, + device, entity_id: str, light_id: int, device_state: list[DeviceState], @@ -113,8 +119,8 @@ async def test_light_control_fail( assert mock_bridge # Test initial state - light off - monkeypatch.setattr(DEVICE, "light", device_state) - mock_bridge.mock_callbacks([DEVICE]) + monkeypatch.setattr(device, "light", device_state) + mock_bridge.mock_callbacks([device]) await hass.async_block_till_done() state = hass.states.get(entity_id) @@ -139,7 +145,7 @@ async def test_light_control_fail( assert state.state == STATE_UNAVAILABLE # Make device available again - mock_bridge.mock_callbacks([DEVICE]) + mock_bridge.mock_callbacks([device]) await hass.async_block_till_done() state = hass.states.get(entity_id)