Make sure command entities restore from state (#38038)

pull/38041/head^2
Joakim Plate 2020-07-22 00:01:31 +02:00 committed by GitHub
parent ad5d7ee615
commit 945acb4e29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 182 additions and 11 deletions

View File

@ -398,12 +398,6 @@ class RfxtrxEntity(RestoreEntity):
"""Restore RFXtrx device state (ON/OFF).""" """Restore RFXtrx device state (ON/OFF)."""
if self._event: if self._event:
self._apply_event(self._event) self._apply_event(self._event)
else:
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.async_on_remove(
self.hass.helpers.dispatcher.async_dispatcher_connect( self.hass.helpers.dispatcher.async_dispatcher_connect(

View File

@ -24,7 +24,12 @@ from . import (
get_pt2262_cmd, get_pt2262_cmd,
get_rfx_object, get_rfx_object,
) )
from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST, DEVICE_PACKET_TYPE_LIGHTING4 from .const import (
ATTR_EVENT,
COMMAND_OFF_LIST,
COMMAND_ON_LIST,
DEVICE_PACKET_TYPE_LIGHTING4,
)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -124,6 +129,17 @@ class RfxtrxBinarySensor(RfxtrxEntity, BinarySensorEntity):
self._cmd_on = cmd_on self._cmd_on = cmd_on
self._cmd_off = cmd_off self._cmd_off = cmd_off
async def async_added_to_hass(self):
"""Restore device state."""
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))
@property @property
def force_update(self) -> bool: def force_update(self) -> bool:
"""We should force updates. Repeated states have meaning.""" """We should force updates. Repeated states have meaning."""

View File

@ -2,7 +2,7 @@
import logging import logging
from homeassistant.components.cover import CoverEntity from homeassistant.components.cover import CoverEntity
from homeassistant.const import CONF_DEVICES from homeassistant.const import CONF_DEVICES, STATE_OPEN
from homeassistant.core import callback from homeassistant.core import callback
from . import ( from . import (
@ -81,6 +81,15 @@ async def async_setup_entry(
class RfxtrxCover(RfxtrxCommandEntity, CoverEntity): class RfxtrxCover(RfxtrxCommandEntity, CoverEntity):
"""Representation of a RFXtrx cover.""" """Representation of a RFXtrx cover."""
async def async_added_to_hass(self):
"""Restore device state."""
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:
self._state = old_state.state == STATE_OPEN
@property @property
def is_closed(self): def is_closed(self):
"""Return if the cover is closed.""" """Return if the cover is closed."""

View File

@ -8,7 +8,7 @@ from homeassistant.components.light import (
SUPPORT_BRIGHTNESS, SUPPORT_BRIGHTNESS,
LightEntity, LightEntity,
) )
from homeassistant.const import CONF_DEVICES from homeassistant.const import CONF_DEVICES, STATE_ON
from homeassistant.core import callback from homeassistant.core import callback
from . import ( from . import (
@ -97,6 +97,16 @@ class RfxtrxLight(RfxtrxCommandEntity, LightEntity):
_brightness = 0 _brightness = 0
async def async_added_to_hass(self):
"""Restore RFXtrx 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:
self._state = old_state.state == STATE_ON
self._brightness = old_state.attributes.get(ATTR_BRIGHTNESS)
@property @property
def brightness(self): def brightness(self):
"""Return the brightness of this light between 0..255.""" """Return the brightness of this light between 0..255."""

View File

@ -20,6 +20,7 @@ from . import (
get_device_id, get_device_id,
get_rfx_object, get_rfx_object,
) )
from .const import ATTR_EVENT
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -125,6 +126,17 @@ class RfxtrxSensor(RfxtrxEntity):
self._device_class = DEVICE_CLASSES.get(data_type) self._device_class = DEVICE_CLASSES.get(data_type)
self._convert_fun = CONVERT_FUNCTIONS.get(data_type, lambda x: x) self._convert_fun = CONVERT_FUNCTIONS.get(data_type, lambda x: x)
async def async_added_to_hass(self):
"""Restore device state."""
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))
@property @property
def state(self): def state(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""

View File

@ -4,7 +4,7 @@ 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 CONF_DEVICES from homeassistant.const import CONF_DEVICES, STATE_ON
from homeassistant.core import callback from homeassistant.core import callback
from . import ( from . import (
@ -91,6 +91,15 @@ async def async_setup_entry(
class RfxtrxSwitch(RfxtrxCommandEntity, SwitchEntity): class RfxtrxSwitch(RfxtrxCommandEntity, SwitchEntity):
"""Representation of a RFXtrx switch.""" """Representation of a RFXtrx switch."""
async def async_added_to_hass(self):
"""Restore device state."""
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:
self._state = old_state.state == STATE_ON
def _apply_event(self, event): def _apply_event(self, event):
"""Apply command from rfxtrx.""" """Apply command from rfxtrx."""
super()._apply_event(event) super()._apply_event(event)

View File

@ -1,12 +1,16 @@
"""The tests for the Rfxtrx sensor platform.""" """The tests for the Rfxtrx sensor platform."""
from datetime import timedelta from datetime import timedelta
import pytest
from homeassistant.components.rfxtrx.const import ATTR_EVENT
from homeassistant.core import State
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from homeassistant.util.dt import utcnow from homeassistant.util.dt import utcnow
from . import _signal_event from . import _signal_event
from tests.common import async_fire_time_changed from tests.common import async_fire_time_changed, mock_restore_cache
async def test_one(hass, rfxtrx): async def test_one(hass, rfxtrx):
@ -59,6 +63,27 @@ async def test_one_pt2262(hass, rfxtrx):
assert state.state == "off" assert state.state == "off"
@pytest.mark.parametrize(
"state,event",
[["on", "0b1100cd0213c7f230010f71"], ["off", "0b1100cd0213c7f230000f71"]],
)
async def test_state_restore(hass, rfxtrx, state, event):
"""State restoration."""
entity_id = "binary_sensor.ac_213c7f2_48"
mock_restore_cache(hass, [State(entity_id, state, attributes={ATTR_EVENT: event})])
assert await async_setup_component(
hass,
"rfxtrx",
{"rfxtrx": {"device": "abcd", "devices": {"0b1100cd0213c7f230010f71": {}}}},
)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state == state
async def test_several(hass, rfxtrx): async def test_several(hass, rfxtrx):
"""Test with 3.""" """Test with 3."""
assert await async_setup_component( assert await async_setup_component(

View File

@ -1,10 +1,15 @@
"""The tests for the Rfxtrx cover platform.""" """The tests for the Rfxtrx cover platform."""
from unittest.mock import call from unittest.mock import call
import pytest
from homeassistant.core import State
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from . import _signal_event from . import _signal_event
from tests.common import mock_restore_cache
async def test_one_cover(hass, rfxtrx): async def test_one_cover(hass, rfxtrx):
"""Test with 1 cover.""" """Test with 1 cover."""
@ -46,6 +51,24 @@ async def test_one_cover(hass, rfxtrx):
] ]
@pytest.mark.parametrize("state", ["open", "closed"])
async def test_state_restore(hass, rfxtrx, state):
"""State restoration."""
entity_id = "cover.lightwaverf_siemens_0213c7_242"
mock_restore_cache(hass, [State(entity_id, state)])
assert await async_setup_component(
hass,
"rfxtrx",
{"rfxtrx": {"device": "abcd", "devices": {"0b1400cd0213c7f20d010f51": {}}}},
)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state == state
async def test_several_covers(hass, rfxtrx): async def test_several_covers(hass, rfxtrx):
"""Test with 3 covers.""" """Test with 3 covers."""
assert await async_setup_component( assert await async_setup_component(

View File

@ -3,10 +3,14 @@ from unittest.mock import call
import pytest import pytest
from homeassistant.components.light import ATTR_BRIGHTNESS
from homeassistant.core import State
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from . import _signal_event from . import _signal_event
from tests.common import mock_restore_cache
async def test_one_light(hass, rfxtrx): async def test_one_light(hass, rfxtrx):
"""Test with 1 light.""" """Test with 1 light."""
@ -83,6 +87,27 @@ async def test_one_light(hass, rfxtrx):
] ]
@pytest.mark.parametrize("state,brightness", [["on", 100], ["on", 50], ["off", None]])
async def test_state_restore(hass, rfxtrx, state, brightness):
"""State restoration."""
entity_id = "light.ac_213c7f2_16"
mock_restore_cache(
hass, [State(entity_id, state, attributes={ATTR_BRIGHTNESS: brightness})]
)
assert await async_setup_component(
hass,
"rfxtrx",
{"rfxtrx": {"device": "abcd", "devices": {"0b1100cd0213c7f210020f51": {}}}},
)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state == state
assert hass.states.get(entity_id).attributes.get(ATTR_BRIGHTNESS) == brightness
async def test_several_lights(hass, rfxtrx): async def test_several_lights(hass, rfxtrx):
"""Test with 3 lights.""" """Test with 3 lights."""
assert await async_setup_component( assert await async_setup_component(

View File

@ -1,9 +1,15 @@
"""The tests for the Rfxtrx sensor platform.""" """The tests for the Rfxtrx sensor platform."""
import pytest
from homeassistant.components.rfxtrx.const import ATTR_EVENT
from homeassistant.const import TEMP_CELSIUS, UNIT_PERCENTAGE from homeassistant.const import TEMP_CELSIUS, UNIT_PERCENTAGE
from homeassistant.core import State
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from . import _signal_event from . import _signal_event
from tests.common import mock_restore_cache
async def test_default_config(hass, rfxtrx): async def test_default_config(hass, rfxtrx):
"""Test with 0 sensor.""" """Test with 0 sensor."""
@ -34,6 +40,27 @@ async def test_one_sensor(hass, rfxtrx):
assert state.attributes.get("unit_of_measurement") == TEMP_CELSIUS assert state.attributes.get("unit_of_measurement") == TEMP_CELSIUS
@pytest.mark.parametrize(
"state,event",
[["18.4", "0a520801070100b81b0279"], ["17.9", "0a52085e070100b31b0279"]],
)
async def test_state_restore(hass, rfxtrx, state, event):
"""State restoration."""
entity_id = "sensor.wt260_wt260h_wt440h_wt450_wt450h_07_01_temperature"
mock_restore_cache(hass, [State(entity_id, state, attributes={ATTR_EVENT: event})])
assert await async_setup_component(
hass,
"rfxtrx",
{"rfxtrx": {"device": "abcd", "devices": {"0a520801070100b81b0279": {}}}},
)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state == state
async def test_one_sensor_no_datatype(hass, rfxtrx): async def test_one_sensor_no_datatype(hass, rfxtrx):
"""Test with 1 sensor.""" """Test with 1 sensor."""
assert await async_setup_component( assert await async_setup_component(

View File

@ -3,10 +3,13 @@ from unittest.mock import call
import pytest import pytest
from homeassistant.core import State
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from . import _signal_event from . import _signal_event
from tests.common import mock_restore_cache
async def test_one_switch(hass, rfxtrx): async def test_one_switch(hass, rfxtrx):
"""Test with 1 switch.""" """Test with 1 switch."""
@ -42,6 +45,24 @@ async def test_one_switch(hass, rfxtrx):
] ]
@pytest.mark.parametrize("state", ["on", "off"])
async def test_state_restore(hass, rfxtrx, state):
"""State restoration."""
entity_id = "switch.ac_213c7f2_16"
mock_restore_cache(hass, [State(entity_id, state)])
assert await async_setup_component(
hass,
"rfxtrx",
{"rfxtrx": {"device": "abcd", "devices": {"0b1100cd0213c7f210010f51": {}}}},
)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state == state
async def test_several_switches(hass, rfxtrx): async def test_several_switches(hass, rfxtrx):
"""Test with 3 switches.""" """Test with 3 switches."""
assert await async_setup_component( assert await async_setup_component(