From 53844488d8dec6354a6085adbb71f5a0ae58e6fa Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Sun, 12 Jul 2020 22:03:22 +0200 Subject: [PATCH] Switch rfxtrx to integration level config (#37742) * Switch to integration level config * Switch to per device config rather than per entity type * All roller shutters should be added as covers (there are non lighting types) * Fixup tests that used invalid packets for platforms * Avoid variable re-use * Allow control events on sensors too That way we get signal level sensors for these too * Lint correction * Don't filter sensors from config Disable sensors from GUI if the entities are not wanted * Correct usage of ATTR_ instead of CONF_ * Make sure the logging when a new entity is added includes the event --- homeassistant/components/rfxtrx/__init__.py | 44 +++-- .../components/rfxtrx/binary_sensor.py | 59 ++---- homeassistant/components/rfxtrx/cover.py | 53 ++--- homeassistant/components/rfxtrx/light.py | 54 ++--- homeassistant/components/rfxtrx/sensor.py | 98 ++++------ homeassistant/components/rfxtrx/switch.py | 58 +++--- tests/components/rfxtrx/conftest.py | 71 +------ tests/components/rfxtrx/test_binary_sensor.py | 176 +++++++---------- tests/components/rfxtrx/test_cover.py | 126 ++++-------- tests/components/rfxtrx/test_init.py | 86 ++------ tests/components/rfxtrx/test_light.py | 175 +++++------------ tests/components/rfxtrx/test_sensor.py | 145 ++++++-------- tests/components/rfxtrx/test_switch.py | 185 ++++-------------- 13 files changed, 430 insertions(+), 900 deletions(-) diff --git a/homeassistant/components/rfxtrx/__init__.py b/homeassistant/components/rfxtrx/__init__.py index bdb810df6a5..7b3dc6ef276 100644 --- a/homeassistant/components/rfxtrx/__init__.py +++ b/homeassistant/components/rfxtrx/__init__.py @@ -6,10 +6,15 @@ import logging import RFXtrx as rfxtrxmod import voluptuous as vol +from homeassistant.components.binary_sensor import DEVICE_CLASSES_SCHEMA from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_STATE, + CONF_COMMAND_OFF, + CONF_COMMAND_ON, CONF_DEVICE, + CONF_DEVICE_CLASS, + CONF_DEVICES, CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_START, @@ -20,6 +25,7 @@ from homeassistant.const import ( UV_INDEX, ) import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.discovery import load_platform from homeassistant.helpers.entity import Entity from homeassistant.util import slugify @@ -29,15 +35,9 @@ DOMAIN = "rfxtrx" DEFAULT_SIGNAL_REPETITIONS = 1 -ATTR_AUTOMATIC_ADD = "automatic_add" -ATTR_DEVICE = "device" -ATTR_DEBUG = "debug" ATTR_FIRE_EVENT = "fire_event" -ATTR_DATA_TYPE = "data_type" -ATTR_DUMMY = "dummy" CONF_DATA_BITS = "data_bits" CONF_AUTOMATIC_ADD = "automatic_add" -CONF_DATA_TYPE = "data_type" CONF_SIGNAL_REPETITIONS = "signal_repetitions" CONF_FIRE_EVENT = "fire_event" CONF_DUMMY = "dummy" @@ -83,10 +83,25 @@ DATA_TYPES = OrderedDict( _LOGGER = logging.getLogger(__name__) DATA_RFXOBJECT = "rfxobject" + +DEVICE_SCHEMA = vol.Schema( + { + vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, + vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean, + vol.Optional(CONF_OFF_DELAY): vol.Any(cv.time_period, cv.positive_timedelta), + vol.Optional(CONF_DATA_BITS): cv.positive_int, + vol.Optional(CONF_COMMAND_ON): cv.byte, + vol.Optional(CONF_COMMAND_OFF): cv.byte, + vol.Optional(CONF_SIGNAL_REPETITIONS, default=1): cv.positive_int, + } +) + BASE_SCHEMA = vol.Schema( { vol.Optional(CONF_DEBUG, default=False): cv.boolean, vol.Optional(CONF_DUMMY, default=False): cv.boolean, + vol.Optional(CONF_AUTOMATIC_ADD, default=False): cv.boolean, + vol.Optional(CONF_DEVICES, default={}): {cv.string: DEVICE_SCHEMA}, } ) @@ -121,11 +136,11 @@ def setup(hass, config): # Callback to HA registered components. hass.helpers.dispatcher.dispatcher_send(SIGNAL_EVENT, event) - device = config[DOMAIN].get(ATTR_DEVICE) + device = config[DOMAIN].get(CONF_DEVICE) host = config[DOMAIN].get(CONF_HOST) port = config[DOMAIN].get(CONF_PORT) - debug = config[DOMAIN][ATTR_DEBUG] - dummy_connection = config[DOMAIN][ATTR_DUMMY] + debug = config[DOMAIN][CONF_DEBUG] + dummy_connection = config[DOMAIN][CONF_DUMMY] if dummy_connection: rfx_object = rfxtrxmod.Connect( @@ -154,6 +169,13 @@ def setup(hass, config): hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown_rfxtrx) hass.data[DATA_RFXOBJECT] = rfx_object + + load_platform(hass, "switch", DOMAIN, config[DOMAIN], config) + load_platform(hass, "light", DOMAIN, config[DOMAIN], config) + load_platform(hass, "cover", DOMAIN, config[DOMAIN], config) + load_platform(hass, "binary_sensor", DOMAIN, config[DOMAIN], config) + load_platform(hass, "sensor", DOMAIN, config[DOMAIN], config) + return True @@ -265,10 +287,10 @@ class RfxtrxDevice(Entity): Contains the common logic for Rfxtrx lights and switches. """ - def __init__(self, name, device, datas, signal_repetitions, event=None): + def __init__(self, device, datas, signal_repetitions, event=None): """Initialize the device.""" self.signal_repetitions = signal_repetitions - self._name = name + self._name = f"{device.type_string} {device.id_string}" self._device = device self._state = datas[ATTR_STATE] self._should_fire_event = datas[ATTR_FIRE_EVENT] diff --git a/homeassistant/components/rfxtrx/binary_sensor.py b/homeassistant/components/rfxtrx/binary_sensor.py index 529e20c956e..4972a8e5622 100644 --- a/homeassistant/components/rfxtrx/binary_sensor.py +++ b/homeassistant/components/rfxtrx/binary_sensor.py @@ -2,21 +2,15 @@ import logging import RFXtrx as rfxtrxmod -import voluptuous as vol -from homeassistant.components.binary_sensor import ( - DEVICE_CLASSES_SCHEMA, - PLATFORM_SCHEMA, - BinarySensorEntity, -) +from homeassistant.components.binary_sensor import BinarySensorEntity from homeassistant.const import ( CONF_COMMAND_OFF, CONF_COMMAND_ON, CONF_DEVICE_CLASS, CONF_DEVICES, - CONF_NAME, ) -from homeassistant.helpers import config_validation as cv, event as evt +from homeassistant.helpers import event as evt from . import ( CONF_AUTOMATIC_ADD, @@ -36,29 +30,6 @@ from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST, DEVICE_PACKET_TYPE_LIGHTIN _LOGGER = logging.getLogger(__name__) -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - vol.Optional(CONF_DEVICES, default={}): { - cv.string: vol.Schema( - { - vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, - vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean, - vol.Optional(CONF_OFF_DELAY): vol.Any( - cv.time_period, cv.positive_timedelta - ), - vol.Optional(CONF_DATA_BITS): cv.positive_int, - vol.Optional(CONF_COMMAND_ON): cv.byte, - vol.Optional(CONF_COMMAND_OFF): cv.byte, - } - ) - }, - vol.Optional(CONF_AUTOMATIC_ADD, default=False): cv.boolean, - }, - extra=vol.ALLOW_EXTRA, -) - - def _get_device_data_bits(device, device_bits): """Deduce data bits for device based on a cache of device bits.""" data_bits = None @@ -72,6 +43,9 @@ def _get_device_data_bits(device, device_bits): def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the Binary Sensor platform to RFXtrx.""" + if discovery_info is None: + return + sensors = [] device_ids = set() @@ -79,11 +53,16 @@ def setup_platform(hass, config, add_entities, discovery_info=None): pt2262_devices = [] - for packet_id, entity in config[CONF_DEVICES].items(): + def supported(event): + return isinstance(event, rfxtrxmod.ControlEvent) + + for packet_id, entity in discovery_info[CONF_DEVICES].items(): event = get_rfx_object(packet_id) if event is None: _LOGGER.error("Invalid device: %s", packet_id) continue + if not supported(event): + return device_id = get_device_id(event.device, data_bits=entity.get(CONF_DATA_BITS)) if device_id in device_ids: @@ -96,7 +75,6 @@ def setup_platform(hass, config, add_entities, discovery_info=None): device = RfxtrxBinarySensor( event.device, - entity.get(CONF_NAME), entity.get(CONF_DEVICE_CLASS), entity[CONF_FIRE_EVENT], entity.get(CONF_OFF_DELAY), @@ -110,7 +88,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): def binary_sensor_update(event): """Call for control updates from the RFXtrx gateway.""" - if not isinstance(event, rfxtrxmod.ControlEvent): + if not supported(event): return data_bits = _get_device_data_bits(event.device, device_bits) @@ -121,19 +99,17 @@ def setup_platform(hass, config, add_entities, discovery_info=None): device_ids.add(device_id) _LOGGER.info( - "Added binary sensor (Device ID: %s Class: %s Sub: %s)", + "Added binary sensor (Device ID: %s Class: %s Sub: %s Event: %s)", event.device.id_string.lower(), event.device.__class__.__name__, event.device.subtype, + "".join(f"{x:02x}" for x in event.data), ) - pkt_id = "".join(f"{x:02x}" for x in event.data) - sensor = RfxtrxBinarySensor( - event.device, pkt_id, data_bits=data_bits, event=event - ) + sensor = RfxtrxBinarySensor(event.device, data_bits=data_bits, event=event) add_entities([sensor]) # Subscribe to main RFXtrx events - if config[CONF_AUTOMATIC_ADD]: + if discovery_info[CONF_AUTOMATIC_ADD]: hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, binary_sensor_update) @@ -143,7 +119,6 @@ class RfxtrxBinarySensor(BinarySensorEntity): def __init__( self, device, - name, device_class=None, should_fire=False, off_delay=None, @@ -155,7 +130,7 @@ class RfxtrxBinarySensor(BinarySensorEntity): """Initialize the RFXtrx sensor.""" self.event = None self._device = device - self._name = name + self._name = f"{device.type_string} {device.id_string}" self._should_fire_event = should_fire self._device_class = device_class self._off_delay = off_delay diff --git a/homeassistant/components/rfxtrx/cover.py b/homeassistant/components/rfxtrx/cover.py index cdb0a21e3b4..afc37186a47 100644 --- a/homeassistant/components/rfxtrx/cover.py +++ b/homeassistant/components/rfxtrx/cover.py @@ -1,12 +1,8 @@ """Support for RFXtrx covers.""" import logging -import RFXtrx as rfxtrxmod -import voluptuous as vol - -from homeassistant.components.cover import PLATFORM_SCHEMA, CoverEntity -from homeassistant.const import ATTR_STATE, CONF_DEVICES, CONF_NAME, STATE_OPEN -from homeassistant.helpers import config_validation as cv +from homeassistant.components.cover import CoverEntity +from homeassistant.const import ATTR_STATE, CONF_DEVICES, STATE_OPEN from homeassistant.helpers.restore_state import RestoreEntity from . import ( @@ -23,36 +19,27 @@ from . import ( ) from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - vol.Optional(CONF_DEVICES, default={}): { - cv.string: vol.Schema( - { - vol.Required(CONF_NAME): cv.string, - vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean, - } - ) - }, - vol.Optional(CONF_AUTOMATIC_ADD, default=False): cv.boolean, - vol.Optional( - CONF_SIGNAL_REPETITIONS, default=DEFAULT_SIGNAL_REPETITIONS - ): vol.Coerce(int), - } -) - _LOGGER = logging.getLogger(__name__) def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the RFXtrx cover.""" + if discovery_info is None: + return + device_ids = set() + def supported(event): + return event.device.known_to_be_rollershutter + entities = [] - for packet_id, entity_info in config[CONF_DEVICES].items(): + for packet_id, entity_info in discovery_info[CONF_DEVICES].items(): event = get_rfx_object(packet_id) if event is None: _LOGGER.error("Invalid device: %s", packet_id) continue + if not supported(event): + continue device_id = get_device_id(event.device) if device_id in device_ids: @@ -60,20 +47,14 @@ def setup_platform(hass, config, add_entities, discovery_info=None): device_ids.add(device_id) datas = {ATTR_STATE: None, ATTR_FIRE_EVENT: entity_info[CONF_FIRE_EVENT]} - entity = RfxtrxCover( - entity_info[CONF_NAME], event.device, datas, config[CONF_SIGNAL_REPETITIONS] - ) + entity = RfxtrxCover(event.device, datas, entity_info[CONF_SIGNAL_REPETITIONS]) entities.append(entity) add_entities(entities) def cover_update(event): """Handle cover updates from the RFXtrx gateway.""" - if ( - not isinstance(event.device, rfxtrxmod.LightingDevice) - or event.device.known_to_be_dimmable - or not event.device.known_to_be_rollershutter - ): + if not supported(event): return device_id = get_device_id(event.device) @@ -82,21 +63,21 @@ def setup_platform(hass, config, add_entities, discovery_info=None): device_ids.add(device_id) _LOGGER.info( - "Added cover (Device ID: %s Class: %s Sub: %s)", + "Added cover (Device ID: %s Class: %s Sub: %s, Event: %s)", event.device.id_string.lower(), event.device.__class__.__name__, event.device.subtype, + "".join(f"{x:02x}" for x in event.data), ) - pkt_id = "".join(f"{x:02x}" for x in event.data) datas = {ATTR_STATE: False, ATTR_FIRE_EVENT: False} entity = RfxtrxCover( - pkt_id, event.device, datas, DEFAULT_SIGNAL_REPETITIONS, event=event + event.device, datas, DEFAULT_SIGNAL_REPETITIONS, event=event ) add_entities([entity]) # Subscribe to main RFXtrx events - if config[CONF_AUTOMATIC_ADD]: + if discovery_info[CONF_AUTOMATIC_ADD]: hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, cover_update) diff --git a/homeassistant/components/rfxtrx/light.py b/homeassistant/components/rfxtrx/light.py index 74915f2b91a..c92d9c2ffce 100644 --- a/homeassistant/components/rfxtrx/light.py +++ b/homeassistant/components/rfxtrx/light.py @@ -2,16 +2,13 @@ import logging import RFXtrx as rfxtrxmod -import voluptuous as vol from homeassistant.components.light import ( ATTR_BRIGHTNESS, - PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS, LightEntity, ) -from homeassistant.const import ATTR_STATE, CONF_DEVICES, CONF_NAME, STATE_ON -from homeassistant.helpers import config_validation as cv +from homeassistant.const import ATTR_STATE, CONF_DEVICES, STATE_ON from homeassistant.helpers.restore_state import RestoreEntity from . import ( @@ -30,37 +27,31 @@ from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST _LOGGER = logging.getLogger(__name__) -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - vol.Optional(CONF_DEVICES, default={}): { - cv.string: vol.Schema( - { - vol.Required(CONF_NAME): cv.string, - vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean, - } - ) - }, - vol.Optional(CONF_AUTOMATIC_ADD, default=False): cv.boolean, - vol.Optional( - CONF_SIGNAL_REPETITIONS, default=DEFAULT_SIGNAL_REPETITIONS - ): vol.Coerce(int), - } -) - SUPPORT_RFXTRX = SUPPORT_BRIGHTNESS def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the RFXtrx platform.""" + if discovery_info is None: + return + device_ids = set() + def supported(event): + return ( + isinstance(event.device, rfxtrxmod.LightingDevice) + and event.device.known_to_be_dimmable + ) + # Add switch from config file entities = [] - for packet_id, entity_info in config[CONF_DEVICES].items(): + for packet_id, entity_info in discovery_info[CONF_DEVICES].items(): event = get_rfx_object(packet_id) if event is None: _LOGGER.error("Invalid device: %s", packet_id) continue + if not supported(event): + return device_id = get_device_id(event.device) if device_id in device_ids: @@ -68,9 +59,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): device_ids.add(device_id) datas = {ATTR_STATE: None, ATTR_FIRE_EVENT: entity_info[CONF_FIRE_EVENT]} - entity = RfxtrxLight( - entity_info[CONF_NAME], event.device, datas, config[CONF_SIGNAL_REPETITIONS] - ) + entity = RfxtrxLight(event.device, datas, entity_info[CONF_SIGNAL_REPETITIONS]) entities.append(entity) @@ -78,10 +67,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): def light_update(event): """Handle light updates from the RFXtrx gateway.""" - if ( - not isinstance(event.device, rfxtrxmod.LightingDevice) - or not event.device.known_to_be_dimmable - ): + if not supported(event): return device_id = get_device_id(event.device) @@ -89,23 +75,23 @@ def setup_platform(hass, config, add_entities, discovery_info=None): return device_ids.add(device_id) - _LOGGER.debug( - "Added light (Device ID: %s Class: %s Sub: %s)", + _LOGGER.info( + "Added light (Device ID: %s Class: %s Sub: %s, Event: %s)", event.device.id_string.lower(), event.device.__class__.__name__, event.device.subtype, + "".join(f"{x:02x}" for x in event.data), ) - pkt_id = "".join(f"{x:02x}" for x in event.data) datas = {ATTR_STATE: None, ATTR_FIRE_EVENT: False} entity = RfxtrxLight( - pkt_id, event.device, datas, DEFAULT_SIGNAL_REPETITIONS, event=event + event.device, datas, DEFAULT_SIGNAL_REPETITIONS, event=event ) add_entities([entity]) # Subscribe to main RFXtrx events - if config[CONF_AUTOMATIC_ADD]: + if discovery_info[CONF_AUTOMATIC_ADD]: hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, light_update) diff --git a/homeassistant/components/rfxtrx/sensor.py b/homeassistant/components/rfxtrx/sensor.py index eee6a590533..52fca503aae 100644 --- a/homeassistant/components/rfxtrx/sensor.py +++ b/homeassistant/components/rfxtrx/sensor.py @@ -1,23 +1,19 @@ """Support for RFXtrx sensors.""" import logging -from RFXtrx import SensorEvent -import voluptuous as vol +from RFXtrx import ControlEvent, SensorEvent from homeassistant.components.sensor import ( DEVICE_CLASS_BATTERY, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_SIGNAL_STRENGTH, DEVICE_CLASS_TEMPERATURE, - PLATFORM_SCHEMA, ) -from homeassistant.const import ATTR_ENTITY_ID, CONF_DEVICES, CONF_NAME -import homeassistant.helpers.config_validation as cv +from homeassistant.const import ATTR_ENTITY_ID, CONF_DEVICES from homeassistant.helpers.entity import Entity from . import ( CONF_AUTOMATIC_ADD, - CONF_DATA_TYPE, CONF_FIRE_EVENT, DATA_TYPES, SIGNAL_EVENT, @@ -27,24 +23,6 @@ from . import ( _LOGGER = logging.getLogger(__name__) -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - vol.Optional(CONF_DEVICES, default={}): { - cv.string: vol.Schema( - { - vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean, - vol.Optional(CONF_DATA_TYPE, default=[]): vol.All( - cv.ensure_list, [vol.In(DATA_TYPES.keys())] - ), - } - ) - }, - vol.Optional(CONF_AUTOMATIC_ADD, default=False): cv.boolean, - }, - extra=vol.ALLOW_EXTRA, -) - def _battery_convert(value): """Battery is given as a value between 0 and 9.""" @@ -76,43 +54,23 @@ CONVERT_FUNCTIONS = { def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the RFXtrx platform.""" + if discovery_info is None: + return + data_ids = set() + def supported(event): + return isinstance(event, (ControlEvent, SensorEvent)) + entities = [] - for packet_id, entity_info in config[CONF_DEVICES].items(): + for packet_id, entity_info in discovery_info[CONF_DEVICES].items(): event = get_rfx_object(packet_id) if event is None: _LOGGER.error("Invalid device: %s", packet_id) continue + if not supported(event): + continue - if entity_info[CONF_DATA_TYPE]: - data_types = entity_info[CONF_DATA_TYPE] - else: - data_types = list(set(event.values) & set(DATA_TYPES)) - - device_id = get_device_id(event.device) - for data_type in data_types: - data_id = (*device_id, data_type) - if data_id in data_ids: - continue - data_ids.add(data_id) - - entity = RfxtrxSensor( - event.device, - entity_info[CONF_NAME], - data_type, - entity_info[CONF_FIRE_EVENT], - ) - entities.append(entity) - - add_entities(entities) - - def sensor_update(event): - """Handle sensor updates from the RFXtrx gateway.""" - if not isinstance(event, SensorEvent): - return - - pkt_id = "".join(f"{x:02x}" for x in event.data) device_id = get_device_id(event.device) for data_type in set(event.values) & set(DATA_TYPES): data_id = (*device_id, data_type) @@ -120,29 +78,49 @@ def setup_platform(hass, config, add_entities, discovery_info=None): continue data_ids.add(data_id) - _LOGGER.debug( - "Added sensor (Device ID: %s Class: %s Sub: %s)", + entity = RfxtrxSensor( + event.device, data_type, entity_info[CONF_FIRE_EVENT], + ) + entities.append(entity) + + add_entities(entities) + + def sensor_update(event): + """Handle sensor updates from the RFXtrx gateway.""" + if not supported(event): + return + + device_id = get_device_id(event.device) + for data_type in set(event.values) & set(DATA_TYPES): + data_id = (*device_id, data_type) + if data_id in data_ids: + continue + data_ids.add(data_id) + + _LOGGER.info( + "Added sensor (Device ID: %s Class: %s Sub: %s, Event: %s)", event.device.id_string.lower(), event.device.__class__.__name__, event.device.subtype, + "".join(f"{x:02x}" for x in event.data), ) - entity = RfxtrxSensor(event.device, pkt_id, data_type, event=event) + entity = RfxtrxSensor(event.device, data_type, event=event) add_entities([entity]) # Subscribe to main RFXtrx events - if config[CONF_AUTOMATIC_ADD]: + if discovery_info[CONF_AUTOMATIC_ADD]: hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, sensor_update) class RfxtrxSensor(Entity): """Representation of a RFXtrx sensor.""" - def __init__(self, device, name, data_type, should_fire_event=False, event=None): + def __init__(self, device, data_type, should_fire_event=False, event=None): """Initialize the sensor.""" self.event = None self._device = device - self._name = name + self._name = f"{device.type_string} {device.id_string} {data_type}" self.should_fire_event = should_fire_event self.data_type = data_type self._unit_of_measurement = DATA_TYPES.get(data_type, "") @@ -180,7 +158,7 @@ class RfxtrxSensor(Entity): @property def name(self): """Get the name of the sensor.""" - return f"{self._name} {self.data_type}" + return self._name @property def device_state_attributes(self): diff --git a/homeassistant/components/rfxtrx/switch.py b/homeassistant/components/rfxtrx/switch.py index e66ce8be8a3..3f08deb64a2 100644 --- a/homeassistant/components/rfxtrx/switch.py +++ b/homeassistant/components/rfxtrx/switch.py @@ -2,11 +2,9 @@ import logging import RFXtrx as rfxtrxmod -import voluptuous as vol -from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchEntity -from homeassistant.const import ATTR_STATE, CONF_DEVICES, CONF_NAME, STATE_ON -from homeassistant.helpers import config_validation as cv +from homeassistant.components.switch import SwitchEntity +from homeassistant.const import ATTR_STATE, CONF_DEVICES, STATE_ON from homeassistant.helpers.restore_state import RestoreEntity from . import ( @@ -15,6 +13,7 @@ from . import ( CONF_FIRE_EVENT, CONF_SIGNAL_REPETITIONS, DEFAULT_SIGNAL_REPETITIONS, + DOMAIN, SIGNAL_EVENT, RfxtrxDevice, fire_command_event, @@ -23,37 +22,34 @@ from . import ( ) from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST -_LOGGER = logging.getLogger(__name__) +DATA_SWITCH = f"{DOMAIN}_switch" -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - vol.Optional(CONF_DEVICES, default={}): { - cv.string: vol.Schema( - { - vol.Required(CONF_NAME): cv.string, - vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean, - } - ) - }, - vol.Optional(CONF_AUTOMATIC_ADD, default=False): cv.boolean, - vol.Optional( - CONF_SIGNAL_REPETITIONS, default=DEFAULT_SIGNAL_REPETITIONS - ): vol.Coerce(int), - } -) +_LOGGER = logging.getLogger(__name__) def setup_platform(hass, config, add_entities_callback, discovery_info=None): """Set up the RFXtrx platform.""" + if discovery_info is None: + return + device_ids = set() + def supported(event): + return ( + isinstance(event.device, rfxtrxmod.LightingDevice) + and not event.device.known_to_be_dimmable + and not event.device.known_to_be_rollershutter + ) + # Add switch from config file entities = [] - for packet_id, entity_info in config[CONF_DEVICES].items(): + for packet_id, entity_info in discovery_info[CONF_DEVICES].items(): event = get_rfx_object(packet_id) if event is None: _LOGGER.error("Invalid device: %s", packet_id) continue + if not supported(event): + continue device_id = get_device_id(event.device) if device_id in device_ids: @@ -61,20 +57,14 @@ def setup_platform(hass, config, add_entities_callback, discovery_info=None): device_ids.add(device_id) datas = {ATTR_STATE: None, ATTR_FIRE_EVENT: entity_info[CONF_FIRE_EVENT]} - entity = RfxtrxSwitch( - entity_info[CONF_NAME], event.device, datas, config[CONF_SIGNAL_REPETITIONS] - ) + entity = RfxtrxSwitch(event.device, datas, entity_info[CONF_SIGNAL_REPETITIONS]) entities.append(entity) add_entities_callback(entities) def switch_update(event): """Handle sensor updates from the RFXtrx gateway.""" - if ( - not isinstance(event.device, rfxtrxmod.LightingDevice) - or event.device.known_to_be_dimmable - or event.device.known_to_be_rollershutter - ): + if not supported(event): return device_id = get_device_id(event.device) @@ -83,21 +73,21 @@ def setup_platform(hass, config, add_entities_callback, discovery_info=None): device_ids.add(device_id) _LOGGER.info( - "Added switch (Device ID: %s Class: %s Sub: %s)", + "Added switch (Device ID: %s Class: %s Sub: %s, Event: %s)", event.device.id_string.lower(), event.device.__class__.__name__, event.device.subtype, + "".join(f"{x:02x}" for x in event.data), ) - pkt_id = "".join(f"{x:02x}" for x in event.data) datas = {ATTR_STATE: None, ATTR_FIRE_EVENT: False} entity = RfxtrxSwitch( - pkt_id, event.device, datas, DEFAULT_SIGNAL_REPETITIONS, event=event + event.device, datas, DEFAULT_SIGNAL_REPETITIONS, event=event ) add_entities_callback([entity]) # Subscribe to main RFXtrx events - if config[CONF_AUTOMATIC_ADD]: + if discovery_info[CONF_AUTOMATIC_ADD]: hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, switch_update) diff --git a/tests/components/rfxtrx/conftest.py b/tests/components/rfxtrx/conftest.py index 18ab207677f..eba322de5a3 100644 --- a/tests/components/rfxtrx/conftest.py +++ b/tests/components/rfxtrx/conftest.py @@ -1,75 +1,12 @@ """Common test tools.""" -import threading from unittest import mock -import RFXtrx import pytest -from homeassistant.components import rfxtrx as rfxtrx_core -from tests.common import mock_component - - -class FixedDummySerial(RFXtrx._dummySerial): # pylint: disable=protected-access - """Fixed dummy serial that doesn't cause max CPU usage.""" - - def __init__(self, *args, **kwargs): - """Init.""" - super().__init__(*args, **kwargs) - self._close_event = threading.Event() - - def read(self, data=None): - """Read.""" - res = super().read(data) - if not res and not data: - self._close_event.wait(0.1) - return res - - def close(self): - """Close.""" - self._close_event.set() - - -class FixedDummyTransport(RFXtrx.DummyTransport): - """Fixed dummy transport that maxes CPU.""" - - def __init__(self, device="", debug=True): - """Init.""" - super().__init__(device, debug) - self._close_event = threading.Event() - - def receive_blocking(self, data=None): - """Read.""" - res = super().receive_blocking(data) - if not res: - self._close_event.wait(0.1) - return res - - def close(self): - """Close.""" - self._close_event.set() - - -@pytest.fixture(autouse=True) -async def rfxtrx_cleanup(): +@pytest.fixture(autouse=True, name="rfxtrx") +async def rfxtrx(hass): """Fixture that cleans up threads from integration.""" - with mock.patch("RFXtrx._dummySerial", new=FixedDummySerial), mock.patch( - "RFXtrx.DummyTransport", new=FixedDummyTransport - ): - yield - - -@pytest.fixture(name="rfxtrx") -async def rfxtrx_fixture(hass): - """Stub out core rfxtrx to test platform.""" - mock_component(hass, "rfxtrx") - - rfxobject = mock.MagicMock() - hass.data[rfxtrx_core.DATA_RFXOBJECT] = rfxobject - - yield rfxobject - - # These test don't listen for stop to do cleanup. - if rfxtrx_core.DATA_RFXOBJECT in hass.data: - hass.data[rfxtrx_core.DATA_RFXOBJECT].close_connection() + with mock.patch("RFXtrx.Connect") as connect, mock.patch("RFXtrx.DummyTransport2"): + yield connect.return_value diff --git a/tests/components/rfxtrx/test_binary_sensor.py b/tests/components/rfxtrx/test_binary_sensor.py index 60a5b3d8c73..74f20a8c062 100644 --- a/tests/components/rfxtrx/test_binary_sensor.py +++ b/tests/components/rfxtrx/test_binary_sensor.py @@ -9,47 +9,38 @@ from . import _signal_event from tests.common import async_fire_time_changed -async def test_default_config(hass, rfxtrx): - """Test with 0 sensor.""" - await async_setup_component( - hass, "binary_sensor", {"binary_sensor": {"platform": "rfxtrx", "devices": {}}} - ) - await hass.async_block_till_done() - - assert len(hass.states.async_all()) == 0 - - async def test_one(hass, rfxtrx): """Test with 1 sensor.""" - await async_setup_component( + assert await async_setup_component( hass, - "binary_sensor", + "rfxtrx", { - "binary_sensor": { - "platform": "rfxtrx", - "devices": {"0a52080705020095220269": {"name": "Test"}}, + "rfxtrx": { + "device": "abcd", + "dummy": True, + "devices": {"0b1100cd0213c7f230010f71": {}}, } }, ) await hass.async_block_till_done() - state = hass.states.get("binary_sensor.test") + state = hass.states.get("binary_sensor.ac_213c7f2_48") assert state assert state.state == "off" - assert state.attributes.get("friendly_name") == "Test" + assert state.attributes.get("friendly_name") == "AC 213c7f2:48" async def test_one_pt2262(hass, rfxtrx): """Test with 1 sensor.""" - await async_setup_component( + assert await async_setup_component( hass, - "binary_sensor", + "rfxtrx", { - "binary_sensor": { - "platform": "rfxtrx", + "rfxtrx": { + "device": "abcd", + "dummy": True, "devices": { "0913000022670e013970": { - "name": "Test", "data_bits": 4, "command_on": 0xE, "command_off": 0x7, @@ -60,136 +51,107 @@ async def test_one_pt2262(hass, rfxtrx): ) await hass.async_block_till_done() - state = hass.states.get("binary_sensor.test") + state = hass.states.get("binary_sensor.pt2262_22670e") assert state assert state.state == "off" # probably aught to be unknown - assert state.attributes.get("friendly_name") == "Test" + assert state.attributes.get("friendly_name") == "PT2262 22670e" await _signal_event(hass, "0913000022670e013970") - state = hass.states.get("binary_sensor.test") - assert state + state = hass.states.get("binary_sensor.pt2262_22670e") assert state.state == "on" - assert state.attributes.get("friendly_name") == "Test" await _signal_event(hass, "09130000226707013d70") - state = hass.states.get("binary_sensor.test") - assert state + state = hass.states.get("binary_sensor.pt2262_22670e") assert state.state == "off" - assert state.attributes.get("friendly_name") == "Test" async def test_several(hass, rfxtrx): """Test with 3.""" - await async_setup_component( + assert await async_setup_component( hass, - "binary_sensor", + "rfxtrx", { - "binary_sensor": { - "platform": "rfxtrx", + "rfxtrx": { + "device": "abcd", + "dummy": True, "devices": { - "0b1100cd0213c7f230010f71": {"name": "Test"}, - "0b1100100118cdea02010f70": {"name": "Bath"}, - "0b1100101118cdea02010f70": {"name": "Living"}, + "0b1100cd0213c7f230010f71": {}, + "0b1100100118cdea02010f70": {}, + "0b1100101118cdea02010f70": {}, }, } }, ) await hass.async_block_till_done() - state = hass.states.get("binary_sensor.test") + state = hass.states.get("binary_sensor.ac_213c7f2_48") assert state assert state.state == "off" - assert state.attributes.get("friendly_name") == "Test" + assert state.attributes.get("friendly_name") == "AC 213c7f2:48" - state = hass.states.get("binary_sensor.bath") + state = hass.states.get("binary_sensor.ac_118cdea_2") assert state assert state.state == "off" - assert state.attributes.get("friendly_name") == "Bath" + assert state.attributes.get("friendly_name") == "AC 118cdea:2" - state = hass.states.get("binary_sensor.living") + state = hass.states.get("binary_sensor.ac_1118cdea_2") assert state assert state.state == "off" - assert state.attributes.get("friendly_name") == "Living" + assert state.attributes.get("friendly_name") == "AC 1118cdea:2" async def test_discover(hass, rfxtrx): """Test with discovery.""" - await async_setup_component( + assert await async_setup_component( hass, - "binary_sensor", - {"binary_sensor": {"platform": "rfxtrx", "automatic_add": True, "devices": {}}}, - ) - await hass.async_block_till_done() - - await _signal_event(hass, "0b1100100118cdea02010f70") - state = hass.states.get("binary_sensor.0b1100100118cdea02010f70") - assert state - assert state.state == "on" - - await _signal_event(hass, "0b1100100118cdeb02010f70") - state = hass.states.get("binary_sensor.0b1100100118cdeb02010f70") - assert state - assert state.state == "on" - - # Trying to add a sensor - await _signal_event(hass, "0a52085e070100b31b0279") - state = hass.states.get("sensor.0a52085e070100b31b0279") - assert state is None - - # Trying to add a light - await _signal_event(hass, "0b1100100118cdea02010f70") - state = hass.states.get("light.0b1100100118cdea02010f70") - assert state is None - - # Trying to add a rollershutter - await _signal_event(hass, "0a1400adf394ab020e0060") - state = hass.states.get("cover.0a1400adf394ab020e0060") - assert state is None - - -async def test_discover_noautoadd(hass, rfxtrx): - """Test with discovery of switch when auto add is False.""" - await async_setup_component( - hass, - "binary_sensor", + "rfxtrx", { - "binary_sensor": { - "platform": "rfxtrx", - "automatic_add": False, - "devices": {}, - } - }, - ) - await hass.async_block_till_done() - - # Trying to add switch - await _signal_event(hass, "0b1100100118cdea02010f70") - assert hass.states.async_all() == [] - - -async def test_off_delay(hass, rfxtrx): - """Test with discovery.""" - await async_setup_component( - hass, - "binary_sensor", - { - "binary_sensor": { - "platform": "rfxtrx", + "rfxtrx": { + "device": "abcd", + "dummy": True, "automatic_add": True, "devices": { - "0b1100100118cdea02010f70": {"name": "Test", "off_delay": 5} + "0b1100cd0213c7f230010f71": {}, + "0b1100100118cdea02010f70": {}, + "0b1100101118cdea02010f70": {}, }, } }, ) await hass.async_block_till_done() - state = hass.states.get("binary_sensor.test") + await _signal_event(hass, "0b1100100118cdea02010f70") + state = hass.states.get("binary_sensor.ac_118cdea_2") + assert state + assert state.state == "on" + + await _signal_event(hass, "0b1100100118cdeb02010f70") + state = hass.states.get("binary_sensor.ac_118cdeb_2") + assert state + assert state.state == "on" + + +async def test_off_delay(hass, rfxtrx): + """Test with discovery.""" + assert await async_setup_component( + hass, + "rfxtrx", + { + "rfxtrx": { + "device": "abcd", + "dummy": True, + "devices": {"0b1100100118cdea02010f70": {"off_delay": 5}}, + } + }, + ) + await hass.async_block_till_done() + + state = hass.states.get("binary_sensor.ac_118cdea_2") assert state assert state.state == "off" await _signal_event(hass, "0b1100100118cdea02010f70") - state = hass.states.get("binary_sensor.test") + state = hass.states.get("binary_sensor.ac_118cdea_2") assert state assert state.state == "on" @@ -197,12 +159,12 @@ async def test_off_delay(hass, rfxtrx): async_fire_time_changed(hass, base_time + timedelta(seconds=4)) await hass.async_block_till_done() - state = hass.states.get("binary_sensor.test") + state = hass.states.get("binary_sensor.ac_118cdea_2") assert state assert state.state == "on" async_fire_time_changed(hass, base_time + timedelta(seconds=6)) await hass.async_block_till_done() - state = hass.states.get("binary_sensor.test") + state = hass.states.get("binary_sensor.ac_118cdea_2") assert state assert state.state == "off" diff --git a/tests/components/rfxtrx/test_cover.py b/tests/components/rfxtrx/test_cover.py index 782800c5d8e..b32fb8aecb3 100644 --- a/tests/components/rfxtrx/test_cover.py +++ b/tests/components/rfxtrx/test_cover.py @@ -1,72 +1,48 @@ """The tests for the Rfxtrx cover platform.""" from unittest.mock import call -from homeassistant.components import rfxtrx as rfxtrx_core from homeassistant.setup import async_setup_component from . import _signal_event -from tests.common import assert_setup_component - - -async def test_valid_config(hass, rfxtrx): - """Test configuration.""" - with assert_setup_component(1): - assert await async_setup_component( - hass, - "cover", - { - "cover": { - "platform": "rfxtrx", - "automatic_add": True, - "devices": { - "0b1100cd0213c7f210010f51": { - "name": "Test", - rfxtrx_core.ATTR_FIRE_EVENT: True, - } - }, - } - }, - ) - await hass.async_block_till_done() - - -async def test_default_config(hass, rfxtrx): - """Test with 0 cover.""" - assert await async_setup_component( - hass, "cover", {"cover": {"platform": "rfxtrx", "devices": {}}} - ) - await hass.async_block_till_done() - - assert len(hass.states.async_all()) == 0 - async def test_one_cover(hass, rfxtrx): """Test with 1 cover.""" assert await async_setup_component( hass, - "cover", + "rfxtrx", { - "cover": { - "platform": "rfxtrx", - "devices": {"0b1400cd0213c7f210010f51": {"name": "Test"}}, + "rfxtrx": { + "device": "abcd", + "dummy": True, + "devices": {"0b1400cd0213c7f20d010f51": {}}, } }, ) await hass.async_block_till_done() - assert len(hass.states.async_all()) == 1 + state = hass.states.get("cover.lightwaverf_siemens_0213c7_242") + assert state await hass.services.async_call( - "cover", "open_cover", {"entity_id": "cover.test"}, blocking=True + "cover", + "open_cover", + {"entity_id": "cover.lightwaverf_siemens_0213c7_242"}, + blocking=True, ) await hass.services.async_call( - "cover", "close_cover", {"entity_id": "cover.test"}, blocking=True + "cover", + "close_cover", + {"entity_id": "cover.lightwaverf_siemens_0213c7_242"}, + blocking=True, ) await hass.services.async_call( - "cover", "stop_cover", {"entity_id": "cover.test"}, blocking=True + "cover", + "stop_cover", + {"entity_id": "cover.lightwaverf_siemens_0213c7_242"}, + blocking=True, ) assert rfxtrx.transport.send.mock_calls == [ @@ -80,74 +56,52 @@ async def test_several_covers(hass, rfxtrx): """Test with 3 covers.""" assert await async_setup_component( hass, - "cover", + "rfxtrx", { - "cover": { - "platform": "rfxtrx", - "signal_repetitions": 3, + "rfxtrx": { + "device": "abcd", + "dummy": True, "devices": { - "0b1100cd0213c7f230010f71": {"name": "Test"}, - "0b1100100118cdea02010f70": {"name": "Bath"}, - "0b1100101118cdea02010f70": {"name": "Living"}, + "0b1400cd0213c7f20d010f51": {}, + "0A1400ADF394AB010D0060": {}, + "09190000009ba8010100": {}, }, } }, ) await hass.async_block_till_done() - state = hass.states.get("cover.test") + state = hass.states.get("cover.lightwaverf_siemens_0213c7_242") assert state assert state.state == "closed" - assert state.attributes.get("friendly_name") == "Test" + assert state.attributes.get("friendly_name") == "LightwaveRF, Siemens 0213c7:242" - state = hass.states.get("cover.bath") + state = hass.states.get("cover.lightwaverf_siemens_f394ab_1") assert state assert state.state == "closed" - assert state.attributes.get("friendly_name") == "Bath" + assert state.attributes.get("friendly_name") == "LightwaveRF, Siemens f394ab:1" - state = hass.states.get("cover.living") + state = hass.states.get("cover.rollertrol_009ba8_1") assert state assert state.state == "closed" - assert state.attributes.get("friendly_name") == "Living" - - assert len(hass.states.async_all()) == 3 + assert state.attributes.get("friendly_name") == "RollerTrol 009ba8:1" async def test_discover_covers(hass, rfxtrx): """Test with discovery of covers.""" assert await async_setup_component( hass, - "cover", - {"cover": {"platform": "rfxtrx", "automatic_add": True, "devices": {}}}, + "rfxtrx", + {"rfxtrx": {"device": "abcd", "dummy": True, "automatic_add": True}}, ) await hass.async_block_till_done() await _signal_event(hass, "0a140002f38cae010f0070") - assert len(hass.states.async_all()) == 1 + state = hass.states.get("cover.lightwaverf_siemens_f38cae_1") + assert state + assert state.state == "open" await _signal_event(hass, "0a1400adf394ab020e0060") - assert len(hass.states.async_all()) == 2 - - # Trying to add a sensor - await _signal_event(hass, "0a52085e070100b31b0279") - assert len(hass.states.async_all()) == 2 - - # Trying to add a light - await _signal_event(hass, "0b1100100118cdea02010f70") - assert len(hass.states.async_all()) == 2 - - -async def test_discover_cover_noautoadd(hass, rfxtrx): - """Test with discovery of cover when auto add is False.""" - assert await async_setup_component( - hass, - "cover", - {"cover": {"platform": "rfxtrx", "automatic_add": False, "devices": {}}}, - ) - await hass.async_block_till_done() - - await _signal_event(hass, "0a1400adf394ab010d0060") - assert len(hass.states.async_all()) == 0 - - await _signal_event(hass, "0a1400adf394ab020e0060") - assert len(hass.states.async_all()) == 0 + state = hass.states.get("cover.lightwaverf_siemens_f394ab_2") + assert state + assert state.state == "open" diff --git a/tests/components/rfxtrx/test_init.py b/tests/components/rfxtrx/test_init.py index f8dd2b17cf0..fb07cb584b7 100644 --- a/tests/components/rfxtrx/test_init.py +++ b/tests/components/rfxtrx/test_init.py @@ -1,8 +1,4 @@ """The tests for the Rfxtrx component.""" -# pylint: disable=protected-access -import asyncio - -from async_timeout import timeout from homeassistant.components import rfxtrx from homeassistant.core import callback @@ -10,37 +6,6 @@ from homeassistant.setup import async_setup_component from . import _signal_event -from tests.common import assert_setup_component - - -async def test_default_config(hass): - """Test configuration.""" - assert await async_setup_component( - hass, - "rfxtrx", - { - "rfxtrx": { - "device": "/dev/serial/by-id/usb" - + "-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0", - "dummy": True, - } - }, - ) - - with assert_setup_component(1, "sensor"): - await async_setup_component( - hass, - "sensor", - {"sensor": {"platform": "rfxtrx", "automatic_add": True, "devices": {}}}, - ) - - # Dummy startup is slow - async with timeout(10): - while len(hass.data[rfxtrx.DATA_RFXOBJECT].sensors()) < 2: - await asyncio.sleep(0.1) - - assert len(hass.data[rfxtrx.DATA_RFXOBJECT].sensors()) == 2 - async def test_valid_config(hass): """Test configuration.""" @@ -100,23 +65,8 @@ async def test_fire_event(hass): "device": "/dev/serial/by-id/usb" + "-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0", "dummy": True, - } - }, - ) - - assert await async_setup_component( - hass, - "switch", - { - "switch": { - "platform": "rfxtrx", "automatic_add": True, - "devices": { - "0b1100cd0213c7f210010f51": { - "name": "Test", - rfxtrx.ATTR_FIRE_EVENT: True, - } - }, + "devices": {"0b1100cd0213c7f210010f51": {rfxtrx.ATTR_FIRE_EVENT: True}}, } }, ) @@ -131,18 +81,20 @@ async def test_fire_event(hass): hass.bus.async_listen(rfxtrx.EVENT_BUTTON_PRESSED, record_event) - state = hass.states.get("switch.test") + state = hass.states.get("switch.ac_213c7f2_16") assert state assert state.state == "off" await _signal_event(hass, "0b1100cd0213c7f210010f51") - state = hass.states.get("switch.test") + state = hass.states.get("switch.ac_213c7f2_16") assert state assert state.state == "on" - assert len(calls) == 1 - assert calls[0].data == {"entity_id": "switch.test", "state": "on"} + assert any( + call.data == {"entity_id": "switch.ac_213c7f2_16", "state": "on"} + for call in calls + ) async def test_fire_event_sensor(hass): @@ -155,26 +107,12 @@ async def test_fire_event_sensor(hass): "device": "/dev/serial/by-id/usb" + "-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0", "dummy": True, + "automatic_add": True, + "devices": {"0a520802060100ff0e0269": {rfxtrx.ATTR_FIRE_EVENT: True}}, } }, ) - await async_setup_component( - hass, - "sensor", - { - "sensor": { - "platform": "rfxtrx", - "automatic_add": True, - "devices": { - "0a520802060100ff0e0269": { - "name": "Test", - rfxtrx.ATTR_FIRE_EVENT: True, - } - }, - } - }, - ) await hass.async_block_till_done() calls = [] @@ -188,4 +126,8 @@ async def test_fire_event_sensor(hass): await _signal_event(hass, "0a520802060101ff0f0269") assert len(calls) == 5 - assert any(call.data == {"entity_id": "sensor.test_temperature"} for call in calls) + assert any( + call.data + == {"entity_id": "sensor.wt260_wt260h_wt440h_wt450_wt450h_06_01_temperature"} + for call in calls + ) diff --git a/tests/components/rfxtrx/test_light.py b/tests/components/rfxtrx/test_light.py index a5e411a0c5f..46b6c10e934 100644 --- a/tests/components/rfxtrx/test_light.py +++ b/tests/components/rfxtrx/test_light.py @@ -3,127 +3,79 @@ from unittest.mock import call import pytest -from homeassistant.components import rfxtrx as rfxtrx_core from homeassistant.setup import async_setup_component from . import _signal_event -from tests.common import assert_setup_component - - -async def test_valid_config(hass, rfxtrx): - """Test configuration.""" - with assert_setup_component(1): - assert await async_setup_component( - hass, - "light", - { - "light": { - "platform": "rfxtrx", - "automatic_add": True, - "devices": { - "0b1100cd0213c7f210010f51": { - "name": "Test", - rfxtrx_core.ATTR_FIRE_EVENT: True, - } - }, - } - }, - ) - - assert await async_setup_component( - hass, - "light", - { - "light": { - "platform": "rfxtrx", - "automatic_add": True, - "devices": { - "0b1100cd0213c7f210010f51": { - "name": "Test", - "signal_repetitions": 3, - } - }, - } - }, - ) - - -async def test_default_config(hass, rfxtrx): - """Test with 0 switches.""" - with assert_setup_component(1): - await async_setup_component( - hass, "light", {"light": {"platform": "rfxtrx", "devices": {}}} - ) - await hass.async_block_till_done() - - assert len(hass.states.async_all()) == 0 - async def test_one_light(hass, rfxtrx): """Test with 1 light.""" - await async_setup_component( + assert await async_setup_component( hass, - "light", + "rfxtrx", { - "light": { - "platform": "rfxtrx", - "devices": {"0b1100cd0213c7f210010f51": {"name": "Test"}}, + "rfxtrx": { + "device": "abcd", + "dummy": True, + "devices": {"0b1100cd0213c7f210020f51": {}}, } }, ) await hass.async_block_till_done() - state = hass.states.get("light.test") + state = hass.states.get("light.ac_213c7f2_16") assert state assert state.state == "off" - assert state.attributes.get("friendly_name") == "Test" + assert state.attributes.get("friendly_name") == "AC 213c7f2:16" await hass.services.async_call( - "light", "turn_on", {"entity_id": "light.test"}, blocking=True + "light", "turn_on", {"entity_id": "light.ac_213c7f2_16"}, blocking=True ) - state = hass.states.get("light.test") + state = hass.states.get("light.ac_213c7f2_16") assert state.state == "on" assert state.attributes.get("brightness") == 255 await hass.services.async_call( - "light", "turn_off", {"entity_id": "light.test"}, blocking=True + "light", "turn_off", {"entity_id": "light.ac_213c7f2_16"}, blocking=True ) - state = hass.states.get("light.test") + state = hass.states.get("light.ac_213c7f2_16") assert state.state == "off" assert state.attributes.get("brightness") is None await hass.services.async_call( "light", "turn_on", - {"entity_id": "light.test", "brightness": 100}, + {"entity_id": "light.ac_213c7f2_16", "brightness": 100}, blocking=True, ) - state = hass.states.get("light.test") + state = hass.states.get("light.ac_213c7f2_16") assert state.state == "on" assert state.attributes.get("brightness") == 100 await hass.services.async_call( - "light", "turn_on", {"entity_id": "light.test", "brightness": 10}, blocking=True + "light", + "turn_on", + {"entity_id": "light.ac_213c7f2_16", "brightness": 10}, + blocking=True, ) - state = hass.states.get("light.test") + state = hass.states.get("light.ac_213c7f2_16") assert state.state == "on" assert state.attributes.get("brightness") == 10 await hass.services.async_call( "light", "turn_on", - {"entity_id": "light.test", "brightness": 255}, + {"entity_id": "light.ac_213c7f2_16", "brightness": 255}, blocking=True, ) - state = hass.states.get("light.test") + state = hass.states.get("light.ac_213c7f2_16") assert state.state == "on" assert state.attributes.get("brightness") == 255 await hass.services.async_call( - "light", "turn_off", {"entity_id": "light.test"}, blocking=True + "light", "turn_off", {"entity_id": "light.ac_213c7f2_16"}, blocking=True ) - state = hass.states.get("light.test") + state = hass.states.get("light.ac_213c7f2_16") assert state.state == "off" assert state.attributes.get("brightness") is None @@ -139,61 +91,59 @@ async def test_one_light(hass, rfxtrx): async def test_several_lights(hass, rfxtrx): """Test with 3 lights.""" - await async_setup_component( + assert await async_setup_component( hass, - "light", + "rfxtrx", { - "light": { - "platform": "rfxtrx", - "signal_repetitions": 3, + "rfxtrx": { + "device": "abcd", + "dummy": True, "devices": { - "0b1100cd0213c7f230010f71": {"name": "Test"}, - "0b1100100118cdea02010f70": {"name": "Bath"}, - "0b1100101118cdea02010f70": {"name": "Living"}, + "0b1100cd0213c7f230020f71": {}, + "0b1100100118cdea02020f70": {}, + "0b1100101118cdea02050f70": {}, }, } }, ) await hass.async_block_till_done() - assert len(hass.states.async_all()) == 3 - - state = hass.states.get("light.test") + state = hass.states.get("light.ac_213c7f2_48") assert state assert state.state == "off" - assert state.attributes.get("friendly_name") == "Test" + assert state.attributes.get("friendly_name") == "AC 213c7f2:48" - state = hass.states.get("light.bath") + state = hass.states.get("light.ac_118cdea_2") assert state assert state.state == "off" - assert state.attributes.get("friendly_name") == "Bath" + assert state.attributes.get("friendly_name") == "AC 118cdea:2" - state = hass.states.get("light.living") + state = hass.states.get("light.ac_1118cdea_2") assert state assert state.state == "off" - assert state.attributes.get("friendly_name") == "Living" - - assert len(hass.states.async_all()) == 3 + assert state.attributes.get("friendly_name") == "AC 1118cdea:2" @pytest.mark.parametrize("repetitions", [1, 3]) async def test_repetitions(hass, rfxtrx, repetitions): """Test signal repetitions.""" - await async_setup_component( + assert await async_setup_component( hass, - "light", + "rfxtrx", { - "light": { - "platform": "rfxtrx", - "signal_repetitions": repetitions, - "devices": {"0b1100cd0213c7f230010f71": {"name": "Test"}}, + "rfxtrx": { + "device": "abcd", + "dummy": True, + "devices": { + "0b1100cd0213c7f230020f71": {"signal_repetitions": repetitions} + }, } }, ) await hass.async_block_till_done() await hass.services.async_call( - "light", "turn_on", {"entity_id": "light.test"}, blocking=True + "light", "turn_on", {"entity_id": "light.ac_213c7f2_48"}, blocking=True ) await hass.async_block_till_done() @@ -202,40 +152,21 @@ async def test_repetitions(hass, rfxtrx, repetitions): async def test_discover_light(hass, rfxtrx): """Test with discovery of lights.""" - await async_setup_component( + assert await async_setup_component( hass, - "light", - {"light": {"platform": "rfxtrx", "automatic_add": True, "devices": {}}}, + "rfxtrx", + {"rfxtrx": {"device": "abcd", "dummy": True, "automatic_add": True}}, ) await hass.async_block_till_done() await _signal_event(hass, "0b11009e00e6116202020070") - state = hass.states.get("light.0b11009e00e6116202020070") + state = hass.states.get("light.ac_0e61162_2") assert state assert state.state == "on" - assert state.attributes.get("friendly_name") == "0b11009e00e6116202020070" + assert state.attributes.get("friendly_name") == "AC 0e61162:2" await _signal_event(hass, "0b1100120118cdea02020070") - state = hass.states.get("light.0b1100120118cdea02020070") + state = hass.states.get("light.ac_118cdea_2") assert state assert state.state == "on" - assert state.attributes.get("friendly_name") == "0b1100120118cdea02020070" - - -async def test_discover_light_noautoadd(hass, rfxtrx): - """Test with discover of light when auto add is False.""" - await async_setup_component( - hass, - "light", - {"light": {"platform": "rfxtrx", "automatic_add": False, "devices": {}}}, - ) - await hass.async_block_till_done() - - await _signal_event(hass, "0b1100120118cdea02020070") - assert hass.states.async_all() == [] - - await _signal_event(hass, "0b1100120118cdea02010070") - assert hass.states.async_all() == [] - - await _signal_event(hass, "0b1100120118cdea02020070") - assert hass.states.async_all() == [] + assert state.attributes.get("friendly_name") == "AC 118cdea:2" diff --git a/tests/components/rfxtrx/test_sensor.py b/tests/components/rfxtrx/test_sensor.py index ca6b8802b23..dd1a689acc4 100644 --- a/tests/components/rfxtrx/test_sensor.py +++ b/tests/components/rfxtrx/test_sensor.py @@ -17,46 +17,46 @@ async def test_default_config(hass, rfxtrx): async def test_one_sensor(hass, rfxtrx): """Test with 1 sensor.""" - await async_setup_component( + assert await async_setup_component( hass, - "sensor", + "rfxtrx", { - "sensor": { - "platform": "rfxtrx", - "devices": { - "0a52080705020095220269": { - "name": "Test", - "data_type": "Temperature", - } - }, + "rfxtrx": { + "device": "abcd", + "dummy": True, + "devices": {"0a52080705020095220269": {}}, } }, ) await hass.async_block_till_done() - state = hass.states.get("sensor.test_temperature") + state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_05_02_temperature") assert state assert state.state == "unknown" - assert state.attributes.get("friendly_name") == "Test Temperature" + assert ( + state.attributes.get("friendly_name") + == "WT260,WT260H,WT440H,WT450,WT450H 05:02 Temperature" + ) assert state.attributes.get("unit_of_measurement") == TEMP_CELSIUS async def test_one_sensor_no_datatype(hass, rfxtrx): """Test with 1 sensor.""" - await async_setup_component( + assert await async_setup_component( hass, - "sensor", + "rfxtrx", { - "sensor": { - "platform": "rfxtrx", - "devices": {"0a52080705020095220269": {"name": "Test"}}, + "rfxtrx": { + "device": "abcd", + "dummy": True, + "devices": {"0a52080705020095220269": {}}, } }, ) await hass.async_block_till_done() - base_id = "sensor.test" - base_name = "Test" + base_id = "sensor.wt260_wt260h_wt440h_wt450_wt450h_05_02" + base_name = "WT260,WT260H,WT440H,WT450,WT450H 05:02" state = hass.states.get(f"{base_id}_temperature") assert state @@ -91,58 +91,63 @@ async def test_one_sensor_no_datatype(hass, rfxtrx): async def test_several_sensors(hass, rfxtrx): """Test with 3 sensors.""" - await async_setup_component( + assert await async_setup_component( hass, - "sensor", + "rfxtrx", { - "sensor": { - "platform": "rfxtrx", + "rfxtrx": { + "device": "abcd", + "dummy": True, "devices": { - "0a52080705020095220269": { - "name": "Test", - "data_type": "Temperature", - }, - "0a520802060100ff0e0269": { - "name": "Bath", - "data_type": ["Temperature", "Humidity"], - }, + "0a52080705020095220269": {}, + "0a520802060100ff0e0269": {}, }, } }, ) + await hass.async_block_till_done() - state = hass.states.get("sensor.test_temperature") + state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_05_02_temperature") assert state assert state.state == "unknown" - assert state.attributes.get("friendly_name") == "Test Temperature" + assert ( + state.attributes.get("friendly_name") + == "WT260,WT260H,WT440H,WT450,WT450H 05:02 Temperature" + ) assert state.attributes.get("unit_of_measurement") == TEMP_CELSIUS - state = hass.states.get("sensor.bath_temperature") + state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_06_01_temperature") assert state assert state.state == "unknown" - assert state.attributes.get("friendly_name") == "Bath Temperature" + assert ( + state.attributes.get("friendly_name") + == "WT260,WT260H,WT440H,WT450,WT450H 06:01 Temperature" + ) assert state.attributes.get("unit_of_measurement") == TEMP_CELSIUS - state = hass.states.get("sensor.bath_humidity") + state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_06_01_humidity") assert state assert state.state == "unknown" - assert state.attributes.get("friendly_name") == "Bath Humidity" + assert ( + state.attributes.get("friendly_name") + == "WT260,WT260H,WT440H,WT450,WT450H 06:01 Humidity" + ) assert state.attributes.get("unit_of_measurement") == UNIT_PERCENTAGE async def test_discover_sensor(hass, rfxtrx): """Test with discovery of sensor.""" - await async_setup_component( + assert await async_setup_component( hass, - "sensor", - {"sensor": {"platform": "rfxtrx", "automatic_add": True, "devices": {}}}, + "rfxtrx", + {"rfxtrx": {"device": "abcd", "dummy": True, "automatic_add": True}}, ) await hass.async_block_till_done() # 1 await _signal_event(hass, "0a520801070100b81b0279") - base_id = "sensor.0a520801070100b81b0279" + base_id = "sensor.wt260_wt260h_wt440h_wt450_wt450h_07_01" state = hass.states.get(f"{base_id}_humidity") assert state @@ -171,7 +176,7 @@ async def test_discover_sensor(hass, rfxtrx): # 2 await _signal_event(hass, "0a52080405020095240279") - base_id = "sensor.0a52080405020095240279" + base_id = "sensor.wt260_wt260h_wt440h_wt450_wt450h_05_02" state = hass.states.get(f"{base_id}_humidity") assert state @@ -200,7 +205,7 @@ async def test_discover_sensor(hass, rfxtrx): # 1 Update await _signal_event(hass, "0a52085e070100b31b0279") - base_id = "sensor.0a520801070100b81b0279" + base_id = "sensor.wt260_wt260h_wt440h_wt450_wt450h_07_01" state = hass.states.get(f"{base_id}_humidity") assert state @@ -230,75 +235,47 @@ async def test_discover_sensor(hass, rfxtrx): assert len(hass.states.async_all()) == 10 -async def test_discover_sensor_noautoadd(hass, rfxtrx): - """Test with discover of sensor when auto add is False.""" - await async_setup_component( - hass, - "sensor", - {"sensor": {"platform": "rfxtrx", "automatic_add": False, "devices": {}}}, - ) - await hass.async_block_till_done() - - await _signal_event(hass, "0a520801070100b81b0279") - assert len(hass.states.async_all()) == 0 - - await _signal_event(hass, "0a52080405020095240279") - assert len(hass.states.async_all()) == 0 - - await _signal_event(hass, "0a52085e070100b31b0279") - assert len(hass.states.async_all()) == 0 - - async def test_update_of_sensors(hass, rfxtrx): """Test with 3 sensors.""" - await async_setup_component( + assert await async_setup_component( hass, - "sensor", + "rfxtrx", { - "sensor": { - "platform": "rfxtrx", + "rfxtrx": { + "device": "abcd", + "dummy": True, "devices": { - "0a52080705020095220269": { - "name": "Test", - "data_type": "Temperature", - }, - "0a520802060100ff0e0269": { - "name": "Bath", - "data_type": ["Temperature", "Humidity"], - }, + "0a52080705020095220269": {}, + "0a520802060100ff0e0269": {}, }, } }, ) await hass.async_block_till_done() - state = hass.states.get("sensor.test_temperature") + state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_05_02_temperature") assert state assert state.state == "unknown" - state = hass.states.get("sensor.bath_temperature") + state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_06_01_temperature") assert state assert state.state == "unknown" - state = hass.states.get("sensor.bath_humidity") + state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_06_01_humidity") assert state assert state.state == "unknown" - assert len(hass.states.async_all()) == 3 - await _signal_event(hass, "0a520802060101ff0f0269") await _signal_event(hass, "0a52080705020085220269") - state = hass.states.get("sensor.test_temperature") + state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_05_02_temperature") assert state assert state.state == "13.3" - state = hass.states.get("sensor.bath_temperature") + state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_06_01_temperature") assert state assert state.state == "51.1" - state = hass.states.get("sensor.bath_humidity") + state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_06_01_humidity") assert state assert state.state == "15" - - assert len(hass.states.async_all()) == 3 diff --git a/tests/components/rfxtrx/test_switch.py b/tests/components/rfxtrx/test_switch.py index 0ed9ead59ef..5b80c06d7b7 100644 --- a/tests/components/rfxtrx/test_switch.py +++ b/tests/components/rfxtrx/test_switch.py @@ -3,121 +3,43 @@ from unittest.mock import call import pytest -from homeassistant.components import rfxtrx as rfxtrx_core from homeassistant.setup import async_setup_component from . import _signal_event -from tests.common import assert_setup_component - - -async def test_valid_config(hass, rfxtrx): - """Test configuration.""" - with assert_setup_component(1): - await async_setup_component( - hass, - "switch", - { - "switch": { - "platform": "rfxtrx", - "automatic_add": True, - "devices": { - "0b1100cd0213c7f210010f51": { - "name": "Test", - rfxtrx_core.ATTR_FIRE_EVENT: True, - } - }, - } - }, - ) - await hass.async_block_till_done() - - -async def test_valid_config_int_device_id(hass, rfxtrx): - """Test configuration.""" - with assert_setup_component(1): - await async_setup_component( - hass, - "switch", - { - "switch": { - "platform": "rfxtrx", - "automatic_add": True, - "devices": { - 710000141010170: { - "name": "Test", - rfxtrx_core.ATTR_FIRE_EVENT: True, - } - }, - } - }, - ) - await hass.async_block_till_done() - - -async def test_invalid_config2(hass, rfxtrx): - """Test invalid configuration.""" - with assert_setup_component(0): - await async_setup_component( - hass, - "switch", - { - "switch": { - "platform": "rfxtrx", - "automatic_add": True, - "invalid_key": "afda", - "devices": { - "0b1100cd0213c7f210010f51": { - "name": "Test", - rfxtrx_core.ATTR_FIRE_EVENT: True, - } - }, - } - }, - ) - await hass.async_block_till_done() - - -async def test_default_config(hass, rfxtrx): - """Test with 0 switches.""" - await async_setup_component( - hass, "switch", {"switch": {"platform": "rfxtrx", "devices": {}}} - ) - await hass.async_block_till_done() - assert hass.states.async_all() == [] - async def test_one_switch(hass, rfxtrx): """Test with 1 switch.""" - await async_setup_component( + assert await async_setup_component( hass, - "switch", + "rfxtrx", { - "switch": { - "platform": "rfxtrx", - "devices": {"0b1100cd0213c7f210010f51": {"name": "Test"}}, + "rfxtrx": { + "device": "abcd", + "dummy": True, + "devices": {"0b1100cd0213c7f210010f51": {}}, } }, ) await hass.async_block_till_done() - state = hass.states.get("switch.test") + state = hass.states.get("switch.ac_213c7f2_16") assert state assert state.state == "off" - assert state.attributes.get("friendly_name") == "Test" + assert state.attributes.get("friendly_name") == "AC 213c7f2:16" await hass.services.async_call( - "switch", "turn_on", {"entity_id": "switch.test"}, blocking=True + "switch", "turn_on", {"entity_id": "switch.ac_213c7f2_16"}, blocking=True ) - state = hass.states.get("switch.test") + state = hass.states.get("switch.ac_213c7f2_16") assert state.state == "on" await hass.services.async_call( - "switch", "turn_off", {"entity_id": "switch.test"}, blocking=True + "switch", "turn_off", {"entity_id": "switch.ac_213c7f2_16"}, blocking=True ) - state = hass.states.get("switch.test") + state = hass.states.get("switch.ac_213c7f2_16") assert state.state == "off" assert rfxtrx.transport.send.mock_calls == [ @@ -128,57 +50,59 @@ async def test_one_switch(hass, rfxtrx): async def test_several_switches(hass, rfxtrx): """Test with 3 switches.""" - await async_setup_component( + assert await async_setup_component( hass, - "switch", + "rfxtrx", { - "switch": { - "platform": "rfxtrx", - "signal_repetitions": 3, + "rfxtrx": { + "device": "abcd", + "dummy": True, "devices": { - "0b1100cd0213c7f230010f71": {"name": "Test"}, - "0b1100100118cdea02010f70": {"name": "Bath"}, - "0b1100101118cdea02010f70": {"name": "Living"}, + "0b1100cd0213c7f230010f71": {}, + "0b1100100118cdea02010f70": {}, + "0b1100101118cdea02010f70": {}, }, } }, ) await hass.async_block_till_done() - state = hass.states.get("switch.test") + state = hass.states.get("switch.ac_213c7f2_48") assert state assert state.state == "off" - assert state.attributes.get("friendly_name") == "Test" + assert state.attributes.get("friendly_name") == "AC 213c7f2:48" - state = hass.states.get("switch.bath") + state = hass.states.get("switch.ac_118cdea_2") assert state assert state.state == "off" - assert state.attributes.get("friendly_name") == "Bath" + assert state.attributes.get("friendly_name") == "AC 118cdea:2" - state = hass.states.get("switch.living") + state = hass.states.get("switch.ac_1118cdea_2") assert state assert state.state == "off" - assert state.attributes.get("friendly_name") == "Living" + assert state.attributes.get("friendly_name") == "AC 1118cdea:2" @pytest.mark.parametrize("repetitions", [1, 3]) async def test_repetitions(hass, rfxtrx, repetitions): """Test signal repetitions.""" - await async_setup_component( + assert await async_setup_component( hass, - "switch", + "rfxtrx", { - "switch": { - "platform": "rfxtrx", - "signal_repetitions": repetitions, - "devices": {"0b1100cd0213c7f230010f71": {"name": "Test"}}, + "rfxtrx": { + "device": "abcd", + "dummy": True, + "devices": { + "0b1100cd0213c7f230010f71": {"signal_repetitions": repetitions} + }, } }, ) await hass.async_block_till_done() await hass.services.async_call( - "switch", "turn_on", {"entity_id": "switch.test"}, blocking=True + "switch", "turn_on", {"entity_id": "switch.ac_213c7f2_48"}, blocking=True ) await hass.async_block_till_done() @@ -187,48 +111,19 @@ async def test_repetitions(hass, rfxtrx, repetitions): async def test_discover_switch(hass, rfxtrx): """Test with discovery of switches.""" - await async_setup_component( + assert await async_setup_component( hass, - "switch", - {"switch": {"platform": "rfxtrx", "automatic_add": True, "devices": {}}}, + "rfxtrx", + {"rfxtrx": {"device": "abcd", "dummy": True, "automatic_add": True}}, ) await hass.async_block_till_done() await _signal_event(hass, "0b1100100118cdea02010f70") - state = hass.states.get("switch.0b1100100118cdea02010f70") + state = hass.states.get("switch.ac_118cdea_2") assert state assert state.state == "on" await _signal_event(hass, "0b1100100118cdeb02010f70") - state = hass.states.get("switch.0b1100100118cdeb02010f70") + state = hass.states.get("switch.ac_118cdeb_2") assert state assert state.state == "on" - - # Trying to add a sensor - await _signal_event(hass, "0a52085e070100b31b0279") - state = hass.states.get("sensor.0a52085e070100b31b0279") - assert state is None - - # Trying to add a light - await _signal_event(hass, "0b1100100118cdea02010f70") - state = hass.states.get("light.0b1100100118cdea02010f70") - assert state is None - - # Trying to add a rollershutter - await _signal_event(hass, "0a1400adf394ab020e0060") - state = hass.states.get("cover.0a1400adf394ab020e0060") - assert state is None - - -async def test_discover_switch_noautoadd(hass, rfxtrx): - """Test with discovery of switch when auto add is False.""" - await async_setup_component( - hass, - "switch", - {"switch": {"platform": "rfxtrx", "automatic_add": False, "devices": {}}}, - ) - await hass.async_block_till_done() - - # Trying to add switch - await _signal_event(hass, "0b1100100118cdea02010f70") - assert hass.states.async_all() == []