Rewrite rfxtrx init logic to do away with global object (#37699)
* Rewrite init logic to do away with global object * Put constant at end * Use a set instead of list for device_ids
This commit is contained in:
parent
b45a952d61
commit
67038c6ba8
11 changed files with 365 additions and 334 deletions
|
@ -8,10 +8,8 @@ import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
ATTR_NAME,
|
|
||||||
ATTR_STATE,
|
ATTR_STATE,
|
||||||
CONF_DEVICE,
|
CONF_DEVICE,
|
||||||
CONF_DEVICES,
|
|
||||||
CONF_HOST,
|
CONF_HOST,
|
||||||
CONF_PORT,
|
CONF_PORT,
|
||||||
EVENT_HOMEASSISTANT_START,
|
EVENT_HOMEASSISTANT_START,
|
||||||
|
@ -25,6 +23,8 @@ import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.util import slugify
|
from homeassistant.util import slugify
|
||||||
|
|
||||||
|
from .const import DEVICE_PACKET_TYPE_LIGHTING4
|
||||||
|
|
||||||
DOMAIN = "rfxtrx"
|
DOMAIN = "rfxtrx"
|
||||||
|
|
||||||
DEFAULT_SIGNAL_REPETITIONS = 1
|
DEFAULT_SIGNAL_REPETITIONS = 1
|
||||||
|
@ -80,7 +80,6 @@ DATA_TYPES = OrderedDict(
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
RFX_DEVICES = {}
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
DATA_RFXOBJECT = "rfxobject"
|
DATA_RFXOBJECT = "rfxobject"
|
||||||
|
|
||||||
|
@ -207,31 +206,15 @@ def get_pt2262_cmd(device_id, data_bits):
|
||||||
return hex(data[-1] & mask)
|
return hex(data[-1] & mask)
|
||||||
|
|
||||||
|
|
||||||
def get_pt2262_device(device_id):
|
def find_possible_pt2262_device(device_ids, device_id):
|
||||||
"""Look for the device which id matches the given device_id parameter."""
|
"""Look for the device which id matches the given device_id parameter."""
|
||||||
for device in RFX_DEVICES.values():
|
for dev_id in device_ids:
|
||||||
if (
|
if len(dev_id) == len(device_id):
|
||||||
hasattr(device, "is_lighting4")
|
|
||||||
and device.masked_id is not None
|
|
||||||
and device.masked_id == get_pt2262_deviceid(device_id, device.data_bits)
|
|
||||||
):
|
|
||||||
_LOGGER.debug(
|
|
||||||
"rfxtrx: found matching device %s for %s", device_id, device.masked_id,
|
|
||||||
)
|
|
||||||
return device
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def find_possible_pt2262_device(device_id):
|
|
||||||
"""Look for the device which id matches the given device_id parameter."""
|
|
||||||
for dev_id, device in RFX_DEVICES.items():
|
|
||||||
if hasattr(device, "is_lighting4") and len(dev_id) == len(device_id):
|
|
||||||
size = None
|
size = None
|
||||||
for i, (char1, char2) in enumerate(zip(dev_id, device_id)):
|
for i, (char1, char2) in enumerate(zip(dev_id, device_id)):
|
||||||
if char1 != char2:
|
if char1 != char2:
|
||||||
break
|
break
|
||||||
size = i
|
size = i
|
||||||
|
|
||||||
if size is not None:
|
if size is not None:
|
||||||
size = len(dev_id) - size - 1
|
size = len(dev_id) - size - 1
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
|
@ -246,60 +229,19 @@ def find_possible_pt2262_device(device_id):
|
||||||
dev_id[-size:],
|
dev_id[-size:],
|
||||||
device_id[-size:],
|
device_id[-size:],
|
||||||
)
|
)
|
||||||
return device
|
return dev_id
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_devices_from_config(config, device):
|
def get_device_id(device, data_bits=None):
|
||||||
"""Read rfxtrx configuration."""
|
"""Calculate a device id for device."""
|
||||||
signal_repetitions = config[CONF_SIGNAL_REPETITIONS]
|
id_string = device.id_string
|
||||||
|
if data_bits and device.packettype == DEVICE_PACKET_TYPE_LIGHTING4:
|
||||||
|
masked_id = get_pt2262_deviceid(id_string, data_bits)
|
||||||
|
if masked_id:
|
||||||
|
id_string = str(masked_id)
|
||||||
|
|
||||||
devices = []
|
return (f"{device.packettype:x}", f"{device.subtype:x}", id_string)
|
||||||
for packet_id, entity_info in config[CONF_DEVICES].items():
|
|
||||||
event = get_rfx_object(packet_id)
|
|
||||||
if event is None:
|
|
||||||
_LOGGER.error("Invalid device: %s", packet_id)
|
|
||||||
continue
|
|
||||||
device_id = slugify(event.device.id_string.lower())
|
|
||||||
if device_id in RFX_DEVICES:
|
|
||||||
continue
|
|
||||||
_LOGGER.debug("Add %s rfxtrx", entity_info[ATTR_NAME])
|
|
||||||
|
|
||||||
# Check if i must fire event
|
|
||||||
fire_event = entity_info[ATTR_FIRE_EVENT]
|
|
||||||
datas = {ATTR_STATE: False, ATTR_FIRE_EVENT: fire_event}
|
|
||||||
|
|
||||||
new_device = device(
|
|
||||||
entity_info[ATTR_NAME], event.device, datas, signal_repetitions
|
|
||||||
)
|
|
||||||
RFX_DEVICES[device_id] = new_device
|
|
||||||
devices.append(new_device)
|
|
||||||
return devices
|
|
||||||
|
|
||||||
|
|
||||||
def get_new_device(event, config, device):
|
|
||||||
"""Add entity if not exist and the automatic_add is True."""
|
|
||||||
device_id = slugify(event.device.id_string.lower())
|
|
||||||
if device_id in RFX_DEVICES:
|
|
||||||
return
|
|
||||||
|
|
||||||
if not config[ATTR_AUTOMATIC_ADD]:
|
|
||||||
return
|
|
||||||
|
|
||||||
pkt_id = "".join(f"{x:02x}" for x in event.data)
|
|
||||||
_LOGGER.debug(
|
|
||||||
"Automatic add %s rfxtrx device (Class: %s Sub: %s Packet_id: %s)",
|
|
||||||
device_id,
|
|
||||||
event.device.__class__.__name__,
|
|
||||||
event.device.subtype,
|
|
||||||
pkt_id,
|
|
||||||
)
|
|
||||||
datas = {ATTR_STATE: False, ATTR_FIRE_EVENT: False}
|
|
||||||
signal_repetitions = config[CONF_SIGNAL_REPETITIONS]
|
|
||||||
new_device = device(pkt_id, event.device, datas, signal_repetitions, event=event)
|
|
||||||
RFX_DEVICES[device_id] = new_device
|
|
||||||
return new_device
|
|
||||||
|
|
||||||
|
|
||||||
def fire_command_event(hass, entity_id, command):
|
def fire_command_event(hass, entity_id, command):
|
||||||
|
@ -330,7 +272,8 @@ class RfxtrxDevice(Entity):
|
||||||
self._device = device
|
self._device = device
|
||||||
self._state = datas[ATTR_STATE]
|
self._state = datas[ATTR_STATE]
|
||||||
self._should_fire_event = datas[ATTR_FIRE_EVENT]
|
self._should_fire_event = datas[ATTR_FIRE_EVENT]
|
||||||
self._unique_id = f"{device.packettype:x}_{device.subtype:x}_{device.id_string}"
|
self._device_id = get_device_id(device)
|
||||||
|
self._unique_id = "_".join(x for x in self._device_id)
|
||||||
|
|
||||||
if event:
|
if event:
|
||||||
self._apply_event(event)
|
self._apply_event(event)
|
||||||
|
|
|
@ -13,31 +13,29 @@ from homeassistant.const import (
|
||||||
CONF_COMMAND_OFF,
|
CONF_COMMAND_OFF,
|
||||||
CONF_COMMAND_ON,
|
CONF_COMMAND_ON,
|
||||||
CONF_DEVICE_CLASS,
|
CONF_DEVICE_CLASS,
|
||||||
|
CONF_DEVICES,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers import config_validation as cv, event as evt
|
from homeassistant.helpers import config_validation as cv, event as evt
|
||||||
from homeassistant.util import slugify
|
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
ATTR_NAME,
|
|
||||||
CONF_AUTOMATIC_ADD,
|
CONF_AUTOMATIC_ADD,
|
||||||
CONF_DATA_BITS,
|
CONF_DATA_BITS,
|
||||||
CONF_DEVICES,
|
|
||||||
CONF_FIRE_EVENT,
|
CONF_FIRE_EVENT,
|
||||||
CONF_OFF_DELAY,
|
CONF_OFF_DELAY,
|
||||||
RFX_DEVICES,
|
|
||||||
SIGNAL_EVENT,
|
SIGNAL_EVENT,
|
||||||
find_possible_pt2262_device,
|
find_possible_pt2262_device,
|
||||||
fire_command_event,
|
fire_command_event,
|
||||||
|
get_device_id,
|
||||||
get_pt2262_cmd,
|
get_pt2262_cmd,
|
||||||
get_pt2262_device,
|
|
||||||
get_pt2262_deviceid,
|
get_pt2262_deviceid,
|
||||||
get_rfx_object,
|
get_rfx_object,
|
||||||
)
|
)
|
||||||
from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST
|
from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST, DEVICE_PACKET_TYPE_LIGHTING4
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_DEVICES, default={}): {
|
vol.Optional(CONF_DEVICES, default={}): {
|
||||||
|
@ -61,28 +59,40 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_device_data_bits(device, device_bits):
|
||||||
|
"""Deduce data bits for device based on a cache of device bits."""
|
||||||
|
data_bits = None
|
||||||
|
if device.packettype == DEVICE_PACKET_TYPE_LIGHTING4:
|
||||||
|
for id_masked, bits in device_bits.items():
|
||||||
|
if get_pt2262_deviceid(device.id_string, bits) == id_masked:
|
||||||
|
data_bits = bits
|
||||||
|
break
|
||||||
|
return data_bits
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up the Binary Sensor platform to RFXtrx."""
|
"""Set up the Binary Sensor platform to RFXtrx."""
|
||||||
sensors = []
|
sensors = []
|
||||||
|
|
||||||
|
device_ids = set()
|
||||||
|
device_bits = {}
|
||||||
|
|
||||||
|
pt2262_devices = []
|
||||||
|
|
||||||
for packet_id, entity in config[CONF_DEVICES].items():
|
for packet_id, entity in config[CONF_DEVICES].items():
|
||||||
event = get_rfx_object(packet_id)
|
event = get_rfx_object(packet_id)
|
||||||
device_id = slugify(event.device.id_string.lower())
|
if event is None:
|
||||||
|
_LOGGER.error("Invalid device: %s", packet_id)
|
||||||
if device_id in RFX_DEVICES:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if entity.get(CONF_DATA_BITS) is not None:
|
device_id = get_device_id(event.device, data_bits=entity.get(CONF_DATA_BITS))
|
||||||
_LOGGER.debug(
|
if device_id in device_ids:
|
||||||
"Masked device id: %s",
|
continue
|
||||||
get_pt2262_deviceid(device_id, entity.get(CONF_DATA_BITS)),
|
device_ids.add(device_id)
|
||||||
)
|
|
||||||
|
|
||||||
_LOGGER.debug(
|
if event.device.packettype == DEVICE_PACKET_TYPE_LIGHTING4:
|
||||||
"Add %s rfxtrx.binary_sensor (class %s)",
|
find_possible_pt2262_device(pt2262_devices, event.device.id_string)
|
||||||
entity[ATTR_NAME],
|
pt2262_devices.append(event.device.id_string)
|
||||||
entity.get(CONF_DEVICE_CLASS),
|
|
||||||
)
|
|
||||||
|
|
||||||
device = RfxtrxBinarySensor(
|
device = RfxtrxBinarySensor(
|
||||||
event.device,
|
event.device,
|
||||||
|
@ -95,7 +105,6 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
entity.get(CONF_COMMAND_OFF),
|
entity.get(CONF_COMMAND_OFF),
|
||||||
)
|
)
|
||||||
sensors.append(device)
|
sensors.append(device)
|
||||||
RFX_DEVICES[device_id] = device
|
|
||||||
|
|
||||||
add_entities(sensors)
|
add_entities(sensors)
|
||||||
|
|
||||||
|
@ -104,34 +113,27 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
if not isinstance(event, rfxtrxmod.ControlEvent):
|
if not isinstance(event, rfxtrxmod.ControlEvent):
|
||||||
return
|
return
|
||||||
|
|
||||||
device_id = slugify(event.device.id_string.lower())
|
data_bits = _get_device_data_bits(event.device, device_bits)
|
||||||
|
|
||||||
sensor = RFX_DEVICES.get(device_id, get_pt2262_device(device_id))
|
device_id = get_device_id(event.device, data_bits=data_bits)
|
||||||
|
if device_id in device_ids:
|
||||||
if sensor is None:
|
|
||||||
# Add the entity if not exists and automatic_add is True
|
|
||||||
if not config[CONF_AUTOMATIC_ADD]:
|
|
||||||
return
|
return
|
||||||
|
device_ids.add(device_id)
|
||||||
|
|
||||||
if event.device.packettype == 0x13:
|
|
||||||
poss_dev = find_possible_pt2262_device(device_id)
|
|
||||||
if poss_dev is not None:
|
|
||||||
poss_id = slugify(poss_dev.event.device.id_string.lower())
|
|
||||||
_LOGGER.debug("Found possible matching device ID: %s", poss_id)
|
|
||||||
|
|
||||||
pkt_id = "".join(f"{x:02x}" for x in event.data)
|
|
||||||
sensor = RfxtrxBinarySensor(event.device, pkt_id, event=event)
|
|
||||||
RFX_DEVICES[device_id] = sensor
|
|
||||||
add_entities([sensor])
|
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"Added binary sensor %s (Device ID: %s Class: %s Sub: %s)",
|
"Added binary sensor (Device ID: %s Class: %s Sub: %s)",
|
||||||
pkt_id,
|
event.device.id_string.lower(),
|
||||||
slugify(event.device.id_string.lower()),
|
|
||||||
event.device.__class__.__name__,
|
event.device.__class__.__name__,
|
||||||
event.device.subtype,
|
event.device.subtype,
|
||||||
)
|
)
|
||||||
|
pkt_id = "".join(f"{x:02x}" for x in event.data)
|
||||||
|
sensor = RfxtrxBinarySensor(
|
||||||
|
event.device, pkt_id, data_bits=data_bits, event=event
|
||||||
|
)
|
||||||
|
add_entities([sensor])
|
||||||
|
|
||||||
# Subscribe to main RFXtrx events
|
# Subscribe to main RFXtrx events
|
||||||
|
if config[CONF_AUTOMATIC_ADD]:
|
||||||
hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, binary_sensor_update)
|
hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, binary_sensor_update)
|
||||||
|
|
||||||
|
|
||||||
|
@ -158,22 +160,13 @@ class RfxtrxBinarySensor(BinarySensorEntity):
|
||||||
self._device_class = device_class
|
self._device_class = device_class
|
||||||
self._off_delay = off_delay
|
self._off_delay = off_delay
|
||||||
self._state = False
|
self._state = False
|
||||||
self.is_lighting4 = device.packettype == 0x13
|
|
||||||
self.delay_listener = None
|
self.delay_listener = None
|
||||||
self._data_bits = data_bits
|
self._data_bits = data_bits
|
||||||
self._cmd_on = cmd_on
|
self._cmd_on = cmd_on
|
||||||
self._cmd_off = cmd_off
|
self._cmd_off = cmd_off
|
||||||
|
|
||||||
if data_bits is not None:
|
self._device_id = get_device_id(device, data_bits=data_bits)
|
||||||
self._masked_id = get_pt2262_deviceid(device.id_string.lower(), data_bits)
|
self._unique_id = "_".join(x for x in self._device_id)
|
||||||
self._unique_id = (
|
|
||||||
f"{device.packettype:x}_{device.subtype:x}_{self._masked_id}"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self._masked_id = None
|
|
||||||
self._unique_id = (
|
|
||||||
f"{device.packettype:x}_{device.subtype:x}_{device.id_string}"
|
|
||||||
)
|
|
||||||
|
|
||||||
if event:
|
if event:
|
||||||
self._apply_event(event)
|
self._apply_event(event)
|
||||||
|
@ -193,11 +186,6 @@ class RfxtrxBinarySensor(BinarySensorEntity):
|
||||||
"""Return the device name."""
|
"""Return the device name."""
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
@property
|
|
||||||
def masked_id(self):
|
|
||||||
"""Return the masked device id (isolated address bits)."""
|
|
||||||
return self._masked_id
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def data_bits(self):
|
def data_bits(self):
|
||||||
"""Return the number of data bits."""
|
"""Return the number of data bits."""
|
||||||
|
@ -263,19 +251,14 @@ class RfxtrxBinarySensor(BinarySensorEntity):
|
||||||
|
|
||||||
def _apply_event(self, event):
|
def _apply_event(self, event):
|
||||||
"""Apply command from rfxtrx."""
|
"""Apply command from rfxtrx."""
|
||||||
if self.is_lighting4:
|
if event.device.packettype == DEVICE_PACKET_TYPE_LIGHTING4:
|
||||||
self._apply_event_lighting4(event)
|
self._apply_event_lighting4(event)
|
||||||
else:
|
else:
|
||||||
self._apply_event_standard(event)
|
self._apply_event_standard(event)
|
||||||
|
|
||||||
def _handle_event(self, event):
|
def _handle_event(self, event):
|
||||||
"""Check if event applies to me and update."""
|
"""Check if event applies to me and update."""
|
||||||
if self._masked_id:
|
if get_device_id(event.device, data_bits=self._data_bits) != self._device_id:
|
||||||
masked_id = get_pt2262_deviceid(event.device.id_string, self._data_bits)
|
|
||||||
if masked_id != self._masked_id:
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
if event.device.id_string != self._device.id_string:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
|
|
|
@ -14,3 +14,4 @@ COMMAND_OFF_LIST = [
|
||||||
"Down",
|
"Down",
|
||||||
"Close (inline relay)",
|
"Close (inline relay)",
|
||||||
]
|
]
|
||||||
|
DEVICE_PACKET_TYPE_LIGHTING4 = 0x13
|
||||||
|
|
|
@ -1,23 +1,25 @@
|
||||||
"""Support for RFXtrx covers."""
|
"""Support for RFXtrx covers."""
|
||||||
|
import logging
|
||||||
|
|
||||||
import RFXtrx as rfxtrxmod
|
import RFXtrx as rfxtrxmod
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.cover import PLATFORM_SCHEMA, CoverEntity
|
from homeassistant.components.cover import PLATFORM_SCHEMA, CoverEntity
|
||||||
from homeassistant.const import CONF_NAME, STATE_OPEN
|
from homeassistant.const import ATTR_STATE, CONF_DEVICES, CONF_NAME, STATE_OPEN
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
|
ATTR_FIRE_EVENT,
|
||||||
CONF_AUTOMATIC_ADD,
|
CONF_AUTOMATIC_ADD,
|
||||||
CONF_DEVICES,
|
|
||||||
CONF_FIRE_EVENT,
|
CONF_FIRE_EVENT,
|
||||||
CONF_SIGNAL_REPETITIONS,
|
CONF_SIGNAL_REPETITIONS,
|
||||||
DEFAULT_SIGNAL_REPETITIONS,
|
DEFAULT_SIGNAL_REPETITIONS,
|
||||||
SIGNAL_EVENT,
|
SIGNAL_EVENT,
|
||||||
RfxtrxDevice,
|
RfxtrxDevice,
|
||||||
fire_command_event,
|
fire_command_event,
|
||||||
get_devices_from_config,
|
get_device_id,
|
||||||
get_new_device,
|
get_rfx_object,
|
||||||
)
|
)
|
||||||
from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST
|
from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST
|
||||||
|
|
||||||
|
@ -38,11 +40,32 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up the RFXtrx cover."""
|
"""Set up the RFXtrx cover."""
|
||||||
covers = get_devices_from_config(config, RfxtrxCover)
|
device_ids = set()
|
||||||
add_entities(covers)
|
|
||||||
|
entities = []
|
||||||
|
for packet_id, entity_info in config[CONF_DEVICES].items():
|
||||||
|
event = get_rfx_object(packet_id)
|
||||||
|
if event is None:
|
||||||
|
_LOGGER.error("Invalid device: %s", packet_id)
|
||||||
|
continue
|
||||||
|
|
||||||
|
device_id = get_device_id(event.device)
|
||||||
|
if device_id in device_ids:
|
||||||
|
continue
|
||||||
|
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]
|
||||||
|
)
|
||||||
|
entities.append(entity)
|
||||||
|
|
||||||
|
add_entities(entities)
|
||||||
|
|
||||||
def cover_update(event):
|
def cover_update(event):
|
||||||
"""Handle cover updates from the RFXtrx gateway."""
|
"""Handle cover updates from the RFXtrx gateway."""
|
||||||
|
@ -53,11 +76,27 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
new_device = get_new_device(event, config, RfxtrxCover)
|
device_id = get_device_id(event.device)
|
||||||
if new_device:
|
if device_id in device_ids:
|
||||||
add_entities([new_device])
|
return
|
||||||
|
device_ids.add(device_id)
|
||||||
|
|
||||||
|
_LOGGER.info(
|
||||||
|
"Added cover (Device ID: %s Class: %s Sub: %s)",
|
||||||
|
event.device.id_string.lower(),
|
||||||
|
event.device.__class__.__name__,
|
||||||
|
event.device.subtype,
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
add_entities([entity])
|
||||||
|
|
||||||
# Subscribe to main RFXtrx events
|
# Subscribe to main RFXtrx events
|
||||||
|
if config[CONF_AUTOMATIC_ADD]:
|
||||||
hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, cover_update)
|
hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, cover_update)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,21 +10,21 @@ from homeassistant.components.light import (
|
||||||
SUPPORT_BRIGHTNESS,
|
SUPPORT_BRIGHTNESS,
|
||||||
LightEntity,
|
LightEntity,
|
||||||
)
|
)
|
||||||
from homeassistant.const import CONF_NAME, STATE_ON
|
from homeassistant.const import ATTR_STATE, CONF_DEVICES, CONF_NAME, STATE_ON
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
|
ATTR_FIRE_EVENT,
|
||||||
CONF_AUTOMATIC_ADD,
|
CONF_AUTOMATIC_ADD,
|
||||||
CONF_DEVICES,
|
|
||||||
CONF_FIRE_EVENT,
|
CONF_FIRE_EVENT,
|
||||||
CONF_SIGNAL_REPETITIONS,
|
CONF_SIGNAL_REPETITIONS,
|
||||||
DEFAULT_SIGNAL_REPETITIONS,
|
DEFAULT_SIGNAL_REPETITIONS,
|
||||||
SIGNAL_EVENT,
|
SIGNAL_EVENT,
|
||||||
RfxtrxDevice,
|
RfxtrxDevice,
|
||||||
fire_command_event,
|
fire_command_event,
|
||||||
get_devices_from_config,
|
get_device_id,
|
||||||
get_new_device,
|
get_rfx_object,
|
||||||
)
|
)
|
||||||
from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST
|
from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST
|
||||||
|
|
||||||
|
@ -52,8 +52,29 @@ SUPPORT_RFXTRX = SUPPORT_BRIGHTNESS
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up the RFXtrx platform."""
|
"""Set up the RFXtrx platform."""
|
||||||
lights = get_devices_from_config(config, RfxtrxLight)
|
device_ids = set()
|
||||||
add_entities(lights)
|
|
||||||
|
# Add switch from config file
|
||||||
|
entities = []
|
||||||
|
for packet_id, entity_info in config[CONF_DEVICES].items():
|
||||||
|
event = get_rfx_object(packet_id)
|
||||||
|
if event is None:
|
||||||
|
_LOGGER.error("Invalid device: %s", packet_id)
|
||||||
|
continue
|
||||||
|
|
||||||
|
device_id = get_device_id(event.device)
|
||||||
|
if device_id in device_ids:
|
||||||
|
continue
|
||||||
|
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]
|
||||||
|
)
|
||||||
|
|
||||||
|
entities.append(entity)
|
||||||
|
|
||||||
|
add_entities(entities)
|
||||||
|
|
||||||
def light_update(event):
|
def light_update(event):
|
||||||
"""Handle light updates from the RFXtrx gateway."""
|
"""Handle light updates from the RFXtrx gateway."""
|
||||||
|
@ -63,11 +84,28 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
new_device = get_new_device(event, config, RfxtrxLight)
|
device_id = get_device_id(event.device)
|
||||||
if new_device:
|
if device_id in device_ids:
|
||||||
add_entities([new_device])
|
return
|
||||||
|
device_ids.add(device_id)
|
||||||
|
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Added light (Device ID: %s Class: %s Sub: %s)",
|
||||||
|
event.device.id_string.lower(),
|
||||||
|
event.device.__class__.__name__,
|
||||||
|
event.device.subtype,
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
add_entities([entity])
|
||||||
|
|
||||||
# Subscribe to main RFXtrx events
|
# Subscribe to main RFXtrx events
|
||||||
|
if config[CONF_AUTOMATIC_ADD]:
|
||||||
hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, light_update)
|
hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, light_update)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,21 +5,17 @@ from RFXtrx import SensorEvent
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
||||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_NAME, CONF_NAME
|
from homeassistant.const import ATTR_ENTITY_ID, CONF_DEVICES, CONF_NAME
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.util import slugify
|
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
ATTR_DATA_TYPE,
|
|
||||||
ATTR_FIRE_EVENT,
|
|
||||||
CONF_AUTOMATIC_ADD,
|
CONF_AUTOMATIC_ADD,
|
||||||
CONF_DATA_TYPE,
|
CONF_DATA_TYPE,
|
||||||
CONF_DEVICES,
|
|
||||||
CONF_FIRE_EVENT,
|
CONF_FIRE_EVENT,
|
||||||
DATA_TYPES,
|
DATA_TYPES,
|
||||||
RFX_DEVICES,
|
|
||||||
SIGNAL_EVENT,
|
SIGNAL_EVENT,
|
||||||
|
get_device_id,
|
||||||
get_rfx_object,
|
get_rfx_object,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -46,63 +42,62 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up the RFXtrx platform."""
|
"""Set up the RFXtrx platform."""
|
||||||
sensors = []
|
data_ids = set()
|
||||||
|
|
||||||
|
entities = []
|
||||||
for packet_id, entity_info in config[CONF_DEVICES].items():
|
for packet_id, entity_info in config[CONF_DEVICES].items():
|
||||||
event = get_rfx_object(packet_id)
|
event = get_rfx_object(packet_id)
|
||||||
device_id = "sensor_{}".format(slugify(event.device.id_string.lower()))
|
if event is None:
|
||||||
if device_id in RFX_DEVICES:
|
_LOGGER.error("Invalid device: %s", packet_id)
|
||||||
continue
|
continue
|
||||||
_LOGGER.info("Add %s rfxtrx.sensor", entity_info[ATTR_NAME])
|
|
||||||
|
|
||||||
sub_sensors = {}
|
if entity_info[CONF_DATA_TYPE]:
|
||||||
data_types = entity_info[ATTR_DATA_TYPE]
|
data_types = entity_info[CONF_DATA_TYPE]
|
||||||
if not data_types:
|
else:
|
||||||
data_types = [""]
|
data_types = list(set(event.values) & set(DATA_TYPES))
|
||||||
for data_type in DATA_TYPES:
|
|
||||||
if data_type in event.values:
|
device_id = get_device_id(event.device)
|
||||||
data_types = [data_type]
|
for data_type in data_types:
|
||||||
break
|
data_id = (*device_id, data_type)
|
||||||
for _data_type in data_types:
|
if data_id in data_ids:
|
||||||
new_sensor = RfxtrxSensor(
|
continue
|
||||||
|
data_ids.add(data_id)
|
||||||
|
|
||||||
|
entity = RfxtrxSensor(
|
||||||
event.device,
|
event.device,
|
||||||
entity_info[ATTR_NAME],
|
entity_info[CONF_NAME],
|
||||||
_data_type,
|
data_type,
|
||||||
entity_info[ATTR_FIRE_EVENT],
|
entity_info[CONF_FIRE_EVENT],
|
||||||
)
|
)
|
||||||
sensors.append(new_sensor)
|
entities.append(entity)
|
||||||
sub_sensors[_data_type] = new_sensor
|
|
||||||
RFX_DEVICES[device_id] = sub_sensors
|
add_entities(entities)
|
||||||
add_entities(sensors)
|
|
||||||
|
|
||||||
def sensor_update(event):
|
def sensor_update(event):
|
||||||
"""Handle sensor updates from the RFXtrx gateway."""
|
"""Handle sensor updates from the RFXtrx gateway."""
|
||||||
if not isinstance(event, SensorEvent):
|
if not isinstance(event, SensorEvent):
|
||||||
return
|
return
|
||||||
|
|
||||||
device_id = f"sensor_{slugify(event.device.id_string.lower())}"
|
|
||||||
|
|
||||||
if device_id in RFX_DEVICES:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Add entity if not exist and the automatic_add is True
|
|
||||||
if not config[CONF_AUTOMATIC_ADD]:
|
|
||||||
return
|
|
||||||
|
|
||||||
pkt_id = "".join(f"{x:02x}" for x in event.data)
|
pkt_id = "".join(f"{x:02x}" for x in event.data)
|
||||||
_LOGGER.info("Automatic add rfxtrx.sensor: %s", pkt_id)
|
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)
|
||||||
|
|
||||||
data_type = ""
|
_LOGGER.debug(
|
||||||
for _data_type in DATA_TYPES:
|
"Added sensor (Device ID: %s Class: %s Sub: %s)",
|
||||||
if _data_type in event.values:
|
event.device.id_string.lower(),
|
||||||
data_type = _data_type
|
event.device.__class__.__name__,
|
||||||
break
|
event.device.subtype,
|
||||||
new_sensor = RfxtrxSensor(event.device, pkt_id, data_type, event=event)
|
)
|
||||||
sub_sensors = {}
|
|
||||||
sub_sensors[new_sensor.data_type] = new_sensor
|
entity = RfxtrxSensor(event.device, pkt_id, data_type, event=event)
|
||||||
RFX_DEVICES[device_id] = sub_sensors
|
add_entities([entity])
|
||||||
add_entities([new_sensor])
|
|
||||||
|
|
||||||
# Subscribe to main RFXtrx events
|
# Subscribe to main RFXtrx events
|
||||||
|
if config[CONF_AUTOMATIC_ADD]:
|
||||||
hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, sensor_update)
|
hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, sensor_update)
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,9 +112,8 @@ class RfxtrxSensor(Entity):
|
||||||
self.should_fire_event = should_fire_event
|
self.should_fire_event = should_fire_event
|
||||||
self.data_type = data_type
|
self.data_type = data_type
|
||||||
self._unit_of_measurement = DATA_TYPES.get(data_type, "")
|
self._unit_of_measurement = DATA_TYPES.get(data_type, "")
|
||||||
self._unique_id = (
|
self._device_id = get_device_id(device)
|
||||||
f"{device.packettype:x}_{device.subtype:x}_{device.id_string}_{data_type}"
|
self._unique_id = "_".join(x for x in (*self._device_id, data_type))
|
||||||
)
|
|
||||||
|
|
||||||
if event:
|
if event:
|
||||||
self._apply_event(event)
|
self._apply_event(event)
|
||||||
|
|
|
@ -5,21 +5,21 @@ import RFXtrx as rfxtrxmod
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchEntity
|
from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchEntity
|
||||||
from homeassistant.const import CONF_NAME, STATE_ON
|
from homeassistant.const import ATTR_STATE, CONF_DEVICES, CONF_NAME, STATE_ON
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
|
ATTR_FIRE_EVENT,
|
||||||
CONF_AUTOMATIC_ADD,
|
CONF_AUTOMATIC_ADD,
|
||||||
CONF_DEVICES,
|
|
||||||
CONF_FIRE_EVENT,
|
CONF_FIRE_EVENT,
|
||||||
CONF_SIGNAL_REPETITIONS,
|
CONF_SIGNAL_REPETITIONS,
|
||||||
DEFAULT_SIGNAL_REPETITIONS,
|
DEFAULT_SIGNAL_REPETITIONS,
|
||||||
SIGNAL_EVENT,
|
SIGNAL_EVENT,
|
||||||
RfxtrxDevice,
|
RfxtrxDevice,
|
||||||
fire_command_event,
|
fire_command_event,
|
||||||
get_devices_from_config,
|
get_device_id,
|
||||||
get_new_device,
|
get_rfx_object,
|
||||||
)
|
)
|
||||||
from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST
|
from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST
|
||||||
|
|
||||||
|
@ -45,9 +45,28 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities_callback, discovery_info=None):
|
def setup_platform(hass, config, add_entities_callback, discovery_info=None):
|
||||||
"""Set up the RFXtrx platform."""
|
"""Set up the RFXtrx platform."""
|
||||||
|
device_ids = set()
|
||||||
|
|
||||||
# Add switch from config file
|
# Add switch from config file
|
||||||
switches = get_devices_from_config(config, RfxtrxSwitch)
|
entities = []
|
||||||
add_entities_callback(switches)
|
for packet_id, entity_info in config[CONF_DEVICES].items():
|
||||||
|
event = get_rfx_object(packet_id)
|
||||||
|
if event is None:
|
||||||
|
_LOGGER.error("Invalid device: %s", packet_id)
|
||||||
|
continue
|
||||||
|
|
||||||
|
device_id = get_device_id(event.device)
|
||||||
|
if device_id in device_ids:
|
||||||
|
continue
|
||||||
|
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]
|
||||||
|
)
|
||||||
|
entities.append(entity)
|
||||||
|
|
||||||
|
add_entities_callback(entities)
|
||||||
|
|
||||||
def switch_update(event):
|
def switch_update(event):
|
||||||
"""Handle sensor updates from the RFXtrx gateway."""
|
"""Handle sensor updates from the RFXtrx gateway."""
|
||||||
|
@ -58,11 +77,27 @@ def setup_platform(hass, config, add_entities_callback, discovery_info=None):
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
new_device = get_new_device(event, config, RfxtrxSwitch)
|
device_id = get_device_id(event.device)
|
||||||
if new_device:
|
if device_id in device_ids:
|
||||||
add_entities_callback([new_device])
|
return
|
||||||
|
device_ids.add(device_id)
|
||||||
|
|
||||||
|
_LOGGER.info(
|
||||||
|
"Added switch (Device ID: %s Class: %s Sub: %s)",
|
||||||
|
event.device.id_string.lower(),
|
||||||
|
event.device.__class__.__name__,
|
||||||
|
event.device.subtype,
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
add_entities_callback([entity])
|
||||||
|
|
||||||
# Subscribe to main RFXtrx events
|
# Subscribe to main RFXtrx events
|
||||||
|
if config[CONF_AUTOMATIC_ADD]:
|
||||||
hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, switch_update)
|
hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, switch_update)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -59,8 +59,6 @@ async def rfxtrx_cleanup():
|
||||||
):
|
):
|
||||||
yield
|
yield
|
||||||
|
|
||||||
rfxtrx_core.RFX_DEVICES.clear()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="rfxtrx")
|
@pytest.fixture(name="rfxtrx")
|
||||||
async def rfxtrx_fixture(hass):
|
async def rfxtrx_fixture(hass):
|
||||||
|
|
|
@ -141,7 +141,7 @@ async def test_fire_event(hass):
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "on"
|
assert state.state == "on"
|
||||||
|
|
||||||
assert 1 == len(calls)
|
assert len(calls) == 1
|
||||||
assert calls[0].data == {"entity_id": "switch.test", "state": "on"}
|
assert calls[0].data == {"entity_id": "switch.test", "state": "on"}
|
||||||
|
|
||||||
|
|
||||||
|
@ -187,5 +187,5 @@ async def test_fire_event_sensor(hass):
|
||||||
hass.bus.async_listen("signal_received", record_event)
|
hass.bus.async_listen("signal_received", record_event)
|
||||||
|
|
||||||
await _signal_event(hass, "0a520802060101ff0f0269")
|
await _signal_event(hass, "0a520802060101ff0f0269")
|
||||||
assert 1 == len(calls)
|
assert len(calls) == 5
|
||||||
assert calls[0].data == {"entity_id": "sensor.test_temperature"}
|
assert any(call.data == {"entity_id": "sensor.test_temperature"} for call in calls)
|
||||||
|
|
|
@ -57,7 +57,7 @@ async def test_default_config(hass, rfxtrx):
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert 0 == len(rfxtrx_core.RFX_DEVICES)
|
assert len(hass.states.async_all()) == 0
|
||||||
|
|
||||||
|
|
||||||
async def test_one_light(hass, rfxtrx):
|
async def test_one_light(hass, rfxtrx):
|
||||||
|
|
|
@ -55,12 +55,39 @@ async def test_one_sensor_no_datatype(hass, rfxtrx):
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
state = hass.states.get("sensor.test_temperature")
|
base_id = "sensor.test"
|
||||||
|
base_name = "Test"
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_temperature")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "unknown"
|
assert state.state == "unknown"
|
||||||
assert state.attributes.get("friendly_name") == "Test Temperature"
|
assert state.attributes.get("friendly_name") == f"{base_name} Temperature"
|
||||||
assert state.attributes.get("unit_of_measurement") == TEMP_CELSIUS
|
assert state.attributes.get("unit_of_measurement") == TEMP_CELSIUS
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_humidity")
|
||||||
|
assert state
|
||||||
|
assert state.state == "unknown"
|
||||||
|
assert state.attributes.get("friendly_name") == f"{base_name} Humidity"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == UNIT_PERCENTAGE
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_humidity_status")
|
||||||
|
assert state
|
||||||
|
assert state.state == "unknown"
|
||||||
|
assert state.attributes.get("friendly_name") == f"{base_name} Humidity status"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == ""
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_rssi_numeric")
|
||||||
|
assert state
|
||||||
|
assert state.state == "unknown"
|
||||||
|
assert state.attributes.get("friendly_name") == f"{base_name} Rssi numeric"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == ""
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_battery_numeric")
|
||||||
|
assert state
|
||||||
|
assert state.state == "unknown"
|
||||||
|
assert state.attributes.get("friendly_name") == f"{base_name} Battery numeric"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == ""
|
||||||
|
|
||||||
|
|
||||||
async def test_several_sensors(hass, rfxtrx):
|
async def test_several_sensors(hass, rfxtrx):
|
||||||
"""Test with 3 sensors."""
|
"""Test with 3 sensors."""
|
||||||
|
@ -113,61 +140,94 @@ async def test_discover_sensor(hass, rfxtrx):
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# 1
|
||||||
await _signal_event(hass, "0a520801070100b81b0279")
|
await _signal_event(hass, "0a520801070100b81b0279")
|
||||||
state = hass.states.get("sensor.0a520801070100b81b0279_temperature")
|
base_id = "sensor.0a520801070100b81b0279"
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_humidity")
|
||||||
|
assert state
|
||||||
|
assert state.state == "27"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == UNIT_PERCENTAGE
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_humidity_status")
|
||||||
|
assert state
|
||||||
|
assert state.state == "normal"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == ""
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_rssi_numeric")
|
||||||
|
assert state
|
||||||
|
assert state.state == "7"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == ""
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_temperature")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "18.4"
|
assert state.state == "18.4"
|
||||||
assert (
|
assert state.attributes.get("unit_of_measurement") == TEMP_CELSIUS
|
||||||
state.attributes.items()
|
|
||||||
>= {
|
|
||||||
"friendly_name": "0a520801070100b81b0279 Temperature",
|
|
||||||
"unit_of_measurement": TEMP_CELSIUS,
|
|
||||||
"Humidity status": "normal",
|
|
||||||
"Temperature": 18.4,
|
|
||||||
"Rssi numeric": 7,
|
|
||||||
"Humidity": 27,
|
|
||||||
"Battery numeric": 9,
|
|
||||||
"Humidity status numeric": 2,
|
|
||||||
}.items()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_battery_numeric")
|
||||||
|
assert state
|
||||||
|
assert state.state == "9"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == ""
|
||||||
|
|
||||||
|
# 2
|
||||||
await _signal_event(hass, "0a52080405020095240279")
|
await _signal_event(hass, "0a52080405020095240279")
|
||||||
state = hass.states.get("sensor.0a52080405020095240279_temperature")
|
base_id = "sensor.0a52080405020095240279"
|
||||||
|
state = hass.states.get(f"{base_id}_humidity")
|
||||||
|
|
||||||
|
assert state
|
||||||
|
assert state.state == "36"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == UNIT_PERCENTAGE
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_humidity_status")
|
||||||
|
assert state
|
||||||
|
assert state.state == "normal"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == ""
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_rssi_numeric")
|
||||||
|
assert state
|
||||||
|
assert state.state == "7"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == ""
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_temperature")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "14.9"
|
assert state.state == "14.9"
|
||||||
assert (
|
assert state.attributes.get("unit_of_measurement") == TEMP_CELSIUS
|
||||||
state.attributes.items()
|
|
||||||
>= {
|
|
||||||
"friendly_name": "0a52080405020095240279 Temperature",
|
|
||||||
"unit_of_measurement": TEMP_CELSIUS,
|
|
||||||
"Humidity status": "normal",
|
|
||||||
"Temperature": 14.9,
|
|
||||||
"Rssi numeric": 7,
|
|
||||||
"Humidity": 36,
|
|
||||||
"Battery numeric": 9,
|
|
||||||
"Humidity status numeric": 2,
|
|
||||||
}.items()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_battery_numeric")
|
||||||
|
assert state
|
||||||
|
assert state.state == "9"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == ""
|
||||||
|
|
||||||
|
# 1 Update
|
||||||
await _signal_event(hass, "0a52085e070100b31b0279")
|
await _signal_event(hass, "0a52085e070100b31b0279")
|
||||||
state = hass.states.get("sensor.0a520801070100b81b0279_temperature")
|
base_id = "sensor.0a520801070100b81b0279"
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_humidity")
|
||||||
|
assert state
|
||||||
|
assert state.state == "27"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == UNIT_PERCENTAGE
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_humidity_status")
|
||||||
|
assert state
|
||||||
|
assert state.state == "normal"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == ""
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_rssi_numeric")
|
||||||
|
assert state
|
||||||
|
assert state.state == "7"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == ""
|
||||||
|
|
||||||
|
state = hass.states.get(f"{base_id}_temperature")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "17.9"
|
assert state.state == "17.9"
|
||||||
assert (
|
assert state.attributes.get("unit_of_measurement") == TEMP_CELSIUS
|
||||||
state.attributes.items()
|
|
||||||
>= {
|
|
||||||
"friendly_name": "0a520801070100b81b0279 Temperature",
|
|
||||||
"unit_of_measurement": TEMP_CELSIUS,
|
|
||||||
"Humidity status": "normal",
|
|
||||||
"Temperature": 17.9,
|
|
||||||
"Rssi numeric": 7,
|
|
||||||
"Humidity": 27,
|
|
||||||
"Battery numeric": 9,
|
|
||||||
"Humidity status numeric": 2,
|
|
||||||
}.items()
|
|
||||||
)
|
|
||||||
|
|
||||||
assert len(hass.states.async_all()) == 2
|
state = hass.states.get(f"{base_id}_battery_numeric")
|
||||||
|
assert state
|
||||||
|
assert state.state == "9"
|
||||||
|
assert state.attributes.get("unit_of_measurement") == ""
|
||||||
|
|
||||||
|
assert len(hass.states.async_all()) == 10
|
||||||
|
|
||||||
|
|
||||||
async def test_discover_sensor_noautoadd(hass, rfxtrx):
|
async def test_discover_sensor_noautoadd(hass, rfxtrx):
|
||||||
|
@ -215,35 +275,14 @@ async def test_update_of_sensors(hass, rfxtrx):
|
||||||
state = hass.states.get("sensor.test_temperature")
|
state = hass.states.get("sensor.test_temperature")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "unknown"
|
assert state.state == "unknown"
|
||||||
assert (
|
|
||||||
state.attributes.items()
|
|
||||||
>= {
|
|
||||||
"friendly_name": "Test Temperature",
|
|
||||||
"unit_of_measurement": TEMP_CELSIUS,
|
|
||||||
}.items()
|
|
||||||
)
|
|
||||||
|
|
||||||
state = hass.states.get("sensor.bath_temperature")
|
state = hass.states.get("sensor.bath_temperature")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "unknown"
|
assert state.state == "unknown"
|
||||||
assert (
|
|
||||||
state.attributes.items()
|
|
||||||
>= {
|
|
||||||
"friendly_name": "Bath Temperature",
|
|
||||||
"unit_of_measurement": TEMP_CELSIUS,
|
|
||||||
}.items()
|
|
||||||
)
|
|
||||||
|
|
||||||
state = hass.states.get("sensor.bath_humidity")
|
state = hass.states.get("sensor.bath_humidity")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "unknown"
|
assert state.state == "unknown"
|
||||||
assert (
|
|
||||||
state.attributes.items()
|
|
||||||
>= {
|
|
||||||
"friendly_name": "Bath Humidity",
|
|
||||||
"unit_of_measurement": UNIT_PERCENTAGE,
|
|
||||||
}.items()
|
|
||||||
)
|
|
||||||
|
|
||||||
assert len(hass.states.async_all()) == 3
|
assert len(hass.states.async_all()) == 3
|
||||||
|
|
||||||
|
@ -253,52 +292,13 @@ async def test_update_of_sensors(hass, rfxtrx):
|
||||||
state = hass.states.get("sensor.test_temperature")
|
state = hass.states.get("sensor.test_temperature")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "13.3"
|
assert state.state == "13.3"
|
||||||
assert (
|
|
||||||
state.attributes.items()
|
|
||||||
>= {
|
|
||||||
"friendly_name": "Test Temperature",
|
|
||||||
"unit_of_measurement": TEMP_CELSIUS,
|
|
||||||
"Battery numeric": 9,
|
|
||||||
"Temperature": 13.3,
|
|
||||||
"Humidity": 34,
|
|
||||||
"Humidity status": "normal",
|
|
||||||
"Humidity status numeric": 2,
|
|
||||||
"Rssi numeric": 6,
|
|
||||||
}.items()
|
|
||||||
)
|
|
||||||
|
|
||||||
state = hass.states.get("sensor.bath_temperature")
|
state = hass.states.get("sensor.bath_temperature")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "51.1"
|
assert state.state == "51.1"
|
||||||
assert (
|
|
||||||
state.attributes.items()
|
|
||||||
>= {
|
|
||||||
"friendly_name": "Bath Temperature",
|
|
||||||
"unit_of_measurement": TEMP_CELSIUS,
|
|
||||||
"Battery numeric": 9,
|
|
||||||
"Temperature": 51.1,
|
|
||||||
"Humidity": 15,
|
|
||||||
"Humidity status": "normal",
|
|
||||||
"Humidity status numeric": 2,
|
|
||||||
"Rssi numeric": 6,
|
|
||||||
}.items()
|
|
||||||
)
|
|
||||||
|
|
||||||
state = hass.states.get("sensor.bath_humidity")
|
state = hass.states.get("sensor.bath_humidity")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "15"
|
assert state.state == "15"
|
||||||
assert (
|
|
||||||
state.attributes.items()
|
|
||||||
>= {
|
|
||||||
"friendly_name": "Bath Humidity",
|
|
||||||
"unit_of_measurement": UNIT_PERCENTAGE,
|
|
||||||
"Battery numeric": 9,
|
|
||||||
"Temperature": 51.1,
|
|
||||||
"Humidity": 15,
|
|
||||||
"Humidity status": "normal",
|
|
||||||
"Humidity status numeric": 2,
|
|
||||||
"Rssi numeric": 6,
|
|
||||||
}.items()
|
|
||||||
)
|
|
||||||
|
|
||||||
assert len(hass.states.async_all()) == 3
|
assert len(hass.states.async_all()) == 3
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue