Skip to content

Commit

Permalink
Bump ZHA dependencies (#104335)
Browse files Browse the repository at this point in the history
  • Loading branch information
puddly authored Nov 29, 2023
1 parent 999875d commit bd8f01b
Show file tree
Hide file tree
Showing 21 changed files with 350 additions and 323 deletions.
108 changes: 77 additions & 31 deletions homeassistant/components/zha/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
import voluptuous as vol
from zhaquirks import setup as setup_quirks
from zigpy.config import CONF_DATABASE, CONF_DEVICE, CONF_DEVICE_PATH
from zigpy.exceptions import NetworkSettingsInconsistent
from zigpy.exceptions import NetworkSettingsInconsistent, TransientConnectionError

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_TYPE, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import Event, HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError
from homeassistant.exceptions import ConfigEntryError, ConfigEntryNotReady
from homeassistant.helpers import device_registry as dr
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_send
Expand All @@ -29,13 +29,16 @@
CONF_CUSTOM_QUIRKS_PATH,
CONF_DEVICE_CONFIG,
CONF_ENABLE_QUIRKS,
CONF_FLOW_CONTROL,
CONF_RADIO_TYPE,
CONF_USB_PATH,
CONF_ZIGPY,
DATA_ZHA,
DOMAIN,
PLATFORMS,
SIGNAL_ADD_ENTITIES,
STARTUP_FAILURE_DELAY_S,
STARTUP_RETRIES,
RadioType,
)
from .core.device import get_device_automation_triggers
Expand Down Expand Up @@ -158,42 +161,67 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b

_LOGGER.debug("Trigger cache: %s", zha_data.device_trigger_cache)

zha_gateway = ZHAGateway(hass, zha_data.yaml_config, config_entry)
# Retry setup a few times before giving up to deal with missing serial ports in VMs
for attempt in range(STARTUP_RETRIES):
try:
zha_gateway = await ZHAGateway.async_from_config(
hass=hass,
config=zha_data.yaml_config,
config_entry=config_entry,
)
break
except NetworkSettingsInconsistent as exc:
await warn_on_inconsistent_network_settings(
hass,
config_entry=config_entry,
old_state=exc.old_state,
new_state=exc.new_state,
)
raise ConfigEntryError(
"Network settings do not match most recent backup"
) from exc
except TransientConnectionError as exc:
raise ConfigEntryNotReady from exc
except Exception as exc: # pylint: disable=broad-except
_LOGGER.debug(
"Couldn't start coordinator (attempt %s of %s)",
attempt + 1,
STARTUP_RETRIES,
exc_info=exc,
)

try:
await zha_gateway.async_initialize()
except NetworkSettingsInconsistent as exc:
await warn_on_inconsistent_network_settings(
hass,
config_entry=config_entry,
old_state=exc.old_state,
new_state=exc.new_state,
)
raise HomeAssistantError(
"Network settings do not match most recent backup"
) from exc
except Exception:
if RadioType[config_entry.data[CONF_RADIO_TYPE]] == RadioType.ezsp:
try:
await warn_on_wrong_silabs_firmware(
hass, config_entry.data[CONF_DEVICE][CONF_DEVICE_PATH]
)
except AlreadyRunningEZSP as exc:
# If connecting fails but we somehow probe EZSP (e.g. stuck in the
# bootloader), reconnect, it should work
raise ConfigEntryNotReady from exc

raise
if attempt < STARTUP_RETRIES - 1:
await asyncio.sleep(STARTUP_FAILURE_DELAY_S)
continue

if RadioType[config_entry.data[CONF_RADIO_TYPE]] == RadioType.ezsp:
try:
# Ignore all exceptions during probing, they shouldn't halt setup
await warn_on_wrong_silabs_firmware(
hass, config_entry.data[CONF_DEVICE][CONF_DEVICE_PATH]
)
except AlreadyRunningEZSP as ezsp_exc:
raise ConfigEntryNotReady from ezsp_exc

raise

repairs.async_delete_blocking_issues(hass)

manufacturer = zha_gateway.state.node_info.manufacturer
model = zha_gateway.state.node_info.model

if manufacturer is None and model is None:
manufacturer = "Unknown"
model = "Unknown"

device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_ZIGBEE, str(zha_gateway.coordinator_ieee))},
identifiers={(DOMAIN, str(zha_gateway.coordinator_ieee))},
connections={(dr.CONNECTION_ZIGBEE, str(zha_gateway.state.node_info.ieee))},
identifiers={(DOMAIN, str(zha_gateway.state.node_info.ieee))},
name="Zigbee Coordinator",
manufacturer="ZHA",
model=zha_gateway.radio_description,
manufacturer=manufacturer,
model=model,
sw_version=zha_gateway.state.node_info.version,
)

websocket_api.async_load_api(hass)
Expand Down Expand Up @@ -267,5 +295,23 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) ->
config_entry.version = 3
hass.config_entries.async_update_entry(config_entry, data=data)

