Shutdown ZHAGateway on hass closing. (#22646)

* Shutdown ZHAGateway on hass stop.
* Cleanup ZHA event leftovers.
This commit is contained in:
Alexei Chetroi 2019-04-03 09:40:48 -04:00 committed by GitHub
parent b797b1513a
commit 625c8e0cee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 21 deletions

View File

@ -16,15 +16,14 @@ from homeassistant.helpers.device_registry import CONNECTION_ZIGBEE
from . import config_flow # noqa # pylint: disable=unused-import from . import config_flow # noqa # pylint: disable=unused-import
from . import api from . import api
from .core import ZHAGateway from .core import ZHAGateway
from .core.channels.registry import populate_channel_registry
from .core.const import ( from .core.const import (
COMPONENTS, CONF_BAUDRATE, CONF_DATABASE, CONF_DEVICE_CONFIG, COMPONENTS, CONF_BAUDRATE, CONF_DATABASE, CONF_DEVICE_CONFIG,
CONF_RADIO_TYPE, CONF_USB_PATH, DATA_ZHA, CONF_RADIO_TYPE, CONF_USB_PATH, DATA_ZHA, DATA_ZHA_CONFIG,
DATA_ZHA_CONFIG, DATA_ZHA_CORE_COMPONENT, DATA_ZHA_DISPATCHERS, DATA_ZHA_CORE_COMPONENT, DATA_ZHA_DISPATCHERS, DATA_ZHA_GATEWAY,
DATA_ZHA_RADIO, DEFAULT_BAUDRATE, DATA_ZHA_GATEWAY, DEFAULT_BAUDRATE, DEFAULT_RADIO_TYPE, DOMAIN, ENABLE_QUIRKS, RadioType)
DEFAULT_RADIO_TYPE, DOMAIN, RadioType, DATA_ZHA_CORE_EVENTS, ENABLE_QUIRKS)
from .core.registries import establish_device_mappings
from .core.channels.registry import populate_channel_registry
from .core.patches import apply_cluster_listener_patch from .core.patches import apply_cluster_listener_patch
from .core.registries import establish_device_mappings
REQUIREMENTS = [ REQUIREMENTS = [
'bellows-homeassistant==0.7.2', 'bellows-homeassistant==0.7.2',
@ -143,9 +142,9 @@ async def async_setup_entry(hass, config_entry):
async def async_zha_shutdown(event): async def async_zha_shutdown(event):
"""Handle shutdown tasks.""" """Handle shutdown tasks."""
await hass.data[DATA_ZHA][DATA_ZHA_GATEWAY].shutdown()
await hass.data[DATA_ZHA][ await hass.data[DATA_ZHA][
DATA_ZHA_GATEWAY].async_update_device_storage() DATA_ZHA_GATEWAY].async_update_device_storage()
hass.data[DATA_ZHA][DATA_ZHA_RADIO].close()
hass.bus.async_listen_once( hass.bus.async_listen_once(
ha_const.EVENT_HOMEASSISTANT_STOP, async_zha_shutdown) ha_const.EVENT_HOMEASSISTANT_STOP, async_zha_shutdown)
@ -154,6 +153,8 @@ async def async_setup_entry(hass, config_entry):
async def async_unload_entry(hass, config_entry): async def async_unload_entry(hass, config_entry):
"""Unload ZHA config entry.""" """Unload ZHA config entry."""
await hass.data[DATA_ZHA][DATA_ZHA_GATEWAY].shutdown()
api.async_unload_api(hass) api.async_unload_api(hass)
dispatchers = hass.data[DATA_ZHA].get(DATA_ZHA_DISPATCHERS, []) dispatchers = hass.data[DATA_ZHA].get(DATA_ZHA_DISPATCHERS, [])
@ -170,11 +171,5 @@ async def async_unload_entry(hass, config_entry):
for entity_id in entity_ids: for entity_id in entity_ids:
await component.async_remove_entity(entity_id) await component.async_remove_entity(entity_id)
# clean up events
hass.data[DATA_ZHA][DATA_ZHA_CORE_EVENTS].clear()
_LOGGER.debug("Closing zha radio")
hass.data[DATA_ZHA][DATA_ZHA_RADIO].close()
del hass.data[DATA_ZHA] del hass.data[DATA_ZHA]
return True return True

View File

@ -17,7 +17,6 @@ BAUD_RATES = [
DATA_ZHA = 'zha' DATA_ZHA = 'zha'
DATA_ZHA_CONFIG = 'config' DATA_ZHA_CONFIG = 'config'
DATA_ZHA_BRIDGE_ID = 'zha_bridge_id' DATA_ZHA_BRIDGE_ID = 'zha_bridge_id'
DATA_ZHA_RADIO = 'zha_radio'
DATA_ZHA_DISPATCHERS = 'zha_dispatchers' DATA_ZHA_DISPATCHERS = 'zha_dispatchers'
DATA_ZHA_CORE_COMPONENT = 'zha_core_component' DATA_ZHA_CORE_COMPONENT = 'zha_core_component'
DATA_ZHA_CORE_EVENTS = 'zha_core_events' DATA_ZHA_CORE_EVENTS = 'zha_core_events'

View File

@ -23,11 +23,11 @@ from .const import (
ADD_DEVICE_RELAY_LOGGERS, ATTR_MANUFACTURER, BELLOWS, CONF_BAUDRATE, ADD_DEVICE_RELAY_LOGGERS, ATTR_MANUFACTURER, BELLOWS, CONF_BAUDRATE,
CONF_DATABASE, CONF_RADIO_TYPE, CONF_USB_PATH, CONTROLLER, CURRENT, CONF_DATABASE, CONF_RADIO_TYPE, CONF_USB_PATH, CONTROLLER, CURRENT,
DATA_ZHA, DATA_ZHA_BRIDGE_ID, DATA_ZHA_CORE_COMPONENT, DATA_ZHA_GATEWAY, DATA_ZHA, DATA_ZHA_BRIDGE_ID, DATA_ZHA_CORE_COMPONENT, DATA_ZHA_GATEWAY,
DATA_ZHA_RADIO, DEBUG_LEVELS, DEFAULT_BAUDRATE, DEFAULT_DATABASE_NAME, DEBUG_LEVELS, DEFAULT_BAUDRATE, DEFAULT_DATABASE_NAME, DEVICE_FULL_INIT,
DEVICE_FULL_INIT, DEVICE_INFO, DEVICE_JOINED, DEVICE_REMOVED, DOMAIN, IEEE, DEVICE_INFO, DEVICE_JOINED, DEVICE_REMOVED, DOMAIN, IEEE, LOG_ENTRY,
LOG_ENTRY, LOG_OUTPUT, MODEL, NWK, ORIGINAL, RADIO, RADIO_DESCRIPTION, LOG_OUTPUT, MODEL, NWK, ORIGINAL, RADIO, RADIO_DESCRIPTION, RAW_INIT,
RAW_INIT, SIGNAL_REMOVE, SIGNATURE, TYPE, ZHA, ZHA_GW_MSG, ZIGPY, SIGNAL_REMOVE, SIGNATURE, TYPE, ZHA, ZHA_GW_MSG, ZIGPY, ZIGPY_DECONZ,
ZIGPY_DECONZ, ZIGPY_XBEE) ZIGPY_XBEE)
from .device import DeviceStatus, ZHADevice from .device import DeviceStatus, ZHADevice
from .discovery import ( from .discovery import (
async_create_device_entity, async_dispatch_discovery_info, async_create_device_entity, async_dispatch_discovery_info,
@ -76,7 +76,6 @@ class ZHAGateway:
radio = radio_details[RADIO] radio = radio_details[RADIO]
self.radio_description = RADIO_TYPES[radio_type][RADIO_DESCRIPTION] self.radio_description = RADIO_TYPES[radio_type][RADIO_DESCRIPTION]
await radio.connect(usb_path, baudrate) await radio.connect(usb_path, baudrate)
self._hass.data[DATA_ZHA][DATA_ZHA_RADIO] = radio
if CONF_DATABASE in self._config: if CONF_DATABASE in self._config:
database = self._config[CONF_DATABASE] database = self._config[CONF_DATABASE]
@ -312,6 +311,11 @@ class ZHAGateway:
} }
) )
async def shutdown(self):
"""Stop ZHA Controller Application."""
_LOGGER.debug("Shutting down ZHA ControllerApplication")
await self.application_controller.shutdown()
@callback @callback
def async_capture_log_levels(): def async_capture_log_levels():

View File

@ -139,7 +139,7 @@ async def check_zigpy_connection(usb_path, radio_type, database_path):
await radio.connect(usb_path, DEFAULT_BAUDRATE) await radio.connect(usb_path, DEFAULT_BAUDRATE)
controller = ControllerApplication(radio, database_path) controller = ControllerApplication(radio, database_path)
await asyncio.wait_for(controller.startup(auto_form=True), timeout=30) await asyncio.wait_for(controller.startup(auto_form=True), timeout=30)
radio.close() await controller.shutdown()
except Exception: # pylint: disable=broad-except except Exception: # pylint: disable=broad-except
return False return False
return True return True