Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
 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
Ejemplo n.º 4
0
            "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)}"