Hi, what region should I set if I’m from Chile / South America?
Or is it not supported?
Hi, what region should I set if I’m from Chile / South America?
Or is it not supported?
Have you tried NA? I didn’t write the WazeRouteCalculator which is a resource of this component. It looks like it only supports 3 regions; US, IL, and EU. The guy who made WazeRouteCalculator added NA which under the hood just flips it to US. US is basically NA. I may be able to update that calculator, but I don’t have control over it. I’ll see what can be done, but for the time being, try using NA or US. Let me know if that works.
Thanks for your reply.
I just tried that but I get the following error:
I tried it placing the GPS coordinates in origin and destination and i tried also putting the address of each one too. But I get the same error.
I’ll have to research it. I know exactly where to change it in the script. I was unable to find the correct code to supply the waze api for south america. They have to have it, I just need to find it. I’ll have some time next week to look around, but I may have to contact waze customer support for the info.
Seems like this PR did not make it to 0.68
Do you have an update since the original that did not load on startup @petro ?
Please add a link if that’s something you recommend until the official waze sensor get’s this feature.
No, but i’ll start working on it. I was hoping it would make the update before I made changes. Looks like that won’t happen. I’ll update over the next few days
Hi there’s, any news.
Plus - a question:
You said polling happens every 5 minutes, but in the DB I see an update saved every 10 minutes - any idea why?
How can I control the time between polls in the config / code?
Thanks!
Yes, polling happens about every 5 minutes. If you want to change the interval, update this line of code:
SCAN_INTERVAL = timedelta(minutes=5)
It’s towards the top of the file.
I’ll let you know when I have an update. Haven’t had a chance to look at it yet.
I’m wondering does this component supports other countries such as those in Asia?
It does not. I’ve been looking for a list of regions that the API supports but I cannot find one. I’m pretty sure that waze app on phones works in Asia. Once I find the region list, I can attempt to add support for the other area’s to the WazeRouteCalculator.py files.
Give this a whirl and let me know if it updates immediately. The interval is still 5 minutes, i’m trying to have it match the google component.
"""
Support for Waze travel time sensor.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.waze_travel_time/
"""
from datetime import timedelta
import logging
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import (
ATTR_ATTRIBUTION, CONF_NAME, CONF_REGION, EVENT_HOMEASSISTANT_START,
ATTR_LATITUDE, ATTR_LONGITUDE)
import homeassistant.helpers.config_validation as cv
import homeassistant.helpers.location as location
from homeassistant.helpers.entity import Entity
from homeassistant.util import Throttle
REQUIREMENTS = ['WazeRouteCalculator==0.5']
_LOGGER = logging.getLogger(__name__)
ATTR_DURATION = 'duration'
ATTR_DISTANCE = 'distance'
ATTR_ROUTE = 'route'
CONF_ATTRIBUTION = "Data provided by the Waze.com"
CONF_DESTINATION = 'destination'
CONF_ORIGIN = 'origin'
DEFAULT_NAME = 'Waze Travel Time'
ICON = 'mdi:car'
REGIONS = ['US', 'NA', 'EU', 'IL']
SCAN_INTERVAL = timedelta(minutes=5)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_ORIGIN): cv.string,
vol.Required(CONF_DESTINATION): cv.string,
vol.Required(CONF_REGION): vol.In(REGIONS),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
})
TRACKABLE_DOMAINS = ['device_tracker', 'sensor', 'zone']
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Waze travel time sensor platform."""
def run_setup(event):
destination = config.get(CONF_DESTINATION)
name = config.get(CONF_NAME)
origin = config.get(CONF_ORIGIN)
region = config.get(CONF_REGION)
sensor = WazeTravelTime(hass, name, origin, destination, region)
add_devices([sensor])
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, run_setup)
class WazeTravelTime(Entity):
"""Representation of a Waze travel time sensor."""
def __init__(self, hass, name, origin, destination, region):
"""Initialize the Waze travel time sensor."""
self._hass = hass
self._name = name
self._region = region
self._state = None
if origin.split('.', 1)[0] in TRACKABLE_DOMAINS:
self._origin_entity_id = origin
else:
self._origin = origin
if destination.split('.', 1)[0] in TRACKABLE_DOMAINS:
self._destination_entity_id = destination
else:
self._destination = destination
self._update()
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def state(self):
"""Return the state of the sensor."""
if self._state is None:
return None
if 'duration' in self._state:
return round(self._state['duration'])
return None
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return 'min'
@property
def icon(self):
"""Icon to use in the frontend, if any."""
return ICON
@property
def device_state_attributes(self):
"""Return the state attributes of the last update."""
if self._state is None:
return None
res = {ATTR_ATTRIBUTION: CONF_ATTRIBUTION}
if 'duration' in self._state:
res[ATTR_DURATION] = self._state['duration']
if 'distance' in self._state:
res[ATTR_DISTANCE] = self._state['distance']
if 'route' in self._state:
res[ATTR_ROUTE] = self._state['route']
return res
def _get_location_from_entity(self, entity_id):
"""Get the location from the entity state or attributes."""
entity = self._hass.states.get(entity_id)
if entity is None:
_LOGGER.error("Unable to find entity %s", entity_id)
return None
# Check if the entity has location attributes (zone)
if location.has_location(entity):
return self._get_location_from_attributes(entity)
# Check if device is in a zone (device_tracker)
zone_entity = self._hass.states.get("zone.%s" % entity.state)
if location.has_location(zone_entity):
_LOGGER.debug(
"%s is in %s, getting zone location",
entity_id, zone_entity.entity_id
)
return self._get_location_from_attributes(zone_entity)
# If zone was not found in state then use the state as the location
if entity_id.startswith("sensor."):
return entity.state
# When everything fails just return nothing
return None
@staticmethod
def _get_location_from_attributes(entity):
"""Get the lat/long string from an entities attributes."""
attr = entity.attributes
return "{},{}".format(attr.get(ATTR_LATITUDE), attr.get(ATTR_LONGITUDE))
def _resolve_zone(self, friendly_name):
entities = self._hass.states.all()
for entity in entities:
if entity.domain == 'zone' and entity.name == friendly_name:
return self._get_location_from_attributes(entity)
return friendly_name
@Throttle(SCAN_INTERVAL)
def update(self):
self._update()
def _update(self):
"""Fetch new state data for the sensor."""
import WazeRouteCalculator
if hasattr(self, '_origin_entity_id'):
self._origin = self._get_location_from_entity(
self._origin_entity_id
)
if hasattr(self, '_destination_entity_id'):
self._destination = self._get_location_from_entity(
self._destination_entity_id
)
self._destination = self._resolve_zone(self._destination)
self._origin = self._resolve_zone(self._origin)
if self._destination is not None and self._origin is not None:
try:
params = WazeRouteCalculator.WazeRouteCalculator(
self._origin, self._destination, self._region)
routes = params.calc_all_routes_info()
route = next(iter(routes))
duration, distance = routes[route]
route = bytes(route, 'ISO-8859-1').decode('UTF-8')
self._state = {
'duration': duration,
'distance': distance,
'route': route}
except WazeRouteCalculator.WRCError as exp:
_LOGGER.error("Error on retrieving data: %s", exp)
return
except KeyError:
_LOGGER.error("Error retrieving data from server")
return
I have 4 Waze sensors setup
with the new code I see one updating immediately after HA launch complete (random - not the same sensor on each load) ** for the rest I see 3 * the following error in the log** (one per sensor):
2018-05-04 09:15:57 ERROR (MainThread) [homeassistant.core] Error doing job: Future exception was never retrieved
Traceback (most recent call last):
File "/usr/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "/config/custom_components/sensor/waze_travel_time.py", line 59, in run_setup
sensor = WazeTravelTime(hass, name, origin, destination, region)
File "/config/custom_components/sensor/waze_travel_time.py", line 85, in __init__
self._update()
File "/config/custom_components/sensor/waze_travel_time.py", line 194, in _update
routes = params.calc_all_routes_info()
File "/usr/lib/python3.6/site-packages/WazeRouteCalculator/WazeRouteCalculator.py", line 142, in calc_all_routes_info
routes = self.get_route(npaths, time_delta)
File "/usr/lib/python3.6/site-packages/WazeRouteCalculator/WazeRouteCalculator.py", line 92, in get_route
response_json = response.json()
File "/usr/lib/python3.6/site-packages/requests/models.py", line 892, in json
return complexjson.loads(self.text, **kwargs)
File "/usr/lib/python3.6/site-packages/simplejson/__init__.py", line 518, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3.6/site-packages/simplejson/decoder.py", line 370, in decode
obj, end = self.raw_decode(s)
File "/usr/lib/python3.6/site-packages/simplejson/decoder.py", line 400, in raw_decode
return self.scan_once(s, idx=_w(s, idx).end())
simplejson.errors.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Okay. That’s odd because I didn’t change anything related to the calculator. I’ll have to see what the initial update is doing because it seems like that is causing the problem. Maybe during startup the devices aren’t initialized yet. I’ll take a look tonight.
what 4 waze sensors do you have setup? I’ve been running this with a 1 minute update (and it loads on startup) without errors for 3 days using 4 sensors: lat/long, device_trackers, zones, and a sensor. Can you link your configuration so I can mimic it?
Nothing special really…
sensor:
- platform: waze_travel_time
name: "iphone to work"
origin: device_tracker.iphone
destination: zone.work
region: 'IL'
- platform: waze_travel_time
name: "iphone to home"
origin: device_tracker.iphone
destination: zone.home
region: 'IL'
#
- platform: waze_travel_time
name: "Home to work"
origin: zone.home
destination: zone.work
region: 'IL'
- platform: waze_travel_time
name: "Work to home"
origin: zone.work
destination: zone.home
region: 'IL'
I’m currently using this Waze component in Hass.io. Would it be possible to get the “avoid toll roads” option as a future configuration variable? Thanks!
I haven’t tried this specific version of the code, but for my purpose there is still an issue with this code. If i use this version it is not defined which route is selected, and for my routes specifically it’s neither the fastest nor the shortest.
I’m unable to make a full pull request but i suggest this change to make it the fastest route by default. This means replacing:
route = next(iter(routes))
by:
route=sorted(routes,key=(lambda key: routes[key][0]))[0]
I’ve tried this in a slightly different version of the code, it gives the fastest route by default. The reason I’ve put this in the forum is that it’s nowhere written the fastest route is selected.
The Waze API claims it’s orders them via the fastest route. I’ve never verified that. Either way, implementing that line won’t be hard. The PR still hasn’t gone through to get into the official build so for the time being, just use your own custom component. I’m going to try to see why the PR isn’t going through and I can ninja this fix in.
Thanx for the reply.
I cannot verify the statement regarding the ordering but the used python lib (WazeRouteCalculator) provides a standard dict, which to my knowledge is not sorted.
I’d happily use my own component until these changes make there way in the official build. Until then keep up the good work.
I see this is included now in 0.70 but the docs don’t mention that the origin and destination can be a zone or a device tracker. Does the included component work in exactly the same way as the custom one?