208 files

This commit is contained in:
Home Assistant Version Control
2026-10-07 02:49:21 +00:00
parent a7107ecbe1
commit cfd0d40c8e
208 changed files with 5434 additions and 901 deletions
@@ -8,10 +8,12 @@ import voluptuous as vol
from homeassistant.components.zone import (
DOMAIN,
ENTITY_ID_HOME,
UPDATE_FIELDS,
Zone,
ZoneStorageCollection,
)
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_RADIUS
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_component import DATA_INSTANCES, EntityComponent
@@ -22,8 +24,24 @@ if TYPE_CHECKING:
from homeassistant.core import ServiceCall
def _is_the_house(entity: Zone) -> bool:
"""Tell whether a zone is the home zone drawn from the house's location.
Home Assistant only draws it when no zone has taken `zone.home` already:
zones from YAML and storage are set up first, and one named Home gets that
entity ID. Those are ordinary zones, and moving the house would not move
them. The drawn one is the only editable zone without a stored ID.
"""
return (
entity.entity_id == ENTITY_ID_HOME
and entity.editable
# pylint: disable-next=protected-access
and "id" not in entity._config # noqa: SLF001
)
class SpookService(AbstractSpookAdminService):
"""Zone service to update a zone on the fly."""
"""Zone service to update a zone on the fly, the home zone included."""
domain = DOMAIN
service = "update"
@@ -50,6 +68,10 @@ class SpookService(AbstractSpookAdminService):
message = f"Could not find entity_id: {call.data['entity_id']}"
raise HomeAssistantError(message)
if _is_the_house(entity):
await self._async_update_home(call)
return
# pylint: disable-next=protected-access
if not entity.editable or "id" not in entity._config: # noqa: SLF001
message = f"This zone is not editable: {call.data['entity_id']}"
@@ -60,3 +82,37 @@ class SpookService(AbstractSpookAdminService):
# pylint: disable-next=protected-access
await collection.async_update_item(entity._config["id"], data) # noqa: SLF001
async def _async_update_home(self, call: ServiceCall) -> None:
"""Move or resize the home zone.
It is not a stored zone: Home Assistant draws it from the location
set for the whole house, and redraws it when that changes. So this
changes the location, the same way Home Assistant's own
`homeassistant.set_location` does, and the radius along with it.
Only those. Its name is the name of the whole house, and a home zone
is never passive.
"""
data = dict(call.data)
data.pop("entity_id")
if unsupported := set(data) - {CONF_LATITUDE, CONF_LONGITUDE, CONF_RADIUS}:
message = (
"The home zone only takes a latitude, longitude and radius, "
f"not: {', '.join(sorted(unsupported))}"
)
raise HomeAssistantError(message)
# Home Assistant keeps the radius of the house in whole meters, and
# never below zero. Cutting a fraction off quietly would be a
# different zone than was asked for, and the location is stored
# without going through the checks its configuration normally does.
if CONF_RADIUS in data:
radius = data[CONF_RADIUS]
if radius != int(radius) or radius < 0:
message = "The home zone takes its radius in whole meters, zero or more"
raise HomeAssistantError(message)
data[CONF_RADIUS] = int(radius)
await self.hass.config.async_update(**data)