Replace rfxtrx entity events with integration events (#37565)

* Drop per entity events

* Correct linting error

* Drop keys()
This commit is contained in:
Joakim Plate 2020-07-13 02:57:19 +02:00 committed by GitHub
parent d3b47b6d89
commit 87f6b7cdd4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 132 additions and 183 deletions

View file

@ -8,8 +8,6 @@ import voluptuous as vol
from homeassistant.components.binary_sensor import DEVICE_CLASSES_SCHEMA from homeassistant.components.binary_sensor import DEVICE_CLASSES_SCHEMA
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_STATE,
CONF_COMMAND_OFF, CONF_COMMAND_OFF,
CONF_COMMAND_ON, CONF_COMMAND_ON,
CONF_DEVICE, CONF_DEVICE,
@ -27,23 +25,20 @@ from homeassistant.const import (
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.discovery import load_platform from homeassistant.helpers.discovery import load_platform
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.util import slugify
from .const import DEVICE_PACKET_TYPE_LIGHTING4 from .const import DEVICE_PACKET_TYPE_LIGHTING4, EVENT_RFXTRX_EVENT
DOMAIN = "rfxtrx" DOMAIN = "rfxtrx"
DEFAULT_SIGNAL_REPETITIONS = 1 DEFAULT_SIGNAL_REPETITIONS = 1
ATTR_FIRE_EVENT = "fire_event" CONF_FIRE_EVENT = "fire_event"
CONF_DATA_BITS = "data_bits" CONF_DATA_BITS = "data_bits"
CONF_AUTOMATIC_ADD = "automatic_add" CONF_AUTOMATIC_ADD = "automatic_add"
CONF_SIGNAL_REPETITIONS = "signal_repetitions" CONF_SIGNAL_REPETITIONS = "signal_repetitions"
CONF_FIRE_EVENT = "fire_event"
CONF_DUMMY = "dummy" CONF_DUMMY = "dummy"
CONF_DEBUG = "debug" CONF_DEBUG = "debug"
CONF_OFF_DELAY = "off_delay" CONF_OFF_DELAY = "off_delay"
EVENT_BUTTON_PRESSED = "button_pressed"
SIGNAL_EVENT = f"{DOMAIN}_event" SIGNAL_EVENT = f"{DOMAIN}_event"
DATA_TYPES = OrderedDict( DATA_TYPES = OrderedDict(
@ -118,23 +113,46 @@ CONFIG_SCHEMA = vol.Schema(
def setup(hass, config): def setup(hass, config):
"""Set up the RFXtrx component.""" """Set up the RFXtrx component."""
# Setup some per device config
device_events = set()
device_bits = {}
for event_code, event_config in config[DOMAIN][CONF_DEVICES].items():
event = get_rfx_object(event_code)
device_id = get_device_id(
event.device, data_bits=event_config.get(CONF_DATA_BITS)
)
device_bits[device_id] = event_config.get(CONF_DATA_BITS)
if event_config[CONF_FIRE_EVENT]:
device_events.add(device_id)
# Declare the Handle event # Declare the Handle event
def handle_receive(event): def handle_receive(event):
"""Handle received messages from RFXtrx gateway.""" """Handle received messages from RFXtrx gateway."""
# Log RFXCOM event # Log RFXCOM event
if not event.device.id_string: if not event.device.id_string:
return return
_LOGGER.debug(
"Receive RFXCOM event from " event_data = {
"(Device_id: %s Class: %s Sub: %s, Pkt_id: %s)", "packet_type": event.device.packettype,
slugify(event.device.id_string.lower()), "sub_type": event.device.subtype,
event.device.__class__.__name__, "type_string": event.device.type_string,
event.device.subtype, "id_string": event.device.id_string,
"".join(f"{x:02x}" for x in event.data), "data": "".join(f"{x:02x}" for x in event.data),
) "values": getattr(event, "values", None),
}
_LOGGER.debug("Receive RFXCOM event: %s", event_data)
data_bits = get_device_data_bits(event.device, device_bits)
device_id = get_device_id(event.device, data_bits=data_bits)
# Callback to HA registered components. # Callback to HA registered components.
hass.helpers.dispatcher.dispatcher_send(SIGNAL_EVENT, event) hass.helpers.dispatcher.dispatcher_send(SIGNAL_EVENT, event, device_id)
# Signal event to any other listeners
if device_id in device_events:
hass.bus.fire(EVENT_RFXTRX_EVENT, event_data)
device = config[DOMAIN].get(CONF_DEVICE) device = config[DOMAIN].get(CONF_DEVICE)
host = config[DOMAIN].get(CONF_HOST) host = config[DOMAIN].get(CONF_HOST)
@ -228,6 +246,17 @@ def get_pt2262_cmd(device_id, data_bits):
return hex(data[-1] & mask) return hex(data[-1] & mask)
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 device_id, bits in device_bits.items():
if get_device_id(device, bits) == device_id:
data_bits = bits
break
return data_bits
def find_possible_pt2262_device(device_ids, 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 dev_id in device_ids: for dev_id in device_ids:
@ -266,35 +295,19 @@ def get_device_id(device, data_bits=None):
return (f"{device.packettype:x}", f"{device.subtype:x}", id_string) return (f"{device.packettype:x}", f"{device.subtype:x}", id_string)
def fire_command_event(hass, entity_id, command):
"""Fire a command event."""
hass.bus.fire(
EVENT_BUTTON_PRESSED, {ATTR_ENTITY_ID: entity_id, ATTR_STATE: command.lower()}
)
_LOGGER.debug(
"Rfxtrx fired event: (event_type: %s, %s: %s, %s: %s)",
EVENT_BUTTON_PRESSED,
ATTR_ENTITY_ID,
entity_id,
ATTR_STATE,
command.lower(),
)
class RfxtrxDevice(Entity): class RfxtrxDevice(Entity):
"""Represents a Rfxtrx device. """Represents a Rfxtrx device.
Contains the common logic for Rfxtrx lights and switches. Contains the common logic for Rfxtrx lights and switches.
""" """
def __init__(self, device, datas, signal_repetitions, event=None): def __init__(self, device, device_id, signal_repetitions, event=None):
"""Initialize the device.""" """Initialize the device."""
self.signal_repetitions = signal_repetitions self.signal_repetitions = signal_repetitions
self._name = f"{device.type_string} {device.id_string}" self._name = f"{device.type_string} {device.id_string}"
self._device = device self._device = device
self._state = datas[ATTR_STATE] self._state = None
self._should_fire_event = datas[ATTR_FIRE_EVENT] self._device_id = device_id
self._device_id = get_device_id(device)
self._unique_id = "_".join(x for x in self._device_id) self._unique_id = "_".join(x for x in self._device_id)
if event: if event:
@ -310,11 +323,6 @@ class RfxtrxDevice(Entity):
"""Return the name of the device if any.""" """Return the name of the device if any."""
return self._name return self._name
@property
def should_fire_event(self):
"""Return is the device must fire event."""
return self._should_fire_event
@property @property
def is_on(self): def is_on(self):
"""Return true if device is on.""" """Return true if device is on."""

View file

@ -15,14 +15,11 @@ from homeassistant.helpers import event as evt
from . import ( from . import (
CONF_AUTOMATIC_ADD, CONF_AUTOMATIC_ADD,
CONF_DATA_BITS, CONF_DATA_BITS,
CONF_FIRE_EVENT,
CONF_OFF_DELAY, CONF_OFF_DELAY,
SIGNAL_EVENT, SIGNAL_EVENT,
find_possible_pt2262_device, find_possible_pt2262_device,
fire_command_event,
get_device_id, get_device_id,
get_pt2262_cmd, get_pt2262_cmd,
get_pt2262_deviceid,
get_rfx_object, get_rfx_object,
) )
from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST, DEVICE_PACKET_TYPE_LIGHTING4 from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST, DEVICE_PACKET_TYPE_LIGHTING4
@ -30,17 +27,6 @@ from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST, DEVICE_PACKET_TYPE_LIGHTIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
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."""
if discovery_info is None: if discovery_info is None:
@ -49,7 +35,6 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
sensors = [] sensors = []
device_ids = set() device_ids = set()
device_bits = {}
pt2262_devices = [] pt2262_devices = []
@ -75,8 +60,8 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
device = RfxtrxBinarySensor( device = RfxtrxBinarySensor(
event.device, event.device,
device_id,
entity.get(CONF_DEVICE_CLASS), entity.get(CONF_DEVICE_CLASS),
entity[CONF_FIRE_EVENT],
entity.get(CONF_OFF_DELAY), entity.get(CONF_OFF_DELAY),
entity.get(CONF_DATA_BITS), entity.get(CONF_DATA_BITS),
entity.get(CONF_COMMAND_ON), entity.get(CONF_COMMAND_ON),
@ -86,14 +71,11 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
add_entities(sensors) add_entities(sensors)
def binary_sensor_update(event): def binary_sensor_update(event, device_id):
"""Call for control updates from the RFXtrx gateway.""" """Call for control updates from the RFXtrx gateway."""
if not supported(event): if not supported(event):
return return
data_bits = _get_device_data_bits(event.device, device_bits)
device_id = get_device_id(event.device, data_bits=data_bits)
if device_id in device_ids: if device_id in device_ids:
return return
device_ids.add(device_id) device_ids.add(device_id)
@ -105,7 +87,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
event.device.subtype, event.device.subtype,
"".join(f"{x:02x}" for x in event.data), "".join(f"{x:02x}" for x in event.data),
) )
sensor = RfxtrxBinarySensor(event.device, data_bits=data_bits, event=event) sensor = RfxtrxBinarySensor(event.device, device_id, event=event)
add_entities([sensor]) add_entities([sensor])
# Subscribe to main RFXtrx events # Subscribe to main RFXtrx events
@ -119,8 +101,8 @@ class RfxtrxBinarySensor(BinarySensorEntity):
def __init__( def __init__(
self, self,
device, device,
device_id,
device_class=None, device_class=None,
should_fire=False,
off_delay=None, off_delay=None,
data_bits=None, data_bits=None,
cmd_on=None, cmd_on=None,
@ -131,16 +113,15 @@ class RfxtrxBinarySensor(BinarySensorEntity):
self.event = None self.event = None
self._device = device self._device = device
self._name = f"{device.type_string} {device.id_string}" self._name = f"{device.type_string} {device.id_string}"
self._should_fire_event = should_fire
self._device_class = device_class self._device_class = device_class
self._data_bits = data_bits
self._off_delay = off_delay self._off_delay = off_delay
self._state = False self._state = False
self.delay_listener = None self.delay_listener = None
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
self._device_id = get_device_id(device, data_bits=data_bits) self._device_id = device_id
self._unique_id = "_".join(x for x in self._device_id) self._unique_id = "_".join(x for x in self._device_id)
if event: if event:
@ -181,11 +162,6 @@ class RfxtrxBinarySensor(BinarySensorEntity):
"""No polling needed.""" """No polling needed."""
return False return False
@property
def should_fire_event(self):
"""Return is the device must fire event."""
return self._should_fire_event
@property @property
def device_class(self): def device_class(self):
"""Return the sensor class.""" """Return the sensor class."""
@ -231,9 +207,9 @@ class RfxtrxBinarySensor(BinarySensorEntity):
else: else:
self._apply_event_standard(event) self._apply_event_standard(event)
def _handle_event(self, event): def _handle_event(self, event, device_id):
"""Check if event applies to me and update.""" """Check if event applies to me and update."""
if get_device_id(event.device, data_bits=self._data_bits) != self._device_id: if device_id != self._device_id:
return return
_LOGGER.debug( _LOGGER.debug(
@ -246,8 +222,6 @@ class RfxtrxBinarySensor(BinarySensorEntity):
self._apply_event(event) self._apply_event(event)
self.schedule_update_ha_state() self.schedule_update_ha_state()
if self.should_fire_event:
fire_command_event(self.hass, self.entity_id, event.values["Command"])
if self.is_on and self.off_delay is not None and self.delay_listener is None: if self.is_on and self.off_delay is not None and self.delay_listener is None:

View file

@ -14,4 +14,7 @@ COMMAND_OFF_LIST = [
"Down", "Down",
"Close (inline relay)", "Close (inline relay)",
] ]
DEVICE_PACKET_TYPE_LIGHTING4 = 0x13 DEVICE_PACKET_TYPE_LIGHTING4 = 0x13
EVENT_RFXTRX_EVENT = "rfxtrx_event"

View file

@ -2,18 +2,15 @@
import logging import logging
from homeassistant.components.cover import CoverEntity from homeassistant.components.cover import CoverEntity
from homeassistant.const import ATTR_STATE, CONF_DEVICES, STATE_OPEN from homeassistant.const import CONF_DEVICES, STATE_OPEN
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_FIRE_EVENT,
CONF_SIGNAL_REPETITIONS, CONF_SIGNAL_REPETITIONS,
DEFAULT_SIGNAL_REPETITIONS, DEFAULT_SIGNAL_REPETITIONS,
SIGNAL_EVENT, SIGNAL_EVENT,
RfxtrxDevice, RfxtrxDevice,
fire_command_event,
get_device_id, get_device_id,
get_rfx_object, get_rfx_object,
) )
@ -46,18 +43,18 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
continue continue
device_ids.add(device_id) device_ids.add(device_id)
datas = {ATTR_STATE: None, ATTR_FIRE_EVENT: entity_info[CONF_FIRE_EVENT]} entity = RfxtrxCover(
entity = RfxtrxCover(event.device, datas, entity_info[CONF_SIGNAL_REPETITIONS]) event.device, device_id, entity_info[CONF_SIGNAL_REPETITIONS]
)
entities.append(entity) entities.append(entity)
add_entities(entities) add_entities(entities)
def cover_update(event): def cover_update(event, device_id):
"""Handle cover updates from the RFXtrx gateway.""" """Handle cover updates from the RFXtrx gateway."""
if not supported(event): if not supported(event):
return return
device_id = get_device_id(event.device)
if device_id in device_ids: if device_id in device_ids:
return return
device_ids.add(device_id) device_ids.add(device_id)
@ -70,9 +67,8 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
"".join(f"{x:02x}" for x in event.data), "".join(f"{x:02x}" for x in event.data),
) )
datas = {ATTR_STATE: False, ATTR_FIRE_EVENT: False}
entity = RfxtrxCover( entity = RfxtrxCover(
event.device, datas, DEFAULT_SIGNAL_REPETITIONS, event=event event.device, device_id, DEFAULT_SIGNAL_REPETITIONS, event=event
) )
add_entities([entity]) add_entities([entity])
@ -127,13 +123,11 @@ class RfxtrxCover(RfxtrxDevice, CoverEntity, RestoreEntity):
elif event.values["Command"] in COMMAND_OFF_LIST: elif event.values["Command"] in COMMAND_OFF_LIST:
self._state = False self._state = False
def _handle_event(self, event): def _handle_event(self, event, device_id):
"""Check if event applies to me and update.""" """Check if event applies to me and update."""
if event.device.id_string != self._device.id_string: if device_id != self._device_id:
return return
self._apply_event(event) self._apply_event(event)
self.schedule_update_ha_state() self.schedule_update_ha_state()
if self.should_fire_event:
fire_command_event(self.hass, self.entity_id, event.values["Command"])

View file

@ -8,18 +8,15 @@ from homeassistant.components.light import (
SUPPORT_BRIGHTNESS, SUPPORT_BRIGHTNESS,
LightEntity, LightEntity,
) )
from homeassistant.const import ATTR_STATE, CONF_DEVICES, STATE_ON from homeassistant.const import CONF_DEVICES, STATE_ON
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_FIRE_EVENT,
CONF_SIGNAL_REPETITIONS, CONF_SIGNAL_REPETITIONS,
DEFAULT_SIGNAL_REPETITIONS, DEFAULT_SIGNAL_REPETITIONS,
SIGNAL_EVENT, SIGNAL_EVENT,
RfxtrxDevice, RfxtrxDevice,
fire_command_event,
get_device_id, get_device_id,
get_rfx_object, get_rfx_object,
) )
@ -58,19 +55,19 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
continue continue
device_ids.add(device_id) device_ids.add(device_id)
datas = {ATTR_STATE: None, ATTR_FIRE_EVENT: entity_info[CONF_FIRE_EVENT]} entity = RfxtrxLight(
entity = RfxtrxLight(event.device, datas, entity_info[CONF_SIGNAL_REPETITIONS]) event.device, device_id, entity_info[CONF_SIGNAL_REPETITIONS]
)
entities.append(entity) entities.append(entity)
add_entities(entities) add_entities(entities)
def light_update(event): def light_update(event, device_id):
"""Handle light updates from the RFXtrx gateway.""" """Handle light updates from the RFXtrx gateway."""
if not supported(event): if not supported(event):
return return
device_id = get_device_id(event.device)
if device_id in device_ids: if device_id in device_ids:
return return
device_ids.add(device_id) device_ids.add(device_id)
@ -83,9 +80,8 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
"".join(f"{x:02x}" for x in event.data), "".join(f"{x:02x}" for x in event.data),
) )
datas = {ATTR_STATE: None, ATTR_FIRE_EVENT: False}
entity = RfxtrxLight( entity = RfxtrxLight(
event.device, datas, DEFAULT_SIGNAL_REPETITIONS, event=event event.device, device_id, DEFAULT_SIGNAL_REPETITIONS, event=event
) )
add_entities([entity]) add_entities([entity])
@ -157,13 +153,11 @@ class RfxtrxLight(RfxtrxDevice, LightEntity, RestoreEntity):
self._brightness = event.values["Dim level"] * 255 // 100 self._brightness = event.values["Dim level"] * 255 // 100
self._state = self._brightness > 0 self._state = self._brightness > 0
def _handle_event(self, event): def _handle_event(self, event, device_id):
"""Check if event applies to me and update.""" """Check if event applies to me and update."""
if event.device.id_string != self._device.id_string: if device_id != self._device_id:
return return
self._apply_event(event) self._apply_event(event)
self.schedule_update_ha_state() self.schedule_update_ha_state()
if self.should_fire_event:
fire_command_event(self.hass, self.entity_id, event.values["Command"])

View file

@ -9,12 +9,11 @@ from homeassistant.components.sensor import (
DEVICE_CLASS_SIGNAL_STRENGTH, DEVICE_CLASS_SIGNAL_STRENGTH,
DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_TEMPERATURE,
) )
from homeassistant.const import ATTR_ENTITY_ID, CONF_DEVICES from homeassistant.const import CONF_DEVICES
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from . import ( from . import (
CONF_AUTOMATIC_ADD, CONF_AUTOMATIC_ADD,
CONF_FIRE_EVENT,
DATA_TYPES, DATA_TYPES,
SIGNAL_EVENT, SIGNAL_EVENT,
get_device_id, get_device_id,
@ -63,7 +62,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
return isinstance(event, (ControlEvent, SensorEvent)) return isinstance(event, (ControlEvent, SensorEvent))
entities = [] entities = []
for packet_id, entity_info in discovery_info[CONF_DEVICES].items(): for packet_id in discovery_info[CONF_DEVICES]:
event = get_rfx_object(packet_id) event = get_rfx_object(packet_id)
if event is None: if event is None:
_LOGGER.error("Invalid device: %s", packet_id) _LOGGER.error("Invalid device: %s", packet_id)
@ -78,19 +77,16 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
continue continue
data_ids.add(data_id) data_ids.add(data_id)
entity = RfxtrxSensor( entity = RfxtrxSensor(event.device, device_id, data_type)
event.device, data_type, entity_info[CONF_FIRE_EVENT],
)
entities.append(entity) entities.append(entity)
add_entities(entities) add_entities(entities)
def sensor_update(event): def sensor_update(event, device_id):
"""Handle sensor updates from the RFXtrx gateway.""" """Handle sensor updates from the RFXtrx gateway."""
if not supported(event): if not supported(event):
return return
device_id = get_device_id(event.device)
for data_type in set(event.values) & set(DATA_TYPES): for data_type in set(event.values) & set(DATA_TYPES):
data_id = (*device_id, data_type) data_id = (*device_id, data_type)
if data_id in data_ids: if data_id in data_ids:
@ -105,7 +101,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
"".join(f"{x:02x}" for x in event.data), "".join(f"{x:02x}" for x in event.data),
) )
entity = RfxtrxSensor(event.device, data_type, event=event) entity = RfxtrxSensor(event.device, device_id, data_type, event=event)
add_entities([entity]) add_entities([entity])
# Subscribe to main RFXtrx events # Subscribe to main RFXtrx events
@ -116,15 +112,14 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
class RfxtrxSensor(Entity): class RfxtrxSensor(Entity):
"""Representation of a RFXtrx sensor.""" """Representation of a RFXtrx sensor."""
def __init__(self, device, data_type, should_fire_event=False, event=None): def __init__(self, device, device_id, data_type, event=None):
"""Initialize the sensor.""" """Initialize the sensor."""
self.event = None self.event = None
self._device = device self._device = device
self._name = f"{device.type_string} {device.id_string} {data_type}" self._name = f"{device.type_string} {device.id_string} {data_type}"
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._device_id = get_device_id(device) self._device_id = device_id
self._unique_id = "_".join(x for x in (*self._device_id, data_type)) self._unique_id = "_".join(x for x in (*self._device_id, data_type))
self._device_class = DEVICE_CLASSES.get(data_type) self._device_class = DEVICE_CLASSES.get(data_type)
@ -186,12 +181,12 @@ class RfxtrxSensor(Entity):
"""Apply command from rfxtrx.""" """Apply command from rfxtrx."""
self.event = event self.event = event
def _handle_event(self, event): def _handle_event(self, event, device_id):
"""Check if event applies to me and update.""" """Check if event applies to me and update."""
if not isinstance(event, SensorEvent): if not isinstance(event, SensorEvent):
return return
if event.device.id_string != self._device.id_string: if device_id != self._device_id:
return return
if self.data_type not in event.values: if self.data_type not in event.values:
@ -207,5 +202,3 @@ class RfxtrxSensor(Entity):
self._apply_event(event) self._apply_event(event)
self.schedule_update_ha_state() self.schedule_update_ha_state()
if self.should_fire_event:
self.hass.bus.fire("signal_received", {ATTR_ENTITY_ID: self.entity_id})

View file

@ -4,19 +4,16 @@ import logging
import RFXtrx as rfxtrxmod import RFXtrx as rfxtrxmod
from homeassistant.components.switch import SwitchEntity from homeassistant.components.switch import SwitchEntity
from homeassistant.const import ATTR_STATE, CONF_DEVICES, STATE_ON from homeassistant.const import CONF_DEVICES, STATE_ON
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_FIRE_EVENT,
CONF_SIGNAL_REPETITIONS, CONF_SIGNAL_REPETITIONS,
DEFAULT_SIGNAL_REPETITIONS, DEFAULT_SIGNAL_REPETITIONS,
DOMAIN, DOMAIN,
SIGNAL_EVENT, SIGNAL_EVENT,
RfxtrxDevice, RfxtrxDevice,
fire_command_event,
get_device_id, get_device_id,
get_rfx_object, get_rfx_object,
) )
@ -56,18 +53,18 @@ def setup_platform(hass, config, add_entities_callback, discovery_info=None):
continue continue
device_ids.add(device_id) device_ids.add(device_id)
datas = {ATTR_STATE: None, ATTR_FIRE_EVENT: entity_info[CONF_FIRE_EVENT]} entity = RfxtrxSwitch(
entity = RfxtrxSwitch(event.device, datas, entity_info[CONF_SIGNAL_REPETITIONS]) event.device, device_id, entity_info[CONF_SIGNAL_REPETITIONS]
)
entities.append(entity) entities.append(entity)
add_entities_callback(entities) add_entities_callback(entities)
def switch_update(event): def switch_update(event, device_id):
"""Handle sensor updates from the RFXtrx gateway.""" """Handle sensor updates from the RFXtrx gateway."""
if not supported(event): if not supported(event):
return return
device_id = get_device_id(event.device)
if device_id in device_ids: if device_id in device_ids:
return return
device_ids.add(device_id) device_ids.add(device_id)
@ -80,9 +77,8 @@ def setup_platform(hass, config, add_entities_callback, discovery_info=None):
"".join(f"{x:02x}" for x in event.data), "".join(f"{x:02x}" for x in event.data),
) )
datas = {ATTR_STATE: None, ATTR_FIRE_EVENT: False}
entity = RfxtrxSwitch( entity = RfxtrxSwitch(
event.device, datas, DEFAULT_SIGNAL_REPETITIONS, event=event event.device, device_id, DEFAULT_SIGNAL_REPETITIONS, event=event
) )
add_entities_callback([entity]) add_entities_callback([entity])
@ -115,16 +111,14 @@ class RfxtrxSwitch(RfxtrxDevice, SwitchEntity, RestoreEntity):
elif event.values["Command"] in COMMAND_OFF_LIST: elif event.values["Command"] in COMMAND_OFF_LIST:
self._state = False self._state = False
def _handle_event(self, event): def _handle_event(self, event, device_id):
"""Check if event applies to me and update.""" """Check if event applies to me and update."""
if event.device.id_string != self._device.id_string: if device_id != self._device_id:
return return
self._apply_event(event) self._apply_event(event)
self.schedule_update_ha_state() self.schedule_update_ha_state()
if self.should_fire_event:
fire_command_event(self.hass, self.entity_id, event.values["Command"])
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn the device on.""" """Turn the device on."""

View file

@ -4,6 +4,11 @@ from homeassistant.components import rfxtrx
async def _signal_event(hass, packet_id): async def _signal_event(hass, packet_id):
event = rfxtrx.get_rfx_object(packet_id) event = rfxtrx.get_rfx_object(packet_id)
hass.helpers.dispatcher.async_dispatcher_send(rfxtrx.SIGNAL_EVENT, event)
await hass.async_add_executor_job(
hass.data[rfxtrx.DATA_RFXOBJECT].event_callback, event,
)
await hass.async_block_till_done()
await hass.async_block_till_done() await hass.async_block_till_done()
return event return event

View file

@ -50,6 +50,7 @@ async def test_one_pt2262(hass, rfxtrx):
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_start()
state = hass.states.get("binary_sensor.pt2262_22670e") state = hass.states.get("binary_sensor.pt2262_22670e")
assert state assert state
@ -119,6 +120,7 @@ async def test_discover(hass, rfxtrx):
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_start()
await _signal_event(hass, "0b1100100118cdea02010f70") await _signal_event(hass, "0b1100100118cdea02010f70")
state = hass.states.get("binary_sensor.ac_118cdea_2") state = hass.states.get("binary_sensor.ac_118cdea_2")
@ -145,6 +147,7 @@ async def test_off_delay(hass, rfxtrx):
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_start()
state = hass.states.get("binary_sensor.ac_118cdea_2") state = hass.states.get("binary_sensor.ac_118cdea_2")
assert state assert state

View file

@ -95,6 +95,7 @@ async def test_discover_covers(hass, rfxtrx):
{"rfxtrx": {"device": "abcd", "dummy": True, "automatic_add": True}}, {"rfxtrx": {"device": "abcd", "dummy": True, "automatic_add": True}},
) )
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_start()
await _signal_event(hass, "0a140002f38cae010f0070") await _signal_event(hass, "0a140002f38cae010f0070")
state = hass.states.get("cover.lightwaverf_siemens_f38cae_1") state = hass.states.get("cover.lightwaverf_siemens_f38cae_1")

View file

@ -66,68 +66,44 @@ async def test_fire_event(hass):
+ "-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0", + "-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0",
"dummy": True, "dummy": True,
"automatic_add": True, "automatic_add": True,
"devices": {"0b1100cd0213c7f210010f51": {rfxtrx.ATTR_FIRE_EVENT: True}}, "devices": {
"0b1100cd0213c7f210010f51": {rfxtrx.CONF_FIRE_EVENT: True},
"0716000100900970": {rfxtrx.CONF_FIRE_EVENT: True},
},
} }
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_start()
calls = [] calls = []
@callback @callback
def record_event(event): def record_event(event):
"""Add recorded event to set.""" """Add recorded event to set."""
calls.append(event) assert event.event_type == "rfxtrx_event"
calls.append(event.data)
hass.bus.async_listen(rfxtrx.EVENT_BUTTON_PRESSED, record_event) hass.bus.async_listen(rfxtrx.const.EVENT_RFXTRX_EVENT, record_event)
state = hass.states.get("switch.ac_213c7f2_16")
assert state
assert state.state == "off"
await _signal_event(hass, "0b1100cd0213c7f210010f51") await _signal_event(hass, "0b1100cd0213c7f210010f51")
await _signal_event(hass, "0716000100900970")
state = hass.states.get("switch.ac_213c7f2_16") assert calls == [
assert state
assert state.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):
"""Test fire event."""
await async_setup_component(
hass,
"rfxtrx",
{ {
"rfxtrx": { "packet_type": 17,
"device": "/dev/serial/by-id/usb" "sub_type": 0,
+ "-RFXCOM_RFXtrx433_A1Y0NJGR-if00-port0", "type_string": "AC",
"dummy": True, "id_string": "213c7f2:16",
"automatic_add": True, "data": "0b1100cd0213c7f210010f51",
"devices": {"0a520802060100ff0e0269": {rfxtrx.ATTR_FIRE_EVENT: True}}, "values": {"Command": "On", "Rssi numeric": 5},
}
}, },
) {
"packet_type": 22,
await hass.async_block_till_done() "sub_type": 0,
"type_string": "Byron SX",
calls = [] "id_string": "00:90",
"data": "0716000100900970",
@callback "values": {"Sound": 9, "Battery numeric": 0, "Rssi numeric": 7},
def record_event(event): },
"""Add recorded event to set.""" ]
calls.append(event)
hass.bus.async_listen("signal_received", record_event)
await _signal_event(hass, "0a520802060101ff0f0269")
assert len(calls) == 5
assert any(
call.data
== {"entity_id": "sensor.wt260_wt260h_wt440h_wt450_wt450h_06_01_temperature"}
for call in calls
)

View file

@ -158,6 +158,7 @@ async def test_discover_light(hass, rfxtrx):
{"rfxtrx": {"device": "abcd", "dummy": True, "automatic_add": True}}, {"rfxtrx": {"device": "abcd", "dummy": True, "automatic_add": True}},
) )
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_start()
await _signal_event(hass, "0b11009e00e6116202020070") await _signal_event(hass, "0b11009e00e6116202020070")
state = hass.states.get("light.ac_0e61162_2") state = hass.states.get("light.ac_0e61162_2")

