mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 09:47:13 +00:00
Make the radius of the home zone configurable (#119385)
This commit is contained in:
parent
8cf1890772
commit
7e61ec96e7
@ -61,6 +61,7 @@ class CheckConfigView(HomeAssistantView):
|
|||||||
vol.Optional("latitude"): cv.latitude,
|
vol.Optional("latitude"): cv.latitude,
|
||||||
vol.Optional("location_name"): str,
|
vol.Optional("location_name"): str,
|
||||||
vol.Optional("longitude"): cv.longitude,
|
vol.Optional("longitude"): cv.longitude,
|
||||||
|
vol.Optional("radius"): cv.positive_int,
|
||||||
vol.Optional("time_zone"): cv.time_zone,
|
vol.Optional("time_zone"): cv.time_zone,
|
||||||
vol.Optional("update_units"): bool,
|
vol.Optional("update_units"): bool,
|
||||||
vol.Optional("unit_system"): unit_system.validate_unit_system,
|
vol.Optional("unit_system"): unit_system.validate_unit_system,
|
||||||
|
@ -302,7 +302,7 @@ def _home_conf(hass: HomeAssistant) -> dict:
|
|||||||
CONF_NAME: hass.config.location_name,
|
CONF_NAME: hass.config.location_name,
|
||||||
CONF_LATITUDE: hass.config.latitude,
|
CONF_LATITUDE: hass.config.latitude,
|
||||||
CONF_LONGITUDE: hass.config.longitude,
|
CONF_LONGITUDE: hass.config.longitude,
|
||||||
CONF_RADIUS: DEFAULT_RADIUS,
|
CONF_RADIUS: hass.config.radius,
|
||||||
CONF_ICON: ICON_HOME,
|
CONF_ICON: ICON_HOME,
|
||||||
CONF_PASSIVE: False,
|
CONF_PASSIVE: False,
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ from .const import (
|
|||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
CONF_PACKAGES,
|
CONF_PACKAGES,
|
||||||
CONF_PLATFORM,
|
CONF_PLATFORM,
|
||||||
|
CONF_RADIUS,
|
||||||
CONF_TEMPERATURE_UNIT,
|
CONF_TEMPERATURE_UNIT,
|
||||||
CONF_TIME_ZONE,
|
CONF_TIME_ZONE,
|
||||||
CONF_TYPE,
|
CONF_TYPE,
|
||||||
@ -342,6 +343,7 @@ CORE_CONFIG_SCHEMA = vol.All(
|
|||||||
CONF_LATITUDE: cv.latitude,
|
CONF_LATITUDE: cv.latitude,
|
||||||
CONF_LONGITUDE: cv.longitude,
|
CONF_LONGITUDE: cv.longitude,
|
||||||
CONF_ELEVATION: vol.Coerce(int),
|
CONF_ELEVATION: vol.Coerce(int),
|
||||||
|
CONF_RADIUS: cv.positive_int,
|
||||||
vol.Remove(CONF_TEMPERATURE_UNIT): cv.temperature_unit,
|
vol.Remove(CONF_TEMPERATURE_UNIT): cv.temperature_unit,
|
||||||
CONF_UNIT_SYSTEM: validate_unit_system,
|
CONF_UNIT_SYSTEM: validate_unit_system,
|
||||||
CONF_TIME_ZONE: cv.time_zone,
|
CONF_TIME_ZONE: cv.time_zone,
|
||||||
@ -882,6 +884,7 @@ async def async_process_ha_core_config(hass: HomeAssistant, config: dict) -> Non
|
|||||||
CONF_CURRENCY,
|
CONF_CURRENCY,
|
||||||
CONF_COUNTRY,
|
CONF_COUNTRY,
|
||||||
CONF_LANGUAGE,
|
CONF_LANGUAGE,
|
||||||
|
CONF_RADIUS,
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
hac.config_source = ConfigSource.YAML
|
hac.config_source = ConfigSource.YAML
|
||||||
@ -898,6 +901,7 @@ async def async_process_ha_core_config(hass: HomeAssistant, config: dict) -> Non
|
|||||||
(CONF_CURRENCY, "currency"),
|
(CONF_CURRENCY, "currency"),
|
||||||
(CONF_COUNTRY, "country"),
|
(CONF_COUNTRY, "country"),
|
||||||
(CONF_LANGUAGE, "language"),
|
(CONF_LANGUAGE, "language"),
|
||||||
|
(CONF_RADIUS, "radius"),
|
||||||
):
|
):
|
||||||
if key in config:
|
if key in config:
|
||||||
setattr(hac, attr, config[key])
|
setattr(hac, attr, config[key])
|
||||||
|
@ -138,7 +138,7 @@ type CALLBACK_TYPE = Callable[[], None]
|
|||||||
|
|
||||||
CORE_STORAGE_KEY = "core.config"
|
CORE_STORAGE_KEY = "core.config"
|
||||||
CORE_STORAGE_VERSION = 1
|
CORE_STORAGE_VERSION = 1
|
||||||
CORE_STORAGE_MINOR_VERSION = 3
|
CORE_STORAGE_MINOR_VERSION = 4
|
||||||
|
|
||||||
DOMAIN = "homeassistant"
|
DOMAIN = "homeassistant"
|
||||||
|
|
||||||
@ -2835,6 +2835,9 @@ class Config:
|
|||||||
|
|
||||||
def __init__(self, hass: HomeAssistant, config_dir: str) -> None:
|
def __init__(self, hass: HomeAssistant, config_dir: str) -> None:
|
||||||
"""Initialize a new config object."""
|
"""Initialize a new config object."""
|
||||||
|
# pylint: disable-next=import-outside-toplevel
|
||||||
|
from .components.zone import DEFAULT_RADIUS
|
||||||
|
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
|
|
||||||
self.latitude: float = 0
|
self.latitude: float = 0
|
||||||
@ -2843,6 +2846,9 @@ class Config:
|
|||||||
self.elevation: int = 0
|
self.elevation: int = 0
|
||||||
"""Elevation (always in meters regardless of the unit system)."""
|
"""Elevation (always in meters regardless of the unit system)."""
|
||||||
|
|
||||||
|
self.radius: int = DEFAULT_RADIUS
|
||||||
|
"""Radius of the Home Zone (always in meters regardless of the unit system)."""
|
||||||
|
|
||||||
self.debug: bool = False
|
self.debug: bool = False
|
||||||
self.location_name: str = "Home"
|
self.location_name: str = "Home"
|
||||||
self.time_zone: str = "UTC"
|
self.time_zone: str = "UTC"
|
||||||
@ -2991,6 +2997,7 @@ class Config:
|
|||||||
"language": self.language,
|
"language": self.language,
|
||||||
"safe_mode": self.safe_mode,
|
"safe_mode": self.safe_mode,
|
||||||
"debug": self.debug,
|
"debug": self.debug,
|
||||||
|
"radius": self.radius,
|
||||||
}
|
}
|
||||||
|
|
||||||
async def async_set_time_zone(self, time_zone_str: str) -> None:
|
async def async_set_time_zone(self, time_zone_str: str) -> None:
|
||||||
@ -3039,6 +3046,7 @@ class Config:
|
|||||||
currency: str | None = None,
|
currency: str | None = None,
|
||||||
country: str | UndefinedType | None = UNDEFINED,
|
country: str | UndefinedType | None = UNDEFINED,
|
||||||
language: str | None = None,
|
language: str | None = None,
|
||||||
|
radius: int | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Update the configuration from a dictionary."""
|
"""Update the configuration from a dictionary."""
|
||||||
self.config_source = source
|
self.config_source = source
|
||||||
@ -3067,6 +3075,8 @@ class Config:
|
|||||||
self.country = country
|
self.country = country
|
||||||
if language is not None:
|
if language is not None:
|
||||||
self.language = language
|
self.language = language
|
||||||
|
if radius is not None:
|
||||||
|
self.radius = radius
|
||||||
|
|
||||||
async def async_update(self, **kwargs: Any) -> None:
|
async def async_update(self, **kwargs: Any) -> None:
|
||||||
"""Update the configuration from a dictionary."""
|
"""Update the configuration from a dictionary."""
|
||||||
@ -3115,6 +3125,7 @@ class Config:
|
|||||||
currency=data.get("currency"),
|
currency=data.get("currency"),
|
||||||
country=data.get("country"),
|
country=data.get("country"),
|
||||||
language=data.get("language"),
|
language=data.get("language"),
|
||||||
|
radius=data["radius"],
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _async_store(self) -> None:
|
async def _async_store(self) -> None:
|
||||||
@ -3133,6 +3144,7 @@ class Config:
|
|||||||
"currency": self.currency,
|
"currency": self.currency,
|
||||||
"country": self.country,
|
"country": self.country,
|
||||||
"language": self.language,
|
"language": self.language,
|
||||||
|
"radius": self.radius,
|
||||||
}
|
}
|
||||||
await self._store.async_save(data)
|
await self._store.async_save(data)
|
||||||
|
|
||||||
@ -3162,6 +3174,10 @@ class Config:
|
|||||||
old_data: dict[str, Any],
|
old_data: dict[str, Any],
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Migrate to the new version."""
|
"""Migrate to the new version."""
|
||||||
|
|
||||||
|
# pylint: disable-next=import-outside-toplevel
|
||||||
|
from .components.zone import DEFAULT_RADIUS
|
||||||
|
|
||||||
data = old_data
|
data = old_data
|
||||||
if old_major_version == 1 and old_minor_version < 2:
|
if old_major_version == 1 and old_minor_version < 2:
|
||||||
# In 1.2, we remove support for "imperial", replaced by "us_customary"
|
# In 1.2, we remove support for "imperial", replaced by "us_customary"
|
||||||
@ -3198,6 +3214,9 @@ class Config:
|
|||||||
# pylint: disable-next=broad-except
|
# pylint: disable-next=broad-except
|
||||||
except Exception:
|
except Exception:
|
||||||
_LOGGER.exception("Unexpected error during core config migration")
|
_LOGGER.exception("Unexpected error during core config migration")
|
||||||
|
if old_major_version == 1 and old_minor_version < 4:
|
||||||
|
# In 1.4, we add the key "radius", initialize it with the default.
|
||||||
|
data.setdefault("radius", DEFAULT_RADIUS)
|
||||||
|
|
||||||
if old_major_version > 1:
|
if old_major_version > 1:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -120,6 +120,7 @@ async def test_websocket_core_update(hass: HomeAssistant, client) -> None:
|
|||||||
assert hass.config.currency == "EUR"
|
assert hass.config.currency == "EUR"
|
||||||
assert hass.config.country != "SE"
|
assert hass.config.country != "SE"
|
||||||
assert hass.config.language != "sv"
|
assert hass.config.language != "sv"
|
||||||
|
assert hass.config.radius != 150
|
||||||
|
|
||||||
with (
|
with (
|
||||||
patch("homeassistant.util.dt.set_default_time_zone") as mock_set_tz,
|
patch("homeassistant.util.dt.set_default_time_zone") as mock_set_tz,
|
||||||
@ -142,6 +143,7 @@ async def test_websocket_core_update(hass: HomeAssistant, client) -> None:
|
|||||||
"currency": "USD",
|
"currency": "USD",
|
||||||
"country": "SE",
|
"country": "SE",
|
||||||
"language": "sv",
|
"language": "sv",
|
||||||
|
"radius": 150,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -162,6 +164,7 @@ async def test_websocket_core_update(hass: HomeAssistant, client) -> None:
|
|||||||
assert hass.config.currency == "USD"
|
assert hass.config.currency == "USD"
|
||||||
assert hass.config.country == "SE"
|
assert hass.config.country == "SE"
|
||||||
assert hass.config.language == "sv"
|
assert hass.config.language == "sv"
|
||||||
|
assert hass.config.radius == 150
|
||||||
|
|
||||||
assert len(mock_set_tz.mock_calls) == 1
|
assert len(mock_set_tz.mock_calls) == 1
|
||||||
assert mock_set_tz.mock_calls[0][1][0] == dt_util.get_time_zone("America/New_York")
|
assert mock_set_tz.mock_calls[0][1][0] == dt_util.get_time_zone("America/New_York")
|
||||||
|
@ -522,6 +522,7 @@ def test_core_config_schema() -> None:
|
|||||||
{"customize": {"entity_id": []}},
|
{"customize": {"entity_id": []}},
|
||||||
{"country": "xx"},
|
{"country": "xx"},
|
||||||
{"language": "xx"},
|
{"language": "xx"},
|
||||||
|
{"radius": -10},
|
||||||
):
|
):
|
||||||
with pytest.raises(MultipleInvalid):
|
with pytest.raises(MultipleInvalid):
|
||||||
config_util.CORE_CONFIG_SCHEMA(value)
|
config_util.CORE_CONFIG_SCHEMA(value)
|
||||||
@ -538,6 +539,7 @@ def test_core_config_schema() -> None:
|
|||||||
"customize": {"sensor.temperature": {"hidden": True}},
|
"customize": {"sensor.temperature": {"hidden": True}},
|
||||||
"country": "SE",
|
"country": "SE",
|
||||||
"language": "sv",
|
"language": "sv",
|
||||||
|
"radius": "10",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -709,10 +711,11 @@ async def test_loading_configuration_from_storage(
|
|||||||
"currency": "EUR",
|
"currency": "EUR",
|
||||||
"country": "SE",
|
"country": "SE",
|
||||||
"language": "sv",
|
"language": "sv",
|
||||||
|
"radius": 150,
|
||||||
},
|
},
|
||||||
"key": "core.config",
|
"key": "core.config",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"minor_version": 3,
|
"minor_version": 4,
|
||||||
}
|
}
|
||||||
await config_util.async_process_ha_core_config(
|
await config_util.async_process_ha_core_config(
|
||||||
hass, {"allowlist_external_dirs": "/etc"}
|
hass, {"allowlist_external_dirs": "/etc"}
|
||||||
@ -729,6 +732,7 @@ async def test_loading_configuration_from_storage(
|
|||||||
assert hass.config.currency == "EUR"
|
assert hass.config.currency == "EUR"
|
||||||
assert hass.config.country == "SE"
|
assert hass.config.country == "SE"
|
||||||
assert hass.config.language == "sv"
|
assert hass.config.language == "sv"
|
||||||
|
assert hass.config.radius == 150
|
||||||
assert len(hass.config.allowlist_external_dirs) == 3
|
assert len(hass.config.allowlist_external_dirs) == 3
|
||||||
assert "/etc" in hass.config.allowlist_external_dirs
|
assert "/etc" in hass.config.allowlist_external_dirs
|
||||||
assert hass.config.config_source is ConfigSource.STORAGE
|
assert hass.config.config_source is ConfigSource.STORAGE
|
||||||
@ -798,15 +802,19 @@ async def test_migration_and_updating_configuration(
|
|||||||
expected_new_core_data["data"]["currency"] = "USD"
|
expected_new_core_data["data"]["currency"] = "USD"
|
||||||
# 1.1 -> 1.2 store migration with migrated unit system
|
# 1.1 -> 1.2 store migration with migrated unit system
|
||||||
expected_new_core_data["data"]["unit_system_v2"] = "us_customary"
|
expected_new_core_data["data"]["unit_system_v2"] = "us_customary"
|
||||||
expected_new_core_data["minor_version"] = 3
|
# 1.1 -> 1.3 defaults for country and language
|
||||||
# defaults for country and language
|
|
||||||
expected_new_core_data["data"]["country"] = None
|
expected_new_core_data["data"]["country"] = None
|
||||||
expected_new_core_data["data"]["language"] = "en"
|
expected_new_core_data["data"]["language"] = "en"
|
||||||
|
# 1.1 -> 1.4 defaults for zone radius
|
||||||
|
expected_new_core_data["data"]["radius"] = 100
|
||||||
|
# Bumped minor version
|
||||||
|
expected_new_core_data["minor_version"] = 4
|
||||||
assert hass_storage["core.config"] == expected_new_core_data
|
assert hass_storage["core.config"] == expected_new_core_data
|
||||||
assert hass.config.latitude == 50
|
assert hass.config.latitude == 50
|
||||||
assert hass.config.currency == "USD"
|
assert hass.config.currency == "USD"
|
||||||
assert hass.config.country is None
|
assert hass.config.country is None
|
||||||
assert hass.config.language == "en"
|
assert hass.config.language == "en"
|
||||||
|
assert hass.config.radius == 100
|
||||||
|
|
||||||
|
|
||||||
async def test_override_stored_configuration(
|
async def test_override_stored_configuration(
|
||||||
@ -860,6 +868,7 @@ async def test_loading_configuration(hass: HomeAssistant) -> None:
|
|||||||
"currency": "EUR",
|
"currency": "EUR",
|
||||||
"country": "SE",
|
"country": "SE",
|
||||||
"language": "sv",
|
"language": "sv",
|
||||||
|
"radius": 150,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -881,6 +890,7 @@ async def test_loading_configuration(hass: HomeAssistant) -> None:
|
|||||||
assert hass.config.currency == "EUR"
|
assert hass.config.currency == "EUR"
|
||||||
assert hass.config.country == "SE"
|
assert hass.config.country == "SE"
|
||||||
assert hass.config.language == "sv"
|
assert hass.config.language == "sv"
|
||||||
|
assert hass.config.radius == 150
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
@ -1936,6 +1936,7 @@ async def test_config_defaults() -> None:
|
|||||||
assert config.currency == "EUR"
|
assert config.currency == "EUR"
|
||||||
assert config.country is None
|
assert config.country is None
|
||||||
assert config.language == "en"
|
assert config.language == "en"
|
||||||
|
assert config.radius == 100
|
||||||
|
|
||||||
|
|
||||||
async def test_config_path_with_file() -> None:
|
async def test_config_path_with_file() -> None:
|
||||||
@ -1983,6 +1984,7 @@ async def test_config_as_dict() -> None:
|
|||||||
"language": "en",
|
"language": "en",
|
||||||
"safe_mode": False,
|
"safe_mode": False,
|
||||||
"debug": False,
|
"debug": False,
|
||||||
|
"radius": 100,
|
||||||
}
|
}
|
||||||
|
|
||||||
assert expected == config.as_dict()
|
assert expected == config.as_dict()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user