From 253182c650336b757936c512dd33f80d72584bb5 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Mon, 18 Dec 2023 11:13:20 +0100 Subject: [PATCH] Reolink change ir to switch (#105916) * Change IR from light to switch * Remove old entity * Add test * Apply suggestions from code review Co-authored-by: Jan-Philipp Benecke --------- Co-authored-by: Jan-Philipp Benecke --- homeassistant/components/reolink/__init__.py | 9 ++++- homeassistant/components/reolink/light.py | 10 ----- homeassistant/components/reolink/strings.json | 6 +-- homeassistant/components/reolink/switch.py | 10 +++++ tests/components/reolink/test_init.py | 38 ++++++++++++++++++- 5 files changed, 58 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/reolink/__init__.py b/homeassistant/components/reolink/__init__.py index 7f8448d277d..028b2c89311 100644 --- a/homeassistant/components/reolink/__init__.py +++ b/homeassistant/components/reolink/__init__.py @@ -16,7 +16,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import EVENT_HOMEASSISTANT_STOP, Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady -from homeassistant.helpers import device_registry as dr +from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import DOMAIN @@ -151,6 +151,13 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b cleanup_disconnected_cams(hass, config_entry.entry_id, host) + # Can be remove in HA 2024.6.0 + entity_reg = er.async_get(hass) + entities = er.async_entries_for_config_entry(entity_reg, config_entry.entry_id) + for entity in entities: + if entity.domain == "light" and entity.unique_id.endswith("ir_lights"): + entity_reg.async_remove(entity.entity_id) + await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS) config_entry.async_on_unload( diff --git a/homeassistant/components/reolink/light.py b/homeassistant/components/reolink/light.py index 8df69b156ad..bc739343c46 100644 --- a/homeassistant/components/reolink/light.py +++ b/homeassistant/components/reolink/light.py @@ -50,16 +50,6 @@ LIGHT_ENTITIES = ( get_brightness_fn=lambda api, ch: api.whiteled_brightness(ch), set_brightness_fn=lambda api, ch, value: api.set_whiteled(ch, brightness=value), ), - ReolinkLightEntityDescription( - key="ir_lights", - cmd_key="GetIrLights", - translation_key="ir_lights", - icon="mdi:led-off", - entity_category=EntityCategory.CONFIG, - supported=lambda api, ch: api.supported(ch, "ir_lights"), - is_on_fn=lambda api, ch: api.ir_enabled(ch), - turn_on_off_fn=lambda api, ch, value: api.set_ir_lights(ch, value), - ), ReolinkLightEntityDescription( key="status_led", cmd_key="GetPowerLed", diff --git a/homeassistant/components/reolink/strings.json b/homeassistant/components/reolink/strings.json index 04b46323e11..04dd0e787ac 100644 --- a/homeassistant/components/reolink/strings.json +++ b/homeassistant/components/reolink/strings.json @@ -238,9 +238,6 @@ "floodlight": { "name": "Floodlight" }, - "ir_lights": { - "name": "Infra red lights in night mode" - }, "status_led": { "name": "Status LED" } @@ -373,6 +370,9 @@ } }, "switch": { + "ir_lights": { + "name": "Infra red lights in night mode" + }, "record_audio": { "name": "Record audio" }, diff --git a/homeassistant/components/reolink/switch.py b/homeassistant/components/reolink/switch.py index 352ba7a1103..2ec3149dc8d 100644 --- a/homeassistant/components/reolink/switch.py +++ b/homeassistant/components/reolink/switch.py @@ -48,6 +48,16 @@ class ReolinkNVRSwitchEntityDescription( SWITCH_ENTITIES = ( + ReolinkSwitchEntityDescription( + key="ir_lights", + cmd_key="GetIrLights", + translation_key="ir_lights", + icon="mdi:led-off", + entity_category=EntityCategory.CONFIG, + supported=lambda api, ch: api.supported(ch, "ir_lights"), + value=lambda api, ch: api.ir_enabled(ch), + method=lambda api, ch, value: api.set_ir_lights(ch, value), + ), ReolinkSwitchEntityDescription( key="record_audio", cmd_key="GetEnc", diff --git a/tests/components/reolink/test_init.py b/tests/components/reolink/test_init.py index 6a9a8b957db..65490129486 100644 --- a/tests/components/reolink/test_init.py +++ b/tests/components/reolink/test_init.py @@ -19,7 +19,7 @@ from homeassistant.helpers import ( from homeassistant.setup import async_setup_component from homeassistant.util.dt import utcnow -from .conftest import TEST_CAM_MODEL, TEST_HOST_MODEL, TEST_NVR_NAME +from .conftest import TEST_CAM_MODEL, TEST_HOST_MODEL, TEST_MAC, TEST_NVR_NAME from tests.common import MockConfigEntry, async_fire_time_changed @@ -172,6 +172,42 @@ async def test_cleanup_disconnected_cams( assert sorted(device_models) == sorted(expected_models) +async def test_cleanup_deprecated_entities( + hass: HomeAssistant, + config_entry: MockConfigEntry, + reolink_connect: MagicMock, + entity_registry: er.EntityRegistry, +) -> None: + """Test deprecated ir_lights light entity is cleaned.""" + reolink_connect.channels = [0] + ir_id = f"{TEST_MAC}_0_ir_lights" + + entity_registry.async_get_or_create( + domain=Platform.LIGHT, + platform=const.DOMAIN, + unique_id=ir_id, + config_entry=config_entry, + suggested_object_id=ir_id, + disabled_by=None, + ) + + assert entity_registry.async_get_entity_id(Platform.LIGHT, const.DOMAIN, ir_id) + assert ( + entity_registry.async_get_entity_id(Platform.SWITCH, const.DOMAIN, ir_id) + is None + ) + + # setup CH 0 and NVR switch entities/device + with patch("homeassistant.components.reolink.PLATFORMS", [Platform.SWITCH]): + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + assert ( + entity_registry.async_get_entity_id(Platform.LIGHT, const.DOMAIN, ir_id) is None + ) + assert entity_registry.async_get_entity_id(Platform.SWITCH, const.DOMAIN, ir_id) + + async def test_no_repair_issue( hass: HomeAssistant, config_entry: MockConfigEntry ) -> None: