mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add Save Persistent States service (#53881)
This commit is contained in:
parent
33c33d844e
commit
3184f0697f
@ -14,13 +14,14 @@ from homeassistant.const import (
|
|||||||
RESTART_EXIT_CODE,
|
RESTART_EXIT_CODE,
|
||||||
SERVICE_HOMEASSISTANT_RESTART,
|
SERVICE_HOMEASSISTANT_RESTART,
|
||||||
SERVICE_HOMEASSISTANT_STOP,
|
SERVICE_HOMEASSISTANT_STOP,
|
||||||
|
SERVICE_SAVE_PERSISTENT_STATES,
|
||||||
SERVICE_TOGGLE,
|
SERVICE_TOGGLE,
|
||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
)
|
)
|
||||||
import homeassistant.core as ha
|
import homeassistant.core as ha
|
||||||
from homeassistant.exceptions import HomeAssistantError, Unauthorized, UnknownUser
|
from homeassistant.exceptions import HomeAssistantError, Unauthorized, UnknownUser
|
||||||
from homeassistant.helpers import config_validation as cv, recorder
|
from homeassistant.helpers import config_validation as cv, recorder, restore_state
|
||||||
from homeassistant.helpers.service import (
|
from homeassistant.helpers.service import (
|
||||||
async_extract_config_entry_ids,
|
async_extract_config_entry_ids,
|
||||||
async_extract_referenced_entity_ids,
|
async_extract_referenced_entity_ids,
|
||||||
@ -53,6 +54,10 @@ SHUTDOWN_SERVICES = (SERVICE_HOMEASSISTANT_STOP, SERVICE_HOMEASSISTANT_RESTART)
|
|||||||
async def async_setup(hass: ha.HomeAssistant, config: dict) -> bool: # noqa: C901
|
async def async_setup(hass: ha.HomeAssistant, config: dict) -> bool: # noqa: C901
|
||||||
"""Set up general services related to Home Assistant."""
|
"""Set up general services related to Home Assistant."""
|
||||||
|
|
||||||
|
async def async_save_persistent_states(service):
|
||||||
|
"""Handle calls to homeassistant.save_persistent_states."""
|
||||||
|
await restore_state.RestoreStateData.async_save_persistent_states(hass)
|
||||||
|
|
||||||
async def async_handle_turn_service(service):
|
async def async_handle_turn_service(service):
|
||||||
"""Handle calls to homeassistant.turn_on/off."""
|
"""Handle calls to homeassistant.turn_on/off."""
|
||||||
referenced = await async_extract_referenced_entity_ids(hass, service)
|
referenced = await async_extract_referenced_entity_ids(hass, service)
|
||||||
@ -114,6 +119,10 @@ async def async_setup(hass: ha.HomeAssistant, config: dict) -> bool: # noqa: C9
|
|||||||
if tasks:
|
if tasks:
|
||||||
await asyncio.gather(*tasks)
|
await asyncio.gather(*tasks)
|
||||||
|
|
||||||
|
hass.services.async_register(
|
||||||
|
ha.DOMAIN, SERVICE_SAVE_PERSISTENT_STATES, async_save_persistent_states
|
||||||
|
)
|
||||||
|
|
||||||
service_schema = vol.Schema({ATTR_ENTITY_ID: cv.entity_ids}, extra=vol.ALLOW_EXTRA)
|
service_schema = vol.Schema({ATTR_ENTITY_ID: cv.entity_ids}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
hass.services.async_register(
|
hass.services.async_register(
|
||||||
|
@ -74,3 +74,9 @@ reload_config_entry:
|
|||||||
example: 8955375327824e14ba89e4b29cc3ec9a
|
example: 8955375327824e14ba89e4b29cc3ec9a
|
||||||
selector:
|
selector:
|
||||||
text:
|
text:
|
||||||
|
|
||||||
|
save_persistent_states:
|
||||||
|
name: Save Persistent States
|
||||||
|
description:
|
||||||
|
Save the persistent states (for entities derived from RestoreEntity) immediately.
|
||||||
|
Maintain the normal periodic saving interval.
|
||||||
|
@ -612,6 +612,7 @@ SERVICE_CLOSE_COVER: Final = "close_cover"
|
|||||||
SERVICE_CLOSE_COVER_TILT: Final = "close_cover_tilt"
|
SERVICE_CLOSE_COVER_TILT: Final = "close_cover_tilt"
|
||||||
SERVICE_OPEN_COVER: Final = "open_cover"
|
SERVICE_OPEN_COVER: Final = "open_cover"
|
||||||
SERVICE_OPEN_COVER_TILT: Final = "open_cover_tilt"
|
SERVICE_OPEN_COVER_TILT: Final = "open_cover_tilt"
|
||||||
|
SERVICE_SAVE_PERSISTENT_STATES: Final = "save_persistent_states"
|
||||||
SERVICE_SET_COVER_POSITION: Final = "set_cover_position"
|
SERVICE_SET_COVER_POSITION: Final = "set_cover_position"
|
||||||
SERVICE_SET_COVER_TILT_POSITION: Final = "set_cover_tilt_position"
|
SERVICE_SET_COVER_TILT_POSITION: Final = "set_cover_tilt_position"
|
||||||
SERVICE_STOP_COVER: Final = "stop_cover"
|
SERVICE_STOP_COVER: Final = "stop_cover"
|
||||||
|
@ -100,6 +100,12 @@ class RestoreStateData:
|
|||||||
|
|
||||||
return cast(RestoreStateData, await load_instance(hass))
|
return cast(RestoreStateData, await load_instance(hass))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def async_save_persistent_states(cls, hass: HomeAssistant) -> None:
|
||||||
|
"""Dump states now."""
|
||||||
|
data = await cls.async_get_instance(hass)
|
||||||
|
await data.async_dump_states()
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant) -> None:
|
def __init__(self, hass: HomeAssistant) -> None:
|
||||||
"""Initialize the restore state data class."""
|
"""Initialize the restore state data class."""
|
||||||
self.hass: HomeAssistant = hass
|
self.hass: HomeAssistant = hass
|
||||||
|
@ -23,6 +23,7 @@ from homeassistant.const import (
|
|||||||
EVENT_CORE_CONFIG_UPDATE,
|
EVENT_CORE_CONFIG_UPDATE,
|
||||||
SERVICE_HOMEASSISTANT_RESTART,
|
SERVICE_HOMEASSISTANT_RESTART,
|
||||||
SERVICE_HOMEASSISTANT_STOP,
|
SERVICE_HOMEASSISTANT_STOP,
|
||||||
|
SERVICE_SAVE_PERSISTENT_STATES,
|
||||||
SERVICE_TOGGLE,
|
SERVICE_TOGGLE,
|
||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
@ -543,3 +544,18 @@ async def test_stop_homeassistant(hass):
|
|||||||
assert not mock_check.called
|
assert not mock_check.called
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert mock_restart.called
|
assert mock_restart.called
|
||||||
|
|
||||||
|
|
||||||
|
async def test_save_persistent_states(hass):
|
||||||
|
"""Test we can call save_persistent_states."""
|
||||||
|
await async_setup_component(hass, "homeassistant", {})
|
||||||
|
with patch(
|
||||||
|
"homeassistant.helpers.restore_state.RestoreStateData.async_save_persistent_states",
|
||||||
|
return_value=None,
|
||||||
|
) as mock_save:
|
||||||
|
await hass.services.async_call(
|
||||||
|
"homeassistant",
|
||||||
|
SERVICE_SAVE_PERSISTENT_STATES,
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
assert mock_save.called
|
||||||
|
@ -98,6 +98,62 @@ async def test_periodic_write(hass):
|
|||||||
assert not mock_write_data.called
|
assert not mock_write_data.called
|
||||||
|
|
||||||
|
|
||||||
|
async def test_save_persistent_states(hass):
|
||||||
|
"""Test that we cancel the currently running job, save the data, and verify the perdiodic job continues."""
|
||||||
|
data = await RestoreStateData.async_get_instance(hass)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
await data.store.async_save([])
|
||||||
|
|
||||||
|
# Emulate a fresh load
|
||||||
|
hass.data[DATA_RESTORE_STATE_TASK] = None
|
||||||
|
|
||||||
|
entity = RestoreEntity()
|
||||||
|
entity.hass = hass
|
||||||
|
entity.entity_id = "input_boolean.b1"
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.helpers.restore_state.Store.async_save"
|
||||||
|
) as mock_write_data:
|
||||||
|
await entity.async_get_last_state()
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Startup Save
|
||||||
|
assert mock_write_data.called
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.helpers.restore_state.Store.async_save"
|
||||||
|
) as mock_write_data:
|
||||||
|
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=10))
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Not quite the first interval
|
||||||
|
assert not mock_write_data.called
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.helpers.restore_state.Store.async_save"
|
||||||
|
) as mock_write_data:
|
||||||
|
await RestoreStateData.async_save_persistent_states(hass)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert mock_write_data.called
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.helpers.restore_state.Store.async_save"
|
||||||
|
) as mock_write_data:
|
||||||
|
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=20))
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
# Verify still saving
|
||||||
|
assert mock_write_data.called
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.helpers.restore_state.Store.async_save"
|
||||||
|
) as mock_write_data:
|
||||||
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
# Verify normal shutdown
|
||||||
|
assert mock_write_data.called
|
||||||
|
|
||||||
|
|
||||||
async def test_hass_starting(hass):
|
async def test_hass_starting(hass):
|
||||||
"""Test that we cache data."""
|
"""Test that we cache data."""
|
||||||
hass.state = CoreState.starting
|
hass.state = CoreState.starting
|
||||||
|
Loading…
x
Reference in New Issue
Block a user