From b4d0562063b5ce23077c8b3d69fb95f4d7de5c5b Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 22 May 2024 01:47:37 -0700 Subject: [PATCH] Adopt new runtime entry data model for AlarmDecoder (#117856) * Adopt new runtime entity data model for AlarmDecoder Transition the AlarmDecoder integration to the new runtime entity model. * Apply change suggestions by epenet Tested & applied the suggestions from epenet. --- .../components/alarmdecoder/__init__.py | 63 ++++++++++--------- .../alarmdecoder/alarm_control_panel.py | 11 ++-- .../components/alarmdecoder/binary_sensor.py | 10 +-- .../components/alarmdecoder/const.py | 5 -- .../components/alarmdecoder/sensor.py | 11 ++-- 5 files changed, 50 insertions(+), 50 deletions(-) diff --git a/homeassistant/components/alarmdecoder/__init__.py b/homeassistant/components/alarmdecoder/__init__.py index 00db77a439b..4abf45b74fa 100644 --- a/homeassistant/components/alarmdecoder/__init__.py +++ b/homeassistant/components/alarmdecoder/__init__.py @@ -1,5 +1,7 @@ """Support for AlarmDecoder devices.""" +from collections.abc import Callable +from dataclasses import dataclass from datetime import timedelta import logging @@ -22,11 +24,6 @@ from homeassistant.helpers.event import async_call_later from .const import ( CONF_DEVICE_BAUD, CONF_DEVICE_PATH, - DATA_AD, - DATA_REMOVE_STOP_LISTENER, - DATA_REMOVE_UPDATE_LISTENER, - DATA_RESTART, - DOMAIN, PROTOCOL_SERIAL, PROTOCOL_SOCKET, SIGNAL_PANEL_MESSAGE, @@ -44,8 +41,22 @@ PLATFORMS = [ Platform.SENSOR, ] +type AlarmDecoderConfigEntry = ConfigEntry[AlarmDecoderData] -async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + +@dataclass +class AlarmDecoderData: + """Runtime data for the AlarmDecoder class.""" + + client: AdExt + remove_update_listener: Callable[[], None] + remove_stop_listener: Callable[[], None] + restart: bool + + +async def async_setup_entry( + hass: HomeAssistant, entry: AlarmDecoderConfigEntry +) -> bool: """Set up AlarmDecoder config flow.""" undo_listener = entry.add_update_listener(_update_listener) @@ -54,10 +65,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: def stop_alarmdecoder(event): """Handle the shutdown of AlarmDecoder.""" - if not hass.data.get(DOMAIN): + if not entry.runtime_data: return _LOGGER.debug("Shutting down alarmdecoder") - hass.data[DOMAIN][entry.entry_id][DATA_RESTART] = False + entry.runtime_data.restart = False controller.close() async def open_connection(now=None): @@ -69,13 +80,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async_call_later(hass, timedelta(seconds=5), open_connection) return _LOGGER.debug("Established a connection with the alarmdecoder") - hass.data[DOMAIN][entry.entry_id][DATA_RESTART] = True + entry.runtime_data.restart = True def handle_closed_connection(event): """Restart after unexpected loss of connection.""" - if not hass.data[DOMAIN][entry.entry_id][DATA_RESTART]: + if not entry.runtime_data.restart: return - hass.data[DOMAIN][entry.entry_id][DATA_RESTART] = False + entry.runtime_data.restart = False _LOGGER.warning("AlarmDecoder unexpectedly lost connection") hass.add_job(open_connection) @@ -119,13 +130,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: EVENT_HOMEASSISTANT_STOP, stop_alarmdecoder ) - hass.data.setdefault(DOMAIN, {}) - hass.data[DOMAIN][entry.entry_id] = { - DATA_AD: controller, - DATA_REMOVE_UPDATE_LISTENER: undo_listener, - DATA_REMOVE_STOP_LISTENER: remove_stop_listener, - DATA_RESTART: False, - } + entry.runtime_data = AlarmDecoderData( + controller, undo_listener, remove_stop_listener, False + ) await open_connection() @@ -136,28 +143,26 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: return True -async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: +async def async_unload_entry( + hass: HomeAssistant, entry: AlarmDecoderConfigEntry +) -> bool: """Unload a AlarmDecoder entry.""" - hass.data[DOMAIN][entry.entry_id][DATA_RESTART] = False + data = entry.runtime_data + data.restart = False unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) if not unload_ok: return False - hass.data[DOMAIN][entry.entry_id][DATA_REMOVE_UPDATE_LISTENER]() - hass.data[DOMAIN][entry.entry_id][DATA_REMOVE_STOP_LISTENER]() - await hass.async_add_executor_job(hass.data[DOMAIN][entry.entry_id][DATA_AD].close) - - if hass.data[DOMAIN][entry.entry_id]: - hass.data[DOMAIN].pop(entry.entry_id) - if not hass.data[DOMAIN]: - hass.data.pop(DOMAIN) + data.remove_update_listener() + data.remove_stop_listener() + await hass.async_add_executor_job(data.client.close) return True -async def _update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None: +async def _update_listener(hass: HomeAssistant, entry: AlarmDecoderConfigEntry) -> None: """Handle options update.""" _LOGGER.debug("AlarmDecoder options updated: %s", entry.as_dict()["options"]) await hass.config_entries.async_reload(entry.entry_id) diff --git a/homeassistant/components/alarmdecoder/alarm_control_panel.py b/homeassistant/components/alarmdecoder/alarm_control_panel.py index d2fc335a27d..7375320f800 100644 --- a/homeassistant/components/alarmdecoder/alarm_control_panel.py +++ b/homeassistant/components/alarmdecoder/alarm_control_panel.py @@ -9,7 +9,6 @@ from homeassistant.components.alarm_control_panel import ( AlarmControlPanelEntityFeature, CodeFormat, ) -from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( ATTR_CODE, STATE_ALARM_ARMED_AWAY, @@ -24,13 +23,12 @@ import homeassistant.helpers.config_validation as cv from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback +from . import AlarmDecoderConfigEntry from .const import ( CONF_ALT_NIGHT_MODE, CONF_AUTO_BYPASS, CONF_CODE_ARM_REQUIRED, - DATA_AD, DEFAULT_ARM_OPTIONS, - DOMAIN, OPTIONS_ARM, SIGNAL_PANEL_MESSAGE, ) @@ -43,15 +41,16 @@ ATTR_KEYPRESS = "keypress" async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback + hass: HomeAssistant, + entry: AlarmDecoderConfigEntry, + async_add_entities: AddEntitiesCallback, ) -> None: """Set up for AlarmDecoder alarm panels.""" options = entry.options arm_options = options.get(OPTIONS_ARM, DEFAULT_ARM_OPTIONS) - client = hass.data[DOMAIN][entry.entry_id][DATA_AD] entity = AlarmDecoderAlarmPanel( - client=client, + client=entry.runtime_data.client, auto_bypass=arm_options[CONF_AUTO_BYPASS], code_arm_required=arm_options[CONF_CODE_ARM_REQUIRED], alt_night_mode=arm_options[CONF_ALT_NIGHT_MODE], diff --git a/homeassistant/components/alarmdecoder/binary_sensor.py b/homeassistant/components/alarmdecoder/binary_sensor.py index 6f92fe3d1c2..1234c9f349b 100644 --- a/homeassistant/components/alarmdecoder/binary_sensor.py +++ b/homeassistant/components/alarmdecoder/binary_sensor.py @@ -3,11 +3,11 @@ import logging from homeassistant.components.binary_sensor import BinarySensorEntity -from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback +from . import AlarmDecoderConfigEntry from .const import ( CONF_RELAY_ADDR, CONF_RELAY_CHAN, @@ -16,9 +16,7 @@ from .const import ( CONF_ZONE_NUMBER, CONF_ZONE_RFID, CONF_ZONE_TYPE, - DATA_AD, DEFAULT_ZONE_OPTIONS, - DOMAIN, OPTIONS_ZONES, SIGNAL_REL_MESSAGE, SIGNAL_RFX_MESSAGE, @@ -40,11 +38,13 @@ ATTR_RF_LOOP1 = "rf_loop1" async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback + hass: HomeAssistant, + entry: AlarmDecoderConfigEntry, + async_add_entities: AddEntitiesCallback, ) -> None: """Set up for AlarmDecoder sensor.""" - client = hass.data[DOMAIN][entry.entry_id][DATA_AD] + client = entry.runtime_data.client zones = entry.options.get(OPTIONS_ZONES, DEFAULT_ZONE_OPTIONS) entities = [] diff --git a/homeassistant/components/alarmdecoder/const.py b/homeassistant/components/alarmdecoder/const.py index 4aba16a9cf8..cefd47fc0a5 100644 --- a/homeassistant/components/alarmdecoder/const.py +++ b/homeassistant/components/alarmdecoder/const.py @@ -13,11 +13,6 @@ CONF_ZONE_NUMBER = "zone_number" CONF_ZONE_RFID = "zone_rfid" CONF_ZONE_TYPE = "zone_type" -DATA_AD = "alarmdecoder" -DATA_REMOVE_STOP_LISTENER = "rm_stop_listener" -DATA_REMOVE_UPDATE_LISTENER = "rm_update_listener" -DATA_RESTART = "restart" - DEFAULT_ALT_NIGHT_MODE = False DEFAULT_AUTO_BYPASS = False DEFAULT_CODE_ARM_REQUIRED = True diff --git a/homeassistant/components/alarmdecoder/sensor.py b/homeassistant/components/alarmdecoder/sensor.py index 2ad78a553f9..f5e744457fd 100644 --- a/homeassistant/components/alarmdecoder/sensor.py +++ b/homeassistant/components/alarmdecoder/sensor.py @@ -1,22 +1,23 @@ """Support for AlarmDecoder sensors (Shows Panel Display).""" from homeassistant.components.sensor import SensorEntity -from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .const import DATA_AD, DOMAIN, SIGNAL_PANEL_MESSAGE +from . import AlarmDecoderConfigEntry +from .const import SIGNAL_PANEL_MESSAGE from .entity import AlarmDecoderEntity async def async_setup_entry( - hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback + hass: HomeAssistant, + entry: AlarmDecoderConfigEntry, + async_add_entities: AddEntitiesCallback, ) -> None: """Set up for AlarmDecoder sensor.""" - client = hass.data[DOMAIN][entry.entry_id][DATA_AD] - entity = AlarmDecoderSensor(client=client) + entity = AlarmDecoderSensor(client=entry.runtime_data.client) async_add_entities([entity])