-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Customise destination resolution and return the source of the resolut…
…ion for use in the UI
- Loading branch information
1 parent
5cb9922
commit 429cb1b
Showing
5 changed files
with
93 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,3 +24,4 @@ repos: | |
- --pretty | ||
- --show-error-codes | ||
- --ignore-missing-imports | ||
- --python-version=3.12 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,81 @@ | ||
"""Helpers for handling location entities.""" | ||
|
||
import logging | ||
|
||
from homeassistant.const import ATTR_LATITUDE, ATTR_LONGITUDE | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers import location | ||
|
||
_LOGGER: logging.Logger = logging.getLogger(__package__) | ||
|
||
|
||
def get_location_entity(hass, entity_id): | ||
"""Get the location from the entity state or attributes.""" | ||
|
||
if (entity := hass.states.get(entity_id)) is None: | ||
_LOGGER.error("Locating %s: Unable to find", entity_id) | ||
raise ValueError("Invalid entity ID") | ||
|
||
# Check if device is in a zone | ||
if not entity_id.startswith("zone"): | ||
if (zone_entity := hass.states.get(f"zone.{entity.state}")) is not None: | ||
if location.has_location(zone_entity): | ||
_LOGGER.debug( | ||
"Locating %s: in %s, getting zone location", | ||
entity_id, | ||
zone_entity.entity_id, | ||
) | ||
return zone_entity | ||
def find_coordinates( | ||
hass: HomeAssistant, name: str, recursion_history: list | None = None | ||
) -> tuple[str | None, str | None]: | ||
"""Try to resolve the a location from a supplied name or entity_id. | ||
_LOGGER.debug( | ||
"Locating %s: in %s, no zone location", | ||
entity_id, | ||
zone_entity.entity_id, | ||
) | ||
else: | ||
_LOGGER.debug("Locating %s: [zone '%s' not found]", entity_id, entity.state) | ||
Will recursively resolve an entity if pointed to by the state of the supplied | ||
entity. | ||
# Check if the entity has location attributes | ||
if location.has_location(entity): | ||
_LOGGER.debug("Locating %s: from attributes", entity_id) | ||
return entity | ||
Returns coordinates in the form of '90.000,180.000', an address or | ||
the state of the last resolved entity. | ||
""" | ||
# Check if a friendly name of a zone was supplied | ||
if (zone_coords := location.resolve_zone(hass, name)) is not None: | ||
_LOGGER.debug( | ||
"%s, getting zone location", | ||
name, | ||
) | ||
return (name, zone_coords) | ||
|
||
# When everything fails just return nothing | ||
return None | ||
# Check if an entity_id was supplied. | ||
if (entity_state := hass.states.get(name)) is None: | ||
_LOGGER.debug("Unable to find entity %s", name) | ||
return None, name | ||
|
||
# Check if entity_state is a zone | ||
zone_entity = hass.states.get(f"zone.{entity_state.state}") | ||
if location.has_location(zone_entity): # type: ignore[arg-type] | ||
_LOGGER.debug( | ||
"%s is in %s, getting zone location", | ||
name, | ||
zone_entity.entity_id, # type: ignore[union-attr] | ||
) | ||
return zone_entity.name, location._get_location_from_attributes(zone_entity) # type: ignore[arg-type] | ||
|
||
def get_location_from_attributes(entity): | ||
"""Get the lat/long string from an entities attributes.""" | ||
attr = entity.attributes | ||
return (float(attr.get(ATTR_LATITUDE)), float(attr.get(ATTR_LONGITUDE))) | ||
# Check if entity_state is a friendly name of a zone | ||
if (zone_coords := location.resolve_zone(hass, entity_state.state)) is not None: | ||
_LOGGER.debug( | ||
"%s is in %s, getting zone location", | ||
name, | ||
entity_state.state, # type: ignore[union-attr] | ||
) | ||
return entity_state.state, zone_coords | ||
|
||
# Check if the entity_state has location attributes | ||
if location.has_location(entity_state): | ||
_LOGGER.debug("%s has coords", name) | ||
return entity_state.name, location._get_location_from_attributes(entity_state) | ||
|
||
def get_location_from_entity(hass, entity_id): | ||
"""Get the location from the entity state or attributes.""" | ||
# Check if entity_state is an entity_id | ||
if recursion_history is None: | ||
recursion_history = [] | ||
recursion_history.append(name) | ||
if entity_state.state in recursion_history: | ||
_LOGGER.error( | ||
( | ||
"Circular reference detected while trying to find coordinates of an" | ||
" entity. The state of %s has already been checked" | ||
), | ||
entity_state.state, | ||
) | ||
return None, None | ||
_LOGGER.debug("Getting nested entity for state: %s", entity_state.state) | ||
nested_entity = hass.states.get(entity_state.state) | ||
if nested_entity is not None: | ||
_LOGGER.debug("Resolving nested entity_id: %s", entity_state.state) | ||
return find_coordinates(hass, entity_state.state, recursion_history) | ||
|
||
return get_location_from_attributes(get_location_entity(hass, entity_id)) | ||
# Might be an address, coordinates or anything else. | ||
# This has to be checked by the caller. | ||
_LOGGER.debug("%s is in (raw state) '%s'", name, entity_state.state) | ||
return None, entity_state.state |