mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Add change service to timer (#84775)
* Add change service * test subtract * Test no change if timer not running * Modify example * Raise * Finalize * test event * Fix tests * Fix tracking time
This commit is contained in:
parent
fc7a421a48
commit
ddb9a6e33c
@ -17,6 +17,7 @@ from homeassistant.const import (
|
|||||||
SERVICE_RELOAD,
|
SERVICE_RELOAD,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, ServiceCall, callback
|
from homeassistant.core import HomeAssistant, ServiceCall, callback
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import collection
|
from homeassistant.helpers import collection
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
@ -50,6 +51,7 @@ STATUS_PAUSED = "paused"
|
|||||||
|
|
||||||
EVENT_TIMER_FINISHED = "timer.finished"
|
EVENT_TIMER_FINISHED = "timer.finished"
|
||||||
EVENT_TIMER_CANCELLED = "timer.cancelled"
|
EVENT_TIMER_CANCELLED = "timer.cancelled"
|
||||||
|
EVENT_TIMER_CHANGED = "timer.changed"
|
||||||
EVENT_TIMER_STARTED = "timer.started"
|
EVENT_TIMER_STARTED = "timer.started"
|
||||||
EVENT_TIMER_RESTARTED = "timer.restarted"
|
EVENT_TIMER_RESTARTED = "timer.restarted"
|
||||||
EVENT_TIMER_PAUSED = "timer.paused"
|
EVENT_TIMER_PAUSED = "timer.paused"
|
||||||
@ -57,6 +59,7 @@ EVENT_TIMER_PAUSED = "timer.paused"
|
|||||||
SERVICE_START = "start"
|
SERVICE_START = "start"
|
||||||
SERVICE_PAUSE = "pause"
|
SERVICE_PAUSE = "pause"
|
||||||
SERVICE_CANCEL = "cancel"
|
SERVICE_CANCEL = "cancel"
|
||||||
|
SERVICE_CHANGE = "change"
|
||||||
SERVICE_FINISH = "finish"
|
SERVICE_FINISH = "finish"
|
||||||
|
|
||||||
STORAGE_KEY = DOMAIN
|
STORAGE_KEY = DOMAIN
|
||||||
@ -158,6 +161,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
component.async_register_entity_service(SERVICE_PAUSE, {}, "async_pause")
|
component.async_register_entity_service(SERVICE_PAUSE, {}, "async_pause")
|
||||||
component.async_register_entity_service(SERVICE_CANCEL, {}, "async_cancel")
|
component.async_register_entity_service(SERVICE_CANCEL, {}, "async_cancel")
|
||||||
component.async_register_entity_service(SERVICE_FINISH, {}, "async_finish")
|
component.async_register_entity_service(SERVICE_FINISH, {}, "async_finish")
|
||||||
|
component.async_register_entity_service(
|
||||||
|
SERVICE_CHANGE,
|
||||||
|
{vol.Optional(ATTR_DURATION, default=DEFAULT_DURATION): cv.time_period},
|
||||||
|
"async_change",
|
||||||
|
)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -321,6 +329,25 @@ class Timer(collection.CollectionEntity, RestoreEntity):
|
|||||||
)
|
)
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_change(self, duration: timedelta) -> None:
|
||||||
|
"""Change duration of a running timer."""
|
||||||
|
if self._listener is None or self._end is None:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"Timer {self.entity_id} is not running, only active timers can be changed"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._listener()
|
||||||
|
self._listener = None
|
||||||
|
self._end += duration
|
||||||
|
self._duration += duration
|
||||||
|
self._remaining = self._end - dt_util.utcnow().replace(microsecond=0)
|
||||||
|
self.hass.bus.async_fire(EVENT_TIMER_CHANGED, {ATTR_ENTITY_ID: self.entity_id})
|
||||||
|
self._listener = async_track_point_in_utc_time(
|
||||||
|
self.hass, self._async_finished, self._end
|
||||||
|
)
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_pause(self):
|
def async_pause(self):
|
||||||
"""Pause a timer."""
|
"""Pause a timer."""
|
||||||
|
@ -33,3 +33,18 @@ finish:
|
|||||||
target:
|
target:
|
||||||
entity:
|
entity:
|
||||||
domain: timer
|
domain: timer
|
||||||
|
|
||||||
|
change:
|
||||||
|
name: Change
|
||||||
|
description: Change a timer
|
||||||
|
target:
|
||||||
|
entity:
|
||||||
|
domain: timer
|
||||||
|
fields:
|
||||||
|
duration:
|
||||||
|
description: Duration to add or subtract to the running timer
|
||||||
|
default: 0
|
||||||
|
required: true
|
||||||
|
example: "00:01:00, 60 or -60"
|
||||||
|
selector:
|
||||||
|
text:
|
||||||
|
@ -17,11 +17,13 @@ from homeassistant.components.timer import (
|
|||||||
DEFAULT_DURATION,
|
DEFAULT_DURATION,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
EVENT_TIMER_CANCELLED,
|
EVENT_TIMER_CANCELLED,
|
||||||
|
EVENT_TIMER_CHANGED,
|
||||||
EVENT_TIMER_FINISHED,
|
EVENT_TIMER_FINISHED,
|
||||||
EVENT_TIMER_PAUSED,
|
EVENT_TIMER_PAUSED,
|
||||||
EVENT_TIMER_RESTARTED,
|
EVENT_TIMER_RESTARTED,
|
||||||
EVENT_TIMER_STARTED,
|
EVENT_TIMER_STARTED,
|
||||||
SERVICE_CANCEL,
|
SERVICE_CANCEL,
|
||||||
|
SERVICE_CHANGE,
|
||||||
SERVICE_FINISH,
|
SERVICE_FINISH,
|
||||||
SERVICE_PAUSE,
|
SERVICE_PAUSE,
|
||||||
SERVICE_START,
|
SERVICE_START,
|
||||||
@ -43,7 +45,7 @@ from homeassistant.const import (
|
|||||||
SERVICE_RELOAD,
|
SERVICE_RELOAD,
|
||||||
)
|
)
|
||||||
from homeassistant.core import Context, CoreState, HomeAssistant, State
|
from homeassistant.core import Context, CoreState, HomeAssistant, State
|
||||||
from homeassistant.exceptions import Unauthorized
|
from homeassistant.exceptions import HomeAssistantError, Unauthorized
|
||||||
from homeassistant.helpers import config_validation as cv, entity_registry as er
|
from homeassistant.helpers import config_validation as cv, entity_registry as er
|
||||||
from homeassistant.helpers.restore_state import (
|
from homeassistant.helpers.restore_state import (
|
||||||
DATA_RESTORE_STATE_TASK,
|
DATA_RESTORE_STATE_TASK,
|
||||||
@ -60,7 +62,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def storage_setup(hass, hass_storage):
|
def storage_setup(hass: HomeAssistant, hass_storage):
|
||||||
"""Storage setup."""
|
"""Storage setup."""
|
||||||
|
|
||||||
async def _storage(items=None, config=None):
|
async def _storage(items=None, config=None):
|
||||||
@ -168,26 +170,91 @@ async def test_methods_and_events(hass: HomeAssistant) -> None:
|
|||||||
hass.bus.async_listen(EVENT_TIMER_PAUSED, fake_event_listener)
|
hass.bus.async_listen(EVENT_TIMER_PAUSED, fake_event_listener)
|
||||||
hass.bus.async_listen(EVENT_TIMER_FINISHED, fake_event_listener)
|
hass.bus.async_listen(EVENT_TIMER_FINISHED, fake_event_listener)
|
||||||
hass.bus.async_listen(EVENT_TIMER_CANCELLED, fake_event_listener)
|
hass.bus.async_listen(EVENT_TIMER_CANCELLED, fake_event_listener)
|
||||||
|
hass.bus.async_listen(EVENT_TIMER_CHANGED, fake_event_listener)
|
||||||
|
|
||||||
steps = [
|
steps = [
|
||||||
{"call": SERVICE_START, "state": STATUS_ACTIVE, "event": EVENT_TIMER_STARTED},
|
{
|
||||||
{"call": SERVICE_PAUSE, "state": STATUS_PAUSED, "event": EVENT_TIMER_PAUSED},
|
"call": SERVICE_START,
|
||||||
{"call": SERVICE_START, "state": STATUS_ACTIVE, "event": EVENT_TIMER_RESTARTED},
|
"state": STATUS_ACTIVE,
|
||||||
{"call": SERVICE_CANCEL, "state": STATUS_IDLE, "event": EVENT_TIMER_CANCELLED},
|
"event": EVENT_TIMER_STARTED,
|
||||||
{"call": SERVICE_START, "state": STATUS_ACTIVE, "event": EVENT_TIMER_STARTED},
|
"data": {},
|
||||||
{"call": SERVICE_FINISH, "state": STATUS_IDLE, "event": EVENT_TIMER_FINISHED},
|
},
|
||||||
{"call": SERVICE_START, "state": STATUS_ACTIVE, "event": EVENT_TIMER_STARTED},
|
{
|
||||||
{"call": SERVICE_PAUSE, "state": STATUS_PAUSED, "event": EVENT_TIMER_PAUSED},
|
"call": SERVICE_PAUSE,
|
||||||
{"call": SERVICE_CANCEL, "state": STATUS_IDLE, "event": EVENT_TIMER_CANCELLED},
|
"state": STATUS_PAUSED,
|
||||||
{"call": SERVICE_START, "state": STATUS_ACTIVE, "event": EVENT_TIMER_STARTED},
|
"event": EVENT_TIMER_PAUSED,
|
||||||
{"call": SERVICE_START, "state": STATUS_ACTIVE, "event": EVENT_TIMER_RESTARTED},
|
"data": {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": SERVICE_START,
|
||||||
|
"state": STATUS_ACTIVE,
|
||||||
|
"event": EVENT_TIMER_RESTARTED,
|
||||||
|
"data": {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": SERVICE_CANCEL,
|
||||||
|
"state": STATUS_IDLE,
|
||||||
|
"event": EVENT_TIMER_CANCELLED,
|
||||||
|
"data": {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": SERVICE_START,
|
||||||
|
"state": STATUS_ACTIVE,
|
||||||
|
"event": EVENT_TIMER_STARTED,
|
||||||
|
"data": {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": SERVICE_FINISH,
|
||||||
|
"state": STATUS_IDLE,
|
||||||
|
"event": EVENT_TIMER_FINISHED,
|
||||||
|
"data": {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": SERVICE_START,
|
||||||
|
"state": STATUS_ACTIVE,
|
||||||
|
"event": EVENT_TIMER_STARTED,
|
||||||
|
"data": {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": SERVICE_PAUSE,
|
||||||
|
"state": STATUS_PAUSED,
|
||||||
|
"event": EVENT_TIMER_PAUSED,
|
||||||
|
"data": {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": SERVICE_CANCEL,
|
||||||
|
"state": STATUS_IDLE,
|
||||||
|
"event": EVENT_TIMER_CANCELLED,
|
||||||
|
"data": {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": SERVICE_START,
|
||||||
|
"state": STATUS_ACTIVE,
|
||||||
|
"event": EVENT_TIMER_STARTED,
|
||||||
|
"data": {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": SERVICE_CHANGE,
|
||||||
|
"state": STATUS_ACTIVE,
|
||||||
|
"event": EVENT_TIMER_CHANGED,
|
||||||
|
"data": {CONF_DURATION: 15},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"call": SERVICE_START,
|
||||||
|
"state": STATUS_ACTIVE,
|
||||||
|
"event": EVENT_TIMER_RESTARTED,
|
||||||
|
"data": {},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
expectedEvents = 0
|
expected_events = 0
|
||||||
for step in steps:
|
for step in steps:
|
||||||
if step["call"] is not None:
|
if step["call"] is not None:
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN, step["call"], {CONF_ENTITY_ID: "timer.test1"}
|
DOMAIN,
|
||||||
|
step["call"],
|
||||||
|
{CONF_ENTITY_ID: "timer.test1", **step["data"]},
|
||||||
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
@ -197,9 +264,9 @@ async def test_methods_and_events(hass: HomeAssistant) -> None:
|
|||||||
assert state.state == step["state"]
|
assert state.state == step["state"]
|
||||||
|
|
||||||
if step["event"] is not None:
|
if step["event"] is not None:
|
||||||
expectedEvents += 1
|
expected_events += 1
|
||||||
assert results[-1].event_type == step["event"]
|
assert results[-1].event_type == step["event"]
|
||||||
assert len(results) == expectedEvents
|
assert len(results) == expected_events
|
||||||
|
|
||||||
|
|
||||||
async def test_start_service(hass: HomeAssistant) -> None:
|
async def test_start_service(hass: HomeAssistant) -> None:
|
||||||
@ -212,7 +279,7 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
|||||||
assert state.attributes[ATTR_DURATION] == "0:00:10"
|
assert state.attributes[ATTR_DURATION] == "0:00:10"
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN, SERVICE_START, {CONF_ENTITY_ID: "timer.test1"}
|
DOMAIN, SERVICE_START, {CONF_ENTITY_ID: "timer.test1"}, blocking=True
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
state = hass.states.get("timer.test1")
|
state = hass.states.get("timer.test1")
|
||||||
@ -222,7 +289,7 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
|||||||
assert state.attributes[ATTR_REMAINING] == "0:00:10"
|
assert state.attributes[ATTR_REMAINING] == "0:00:10"
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN, SERVICE_CANCEL, {CONF_ENTITY_ID: "timer.test1"}
|
DOMAIN, SERVICE_CANCEL, {CONF_ENTITY_ID: "timer.test1"}, blocking=True
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
state = hass.states.get("timer.test1")
|
state = hass.states.get("timer.test1")
|
||||||
@ -231,8 +298,20 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
|||||||
assert state.attributes[ATTR_DURATION] == "0:00:10"
|
assert state.attributes[ATTR_DURATION] == "0:00:10"
|
||||||
assert ATTR_REMAINING not in state.attributes
|
assert ATTR_REMAINING not in state.attributes
|
||||||
|
|
||||||
|
with pytest.raises(HomeAssistantError):
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_CHANGE,
|
||||||
|
{CONF_ENTITY_ID: "timer.test1", CONF_DURATION: 10},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN, SERVICE_START, {CONF_ENTITY_ID: "timer.test1", CONF_DURATION: 15}
|
DOMAIN,
|
||||||
|
SERVICE_START,
|
||||||
|
{CONF_ENTITY_ID: "timer.test1", CONF_DURATION: 15},
|
||||||
|
blocking=True,
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
state = hass.states.get("timer.test1")
|
state = hass.states.get("timer.test1")
|
||||||
@ -241,6 +320,57 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
|||||||
assert state.attributes[ATTR_DURATION] == "0:00:15"
|
assert state.attributes[ATTR_DURATION] == "0:00:15"
|
||||||
assert state.attributes[ATTR_REMAINING] == "0:00:15"
|
assert state.attributes[ATTR_REMAINING] == "0:00:15"
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_CHANGE,
|
||||||
|
{CONF_ENTITY_ID: "timer.test1", CONF_DURATION: 15},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("timer.test1")
|
||||||
|
assert state
|
||||||
|
assert state.state == STATUS_ACTIVE
|
||||||
|
assert state.attributes[ATTR_DURATION] == "0:00:30"
|
||||||
|
assert state.attributes[ATTR_REMAINING] == "0:00:30"
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_CHANGE,
|
||||||
|
{CONF_ENTITY_ID: "timer.test1", CONF_DURATION: -10},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("timer.test1")
|
||||||
|
assert state
|
||||||
|
assert state.state == STATUS_ACTIVE
|
||||||
|
assert state.attributes[ATTR_DURATION] == "0:00:20"
|
||||||
|
assert state.attributes[ATTR_REMAINING] == "0:00:20"
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN, SERVICE_CANCEL, {CONF_ENTITY_ID: "timer.test1"}, blocking=True
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("timer.test1")
|
||||||
|
assert state
|
||||||
|
assert state.state == STATUS_IDLE
|
||||||
|
assert state.attributes[ATTR_DURATION] == "0:00:20"
|
||||||
|
assert ATTR_REMAINING not in state.attributes
|
||||||
|
|
||||||
|
with pytest.raises(HomeAssistantError):
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_CHANGE,
|
||||||
|
{CONF_ENTITY_ID: "timer.test1", CONF_DURATION: 10},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("timer.test1")
|
||||||
|
assert state
|
||||||
|
assert state.state == STATUS_IDLE
|
||||||
|
assert state.attributes[ATTR_DURATION] == "0:00:20"
|
||||||
|
assert ATTR_REMAINING not in state.attributes
|
||||||
|
|
||||||
|
|
||||||
async def test_wait_till_timer_expires(hass: HomeAssistant) -> None:
|
async def test_wait_till_timer_expires(hass: HomeAssistant) -> None:
|
||||||
"""Test for a timer to end."""
|
"""Test for a timer to end."""
|
||||||
@ -262,9 +392,10 @@ async def test_wait_till_timer_expires(hass: HomeAssistant) -> None:
|
|||||||
hass.bus.async_listen(EVENT_TIMER_PAUSED, fake_event_listener)
|
hass.bus.async_listen(EVENT_TIMER_PAUSED, fake_event_listener)
|
||||||
hass.bus.async_listen(EVENT_TIMER_FINISHED, fake_event_listener)
|
hass.bus.async_listen(EVENT_TIMER_FINISHED, fake_event_listener)
|
||||||
hass.bus.async_listen(EVENT_TIMER_CANCELLED, fake_event_listener)
|
hass.bus.async_listen(EVENT_TIMER_CANCELLED, fake_event_listener)
|
||||||
|
hass.bus.async_listen(EVENT_TIMER_CHANGED, fake_event_listener)
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN, SERVICE_START, {CONF_ENTITY_ID: "timer.test1"}
|
DOMAIN, SERVICE_START, {CONF_ENTITY_ID: "timer.test1"}, blocking=True
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
@ -275,15 +406,37 @@ async def test_wait_till_timer_expires(hass: HomeAssistant) -> None:
|
|||||||
assert results[-1].event_type == EVENT_TIMER_STARTED
|
assert results[-1].event_type == EVENT_TIMER_STARTED
|
||||||
assert len(results) == 1
|
assert len(results) == 1
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_CHANGE,
|
||||||
|
{CONF_ENTITY_ID: "timer.test1", CONF_DURATION: 10},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("timer.test1")
|
||||||
|
assert state
|
||||||
|
assert state.state == STATUS_ACTIVE
|
||||||
|
|
||||||
|
assert results[-1].event_type == EVENT_TIMER_CHANGED
|
||||||
|
assert len(results) == 2
|
||||||
|
|
||||||
async_fire_time_changed(hass, utcnow() + timedelta(seconds=10))
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=10))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("timer.test1")
|
||||||
|
assert state
|
||||||
|
assert state.state == STATUS_ACTIVE
|
||||||
|
|
||||||
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=20))
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
state = hass.states.get("timer.test1")
|
state = hass.states.get("timer.test1")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == STATUS_IDLE
|
assert state.state == STATUS_IDLE
|
||||||
|
|
||||||
assert results[-1].event_type == EVENT_TIMER_FINISHED
|
assert results[-1].event_type == EVENT_TIMER_FINISHED
|
||||||
assert len(results) == 2
|
assert len(results) == 3
|
||||||
|
|
||||||
|
|
||||||
async def test_no_initial_state_and_no_restore_state(hass: HomeAssistant) -> None:
|
async def test_no_initial_state_and_no_restore_state(hass: HomeAssistant) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user