mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 04:37:06 +00:00
Discover new devices at runtime in onewire (#135199)
This commit is contained in:
parent
24c70caf33
commit
475a2fb828
@ -37,6 +37,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: OneWireConfigEntry) -> b
|
|||||||
|
|
||||||
await hass.config_entries.async_forward_entry_setups(entry, _PLATFORMS)
|
await hass.config_entries.async_forward_entry_setups(entry, _PLATFORMS)
|
||||||
|
|
||||||
|
onewire_hub.schedule_scan_for_new_devices()
|
||||||
|
|
||||||
entry.async_on_unload(entry.add_update_listener(options_update_listener))
|
entry.async_on_unload(entry.add_update_listener(options_update_listener))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -13,11 +13,17 @@ from homeassistant.components.binary_sensor import (
|
|||||||
)
|
)
|
||||||
from homeassistant.const import EntityCategory
|
from homeassistant.const import EntityCategory
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import DEVICE_KEYS_0_3, DEVICE_KEYS_0_7, DEVICE_KEYS_A_B, READ_MODE_BOOL
|
from .const import DEVICE_KEYS_0_3, DEVICE_KEYS_0_7, DEVICE_KEYS_A_B, READ_MODE_BOOL
|
||||||
from .entity import OneWireEntity, OneWireEntityDescription
|
from .entity import OneWireEntity, OneWireEntityDescription
|
||||||
from .onewirehub import OneWireConfigEntry, OneWireHub
|
from .onewirehub import (
|
||||||
|
SIGNAL_NEW_DEVICE_CONNECTED,
|
||||||
|
OneWireConfigEntry,
|
||||||
|
OneWireHub,
|
||||||
|
OWDeviceDescription,
|
||||||
|
)
|
||||||
|
|
||||||
# the library uses non-persistent connections
|
# the library uses non-persistent connections
|
||||||
# and concurrent access to the bus is managed by the server
|
# and concurrent access to the bus is managed by the server
|
||||||
@ -98,16 +104,28 @@ async def async_setup_entry(
|
|||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up 1-Wire platform."""
|
"""Set up 1-Wire platform."""
|
||||||
async_add_entities(get_entities(config_entry.runtime_data), True)
|
|
||||||
|
async def _add_entities(
|
||||||
|
hub: OneWireHub, devices: list[OWDeviceDescription]
|
||||||
|
) -> None:
|
||||||
|
"""Add 1-Wire entities for all devices."""
|
||||||
|
if not devices:
|
||||||
|
return
|
||||||
|
async_add_entities(get_entities(hub, devices), True)
|
||||||
|
|
||||||
|
hub = config_entry.runtime_data
|
||||||
|
await _add_entities(hub, hub.devices)
|
||||||
|
config_entry.async_on_unload(
|
||||||
|
async_dispatcher_connect(hass, SIGNAL_NEW_DEVICE_CONNECTED, _add_entities)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_entities(onewire_hub: OneWireHub) -> list[OneWireBinarySensor]:
|
def get_entities(
|
||||||
|
onewire_hub: OneWireHub, devices: list[OWDeviceDescription]
|
||||||
|
) -> list[OneWireBinarySensor]:
|
||||||
"""Get a list of entities."""
|
"""Get a list of entities."""
|
||||||
if not onewire_hub.devices:
|
|
||||||
return []
|
|
||||||
|
|
||||||
entities: list[OneWireBinarySensor] = []
|
entities: list[OneWireBinarySensor] = []
|
||||||
for device in onewire_hub.devices:
|
for device in devices:
|
||||||
family = device.family
|
family = device.family
|
||||||
device_id = device.id
|
device_id = device.id
|
||||||
device_type = device.type
|
device_type = device.type
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from datetime import datetime, timedelta
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@ -9,9 +10,12 @@ from pyownet import protocol
|
|||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import ATTR_VIA_DEVICE, CONF_HOST, CONF_PORT
|
from homeassistant.const import ATTR_VIA_DEVICE, CONF_HOST, CONF_PORT
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr
|
||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
|
from homeassistant.helpers.event import async_track_time_interval
|
||||||
|
from homeassistant.util.signal_type import SignalType
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
DEVICE_SUPPORT,
|
DEVICE_SUPPORT,
|
||||||
@ -32,10 +36,15 @@ DEVICE_MANUFACTURER = {
|
|||||||
"EF": MANUFACTURER_HOBBYBOARDS,
|
"EF": MANUFACTURER_HOBBYBOARDS,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_DEVICE_SCAN_INTERVAL = timedelta(minutes=5)
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
type OneWireConfigEntry = ConfigEntry[OneWireHub]
|
type OneWireConfigEntry = ConfigEntry[OneWireHub]
|
||||||
|
|
||||||
|
SIGNAL_NEW_DEVICE_CONNECTED = SignalType["OneWireHub", list[OWDeviceDescription]](
|
||||||
|
f"{DOMAIN}_new_device_connected"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _is_known_device(device_family: str, device_type: str | None) -> bool:
|
def _is_known_device(device_family: str, device_type: str | None) -> bool:
|
||||||
"""Check if device family/type is known to the library."""
|
"""Check if device family/type is known to the library."""
|
||||||
@ -69,14 +78,42 @@ class OneWireHub:
|
|||||||
async def initialize(self) -> None:
|
async def initialize(self) -> None:
|
||||||
"""Initialize a config entry."""
|
"""Initialize a config entry."""
|
||||||
await self._hass.async_add_executor_job(self._initialize)
|
await self._hass.async_add_executor_job(self._initialize)
|
||||||
# Populate the device registry
|
self._populate_device_registry(self.devices)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _populate_device_registry(self, devices: list[OWDeviceDescription]) -> None:
|
||||||
|
"""Populate the device registry."""
|
||||||
device_registry = dr.async_get(self._hass)
|
device_registry = dr.async_get(self._hass)
|
||||||
for device in self.devices:
|
for device in devices:
|
||||||
device_registry.async_get_or_create(
|
device_registry.async_get_or_create(
|
||||||
config_entry_id=self._config_entry.entry_id,
|
config_entry_id=self._config_entry.entry_id,
|
||||||
**device.device_info,
|
**device.device_info,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def schedule_scan_for_new_devices(self) -> None:
|
||||||
|
"""Schedule a regular scan of the bus for new devices."""
|
||||||
|
self._config_entry.async_on_unload(
|
||||||
|
async_track_time_interval(
|
||||||
|
self._hass, self._scan_for_new_devices, _DEVICE_SCAN_INTERVAL
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _scan_for_new_devices(self, _: datetime) -> None:
|
||||||
|
"""Scan the bus for new devices."""
|
||||||
|
devices = await self._hass.async_add_executor_job(
|
||||||
|
_discover_devices, self.owproxy
|
||||||
|
)
|
||||||
|
existing_device_ids = [device.id for device in self.devices]
|
||||||
|
new_devices = [
|
||||||
|
device for device in devices if device.id not in existing_device_ids
|
||||||
|
]
|
||||||
|
if new_devices:
|
||||||
|
self.devices.extend(new_devices)
|
||||||
|
self._populate_device_registry(new_devices)
|
||||||
|
async_dispatcher_send(
|
||||||
|
self._hass, SIGNAL_NEW_DEVICE_CONNECTED, self, new_devices
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _discover_devices(
|
def _discover_devices(
|
||||||
owproxy: protocol._Proxy, path: str = "/", parent_id: str | None = None
|
owproxy: protocol._Proxy, path: str = "/", parent_id: str | None = None
|
||||||
|
@ -84,8 +84,8 @@ rules:
|
|||||||
comment: It doesn't make sense to override defaults
|
comment: It doesn't make sense to override defaults
|
||||||
reconfiguration-flow: done
|
reconfiguration-flow: done
|
||||||
dynamic-devices:
|
dynamic-devices:
|
||||||
status: todo
|
status: done
|
||||||
comment: Not yet implemented
|
comment: The bus is scanned for new devices at regular interval
|
||||||
discovery-update-info:
|
discovery-update-info:
|
||||||
status: todo
|
status: todo
|
||||||
comment: Under review
|
comment: Under review
|
||||||
|
@ -9,11 +9,17 @@ import os
|
|||||||
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
||||||
from homeassistant.const import EntityCategory
|
from homeassistant.const import EntityCategory
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import READ_MODE_INT
|
from .const import READ_MODE_INT
|
||||||
from .entity import OneWireEntity, OneWireEntityDescription
|
from .entity import OneWireEntity, OneWireEntityDescription
|
||||||
from .onewirehub import OneWireConfigEntry, OneWireHub
|
from .onewirehub import (
|
||||||
|
SIGNAL_NEW_DEVICE_CONNECTED,
|
||||||
|
OneWireConfigEntry,
|
||||||
|
OneWireHub,
|
||||||
|
OWDeviceDescription,
|
||||||
|
)
|
||||||
|
|
||||||
# the library uses non-persistent connections
|
# the library uses non-persistent connections
|
||||||
# and concurrent access to the bus is managed by the server
|
# and concurrent access to the bus is managed by the server
|
||||||
@ -45,17 +51,29 @@ async def async_setup_entry(
|
|||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up 1-Wire platform."""
|
"""Set up 1-Wire platform."""
|
||||||
async_add_entities(get_entities(config_entry.runtime_data), True)
|
|
||||||
|
async def _add_entities(
|
||||||
|
hub: OneWireHub, devices: list[OWDeviceDescription]
|
||||||
|
) -> None:
|
||||||
|
"""Add 1-Wire entities for all devices."""
|
||||||
|
if not devices:
|
||||||
|
return
|
||||||
|
async_add_entities(get_entities(hub, devices), True)
|
||||||
|
|
||||||
|
hub = config_entry.runtime_data
|
||||||
|
await _add_entities(hub, hub.devices)
|
||||||
|
config_entry.async_on_unload(
|
||||||
|
async_dispatcher_connect(hass, SIGNAL_NEW_DEVICE_CONNECTED, _add_entities)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_entities(onewire_hub: OneWireHub) -> list[OneWireSelectEntity]:
|
def get_entities(
|
||||||
|
onewire_hub: OneWireHub, devices: list[OWDeviceDescription]
|
||||||
|
) -> list[OneWireSelectEntity]:
|
||||||
"""Get a list of entities."""
|
"""Get a list of entities."""
|
||||||
if not onewire_hub.devices:
|
|
||||||
return []
|
|
||||||
|
|
||||||
entities: list[OneWireSelectEntity] = []
|
entities: list[OneWireSelectEntity] = []
|
||||||
|
|
||||||
for device in onewire_hub.devices:
|
for device in devices:
|
||||||
family = device.family
|
family = device.family
|
||||||
device_id = device.id
|
device_id = device.id
|
||||||
device_info = device.device_info
|
device_info = device.device_info
|
||||||
|
@ -26,6 +26,7 @@ from homeassistant.const import (
|
|||||||
UnitOfTemperature,
|
UnitOfTemperature,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import StateType
|
from homeassistant.helpers.typing import StateType
|
||||||
|
|
||||||
@ -39,7 +40,12 @@ from .const import (
|
|||||||
READ_MODE_INT,
|
READ_MODE_INT,
|
||||||
)
|
)
|
||||||
from .entity import OneWireEntity, OneWireEntityDescription
|
from .entity import OneWireEntity, OneWireEntityDescription
|
||||||
from .onewirehub import OneWireConfigEntry, OneWireHub
|
from .onewirehub import (
|
||||||
|
SIGNAL_NEW_DEVICE_CONNECTED,
|
||||||
|
OneWireConfigEntry,
|
||||||
|
OneWireHub,
|
||||||
|
OWDeviceDescription,
|
||||||
|
)
|
||||||
|
|
||||||
# the library uses non-persistent connections
|
# the library uses non-persistent connections
|
||||||
# and concurrent access to the bus is managed by the server
|
# and concurrent access to the bus is managed by the server
|
||||||
@ -357,23 +363,35 @@ async def async_setup_entry(
|
|||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up 1-Wire platform."""
|
"""Set up 1-Wire platform."""
|
||||||
|
|
||||||
|
async def _add_entities(
|
||||||
|
hub: OneWireHub, devices: list[OWDeviceDescription]
|
||||||
|
) -> None:
|
||||||
|
"""Add 1-Wire entities for all devices."""
|
||||||
|
if not devices:
|
||||||
|
return
|
||||||
# note: we have to go through the executor as SENSOR platform
|
# note: we have to go through the executor as SENSOR platform
|
||||||
# makes extra calls to the hub during device listing
|
# makes extra calls to the hub during device listing
|
||||||
entities = await hass.async_add_executor_job(
|
entities = await hass.async_add_executor_job(
|
||||||
get_entities, config_entry.runtime_data, config_entry.options
|
get_entities, hub, devices, config_entry.options
|
||||||
)
|
)
|
||||||
async_add_entities(entities, True)
|
async_add_entities(entities, True)
|
||||||
|
|
||||||
|
hub = config_entry.runtime_data
|
||||||
|
await _add_entities(hub, hub.devices)
|
||||||
|
config_entry.async_on_unload(
|
||||||
|
async_dispatcher_connect(hass, SIGNAL_NEW_DEVICE_CONNECTED, _add_entities)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_entities(
|
def get_entities(
|
||||||
onewire_hub: OneWireHub, options: MappingProxyType[str, Any]
|
onewire_hub: OneWireHub,
|
||||||
|
devices: list[OWDeviceDescription],
|
||||||
|
options: MappingProxyType[str, Any],
|
||||||
) -> list[OneWireSensor]:
|
) -> list[OneWireSensor]:
|
||||||
"""Get a list of entities."""
|
"""Get a list of entities."""
|
||||||
if not onewire_hub.devices:
|
|
||||||
return []
|
|
||||||
|
|
||||||
entities: list[OneWireSensor] = []
|
entities: list[OneWireSensor] = []
|
||||||
for device in onewire_hub.devices:
|
for device in devices:
|
||||||
family = device.family
|
family = device.family
|
||||||
device_type = device.type
|
device_type = device.type
|
||||||
device_id = device.id
|
device_id = device.id
|
||||||
|
@ -10,11 +10,17 @@ from typing import Any
|
|||||||
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
|
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
|
||||||
from homeassistant.const import EntityCategory
|
from homeassistant.const import EntityCategory
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import DEVICE_KEYS_0_3, DEVICE_KEYS_0_7, DEVICE_KEYS_A_B, READ_MODE_BOOL
|
from .const import DEVICE_KEYS_0_3, DEVICE_KEYS_0_7, DEVICE_KEYS_A_B, READ_MODE_BOOL
|
||||||
from .entity import OneWireEntity, OneWireEntityDescription
|
from .entity import OneWireEntity, OneWireEntityDescription
|
||||||
from .onewirehub import OneWireConfigEntry, OneWireHub
|
from .onewirehub import (
|
||||||
|
SIGNAL_NEW_DEVICE_CONNECTED,
|
||||||
|
OneWireConfigEntry,
|
||||||
|
OneWireHub,
|
||||||
|
OWDeviceDescription,
|
||||||
|
)
|
||||||
|
|
||||||
# the library uses non-persistent connections
|
# the library uses non-persistent connections
|
||||||
# and concurrent access to the bus is managed by the server
|
# and concurrent access to the bus is managed by the server
|
||||||
@ -158,17 +164,29 @@ async def async_setup_entry(
|
|||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up 1-Wire platform."""
|
"""Set up 1-Wire platform."""
|
||||||
async_add_entities(get_entities(config_entry.runtime_data), True)
|
|
||||||
|
async def _add_entities(
|
||||||
|
hub: OneWireHub, devices: list[OWDeviceDescription]
|
||||||
|
) -> None:
|
||||||
|
"""Add 1-Wire entities for all devices."""
|
||||||
|
if not devices:
|
||||||
|
return
|
||||||
|
async_add_entities(get_entities(hub, devices), True)
|
||||||
|
|
||||||
|
hub = config_entry.runtime_data
|
||||||
|
await _add_entities(hub, hub.devices)
|
||||||
|
config_entry.async_on_unload(
|
||||||
|
async_dispatcher_connect(hass, SIGNAL_NEW_DEVICE_CONNECTED, _add_entities)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_entities(onewire_hub: OneWireHub) -> list[OneWireSwitch]:
|
def get_entities(
|
||||||
|
onewire_hub: OneWireHub, devices: list[OWDeviceDescription]
|
||||||
|
) -> list[OneWireSwitch]:
|
||||||
"""Get a list of entities."""
|
"""Get a list of entities."""
|
||||||
if not onewire_hub.devices:
|
|
||||||
return []
|
|
||||||
|
|
||||||
entities: list[OneWireSwitch] = []
|
entities: list[OneWireSwitch] = []
|
||||||
|
|
||||||
for device in onewire_hub.devices:
|
for device in devices:
|
||||||
family = device.family
|
family = device.family
|
||||||
device_type = device.type
|
device_type = device.type
|
||||||
device_id = device.id
|
device_id = device.id
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy.assertion import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.components.onewire.onewirehub import _DEVICE_SCAN_INTERVAL
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
@ -13,7 +15,7 @@ from homeassistant.helpers import entity_registry as er
|
|||||||
from . import setup_owproxy_mock_devices
|
from . import setup_owproxy_mock_devices
|
||||||
from .const import MOCK_OWPROXY_DEVICES
|
from .const import MOCK_OWPROXY_DEVICES
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, snapshot_platform
|
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
@ -31,8 +33,35 @@ async def test_binary_sensors(
|
|||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test for 1-Wire binary sensors."""
|
"""Test for 1-Wire binary sensor entities."""
|
||||||
setup_owproxy_mock_devices(owproxy, MOCK_OWPROXY_DEVICES.keys())
|
setup_owproxy_mock_devices(owproxy, MOCK_OWPROXY_DEVICES.keys())
|
||||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
|
||||||
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_id", ["29.111111111111"])
|
||||||
|
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||||
|
async def test_binary_sensors_delayed(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
owproxy: MagicMock,
|
||||||
|
device_id: str,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
) -> None:
|
||||||
|
"""Test for delayed 1-Wire binary sensor entities."""
|
||||||
|
setup_owproxy_mock_devices(owproxy, [])
|
||||||
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
|
||||||
|
assert not er.async_entries_for_config_entry(entity_registry, config_entry.entry_id)
|
||||||
|
|
||||||
|
setup_owproxy_mock_devices(owproxy, [device_id])
|
||||||
|
freezer.tick(_DEVICE_SCAN_INTERVAL)
|
||||||
|
async_fire_time_changed(hass)
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
len(er.async_entries_for_config_entry(entity_registry, config_entry.entry_id))
|
||||||
|
== 8
|
||||||
|
)
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
from pyownet import protocol
|
from pyownet import protocol
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy.assertion import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.components.onewire.const import DOMAIN
|
from homeassistant.components.onewire.const import DOMAIN
|
||||||
|
from homeassistant.components.onewire.onewirehub import _DEVICE_SCAN_INTERVAL
|
||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -17,7 +19,7 @@ from homeassistant.setup import async_setup_component
|
|||||||
from . import setup_owproxy_mock_devices
|
from . import setup_owproxy_mock_devices
|
||||||
from .const import MOCK_OWPROXY_DEVICES
|
from .const import MOCK_OWPROXY_DEVICES
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||||
from tests.typing import WebSocketGenerator
|
from tests.typing import WebSocketGenerator
|
||||||
|
|
||||||
|
|
||||||
@ -102,6 +104,31 @@ async def test_registry(
|
|||||||
assert device_entry == snapshot(name=f"{device_entry.name}-entry")
|
assert device_entry == snapshot(name=f"{device_entry.name}-entry")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||||
|
async def test_registry_delayed(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
owproxy: MagicMock,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
) -> None:
|
||||||
|
"""Test device are correctly registered."""
|
||||||
|
setup_owproxy_mock_devices(owproxy, [])
|
||||||
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
|
||||||
|
assert not dr.async_entries_for_config_entry(device_registry, config_entry.entry_id)
|
||||||
|
|
||||||
|
setup_owproxy_mock_devices(owproxy, ["1F.111111111111"])
|
||||||
|
freezer.tick(_DEVICE_SCAN_INTERVAL)
|
||||||
|
async_fire_time_changed(hass)
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
len(dr.async_entries_for_config_entry(device_registry, config_entry.entry_id))
|
||||||
|
== 2
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@patch("homeassistant.components.onewire._PLATFORMS", [Platform.SENSOR])
|
@patch("homeassistant.components.onewire._PLATFORMS", [Platform.SENSOR])
|
||||||
async def test_registry_cleanup(
|
async def test_registry_cleanup(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy.assertion import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.components.onewire.onewirehub import _DEVICE_SCAN_INTERVAL
|
||||||
from homeassistant.components.select import (
|
from homeassistant.components.select import (
|
||||||
DOMAIN as SELECT_DOMAIN,
|
DOMAIN as SELECT_DOMAIN,
|
||||||
SERVICE_SELECT_OPTION,
|
SERVICE_SELECT_OPTION,
|
||||||
@ -17,7 +19,7 @@ from homeassistant.helpers import entity_registry as er
|
|||||||
from . import setup_owproxy_mock_devices
|
from . import setup_owproxy_mock_devices
|
||||||
from .const import MOCK_OWPROXY_DEVICES
|
from .const import MOCK_OWPROXY_DEVICES
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, snapshot_platform
|
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
@ -42,6 +44,33 @@ async def test_selects(
|
|||||||
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_id", ["28.111111111111"])
|
||||||
|
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||||
|
async def test_selects_delayed(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
owproxy: MagicMock,
|
||||||
|
device_id: str,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
) -> None:
|
||||||
|
"""Test for delayed 1-Wire select entities."""
|
||||||
|
setup_owproxy_mock_devices(owproxy, [])
|
||||||
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
|
||||||
|
assert not er.async_entries_for_config_entry(entity_registry, config_entry.entry_id)
|
||||||
|
|
||||||
|
setup_owproxy_mock_devices(owproxy, [device_id])
|
||||||
|
freezer.tick(_DEVICE_SCAN_INTERVAL)
|
||||||
|
async_fire_time_changed(hass)
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
len(er.async_entries_for_config_entry(entity_registry, config_entry.entry_id))
|
||||||
|
== 1
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("device_id", ["28.111111111111"])
|
@pytest.mark.parametrize("device_id", ["28.111111111111"])
|
||||||
async def test_selection_option_service(
|
async def test_selection_option_service(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
@ -5,10 +5,12 @@ from copy import deepcopy
|
|||||||
import logging
|
import logging
|
||||||
from unittest.mock import MagicMock, _patch_dict, patch
|
from unittest.mock import MagicMock, _patch_dict, patch
|
||||||
|
|
||||||
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
from pyownet.protocol import OwnetError
|
from pyownet.protocol import OwnetError
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy.assertion import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.components.onewire.onewirehub import _DEVICE_SCAN_INTERVAL
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
@ -16,7 +18,7 @@ from homeassistant.helpers import entity_registry as er
|
|||||||
from . import setup_owproxy_mock_devices
|
from . import setup_owproxy_mock_devices
|
||||||
from .const import ATTR_INJECT_READS, MOCK_OWPROXY_DEVICES
|
from .const import ATTR_INJECT_READS, MOCK_OWPROXY_DEVICES
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, snapshot_platform
|
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
@ -34,13 +36,40 @@ async def test_sensors(
|
|||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test for 1-Wire sensors."""
|
"""Test for 1-Wire sensor entities."""
|
||||||
setup_owproxy_mock_devices(owproxy, MOCK_OWPROXY_DEVICES.keys())
|
setup_owproxy_mock_devices(owproxy, MOCK_OWPROXY_DEVICES.keys())
|
||||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
|
||||||
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_id", ["12.111111111111"])
|
||||||
|
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||||
|
async def test_sensors_delayed(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
owproxy: MagicMock,
|
||||||
|
device_id: str,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
) -> None:
|
||||||
|
"""Test for delayed 1-Wire sensor entities."""
|
||||||
|
setup_owproxy_mock_devices(owproxy, [])
|
||||||
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
|
||||||
|
assert not er.async_entries_for_config_entry(entity_registry, config_entry.entry_id)
|
||||||
|
|
||||||
|
setup_owproxy_mock_devices(owproxy, [device_id])
|
||||||
|
freezer.tick(_DEVICE_SCAN_INTERVAL)
|
||||||
|
async_fire_time_changed(hass)
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
len(er.async_entries_for_config_entry(entity_registry, config_entry.entry_id))
|
||||||
|
== 2
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("device_id", ["12.111111111111"])
|
@pytest.mark.parametrize("device_id", ["12.111111111111"])
|
||||||
async def test_tai8570_sensors(
|
async def test_tai8570_sensors(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy.assertion import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.components.onewire.onewirehub import _DEVICE_SCAN_INTERVAL
|
||||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
@ -20,7 +22,7 @@ from homeassistant.helpers import entity_registry as er
|
|||||||
from . import setup_owproxy_mock_devices
|
from . import setup_owproxy_mock_devices
|
||||||
from .const import MOCK_OWPROXY_DEVICES
|
from .const import MOCK_OWPROXY_DEVICES
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, snapshot_platform
|
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
@ -38,13 +40,40 @@ async def test_switches(
|
|||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test for 1-Wire switches."""
|
"""Test for 1-Wire switch entities."""
|
||||||
setup_owproxy_mock_devices(owproxy, MOCK_OWPROXY_DEVICES.keys())
|
setup_owproxy_mock_devices(owproxy, MOCK_OWPROXY_DEVICES.keys())
|
||||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
|
||||||
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_id", ["05.111111111111"])
|
||||||
|
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||||
|
async def test_switches_delayed(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
owproxy: MagicMock,
|
||||||
|
device_id: str,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
) -> None:
|
||||||
|
"""Test for delayed 1-Wire switch entities."""
|
||||||
|
setup_owproxy_mock_devices(owproxy, [])
|
||||||
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
|
||||||
|
assert not er.async_entries_for_config_entry(entity_registry, config_entry.entry_id)
|
||||||
|
|
||||||
|
setup_owproxy_mock_devices(owproxy, [device_id])
|
||||||
|
freezer.tick(_DEVICE_SCAN_INTERVAL)
|
||||||
|
async_fire_time_changed(hass)
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
len(er.async_entries_for_config_entry(entity_registry, config_entry.entry_id))
|
||||||
|
== 1
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("device_id", ["05.111111111111"])
|
@pytest.mark.parametrize("device_id", ["05.111111111111"])
|
||||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||||
async def test_switch_toggle(
|
async def test_switch_toggle(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user