View file

@ -105,8 +105,8 @@ async def test_several_sensors(hass, rfxtrx):
} }
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_start()
state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_05_02_temperature") state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_05_02_temperature")
assert state assert state
@ -144,6 +144,7 @@ async def test_discover_sensor(hass, rfxtrx):
{"rfxtrx": {"device": "abcd", "dummy": True, "automatic_add": True}}, {"rfxtrx": {"device": "abcd", "dummy": True, "automatic_add": True}},
) )
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_start()
# 1 # 1
await _signal_event(hass, "0a520801070100b81b0279") await _signal_event(hass, "0a520801070100b81b0279")
@ -252,6 +253,7 @@ async def test_update_of_sensors(hass, rfxtrx):
}, },
) )
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_start()
state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_05_02_temperature") state = hass.states.get("sensor.wt260_wt260h_wt440h_wt450_wt450h_05_02_temperature")
assert state assert state

View file

@ -117,6 +117,7 @@ async def test_discover_switch(hass, rfxtrx):
{"rfxtrx": {"device": "abcd", "dummy": True, "automatic_add": True}}, {"rfxtrx": {"device": "abcd", "dummy": True, "automatic_add": True}},
) )
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_start()
await _signal_event(hass, "0b1100100118cdea02010f70") await _signal_event(hass, "0b1100100118cdea02010f70")
state = hass.states.get("switch.ac_118cdea_2") state = hass.states.get("switch.ac_118cdea_2")