def find_coordinates( hass: HomeAssistantType, entity_id: str, recursion_history: Optional[list] = None) -> Optional[str]: """Find the gps coordinates of the entity in the form of '90.000,180.000'.""" entity_state = hass.states.get(entity_id) if entity_state is None: _LOGGER.error("Unable to find entity %s", entity_id) return None # Check if the entity has location attributes if has_location(entity_state): return _get_location_from_attributes(entity_state) # Check if device is in a zone zone_entity = hass.states.get(f"zone.{entity_state.state}") if has_location(zone_entity): # type: ignore _LOGGER.debug( "%s is in %s, getting zone location", entity_id, zone_entity.entity_id # type: ignore ) return _get_location_from_attributes(zone_entity) # type: ignore # Resolve nested entity if recursion_history is None: recursion_history = [] recursion_history.append(entity_id) 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 _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) # Check if state is valid coordinate set try: # Import here, not at top-level to avoid circular import import homeassistant.helpers.config_validation as cv # pylint: disable=import-outside-toplevel cv.gps(entity_state.state.split(",")) except vol.Invalid: _LOGGER.error( "Entity %s does not contain a location and does not point at an entity that does: %s", entity_id, entity_state.state, ) return None else: return entity_state.state
def _prepare_parameters( self, ) -> tuple[list[str], list[str], str | None, str | None]: """Prepare parameters for the HERE api.""" if self.config.origin_entity_id is not None: origin = find_coordinates(self.hass, self.config.origin_entity_id) else: origin = self.config.origin if self.config.destination_entity_id is not None: destination = find_coordinates(self.hass, self.config.destination_entity_id) else: destination = self.config.destination if destination is None: raise InvalidCoordinatesException("Destination must be configured") try: here_formatted_destination = destination.split(",") vol.Schema(cv.gps(here_formatted_destination)) except (vol.Invalid) as ex: raise InvalidCoordinatesException( f"{destination} are not valid coordinates") from ex if origin is None: raise InvalidCoordinatesException("Origin must be configured") try: here_formatted_origin = origin.split(",") vol.Schema(cv.gps(here_formatted_origin)) except (AttributeError, vol.Invalid) as ex: raise InvalidCoordinatesException( f"{origin} are not valid coordinates") from ex arrival: str | None = None departure: str | None = None if self.config.arrival is not None: arrival = convert_time_to_isodate(self.config.arrival) if self.config.departure is not None: departure = convert_time_to_isodate(self.config.departure) if arrival is None and departure is None: departure = "now" return (here_formatted_origin, here_formatted_destination, arrival, departure)
def _from_entity_id(entity_id: str) -> list[str]: coordinates = find_coordinates(self.hass, entity_id) if coordinates is None: raise InvalidCoordinatesException( f"No coordinatnes found for {entity_id}") try: here_formatted_coordinates = coordinates.split(",") vol.Schema(cv.gps(here_formatted_coordinates)) except (AttributeError, vol.Invalid) as ex: raise InvalidCoordinatesException( f"{coordinates} are not valid coordinates") from ex return here_formatted_coordinates
"Circular reference detected while trying to find coordinates of an entity. The state of %s has already been checked", entity_state.state, ) return 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) # Check if state is valid coordinate set try: # Import here, not at top-level to avoid circular import import homeassistant.helpers.config_validation as cv # pylint: disable=import-outside-toplevel cv.gps(entity_state.state.split(",")) except vol.Invalid: _LOGGER.error( "Entity %s does not contain a location and does not point at an entity that does: %s", entity_id, entity_state.state, ) return None else: return entity_state.state def _get_location_from_attributes(entity_state: State) -> str: """Get the lat/long string from an entities attributes.""" attr = entity_state.attributes return f"{attr.get(ATTR_LATITUDE)},{attr.get(ATTR_LONGITUDE)}"