if config_entry.version == 3:
data = {**config_entry.data}

if not data[CONF_DEVICE].get(CONF_BAUDRATE):
data[CONF_DEVICE][CONF_BAUDRATE] = {
"deconz": 38400,
"xbee": 57600,
"ezsp": 57600,
"znp": 115200,
"zigate": 115200,
}[data[CONF_RADIO_TYPE]]

if not data[CONF_DEVICE].get(CONF_FLOW_CONTROL):
data[CONF_DEVICE][CONF_FLOW_CONTROL] = None

config_entry.version = 4
hass.config_entries.async_update_entry(config_entry, data=data)

_LOGGER.info("Migration to version %s successful", config_entry.version)
return True
26 changes: 11 additions & 15 deletions homeassistant/components/zha/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@

from .core.const import (
CONF_BAUDRATE,
CONF_FLOWCONTROL,
CONF_FLOW_CONTROL,
CONF_RADIO_TYPE,
DOMAIN,
RadioType,
)
from .radio_manager import (
DEVICE_SCHEMA,
HARDWARE_DISCOVERY_SCHEMA,
RECOMMENDED_RADIOS,
ProbeResult,
Expand All @@ -42,7 +43,7 @@
CONF_MANUAL_PATH = "Enter Manually"
SUPPORTED_PORT_SETTINGS = (
CONF_BAUDRATE,
CONF_FLOWCONTROL,
CONF_FLOW_CONTROL,
)
DECONZ_DOMAIN = "deconz"

Expand Down Expand Up @@ -160,7 +161,7 @@ async def _async_create_radio_entry(self) -> FlowResult:
return self.async_create_entry(
title=self._title,
data={
CONF_DEVICE: device_settings,
CONF_DEVICE: DEVICE_SCHEMA(device_settings),
CONF_RADIO_TYPE: self._radio_mgr.radio_type.name,
},
)
Expand Down Expand Up @@ -281,7 +282,7 @@ async def async_step_manual_port_config(
for (
param,
value,
) in self._radio_mgr.radio_type.controller.SCHEMA_DEVICE.schema.items():
) in DEVICE_SCHEMA.schema.items():
if param not in SUPPORTED_PORT_SETTINGS:
continue

Expand Down Expand Up @@ -488,7 +489,7 @@ async def async_step_maybe_confirm_ezsp_restore(
class ZhaConfigFlowHandler(BaseZhaFlow, config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow."""

VERSION = 3
VERSION = 4

async def _set_unique_id_or_update_path(
self, unique_id: str, device_path: str
Expand Down Expand Up @@ -646,22 +647,17 @@ async def async_step_hardware(

name = discovery_data["name"]
radio_type = self._radio_mgr.parse_radio_type(discovery_data["radio_type"])

try:
device_settings = radio_type.controller.SCHEMA_DEVICE(
discovery_data["port"]
)
except vol.Invalid:
return self.async_abort(reason="invalid_hardware_data")
device_settings = discovery_data["port"]
device_path = device_settings[CONF_DEVICE_PATH]

await self._set_unique_id_or_update_path(
unique_id=f"{name}_{radio_type.name}_{device_settings[CONF_DEVICE_PATH]}",
device_path=device_settings[CONF_DEVICE_PATH],
unique_id=f"{name}_{radio_type.name}_{device_path}",
device_path=device_path,
)

self._title = name
self._radio_mgr.radio_type = radio_type
self._radio_mgr.device_path = device_settings[CONF_DEVICE_PATH]
self._radio_mgr.device_path = device_path
self._radio_mgr.device_settings = device_settings
self.context["title_placeholders"] = {CONF_NAME: name}

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/zha/core/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
CONF_ALARM_ARM_REQUIRES_CODE = "alarm_arm_requires_code"

CONF_BAUDRATE = "baudrate"
CONF_FLOW_CONTROL = "flow_control"
CONF_CUSTOM_QUIRKS_PATH = "custom_quirks_path"
CONF_DEFAULT_LIGHT_TRANSITION = "default_light_transition"
CONF_DEVICE_CONFIG = "device_config"
Expand All @@ -136,7 +137,6 @@
CONF_GROUP_MEMBERS_ASSUME_STATE = "group_members_assume_state"
CONF_ENABLE_IDENTIFY_ON_JOIN = "enable_identify_on_join"
CONF_ENABLE_QUIRKS = "enable_quirks"
CONF_FLOWCONTROL = "flow_control"
CONF_RADIO_TYPE = "radio_type"
CONF_USB_PATH = "usb_path"
CONF_USE_THREAD = "use_thread"
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/zha/core/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ def is_active_coordinator(self) -> bool:
if not self.is_coordinator:
return False

return self.ieee == self.gateway.coordinator_ieee
return self.ieee == self.gateway.state.node_info.ieee

@property
def is_end_device(self) -> bool | None:
Expand Down
Loading

0 comments on commit bd8f01b

Please sign in to comment.