mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 13:47:35 +00:00
Rfxtrx use previous received event to do complete restore (#37819)
* Add event attribute to display last received event * Restore state using event attribute * Allow empty dict for device config * Must also validate normal case * Do early return
This commit is contained in:
parent
f5b628c04f
commit
7c9be024bb
@ -24,7 +24,7 @@ from homeassistant.const import (
|
||||
UV_INDEX,
|
||||
)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
||||
from .const import (
|
||||
ATTR_EVENT,
|
||||
@ -92,9 +92,15 @@ def _bytearray_string(data):
|
||||
raise vol.Invalid("Data must be a hex string with multiple of two characters")
|
||||
|
||||
|
||||
def _ensure_device(value):
|
||||
if value is None:
|
||||
return DEVICE_DATA_SCHEMA({})
|
||||
return DEVICE_DATA_SCHEMA(value)
|
||||
|
||||
|
||||
SERVICE_SEND_SCHEMA = vol.Schema({ATTR_EVENT: _bytearray_string})
|
||||
|
||||
DEVICE_SCHEMA = vol.Schema(
|
||||
DEVICE_DATA_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
|
||||
vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean,
|
||||
@ -110,7 +116,7 @@ BASE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_DEBUG, default=False): cv.boolean,
|
||||
vol.Optional(CONF_AUTOMATIC_ADD, default=False): cv.boolean,
|
||||
vol.Optional(CONF_DEVICES, default={}): {cv.string: DEVICE_SCHEMA},
|
||||
vol.Optional(CONF_DEVICES, default={}): {cv.string: _ensure_device},
|
||||
}
|
||||
)
|
||||
|
||||
@ -337,7 +343,7 @@ def get_device_id(device, data_bits=None):
|
||||
return (f"{device.packettype:x}", f"{device.subtype:x}", id_string)
|
||||
|
||||
|
||||
class RfxtrxDevice(Entity):
|
||||
class RfxtrxDevice(RestoreEntity):
|
||||
"""Represents a Rfxtrx device.
|
||||
|
||||
Contains the common logic for Rfxtrx lights and switches.
|
||||
@ -348,6 +354,7 @@ class RfxtrxDevice(Entity):
|
||||
self.signal_repetitions = signal_repetitions
|
||||
self._name = f"{device.type_string} {device.id_string}"
|
||||
self._device = device
|
||||
self._event = None
|
||||
self._state = None
|
||||
self._device_id = device_id
|
||||
self._unique_id = "_".join(x for x in self._device_id)
|
||||
@ -355,6 +362,17 @@ class RfxtrxDevice(Entity):
|
||||
if event:
|
||||
self._apply_event(event)
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Restore RFXtrx device state (ON/OFF)."""
|
||||
if self._event:
|
||||
return
|
||||
|
||||
old_state = await self.async_get_last_state()
|
||||
if old_state is not None:
|
||||
event = old_state.attributes.get(ATTR_EVENT)
|
||||
if event:
|
||||
self._apply_event(get_rfx_object(event))
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
"""No polling needed for a RFXtrx switch."""
|
||||
@ -365,6 +383,13 @@ class RfxtrxDevice(Entity):
|
||||
"""Return the name of the device if any."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the device state attributes."""
|
||||
if not self._event:
|
||||
return None
|
||||
return {ATTR_EVENT: "".join(f"{x:02x}" for x in self._event.data)}
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if device is on."""
|
||||
@ -391,6 +416,7 @@ class RfxtrxDevice(Entity):
|
||||
|
||||
def _apply_event(self, event):
|
||||
"""Apply a received event."""
|
||||
self._event = event
|
||||
|
||||
def _send_command(self, command, brightness=0):
|
||||
rfx_object = self.hass.data[DATA_RFXOBJECT]
|
||||
|
@ -12,6 +12,7 @@ from homeassistant.const import (
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers import event as evt
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
||||
from . import (
|
||||
CONF_AUTOMATIC_ADD,
|
||||
@ -25,6 +26,7 @@ from . import (
|
||||
get_rfx_object,
|
||||
)
|
||||
from .const import (
|
||||
ATTR_EVENT,
|
||||
COMMAND_OFF_LIST,
|
||||
COMMAND_ON_LIST,
|
||||
DATA_RFXTRX_CONFIG,
|
||||
@ -105,7 +107,7 @@ async def async_setup_entry(
|
||||
)
|
||||
|
||||
|
||||
class RfxtrxBinarySensor(BinarySensorEntity):
|
||||
class RfxtrxBinarySensor(BinarySensorEntity, RestoreEntity):
|
||||
"""A representation of a RFXtrx binary sensor."""
|
||||
|
||||
def __init__(
|
||||
@ -120,7 +122,7 @@ class RfxtrxBinarySensor(BinarySensorEntity):
|
||||
event=None,
|
||||
):
|
||||
"""Initialize the RFXtrx sensor."""
|
||||
self.event = None
|
||||
self._event = None
|
||||
self._device = device
|
||||
self._name = f"{device.type_string} {device.id_string}"
|
||||
self._device_class = device_class
|
||||
@ -141,6 +143,13 @@ class RfxtrxBinarySensor(BinarySensorEntity):
|
||||
"""Restore RFXtrx switch device state (ON/OFF)."""
|
||||
await super().async_added_to_hass()
|
||||
|
||||
if self._event is None:
|
||||
old_state = await self.async_get_last_state()
|
||||
if old_state is not None:
|
||||
event = old_state.attributes.get(ATTR_EVENT)
|
||||
if event:
|
||||
self._apply_event(get_rfx_object(event))
|
||||
|
||||
self.async_on_remove(
|
||||
self.hass.helpers.dispatcher.async_dispatcher_connect(
|
||||
SIGNAL_EVENT, self._handle_event
|
||||
@ -152,6 +161,13 @@ class RfxtrxBinarySensor(BinarySensorEntity):
|
||||
"""Return the device name."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the device state attributes."""
|
||||
if not self._event:
|
||||
return None
|
||||
return {ATTR_EVENT: "".join(f"{x:02x}" for x in self._event.data)}
|
||||
|
||||
@property
|
||||
def data_bits(self):
|
||||
"""Return the number of data bits."""
|
||||
@ -221,6 +237,7 @@ class RfxtrxBinarySensor(BinarySensorEntity):
|
||||
|
||||
def _apply_event(self, event):
|
||||
"""Apply command from rfxtrx."""
|
||||
self._event = event
|
||||
if event.device.packettype == DEVICE_PACKET_TYPE_LIGHTING4:
|
||||
self._apply_event_lighting4(event)
|
||||
else:
|
||||
|
@ -2,7 +2,7 @@
|
||||
import logging
|
||||
|
||||
from homeassistant.components.cover import CoverEntity
|
||||
from homeassistant.const import CONF_DEVICES, STATE_OPEN
|
||||
from homeassistant.const import CONF_DEVICES
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
||||
@ -86,10 +86,6 @@ class RfxtrxCover(RfxtrxDevice, CoverEntity, RestoreEntity):
|
||||
"""Restore RFXtrx cover device state (OPEN/CLOSE)."""
|
||||
await super().async_added_to_hass()
|
||||
|
||||
old_state = await self.async_get_last_state()
|
||||
if old_state is not None:
|
||||
self._state = old_state.state == STATE_OPEN
|
||||
|
||||
self.async_on_remove(
|
||||
self.hass.helpers.dispatcher.async_dispatcher_connect(
|
||||
SIGNAL_EVENT, self._handle_event
|
||||
@ -120,6 +116,7 @@ class RfxtrxCover(RfxtrxDevice, CoverEntity, RestoreEntity):
|
||||
|
||||
def _apply_event(self, event):
|
||||
"""Apply command from rfxtrx."""
|
||||
super()._apply_event(event)
|
||||
if event.values["Command"] in COMMAND_ON_LIST:
|
||||
self._state = True
|
||||
elif event.values["Command"] in COMMAND_OFF_LIST:
|
||||
|
@ -8,9 +8,8 @@ from homeassistant.components.light import (
|
||||
SUPPORT_BRIGHTNESS,
|
||||
LightEntity,
|
||||
)
|
||||
from homeassistant.const import CONF_DEVICES, STATE_ON
|
||||
from homeassistant.const import CONF_DEVICES
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
||||
from . import (
|
||||
CONF_AUTOMATIC_ADD,
|
||||
@ -93,7 +92,7 @@ async def async_setup_entry(
|
||||
hass.helpers.dispatcher.async_dispatcher_connect(SIGNAL_EVENT, light_update)
|
||||
|
||||
|
||||
class RfxtrxLight(RfxtrxDevice, LightEntity, RestoreEntity):
|
||||
class RfxtrxLight(RfxtrxDevice, LightEntity):
|
||||
"""Representation of a RFXtrx light."""
|
||||
|
||||
_brightness = 0
|
||||
@ -102,17 +101,6 @@ class RfxtrxLight(RfxtrxDevice, LightEntity, RestoreEntity):
|
||||
"""Restore RFXtrx device state (ON/OFF)."""
|
||||
await super().async_added_to_hass()
|
||||
|
||||
old_state = await self.async_get_last_state()
|
||||
if old_state is not None:
|
||||
self._state = old_state.state == STATE_ON
|
||||
|
||||
# Restore the brightness of dimmable devices
|
||||
if (
|
||||
old_state is not None
|
||||
and old_state.attributes.get(ATTR_BRIGHTNESS) is not None
|
||||
):
|
||||
self._brightness = int(old_state.attributes[ATTR_BRIGHTNESS])
|
||||
|
||||
self.async_on_remove(
|
||||
self.hass.helpers.dispatcher.async_dispatcher_connect(
|
||||
SIGNAL_EVENT, self._handle_event
|
||||
@ -147,6 +135,7 @@ class RfxtrxLight(RfxtrxDevice, LightEntity, RestoreEntity):
|
||||
|
||||
def _apply_event(self, event):
|
||||
"""Apply command from rfxtrx."""
|
||||
super()._apply_event(event)
|
||||
if event.values["Command"] in COMMAND_ON_LIST:
|
||||
self._state = True
|
||||
elif event.values["Command"] in COMMAND_OFF_LIST:
|
||||
|
@ -11,7 +11,7 @@ from homeassistant.components.sensor import (
|
||||
)
|
||||
from homeassistant.const import CONF_DEVICES
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
||||
from . import (
|
||||
CONF_AUTOMATIC_ADD,
|
||||
@ -21,7 +21,7 @@ from . import (
|
||||
get_device_id,
|
||||
get_rfx_object,
|
||||
)
|
||||
from .const import DATA_RFXTRX_CONFIG
|
||||
from .const import ATTR_EVENT, DATA_RFXTRX_CONFIG
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -113,12 +113,12 @@ async def async_setup_entry(
|
||||
hass.helpers.dispatcher.async_dispatcher_connect(SIGNAL_EVENT, sensor_update)
|
||||
|
||||
|
||||
class RfxtrxSensor(Entity):
|
||||
class RfxtrxSensor(RestoreEntity):
|
||||
"""Representation of a RFXtrx sensor."""
|
||||
|
||||
def __init__(self, device, device_id, data_type, event=None):
|
||||
"""Initialize the sensor."""
|
||||
self.event = None
|
||||
self._event = None
|
||||
self._device = device
|
||||
self._name = f"{device.type_string} {device.id_string} {data_type}"
|
||||
self.data_type = data_type
|
||||
@ -136,6 +136,13 @@ class RfxtrxSensor(Entity):
|
||||
"""Restore RFXtrx switch device state (ON/OFF)."""
|
||||
await super().async_added_to_hass()
|
||||
|
||||
if self._event is None:
|
||||
old_state = await self.async_get_last_state()
|
||||
if old_state is not None:
|
||||
event = old_state.attributes.get(ATTR_EVENT)
|
||||
if event:
|
||||
self._apply_event(get_rfx_object(event))
|
||||
|
||||
self.async_on_remove(
|
||||
self.hass.helpers.dispatcher.async_dispatcher_connect(
|
||||
SIGNAL_EVENT, self._handle_event
|
||||
@ -149,9 +156,9 @@ class RfxtrxSensor(Entity):
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the sensor."""
|
||||
if not self.event:
|
||||
if not self._event:
|
||||
return None
|
||||
value = self.event.values.get(self.data_type)
|
||||
value = self._event.values.get(self.data_type)
|
||||
return self._convert_fun(value)
|
||||
|
||||
@property
|
||||
@ -162,9 +169,9 @@ class RfxtrxSensor(Entity):
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the device state attributes."""
|
||||
if not self.event:
|
||||
if not self._event:
|
||||
return None
|
||||
return self.event.values
|
||||
return {ATTR_EVENT: "".join(f"{x:02x}" for x in self._event.data)}
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
@ -192,7 +199,7 @@ class RfxtrxSensor(Entity):
|
||||
|
||||
def _apply_event(self, event):
|
||||
"""Apply command from rfxtrx."""
|
||||
self.event = event
|
||||
self._event = event
|
||||
|
||||
@callback
|
||||
def _handle_event(self, event, device_id):
|
||||
|
@ -4,7 +4,7 @@ import logging
|
||||
import RFXtrx as rfxtrxmod
|
||||
|
||||
from homeassistant.components.switch import SwitchEntity
|
||||
from homeassistant.const import CONF_DEVICES, STATE_ON
|
||||
from homeassistant.const import CONF_DEVICES
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
||||
@ -96,10 +96,6 @@ class RfxtrxSwitch(RfxtrxDevice, SwitchEntity, RestoreEntity):
|
||||
"""Restore RFXtrx switch device state (ON/OFF)."""
|
||||
await super().async_added_to_hass()
|
||||
|
||||
old_state = await self.async_get_last_state()
|
||||
if old_state is not None:
|
||||
self._state = old_state.state == STATE_ON
|
||||
|
||||
self.async_on_remove(
|
||||
self.hass.helpers.dispatcher.async_dispatcher_connect(
|
||||
SIGNAL_EVENT, self._handle_event
|
||||
@ -108,6 +104,7 @@ class RfxtrxSwitch(RfxtrxDevice, SwitchEntity, RestoreEntity):
|
||||
|
||||
def _apply_event(self, event):
|
||||
"""Apply command from rfxtrx."""
|
||||
super()._apply_event(event)
|
||||
if event.values["Command"] in COMMAND_ON_LIST:
|
||||
self._state = True
|
||||
elif event.values["Command"] in COMMAND_OFF_LIST:
|
||||
|
Loading…
x
Reference in New Issue
Block a user