mirror of
https://github.com/home-assistant/core.git
synced 2025-09-06 05:11:35 +02:00
Add binary sensor platform to qbus integration (#149975)
This commit is contained in:
144
homeassistant/components/qbus/binary_sensor.py
Normal file
144
homeassistant/components/qbus/binary_sensor.py
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
"""Support for Qbus binary sensor."""
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import cast
|
||||||
|
|
||||||
|
from qbusmqttapi.discovery import QbusMqttDevice, QbusMqttOutput
|
||||||
|
from qbusmqttapi.factory import QbusMqttTopicFactory
|
||||||
|
from qbusmqttapi.state import QbusMqttDeviceState, QbusMqttWeatherState
|
||||||
|
|
||||||
|
from homeassistant.components.binary_sensor import (
|
||||||
|
BinarySensorDeviceClass,
|
||||||
|
BinarySensorEntity,
|
||||||
|
BinarySensorEntityDescription,
|
||||||
|
)
|
||||||
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .coordinator import QbusConfigEntry
|
||||||
|
from .entity import (
|
||||||
|
QbusEntity,
|
||||||
|
create_device_identifier,
|
||||||
|
create_unique_id,
|
||||||
|
determine_new_outputs,
|
||||||
|
)
|
||||||
|
|
||||||
|
PARALLEL_UPDATES = 0
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True, kw_only=True)
|
||||||
|
class QbusWeatherDescription(BinarySensorEntityDescription):
|
||||||
|
"""Description for Qbus weather entities."""
|
||||||
|
|
||||||
|
property: str
|
||||||
|
|
||||||
|
|
||||||
|
_WEATHER_DESCRIPTIONS = (
|
||||||
|
QbusWeatherDescription(
|
||||||
|
key="raining",
|
||||||
|
property="raining",
|
||||||
|
translation_key="raining",
|
||||||
|
),
|
||||||
|
QbusWeatherDescription(
|
||||||
|
key="twilight",
|
||||||
|
property="twilight",
|
||||||
|
translation_key="twilight",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entry: QbusConfigEntry,
|
||||||
|
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Set up binary sensor entities."""
|
||||||
|
|
||||||
|
coordinator = entry.runtime_data
|
||||||
|
added_outputs: list[QbusMqttOutput] = []
|
||||||
|
added_controllers: list[str] = []
|
||||||
|
|
||||||
|
def _create_weather_entities() -> list[BinarySensorEntity]:
|
||||||
|
new_outputs = determine_new_outputs(
|
||||||
|
coordinator, added_outputs, lambda output: output.type == "weatherstation"
|
||||||
|
)
|
||||||
|
|
||||||
|
return [
|
||||||
|
QbusWeatherBinarySensor(output, description)
|
||||||
|
for output in new_outputs
|
||||||
|
for description in _WEATHER_DESCRIPTIONS
|
||||||
|
]
|
||||||
|
|
||||||
|
def _create_controller_entities() -> list[BinarySensorEntity]:
|
||||||
|
if coordinator.data and coordinator.data.id not in added_controllers:
|
||||||
|
added_controllers.extend(coordinator.data.id)
|
||||||
|
return [QbusControllerConnectedBinarySensor(coordinator.data)]
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def _check_outputs() -> None:
|
||||||
|
entities = [*_create_weather_entities(), *_create_controller_entities()]
|
||||||
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
_check_outputs()
|
||||||
|
entry.async_on_unload(coordinator.async_add_listener(_check_outputs))
|
||||||
|
|
||||||
|
|
||||||
|
class QbusWeatherBinarySensor(QbusEntity, BinarySensorEntity):
|
||||||
|
"""Representation of a Qbus weather binary sensor."""
|
||||||
|
|
||||||
|
_state_cls = QbusMqttWeatherState
|
||||||
|
|
||||||
|
entity_description: QbusWeatherDescription
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, mqtt_output: QbusMqttOutput, description: QbusWeatherDescription
|
||||||
|
) -> None:
|
||||||
|
"""Initialize binary sensor entity."""
|
||||||
|
|
||||||
|
super().__init__(mqtt_output, id_suffix=description.key)
|
||||||
|
|
||||||
|
self.entity_description = description
|
||||||
|
|
||||||
|
async def _handle_state_received(self, state: QbusMqttWeatherState) -> None:
|
||||||
|
if value := state.read_property(self.entity_description.property, None):
|
||||||
|
self._attr_is_on = (
|
||||||
|
None if value is None else cast(str, value).lower() == "true"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class QbusControllerConnectedBinarySensor(BinarySensorEntity):
|
||||||
|
"""Representation of the Qbus controller connected sensor."""
|
||||||
|
|
||||||
|
_attr_has_entity_name = True
|
||||||
|
_attr_name = None
|
||||||
|
_attr_should_poll = False
|
||||||
|
_attr_device_class = BinarySensorDeviceClass.CONNECTIVITY
|
||||||
|
|
||||||
|
def __init__(self, controller: QbusMqttDevice) -> None:
|
||||||
|
"""Initialize binary sensor entity."""
|
||||||
|
self._controller = controller
|
||||||
|
|
||||||
|
self._attr_unique_id = create_unique_id(controller.serial_number, "connected")
|
||||||
|
self._attr_device_info = DeviceInfo(
|
||||||
|
identifiers={create_device_identifier(controller)}
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_added_to_hass(self) -> None:
|
||||||
|
"""Run when entity about to be added to hass."""
|
||||||
|
topic = QbusMqttTopicFactory().get_device_state_topic(self._controller.id)
|
||||||
|
self.async_on_remove(
|
||||||
|
async_dispatcher_connect(
|
||||||
|
self.hass,
|
||||||
|
f"{DOMAIN}_{topic}",
|
||||||
|
self._state_received,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _state_received(self, state: QbusMqttDeviceState) -> None:
|
||||||
|
self._attr_is_on = state.properties.connected if state.properties else None
|
||||||
|
self.async_schedule_update_ha_state()
|
@@ -6,6 +6,7 @@ from homeassistant.const import Platform
|
|||||||
|
|
||||||
DOMAIN: Final = "qbus"
|
DOMAIN: Final = "qbus"
|
||||||
PLATFORMS: list[Platform] = [
|
PLATFORMS: list[Platform] = [
|
||||||
|
Platform.BINARY_SENSOR,
|
||||||
Platform.CLIMATE,
|
Platform.CLIMATE,
|
||||||
Platform.COVER,
|
Platform.COVER,
|
||||||
Platform.LIGHT,
|
Platform.LIGHT,
|
||||||
|
@@ -6,7 +6,7 @@ from datetime import datetime
|
|||||||
import logging
|
import logging
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
from qbusmqttapi.discovery import QbusDiscovery, QbusMqttDevice, QbusMqttOutput
|
from qbusmqttapi.discovery import QbusDiscovery, QbusMqttDevice
|
||||||
from qbusmqttapi.factory import QbusMqttMessageFactory, QbusMqttTopicFactory
|
from qbusmqttapi.factory import QbusMqttMessageFactory, QbusMqttTopicFactory
|
||||||
|
|
||||||
from homeassistant.components.mqtt import (
|
from homeassistant.components.mqtt import (
|
||||||
@@ -19,6 +19,7 @@ from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
|||||||
from homeassistant.core import CALLBACK_TYPE, Event, HomeAssistant
|
from homeassistant.core import CALLBACK_TYPE, Event, HomeAssistant
|
||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr
|
||||||
from homeassistant.helpers.device_registry import format_mac
|
from homeassistant.helpers.device_registry import format_mac
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.helpers.event import async_call_later
|
from homeassistant.helpers.event import async_call_later
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
from homeassistant.util.hass_dict import HassKey
|
from homeassistant.util.hass_dict import HassKey
|
||||||
@@ -32,7 +33,7 @@ type QbusConfigEntry = ConfigEntry[QbusControllerCoordinator]
|
|||||||
QBUS_KEY: HassKey[QbusConfigCoordinator] = HassKey(DOMAIN)
|
QBUS_KEY: HassKey[QbusConfigCoordinator] = HassKey(DOMAIN)
|
||||||
|
|
||||||
|
|
||||||
class QbusControllerCoordinator(DataUpdateCoordinator[list[QbusMqttOutput]]):
|
class QbusControllerCoordinator(DataUpdateCoordinator[QbusMqttDevice | None]):
|
||||||
"""Qbus data coordinator."""
|
"""Qbus data coordinator."""
|
||||||
|
|
||||||
_STATE_REQUEST_DELAY = 3
|
_STATE_REQUEST_DELAY = 3
|
||||||
@@ -63,8 +64,8 @@ class QbusControllerCoordinator(DataUpdateCoordinator[list[QbusMqttOutput]]):
|
|||||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self.shutdown)
|
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self.shutdown)
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _async_update_data(self) -> list[QbusMqttOutput]:
|
async def _async_update_data(self) -> QbusMqttDevice | None:
|
||||||
return self._controller.outputs if self._controller else []
|
return self._controller
|
||||||
|
|
||||||
def shutdown(self, event: Event | None = None) -> None:
|
def shutdown(self, event: Event | None = None) -> None:
|
||||||
"""Shutdown Qbus coordinator."""
|
"""Shutdown Qbus coordinator."""
|
||||||
@@ -140,14 +141,19 @@ class QbusControllerCoordinator(DataUpdateCoordinator[list[QbusMqttOutput]]):
|
|||||||
"%s - Receiving controller state %s", self.config_entry.unique_id, msg.topic
|
"%s - Receiving controller state %s", self.config_entry.unique_id, msg.topic
|
||||||
)
|
)
|
||||||
|
|
||||||
if self._controller is None or self._controller_activated:
|
if self._controller is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
state = self._message_factory.parse_device_state(msg.payload)
|
state = self._message_factory.parse_device_state(msg.payload)
|
||||||
|
|
||||||
if state and state.properties and state.properties.connectable is False:
|
if state and state.properties:
|
||||||
|
async_dispatcher_send(self.hass, f"{DOMAIN}_{msg.topic}", state)
|
||||||
|
|
||||||
|
if not self._controller_activated and state.properties.connectable is False:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"%s - Activating controller %s", self.config_entry.unique_id, state.id
|
"%s - Activating controller %s",
|
||||||
|
self.config_entry.unique_id,
|
||||||
|
state.id,
|
||||||
)
|
)
|
||||||
self._controller_activated = True
|
self._controller_activated = True
|
||||||
request = self._message_factory.create_device_activate_request(
|
request = self._message_factory.create_device_activate_request(
|
||||||
|
@@ -7,7 +7,7 @@ from collections.abc import Callable
|
|||||||
import re
|
import re
|
||||||
from typing import Generic, TypeVar, cast
|
from typing import Generic, TypeVar, cast
|
||||||
|
|
||||||
from qbusmqttapi.discovery import QbusMqttOutput
|
from qbusmqttapi.discovery import QbusMqttDevice, QbusMqttOutput
|
||||||
from qbusmqttapi.factory import QbusMqttMessageFactory, QbusMqttTopicFactory
|
from qbusmqttapi.factory import QbusMqttMessageFactory, QbusMqttTopicFactory
|
||||||
from qbusmqttapi.state import QbusMqttState
|
from qbusmqttapi.state import QbusMqttState
|
||||||
|
|
||||||
@@ -44,11 +44,15 @@ def determine_new_outputs(
|
|||||||
|
|
||||||
added_ref_ids = {k.ref_id for k in added_outputs}
|
added_ref_ids = {k.ref_id for k in added_outputs}
|
||||||
|
|
||||||
new_outputs = [
|
new_outputs = (
|
||||||
|
[
|
||||||
output
|
output
|
||||||
for output in coordinator.data
|
for output in coordinator.data.outputs
|
||||||
if filter_fn(output) and output.ref_id not in added_ref_ids
|
if filter_fn(output) and output.ref_id not in added_ref_ids
|
||||||
]
|
]
|
||||||
|
if coordinator.data
|
||||||
|
else []
|
||||||
|
)
|
||||||
|
|
||||||
if new_outputs:
|
if new_outputs:
|
||||||
added_outputs.extend(new_outputs)
|
added_outputs.extend(new_outputs)
|
||||||
@@ -64,9 +68,14 @@ def format_ref_id(ref_id: str) -> str | None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def create_main_device_identifier(mqtt_output: QbusMqttOutput) -> tuple[str, str]:
|
def create_device_identifier(mqtt_device: QbusMqttDevice) -> tuple[str, str]:
|
||||||
"""Create the identifier referring to the main device this output belongs to."""
|
"""Create the device identifier."""
|
||||||
return (DOMAIN, format_mac(mqtt_output.device.mac))
|
return (DOMAIN, format_mac(mqtt_device.mac))
|
||||||
|
|
||||||
|
|
||||||
|
def create_unique_id(serial_number: str, suffix: str) -> str:
|
||||||
|
"""Create the unique id."""
|
||||||
|
return f"ctd_{serial_number}_{suffix}"
|
||||||
|
|
||||||
|
|
||||||
class QbusEntity(Entity, Generic[StateT], ABC):
|
class QbusEntity(Entity, Generic[StateT], ABC):
|
||||||
@@ -95,16 +104,18 @@ class QbusEntity(Entity, Generic[StateT], ABC):
|
|||||||
)
|
)
|
||||||
|
|
||||||
ref_id = format_ref_id(mqtt_output.ref_id)
|
ref_id = format_ref_id(mqtt_output.ref_id)
|
||||||
unique_id = f"ctd_{mqtt_output.device.serial_number}_{ref_id}"
|
suffix = ref_id or ""
|
||||||
|
|
||||||
if id_suffix:
|
if id_suffix:
|
||||||
unique_id += f"_{id_suffix}"
|
suffix += f"_{id_suffix}"
|
||||||
|
|
||||||
self._attr_unique_id = unique_id
|
self._attr_unique_id = create_unique_id(
|
||||||
|
mqtt_output.device.serial_number, suffix
|
||||||
|
)
|
||||||
|
|
||||||
if link_to_main_device:
|
if link_to_main_device:
|
||||||
self._attr_device_info = DeviceInfo(
|
self._attr_device_info = DeviceInfo(
|
||||||
identifiers={create_main_device_identifier(mqtt_output)}
|
identifiers={create_device_identifier(mqtt_output.device)}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self._attr_device_info = DeviceInfo(
|
self._attr_device_info = DeviceInfo(
|
||||||
@@ -112,7 +123,7 @@ class QbusEntity(Entity, Generic[StateT], ABC):
|
|||||||
manufacturer=MANUFACTURER,
|
manufacturer=MANUFACTURER,
|
||||||
identifiers={(DOMAIN, f"{mqtt_output.device.serial_number}_{ref_id}")},
|
identifiers={(DOMAIN, f"{mqtt_output.device.serial_number}_{ref_id}")},
|
||||||
suggested_area=mqtt_output.location.title(),
|
suggested_area=mqtt_output.location.title(),
|
||||||
via_device=create_main_device_identifier(mqtt_output),
|
via_device=create_device_identifier(mqtt_output.device),
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_added_to_hass(self) -> None:
|
async def async_added_to_hass(self) -> None:
|
||||||
|
12
homeassistant/components/qbus/icons.json
Normal file
12
homeassistant/components/qbus/icons.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"entity": {
|
||||||
|
"binary_sensor": {
|
||||||
|
"raining": {
|
||||||
|
"default": "mdi:weather-pouring"
|
||||||
|
},
|
||||||
|
"twilight": {
|
||||||
|
"default": "mdi:weather-sunset"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -17,6 +17,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"entity": {
|
"entity": {
|
||||||
|
"binary_sensor": {
|
||||||
|
"raining": {
|
||||||
|
"name": "Raining"
|
||||||
|
},
|
||||||
|
"twilight": {
|
||||||
|
"name": "Twilight"
|
||||||
|
}
|
||||||
|
},
|
||||||
"sensor": {
|
"sensor": {
|
||||||
"daylight": {
|
"daylight": {
|
||||||
"name": "Daylight"
|
"name": "Daylight"
|
||||||
|
146
tests/components/qbus/snapshots/test_binary_sensor.ambr
Normal file
146
tests/components/qbus/snapshots/test_binary_sensor.ambr
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
# serializer version: 1
|
||||||
|
# name: test_binary_sensor[binary_sensor.ctd_000001-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': None,
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'binary_sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'binary_sensor.ctd_000001',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <BinarySensorDeviceClass.CONNECTIVITY: 'connectivity'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': None,
|
||||||
|
'platform': 'qbus',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'suggested_object_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': None,
|
||||||
|
'unique_id': 'ctd_000001_connected',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_binary_sensor[binary_sensor.ctd_000001-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'connectivity',
|
||||||
|
'friendly_name': 'CTD 000001',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'binary_sensor.ctd_000001',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'unknown',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_binary_sensor[binary_sensor.weersensor_raining-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': None,
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'binary_sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'binary_sensor.weersensor_raining',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': None,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Raining',
|
||||||
|
'platform': 'qbus',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'suggested_object_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'raining',
|
||||||
|
'unique_id': 'ctd_000001_21007_raining',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_binary_sensor[binary_sensor.weersensor_raining-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'friendly_name': 'Weersensor Raining',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'binary_sensor.weersensor_raining',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'unknown',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_binary_sensor[binary_sensor.weersensor_twilight-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': None,
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'binary_sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'binary_sensor.weersensor_twilight',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': None,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Twilight',
|
||||||
|
'platform': 'qbus',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'suggested_object_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'twilight',
|
||||||
|
'unique_id': 'ctd_000001_21007_twilight',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_binary_sensor[binary_sensor.weersensor_twilight-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'friendly_name': 'Weersensor Twilight',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'binary_sensor.weersensor_twilight',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'unknown',
|
||||||
|
})
|
||||||
|
# ---
|
27
tests/components/qbus/test_binary_sensor.py
Normal file
27
tests/components/qbus/test_binary_sensor.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
"""Test Qbus binary sensors."""
|
||||||
|
|
||||||
|
from collections.abc import Awaitable, Callable
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.const import Platform
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry, snapshot_platform
|
||||||
|
|
||||||
|
|
||||||
|
async def test_binary_sensor(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
setup_integration_deferred: Callable[[], Awaitable],
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test binary sensor."""
|
||||||
|
|
||||||
|
with patch("homeassistant.components.qbus.PLATFORMS", [Platform.BINARY_SENSOR]):
|
||||||
|
await setup_integration_deferred()
|
||||||
|
|
||||||
|
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
Reference in New Issue
Block a user