mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 10:17:09 +00:00
Fix Motion Blinds checking interface for multiple gateways (#71474)
* fix checking interface for multiple gateways * fix black * setup lock for shared multicast listener * fix black * bump motionblinds to 0.6.7 * compensate for extra Lock_key * unregister gateway when unloading * unsubscribe stop listener * fix black * only unsubscribe listener on last gateway remove * catch OSError for invalid interfaces * test coverage * make stop listen on last config entry more robust * also check ConfigEntryState * fix black
This commit is contained in:
parent
1d6e404512
commit
9be7b02613
@ -7,7 +7,7 @@ from typing import TYPE_CHECKING
|
|||||||
|
|
||||||
from motionblinds import DEVICE_TYPES_WIFI, AsyncMotionMulticast, ParseException
|
from motionblinds import DEVICE_TYPES_WIFI, AsyncMotionMulticast, ParseException
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry, ConfigEntryState
|
||||||
from homeassistant.const import CONF_API_KEY, CONF_HOST, EVENT_HOMEASSISTANT_STOP
|
from homeassistant.const import CONF_API_KEY, CONF_HOST, EVENT_HOMEASSISTANT_STOP
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
@ -25,6 +25,8 @@ from .const import (
|
|||||||
KEY_COORDINATOR,
|
KEY_COORDINATOR,
|
||||||
KEY_GATEWAY,
|
KEY_GATEWAY,
|
||||||
KEY_MULTICAST_LISTENER,
|
KEY_MULTICAST_LISTENER,
|
||||||
|
KEY_SETUP_LOCK,
|
||||||
|
KEY_UNSUB_STOP,
|
||||||
KEY_VERSION,
|
KEY_VERSION,
|
||||||
MANUFACTURER,
|
MANUFACTURER,
|
||||||
PLATFORMS,
|
PLATFORMS,
|
||||||
@ -106,6 +108,7 @@ class DataUpdateCoordinatorMotionBlinds(DataUpdateCoordinator):
|
|||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Set up the motion_blinds components from a config entry."""
|
"""Set up the motion_blinds components from a config entry."""
|
||||||
hass.data.setdefault(DOMAIN, {})
|
hass.data.setdefault(DOMAIN, {})
|
||||||
|
setup_lock = hass.data[DOMAIN].setdefault(KEY_SETUP_LOCK, asyncio.Lock())
|
||||||
host = entry.data[CONF_HOST]
|
host = entry.data[CONF_HOST]
|
||||||
key = entry.data[CONF_API_KEY]
|
key = entry.data[CONF_API_KEY]
|
||||||
multicast_interface = entry.data.get(CONF_INTERFACE, DEFAULT_INTERFACE)
|
multicast_interface = entry.data.get(CONF_INTERFACE, DEFAULT_INTERFACE)
|
||||||
@ -113,9 +116,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
|
|
||||||
entry.async_on_unload(entry.add_update_listener(update_listener))
|
entry.async_on_unload(entry.add_update_listener(update_listener))
|
||||||
|
|
||||||
|
# Create multicast Listener
|
||||||
|
async with setup_lock:
|
||||||
|
if KEY_MULTICAST_LISTENER not in hass.data[DOMAIN]:
|
||||||
# check multicast interface
|
# check multicast interface
|
||||||
check_multicast_class = ConnectMotionGateway(hass, interface=multicast_interface)
|
check_multicast_class = ConnectMotionGateway(
|
||||||
working_interface = await check_multicast_class.async_check_interface(host, key)
|
hass, interface=multicast_interface
|
||||||
|
)
|
||||||
|
working_interface = await check_multicast_class.async_check_interface(
|
||||||
|
host, key
|
||||||
|
)
|
||||||
if working_interface != multicast_interface:
|
if working_interface != multicast_interface:
|
||||||
data = {**entry.data, CONF_INTERFACE: working_interface}
|
data = {**entry.data, CONF_INTERFACE: working_interface}
|
||||||
hass.config_entries.async_update_entry(entry, data=data)
|
hass.config_entries.async_update_entry(entry, data=data)
|
||||||
@ -126,8 +136,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
working_interface,
|
working_interface,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create multicast Listener
|
|
||||||
if KEY_MULTICAST_LISTENER not in hass.data[DOMAIN]:
|
|
||||||
multicast = AsyncMotionMulticast(interface=working_interface)
|
multicast = AsyncMotionMulticast(interface=working_interface)
|
||||||
hass.data[DOMAIN][KEY_MULTICAST_LISTENER] = multicast
|
hass.data[DOMAIN][KEY_MULTICAST_LISTENER] = multicast
|
||||||
# start listening for local pushes (only once)
|
# start listening for local pushes (only once)
|
||||||
@ -139,7 +147,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
_LOGGER.debug("Shutting down Motion Listener")
|
_LOGGER.debug("Shutting down Motion Listener")
|
||||||
multicast.Stop_listen()
|
multicast.Stop_listen()
|
||||||
|
|
||||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_motion_multicast)
|
unsub = hass.bus.async_listen_once(
|
||||||
|
EVENT_HOMEASSISTANT_STOP, stop_motion_multicast
|
||||||
|
)
|
||||||
|
hass.data[DOMAIN][KEY_UNSUB_STOP] = unsub
|
||||||
|
|
||||||
# Connect to motion gateway
|
# Connect to motion gateway
|
||||||
multicast = hass.data[DOMAIN][KEY_MULTICAST_LISTENER]
|
multicast = hass.data[DOMAIN][KEY_MULTICAST_LISTENER]
|
||||||
@ -205,10 +216,19 @@ async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) ->
|
|||||||
)
|
)
|
||||||
|
|
||||||
if unload_ok:
|
if unload_ok:
|
||||||
|
multicast = hass.data[DOMAIN][KEY_MULTICAST_LISTENER]
|
||||||
|
multicast.Unregister_motion_gateway(config_entry.data[CONF_HOST])
|
||||||
hass.data[DOMAIN].pop(config_entry.entry_id)
|
hass.data[DOMAIN].pop(config_entry.entry_id)
|
||||||
|
|
||||||
if len(hass.data[DOMAIN]) == 1:
|
loaded_entries = [
|
||||||
|
entry
|
||||||
|
for entry in hass.config_entries.async_entries(DOMAIN)
|
||||||
|
if entry.state == ConfigEntryState.LOADED
|
||||||
|
]
|
||||||
|
if len(loaded_entries) == 1:
|
||||||
# No motion gateways left, stop Motion multicast
|
# No motion gateways left, stop Motion multicast
|
||||||
|
unsub_stop = hass.data[DOMAIN].pop(KEY_UNSUB_STOP)
|
||||||
|
unsub_stop()
|
||||||
_LOGGER.debug("Shutting down Motion Listener")
|
_LOGGER.debug("Shutting down Motion Listener")
|
||||||
multicast = hass.data[DOMAIN].pop(KEY_MULTICAST_LISTENER)
|
multicast = hass.data[DOMAIN].pop(KEY_MULTICAST_LISTENER)
|
||||||
multicast.Stop_listen()
|
multicast.Stop_listen()
|
||||||
|
@ -16,6 +16,8 @@ KEY_GATEWAY = "gateway"
|
|||||||
KEY_API_LOCK = "api_lock"
|
KEY_API_LOCK = "api_lock"
|
||||||
KEY_COORDINATOR = "coordinator"
|
KEY_COORDINATOR = "coordinator"
|
||||||
KEY_MULTICAST_LISTENER = "multicast_listener"
|
KEY_MULTICAST_LISTENER = "multicast_listener"
|
||||||
|
KEY_SETUP_LOCK = "setup_lock"
|
||||||
|
KEY_UNSUB_STOP = "unsub_stop"
|
||||||
KEY_VERSION = "version"
|
KEY_VERSION = "version"
|
||||||
|
|
||||||
ATTR_WIDTH = "width"
|
ATTR_WIDTH = "width"
|
||||||
|
@ -101,6 +101,8 @@ class ConnectMotionGateway:
|
|||||||
await check_multicast.Start_listen()
|
await check_multicast.Start_listen()
|
||||||
except socket.gaierror:
|
except socket.gaierror:
|
||||||
continue
|
continue
|
||||||
|
except OSError:
|
||||||
|
continue
|
||||||
|
|
||||||
# trigger test multicast
|
# trigger test multicast
|
||||||
self._gateway_device = MotionGateway(
|
self._gateway_device = MotionGateway(
|
||||||
|
@ -336,6 +336,10 @@ async def test_dhcp_flow(hass):
|
|||||||
assert result["step_id"] == "connect"
|
assert result["step_id"] == "connect"
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.motion_blinds.gateway.AsyncMotionMulticast.Start_listen",
|
||||||
|
side_effect=OSError,
|
||||||
|
):
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{CONF_API_KEY: TEST_API_KEY},
|
{CONF_API_KEY: TEST_API_KEY},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user