diff --git a/homeassistant/components/harmony/__init__.py b/homeassistant/components/harmony/__init__.py index c273d087580..cd69bd8017c 100644 --- a/homeassistant/components/harmony/__init__.py +++ b/homeassistant/components/harmony/__init__.py @@ -4,13 +4,20 @@ import logging from homeassistant.components.remote import ATTR_ACTIVITY, ATTR_DELAY_SECS from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_HOST, CONF_NAME +from homeassistant.const import CONF_HOST, CONF_NAME, EVENT_HOMEASSISTANT_STOP from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers import entity_registry from homeassistant.helpers.dispatcher import async_dispatcher_send -from .const import DOMAIN, HARMONY_OPTIONS_UPDATE, PLATFORMS +from .const import ( + CANCEL_LISTENER, + CANCEL_STOP, + DOMAIN, + HARMONY_DATA, + HARMONY_OPTIONS_UPDATE, + PLATFORMS, +) from .data import HarmonyData _LOGGER = logging.getLogger(__name__) @@ -35,12 +42,21 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): if not connected_ok: raise ConfigEntryNotReady - hass.data.setdefault(DOMAIN, {}) - hass.data[DOMAIN][entry.entry_id] = data - await _migrate_old_unique_ids(hass, entry.entry_id, data) - entry.add_update_listener(_update_listener) + cancel_listener = entry.add_update_listener(_update_listener) + + async def _async_on_stop(event): + await data.shutdown() + + cancel_stop = hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, _async_on_stop) + + hass.data.setdefault(DOMAIN, {}) + hass.data[DOMAIN][entry.entry_id] = { + HARMONY_DATA: data, + CANCEL_LISTENER: cancel_listener, + CANCEL_STOP: cancel_stop, + } for platform in PLATFORMS: hass.async_create_task( @@ -109,8 +125,10 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry): ) # Shutdown a harmony remote for removal - data = hass.data[DOMAIN][entry.entry_id] - await data.shutdown() + entry_data = hass.data[DOMAIN][entry.entry_id] + entry_data[CANCEL_LISTENER]() + entry_data[CANCEL_STOP]() + await entry_data[HARMONY_DATA].shutdown() if unload_ok: hass.data[DOMAIN].pop(entry.entry_id) diff --git a/homeassistant/components/harmony/config_flow.py b/homeassistant/components/harmony/config_flow.py index a91c1f3b5ca..2f2f7dc7ce4 100644 --- a/homeassistant/components/harmony/config_flow.py +++ b/homeassistant/components/harmony/config_flow.py @@ -14,7 +14,7 @@ from homeassistant.components.remote import ( from homeassistant.const import CONF_HOST, CONF_NAME from homeassistant.core import callback -from .const import DOMAIN, PREVIOUS_ACTIVE_ACTIVITY, UNIQUE_ID +from .const import DOMAIN, HARMONY_DATA, PREVIOUS_ACTIVE_ACTIVITY, UNIQUE_ID from .util import ( find_best_name_for_remote, find_unique_id_for_remote, @@ -180,7 +180,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow): if user_input is not None: return self.async_create_entry(title="", data=user_input) - remote = self.hass.data[DOMAIN][self.config_entry.entry_id] + remote = self.hass.data[DOMAIN][self.config_entry.entry_id][HARMONY_DATA] data_schema = vol.Schema( { diff --git a/homeassistant/components/harmony/const.py b/homeassistant/components/harmony/const.py index d7b4d8248ed..0d8d893a98e 100644 --- a/homeassistant/components/harmony/const.py +++ b/homeassistant/components/harmony/const.py @@ -10,3 +10,8 @@ ATTR_DEVICES_LIST = "devices_list" ATTR_LAST_ACTIVITY = "last_activity" ATTR_ACTIVITY_STARTING = "activity_starting" PREVIOUS_ACTIVE_ACTIVITY = "Previous Active Activity" + + +HARMONY_DATA = "harmony_data" +CANCEL_LISTENER = "cancel_listener" +CANCEL_STOP = "cancel_stop" diff --git a/homeassistant/components/harmony/remote.py b/homeassistant/components/harmony/remote.py index a09f32ee95e..518ff92368c 100644 --- a/homeassistant/components/harmony/remote.py +++ b/homeassistant/components/harmony/remote.py @@ -29,6 +29,7 @@ from .const import ( ATTR_DEVICES_LIST, ATTR_LAST_ACTIVITY, DOMAIN, + HARMONY_DATA, HARMONY_OPTIONS_UPDATE, PREVIOUS_ACTIVE_ACTIVITY, SERVICE_CHANGE_CHANNEL, @@ -58,7 +59,7 @@ async def async_setup_entry( ): """Set up the Harmony config entry.""" - data = hass.data[DOMAIN][entry.entry_id] + data = hass.data[DOMAIN][entry.entry_id][HARMONY_DATA] _LOGGER.debug("HarmonyData : %s", data) diff --git a/homeassistant/components/harmony/switch.py b/homeassistant/components/harmony/switch.py index 5aac145e749..1da128b3d7b 100644 --- a/homeassistant/components/harmony/switch.py +++ b/homeassistant/components/harmony/switch.py @@ -5,7 +5,7 @@ from homeassistant.components.switch import SwitchEntity from homeassistant.const import CONF_NAME from .connection_state import ConnectionStateMixin -from .const import DOMAIN +from .const import DOMAIN, HARMONY_DATA from .data import HarmonyData from .subscriber import HarmonyCallback @@ -14,7 +14,7 @@ _LOGGER = logging.getLogger(__name__) async def async_setup_entry(hass, entry, async_add_entities): """Set up harmony activity switches.""" - data = hass.data[DOMAIN][entry.entry_id] + data = hass.data[DOMAIN][entry.entry_id][HARMONY_DATA] activities = data.activities switches = [] diff --git a/tests/components/harmony/test_remote.py b/tests/components/harmony/test_remote.py index 8c4d67e1117..4222244f00d 100644 --- a/tests/components/harmony/test_remote.py +++ b/tests/components/harmony/test_remote.py @@ -6,6 +6,7 @@ from aioharmony.const import SendCommandDevice from homeassistant.components.harmony.const import ( DOMAIN, + HARMONY_DATA, SERVICE_CHANGE_CHANNEL, SERVICE_SYNC, ) @@ -159,7 +160,7 @@ async def test_async_send_command(mock_hc, hass, mock_write_config): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - data = hass.data[DOMAIN][entry.entry_id] + data = hass.data[DOMAIN][entry.entry_id][HARMONY_DATA] send_commands_mock = data._client.send_commands # No device provided @@ -297,7 +298,7 @@ async def test_async_send_command_custom_delay(mock_hc, hass, mock_write_config) await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - data = hass.data[DOMAIN][entry.entry_id] + data = hass.data[DOMAIN][entry.entry_id][HARMONY_DATA] send_commands_mock = data._client.send_commands # Tell the TV to play by id @@ -333,7 +334,7 @@ async def test_change_channel(mock_hc, hass, mock_write_config): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - data = hass.data[DOMAIN][entry.entry_id] + data = hass.data[DOMAIN][entry.entry_id][HARMONY_DATA] change_channel_mock = data._client.change_channel # Tell the remote to change channels @@ -358,7 +359,7 @@ async def test_sync(mock_hc, mock_write_config, hass): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - data = hass.data[DOMAIN][entry.entry_id] + data = hass.data[DOMAIN][entry.entry_id][HARMONY_DATA] sync_mock = data._client.sync # Tell the remote to change channels