1 """Support for Google travel time sensors."""
3 from __future__
import annotations
5 from datetime
import datetime, timedelta
8 from googlemaps
import Client
9 from googlemaps.distance_matrix
import distance_matrix
10 from googlemaps.exceptions
import ApiError, Timeout, TransportError
21 EVENT_HOMEASSISTANT_STARTED,
40 _LOGGER = logging.getLogger(__name__)
46 """Take a string like 08:00:00 and convert it to a unix timestamp."""
47 combined = datetime.combine(
48 dt_util.start_of_local_day(), dt_util.parse_time(timestr)
50 if combined < datetime.now():
52 return dt_util.as_timestamp(combined)
57 config_entry: ConfigEntry,
58 async_add_entities: AddEntitiesCallback,
60 """Set up a Google travel time sensor entry."""
61 api_key = config_entry.data[CONF_API_KEY]
62 origin = config_entry.data[CONF_ORIGIN]
63 destination = config_entry.data[CONF_DESTINATION]
64 name = config_entry.data.get(CONF_NAME, DEFAULT_NAME)
66 client = Client(api_key, timeout=10)
69 config_entry, name, api_key, origin, destination, client
76 """Representation of a Google travel time sensor."""
78 _attr_attribution = ATTRIBUTION
79 _attr_native_unit_of_measurement = UnitOfTime.MINUTES
80 _attr_device_class = SensorDeviceClass.DURATION
81 _attr_state_class = SensorStateClass.MEASUREMENT
83 def __init__(self, config_entry, name, api_key, origin, destination, client):
84 """Initialize the sensor."""
88 entry_type=DeviceEntryType.SERVICE,
89 identifiers={(DOMAIN, api_key)},
103 """Handle when entity is added."""
104 if self.
hasshass.state
is not CoreState.running:
105 self.
hasshass.bus.async_listen_once(
106 EVENT_HOMEASSISTANT_STARTED, self.
first_updatefirst_update
113 """Return the state of the sensor."""
114 if self.
_matrix_matrix
is None:
117 _data = self.
_matrix_matrix[
"rows"][0][
"elements"][0]
118 if "duration_in_traffic" in _data:
119 return round(_data[
"duration_in_traffic"][
"value"] / 60)
120 if "duration" in _data:
121 return round(_data[
"duration"][
"value"] / 60)
126 """Return the state attributes."""
127 if self.
_matrix_matrix
is None:
130 res = self.
_matrix_matrix.copy()
134 _data = self.
_matrix_matrix[
"rows"][0][
"elements"][0]
135 if "duration_in_traffic" in _data:
136 res[
"duration_in_traffic"] = _data[
"duration_in_traffic"][
"text"]
137 if "duration" in _data:
138 res[
"duration"] = _data[
"duration"][
"text"]
139 if "distance" in _data:
140 res[
"distance"] = _data[
"distance"][
"text"]
146 """Run the first update and write the state."""
147 await self.
hasshass.async_add_executor_job(self.
updateupdate)
151 """Get the latest data from Google."""
152 options_copy = self.
_config_entry_config_entry.options.copy()
153 dtime = options_copy.get(CONF_DEPARTURE_TIME)
154 atime = options_copy.get(CONF_ARRIVAL_TIME)
155 if dtime
is not None and ":" in dtime:
157 elif dtime
is not None:
158 options_copy[CONF_DEPARTURE_TIME] = dtime
160 options_copy[CONF_DEPARTURE_TIME] =
"now"
162 if atime
is not None and ":" in atime:
164 elif atime
is not None:
165 options_copy[CONF_ARRIVAL_TIME] = atime
171 "Getting update for origin: %s destination: %s",
177 self.
_matrix_matrix = distance_matrix(
183 except (ApiError, TransportError, Timeout)
as ex:
184 _LOGGER.error(
"Error getting travel time: %s", ex)
def first_update(self, _=None)
None async_added_to_hass(self)
def extra_state_attributes(self)
def __init__(self, config_entry, name, api_key, origin, destination, client)
None async_write_ha_state(self)
def convert_time_to_utc(timestr)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
str|None find_coordinates(HomeAssistant hass, str name, list|None recursion_history=None)