From a3310330f41ec619795ae540a3a4b8602f80f507 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Thu, 9 Jul 2020 11:40:37 +0200 Subject: [PATCH] Split handling and application of event (#37665) This way _handle_event can contain things available when entity has been added to home assistant, and _apply event can remain internal and used on init. --- homeassistant/components/rfxtrx/__init__.py | 29 +++---- .../components/rfxtrx/binary_sensor.py | 78 ++++++++++--------- homeassistant/components/rfxtrx/cover.py | 26 +++---- homeassistant/components/rfxtrx/light.py | 26 +++---- homeassistant/components/rfxtrx/sensor.py | 63 +++++++-------- homeassistant/components/rfxtrx/switch.py | 28 +++---- 6 files changed, 127 insertions(+), 123 deletions(-) diff --git a/homeassistant/components/rfxtrx/__init__.py b/homeassistant/components/rfxtrx/__init__.py index f817668156f..c20d50fee3f 100644 --- a/homeassistant/components/rfxtrx/__init__.py +++ b/homeassistant/components/rfxtrx/__init__.py @@ -270,7 +270,9 @@ def get_devices_from_config(config, device): fire_event = entity_info[ATTR_FIRE_EVENT] datas = {ATTR_STATE: False, ATTR_FIRE_EVENT: fire_event} - new_device = device(entity_info[ATTR_NAME], event, datas, signal_repetitions) + new_device = device( + entity_info[ATTR_NAME], event.device, datas, signal_repetitions + ) RFX_DEVICES[device_id] = new_device devices.append(new_device) return devices @@ -295,7 +297,7 @@ def get_new_device(event, config, device): ) datas = {ATTR_STATE: False, ATTR_FIRE_EVENT: False} signal_repetitions = config[CONF_SIGNAL_REPETITIONS] - new_device = device(pkt_id, event, datas, signal_repetitions) + new_device = device(pkt_id, event.device, datas, signal_repetitions, event=event) RFX_DEVICES[device_id] = new_device return new_device @@ -321,14 +323,17 @@ class RfxtrxDevice(Entity): Contains the common logic for Rfxtrx lights and switches. """ - def __init__(self, name, event, datas, signal_repetitions): + def __init__(self, name, device, datas, signal_repetitions, event=None): """Initialize the device.""" self.signal_repetitions = signal_repetitions self._name = name - self._event = event + self._device = device self._state = datas[ATTR_STATE] self._should_fire_event = datas[ATTR_FIRE_EVENT] - self._unique_id = f"{event.device.packettype:x}_{event.device.subtype:x}_{event.device.id_string}" + self._unique_id = f"{device.packettype:x}_{device.subtype:x}_{device.id_string}" + + if event: + self._apply_event(event) @property def should_poll(self): @@ -364,38 +369,36 @@ class RfxtrxDevice(Entity): """Apply a received event.""" def _send_command(self, command, brightness=0): - if not self._event: - return rfx_object = self.hass.data[DATA_RFXOBJECT] if command == "turn_on": for _ in range(self.signal_repetitions): - self._event.device.send_on(rfx_object.transport) + self._device.send_on(rfx_object.transport) self._state = True elif command == "dim": for _ in range(self.signal_repetitions): - self._event.device.send_dim(rfx_object.transport, brightness) + self._device.send_dim(rfx_object.transport, brightness) self._state = True elif command == "turn_off": for _ in range(self.signal_repetitions): - self._event.device.send_off(rfx_object.transport) + self._device.send_off(rfx_object.transport) self._state = False elif command == "roll_up": for _ in range(self.signal_repetitions): - self._event.device.send_open(rfx_object.transport) + self._device.send_open(rfx_object.transport) self._state = True elif command == "roll_down": for _ in range(self.signal_repetitions): - self._event.device.send_close(rfx_object.transport) + self._device.send_close(rfx_object.transport) self._state = False elif command == "stop_roll": for _ in range(self.signal_repetitions): - self._event.device.send_stop(rfx_object.transport) + self._device.send_stop(rfx_object.transport) self._state = True if self.hass: diff --git a/homeassistant/components/rfxtrx/binary_sensor.py b/homeassistant/components/rfxtrx/binary_sensor.py index 13ba00af0bf..c37abdeb08e 100644 --- a/homeassistant/components/rfxtrx/binary_sensor.py +++ b/homeassistant/components/rfxtrx/binary_sensor.py @@ -85,7 +85,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): ) device = RfxtrxBinarySensor( - event, + event.device, entity.get(CONF_NAME), entity.get(CONF_DEVICE_CLASS), entity[CONF_FIRE_EVENT], @@ -120,8 +120,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): _LOGGER.debug("Found possible matching device ID: %s", poss_id) pkt_id = "".join(f"{x:02x}" for x in event.data) - sensor = RfxtrxBinarySensor(event, pkt_id) - sensor.apply_event(event) + sensor = RfxtrxBinarySensor(event.device, pkt_id, event=event) RFX_DEVICES[device_id] = sensor add_entities([sensor]) _LOGGER.info( @@ -141,7 +140,7 @@ class RfxtrxBinarySensor(BinarySensorEntity): def __init__( self, - event, + device, name, device_class=None, should_fire=False, @@ -149,55 +148,43 @@ class RfxtrxBinarySensor(BinarySensorEntity): data_bits=None, cmd_on=None, cmd_off=None, + event=None, ): """Initialize the RFXtrx sensor.""" - self.event = event + self.event = None + self._device = device self._name = name self._should_fire_event = should_fire self._device_class = device_class self._off_delay = off_delay self._state = False - self.is_lighting4 = event.device.packettype == 0x13 + self.is_lighting4 = device.packettype == 0x13 self.delay_listener = None self._data_bits = data_bits self._cmd_on = cmd_on self._cmd_off = cmd_off if data_bits is not None: - self._masked_id = get_pt2262_deviceid( - event.device.id_string.lower(), data_bits + self._masked_id = get_pt2262_deviceid(device.id_string.lower(), data_bits) + self._unique_id = ( + f"{device.packettype:x}_{device.subtype:x}_{self._masked_id}" ) - self._unique_id = f"{event.device.packettype:x}_{event.device.subtype:x}_{self._masked_id}" else: self._masked_id = None - self._unique_id = f"{event.device.packettype:x}_{event.device.subtype:x}_{event.device.id_string}" + self._unique_id = ( + f"{device.packettype:x}_{device.subtype:x}_{device.id_string}" + ) + + if event: + self._apply_event(event) async def async_added_to_hass(self): """Restore RFXtrx switch device state (ON/OFF).""" await super().async_added_to_hass() - def _handle_event(event): - """Check if event applies to me and update.""" - if self._masked_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.event.device.id_string: - return - - _LOGGER.debug( - "Binary sensor update (Device ID: %s Class: %s Sub: %s)", - event.device.id_string, - event.device.__class__.__name__, - event.device.subtype, - ) - - self.apply_event(event) - self.async_on_remove( self.hass.helpers.dispatcher.async_dispatcher_connect( - SIGNAL_EVENT, _handle_event + SIGNAL_EVENT, self._handle_event ) ) @@ -274,17 +261,35 @@ class RfxtrxBinarySensor(BinarySensorEntity): elif event.values["Command"] in COMMAND_OFF_LIST: self._state = False - def apply_event(self, event): + def _apply_event(self, event): """Apply command from rfxtrx.""" if self.is_lighting4: self._apply_event_lighting4(event) else: self._apply_event_standard(event) - if self.hass: - self.schedule_update_ha_state() - if self.should_fire_event: - fire_command_event(self.hass, self.entity_id, event.values["Command"]) + def _handle_event(self, event): + """Check if event applies to me and update.""" + if self._masked_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 + + _LOGGER.debug( + "Binary sensor update (Device ID: %s Class: %s Sub: %s)", + event.device.id_string, + event.device.__class__.__name__, + event.device.subtype, + ) + + self._apply_event(event) + + 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: @@ -292,8 +297,7 @@ class RfxtrxBinarySensor(BinarySensorEntity): """Switch device off after a delay.""" self.delay_listener = None self._state = False - if self.hass: - self.schedule_update_ha_state() + self.schedule_update_ha_state() self.delay_listener = evt.call_later( self.hass, self.off_delay.total_seconds(), off_delay_listener diff --git a/homeassistant/components/rfxtrx/cover.py b/homeassistant/components/rfxtrx/cover.py index e1746ff79e8..dde282423f2 100644 --- a/homeassistant/components/rfxtrx/cover.py +++ b/homeassistant/components/rfxtrx/cover.py @@ -55,7 +55,6 @@ def setup_platform(hass, config, add_entities, discovery_info=None): new_device = get_new_device(event, config, RfxtrxCover) if new_device: - new_device.apply_event(event) add_entities([new_device]) # Subscribe to main RFXtrx events @@ -73,16 +72,9 @@ class RfxtrxCover(RfxtrxDevice, CoverEntity, RestoreEntity): if old_state is not None: self._state = old_state.state == STATE_OPEN - def _handle_event(event): - """Check if event applies to me and update.""" - if event.device.id_string != self._event.device.id_string: - return - - self.apply_event(event) - self.async_on_remove( self.hass.helpers.dispatcher.async_dispatcher_connect( - SIGNAL_EVENT, _handle_event + SIGNAL_EVENT, self._handle_event ) ) @@ -108,14 +100,20 @@ class RfxtrxCover(RfxtrxDevice, CoverEntity, RestoreEntity): """Stop the cover.""" self._send_command("stop_roll") - def apply_event(self, event): + def _apply_event(self, event): """Apply command from rfxtrx.""" if event.values["Command"] in COMMAND_ON_LIST: self._state = True elif event.values["Command"] in COMMAND_OFF_LIST: self._state = False - if self.hass: - self.schedule_update_ha_state() - if self.should_fire_event: - fire_command_event(self.hass, self.entity_id, event.values["Command"]) + def _handle_event(self, event): + """Check if event applies to me and update.""" + if event.device.id_string != self._device.id_string: + return + + self._apply_event(event) + + self.schedule_update_ha_state() + if self.should_fire_event: + fire_command_event(self.hass, self.entity_id, event.values["Command"]) diff --git a/homeassistant/components/rfxtrx/light.py b/homeassistant/components/rfxtrx/light.py index 8b65221090d..d6935677f2f 100644 --- a/homeassistant/components/rfxtrx/light.py +++ b/homeassistant/components/rfxtrx/light.py @@ -65,7 +65,6 @@ def setup_platform(hass, config, add_entities, discovery_info=None): new_device = get_new_device(event, config, RfxtrxLight) if new_device: - new_device.apply_event(event) add_entities([new_device]) # Subscribe to main RFXtrx events @@ -92,16 +91,9 @@ class RfxtrxLight(RfxtrxDevice, LightEntity, RestoreEntity): ): self._brightness = int(old_state.attributes[ATTR_BRIGHTNESS]) - def _handle_event(event): - """Check if event applies to me and update.""" - if event.device.id_string != self._event.device.id_string: - return - - self.apply_event(event) - self.async_on_remove( self.hass.helpers.dispatcher.async_dispatcher_connect( - SIGNAL_EVENT, _handle_event + SIGNAL_EVENT, self._handle_event ) ) @@ -131,7 +123,7 @@ class RfxtrxLight(RfxtrxDevice, LightEntity, RestoreEntity): self._brightness = 0 self._send_command("turn_off") - def apply_event(self, event): + def _apply_event(self, event): """Apply command from rfxtrx.""" if event.values["Command"] in COMMAND_ON_LIST: self._state = True @@ -141,7 +133,13 @@ class RfxtrxLight(RfxtrxDevice, LightEntity, RestoreEntity): self._brightness = event.values["Dim level"] * 255 // 100 self._state = self._brightness > 0 - if self.hass: - self.schedule_update_ha_state() - if self.should_fire_event: - fire_command_event(self.hass, self.entity_id, event.values["Command"]) + def _handle_event(self, event): + """Check if event applies to me and update.""" + if event.device.id_string != self._device.id_string: + return + + self._apply_event(event) + + self.schedule_update_ha_state() + if self.should_fire_event: + fire_command_event(self.hass, self.entity_id, event.values["Command"]) diff --git a/homeassistant/components/rfxtrx/sensor.py b/homeassistant/components/rfxtrx/sensor.py index 76b033aebee..cc7a817a061 100644 --- a/homeassistant/components/rfxtrx/sensor.py +++ b/homeassistant/components/rfxtrx/sensor.py @@ -64,7 +64,6 @@ def setup_platform(hass, config, add_entities, discovery_info=None): break for _data_type in data_types: new_sensor = RfxtrxSensor( - None, event.device, entity_info[ATTR_NAME], _data_type, @@ -97,8 +96,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): if _data_type in event.values: data_type = _data_type break - new_sensor = RfxtrxSensor(event, event.device, pkt_id, data_type) - new_sensor.apply_event(event) + new_sensor = RfxtrxSensor(event.device, pkt_id, data_type, event=event) sub_sensors = {} sub_sensors[new_sensor.data_type] = new_sensor RFX_DEVICES[device_id] = sub_sensors @@ -111,9 +109,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None): class RfxtrxSensor(Entity): """Representation of a RFXtrx sensor.""" - def __init__(self, event, device, name, data_type, should_fire_event=False): + def __init__(self, device, name, data_type, should_fire_event=False, event=None): """Initialize the sensor.""" - self.event = event + self.event = None self._device = device self._name = name self.should_fire_event = should_fire_event @@ -123,33 +121,16 @@ class RfxtrxSensor(Entity): f"{device.packettype:x}_{device.subtype:x}_{device.id_string}_{data_type}" ) + if event: + self._apply_event(event) + async def async_added_to_hass(self): """Restore RFXtrx switch device state (ON/OFF).""" await super().async_added_to_hass() - def _handle_event(event): - """Check if event applies to me and update.""" - if not isinstance(event, SensorEvent): - return - - if event.device.id_string != self._device.id_string: - return - - if self.data_type not in event.values: - return - - _LOGGER.debug( - "Sensor update (Device ID: %s Class: %s Sub: %s)", - event.device.id_string, - event.device.__class__.__name__, - event.device.subtype, - ) - - self.apply_event(event) - self.async_on_remove( self.hass.helpers.dispatcher.async_dispatcher_connect( - SIGNAL_EVENT, _handle_event + SIGNAL_EVENT, self._handle_event ) ) @@ -186,10 +167,30 @@ class RfxtrxSensor(Entity): """Return unique identifier of remote device.""" return self._unique_id - def apply_event(self, event): + def _apply_event(self, event): """Apply command from rfxtrx.""" self.event = event - if self.hass: - self.schedule_update_ha_state() - if self.should_fire_event: - self.hass.bus.fire("signal_received", {ATTR_ENTITY_ID: self.entity_id}) + + def _handle_event(self, event): + """Check if event applies to me and update.""" + if not isinstance(event, SensorEvent): + return + + if event.device.id_string != self._device.id_string: + return + + if self.data_type not in event.values: + return + + _LOGGER.debug( + "Sensor update (Device ID: %s Class: %s Sub: %s)", + event.device.id_string, + event.device.__class__.__name__, + event.device.subtype, + ) + + self._apply_event(event) + + self.schedule_update_ha_state() + if self.should_fire_event: + self.hass.bus.fire("signal_received", {ATTR_ENTITY_ID: self.entity_id}) diff --git a/homeassistant/components/rfxtrx/switch.py b/homeassistant/components/rfxtrx/switch.py index 11c13b10bb4..110c5544d91 100644 --- a/homeassistant/components/rfxtrx/switch.py +++ b/homeassistant/components/rfxtrx/switch.py @@ -60,7 +60,6 @@ def setup_platform(hass, config, add_entities_callback, discovery_info=None): new_device = get_new_device(event, config, RfxtrxSwitch) if new_device: - new_device.apply_event(event) add_entities_callback([new_device]) # Subscribe to main RFXtrx events @@ -78,35 +77,36 @@ class RfxtrxSwitch(RfxtrxDevice, SwitchEntity, RestoreEntity): if old_state is not None: self._state = old_state.state == STATE_ON - def _handle_event(event): - """Check if event applies to me and update.""" - if event.device.id_string != self._event.device.id_string: - return - - self.apply_event(event) - self.async_on_remove( self.hass.helpers.dispatcher.async_dispatcher_connect( - SIGNAL_EVENT, _handle_event + SIGNAL_EVENT, self._handle_event ) ) - def apply_event(self, event): + def _apply_event(self, event): """Apply command from rfxtrx.""" if event.values["Command"] in COMMAND_ON_LIST: self._state = True elif event.values["Command"] in COMMAND_OFF_LIST: self._state = False - if self.hass: - self.schedule_update_ha_state() - if self.should_fire_event: - fire_command_event(self.hass, self.entity_id, event.values["Command"]) + def _handle_event(self, event): + """Check if event applies to me and update.""" + if event.device.id_string != self._device.id_string: + return + + self._apply_event(event) + + 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): """Turn the device on.""" self._send_command("turn_on") + self.schedule_update_ha_state() def turn_off(self, **kwargs): """Turn the device off.""" self._send_command("turn_off") + self.schedule_update_ha_state()