Doesn’t look like the fix made it in 0.88.0
I ended up for now just modifying the wazeroutecalculator.py changef line 130 to this
route_distance = (distance / 1000) * 0.621371
It’s hackish, and will be overwritten on the next update, but for now it’s working.
make it a custom component with that change and it won’t be overwritten. I plan on going through the component sometime soon. Trying to set up a proper dev environment. Hasn’t been going great.
Quick question, How would you make this a custom component under the new naming convention? wazeroutecalculator.py is a dependency of the waze_travel_time.py under sensors, right? I dont really fully understand the file and system structure quite yet. I kind of get the sensors and all the .py under there,but not as much when it comes to dependencies.
here are the upcoming changes to the component
view the file in raw format. Copy the contents.
Go to your config folder. Create the following path
custom_components\sensor
inside that folder create a file named waze_travel_time.py
paste the raw contents into that file.
The component now pays attention to your system units and converts the numbers over (imperial = miles, metric = km). It also turns that stupid reoccurring error into a warning. So now you can suppress the warning.
Looks like the following fix was added to 0.89.0, but after upgrading, I get the errors below.
Fix "Unable to find entity" at Waze component ([@VirtualL](https://github.com/VirtualL) - [#21087](https://github.com/home-assistant/home-assistant/pull/21087)) ([sensor.waze_travel_time docs](https://www.home-assistant.io/components/sensor.waze_travel_time/))
2019-03-07 08:40:16 ERROR (Thread-4) [homeassistant.components.sensor.waze_travel_time] Error on retrieving data: empty response
2019-03-07 08:40:16 ERROR (Thread-12) [homeassistant.components.sensor.waze_travel_time] Error on retrieving data: empty response
Yes this means waze api didn’t respond. This is unavoidable as I have no control over the waze api returning errors. The next build will switch that to a warning.
Awesome, thanks.
hopefully it is just a waze api issue, but today i upgraded to 89 and also instantly got that error as above
The waze api that the component uses is an unofficial API. The likelihood of this getting better is low.
Ok after further investigation, it appears as if there is an issue in WazeRouteCalculator. A pr has been created. If anyone has the time, please check out the PR on WazeRouteCalculator. It should fix all these empty response errors in the logs.
Disclaimer
This error is OUTSIDE HA. I have no control over the fix. Please comment on the PR, even test out the PR if you can. I have no affiliation with WazeRouteCalculator, hopefully the dev will accept my PR. It fixed issues in 11 sensors that I use. I went from 700/1320+ plus errors per hour down to zero 4/1320 per hour. This was with a polling of twice a minute. In theory it should reduce issues to zero over a 24 hour period polling every 5 minutes (Normal settings in HA).
HI and thanks for your efforts on this.
I’d be gad to test and try, to see what happens.
Can we add this as a custom_component? If so, how exactly.
If you use the following code as /config/custom_components/waze_travel_time/sensor.py
, this will test and execute the PR as well as use the new configuration for waze.
disclaimer: This should only be used testing. Do not use it as your custom 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 re
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, CONF_UNIT_SYSTEM_METRIC,
CONF_UNIT_SYSTEM_IMPERIAL)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers import location
from homeassistant.helpers.entity import Entity
REQUIREMENTS = ['https://github.com/kovacsbalu/WazeRouteCalculator/archive/04e9e9485ce61465dec6bebff1d9e987154abe6b.zip#WazeRouteCalculator==0.9.1b0']
_LOGGER = logging.getLogger(__name__)
ATTR_DURATION = 'duration'
ATTR_DISTANCE = 'distance'
ATTR_ROUTE = 'route'
ATTRIBUTION = "Powered by Waze"
CONF_DESTINATION = 'destination'
CONF_ORIGIN = 'origin'
CONF_INCL_FILTER = 'incl_filter'
CONF_EXCL_FILTER = 'excl_filter'
CONF_REALTIME = 'realtime'
CONF_UNITS = 'units'
CONF_VEHICLE_TYPE = 'vehicle_type'
DEFAULT_NAME = 'Waze Travel Time'
DEFAULT_REALTIME = False
DEFAULT_VEHICLE_TYPE = 'car'
ICON = 'mdi:car'
UNITS = [CONF_UNIT_SYSTEM_METRIC, CONF_UNIT_SYSTEM_IMPERIAL]
REGIONS = ['US', 'NA', 'EU', 'IL', 'AU']
VEHICLE_TYPES = ['car', 'taxi', 'motorcycle']
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,
vol.Optional(CONF_INCL_FILTER): cv.string,
vol.Optional(CONF_EXCL_FILTER): cv.string,
vol.Optional(CONF_REALTIME, default=DEFAULT_REALTIME): cv.boolean,
vol.Optional(CONF_VEHICLE_TYPE,
default=DEFAULT_VEHICLE_TYPE): vol.In(VEHICLE_TYPES),
vol.Optional(CONF_UNITS): vol.In(UNITS)
})
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Waze travel time sensor platform."""
destination = config.get(CONF_DESTINATION)
name = config.get(CONF_NAME)
origin = config.get(CONF_ORIGIN)
region = config.get(CONF_REGION)
incl_filter = config.get(CONF_INCL_FILTER)
excl_filter = config.get(CONF_EXCL_FILTER)
realtime = config.get(CONF_REALTIME)
vehicle_type = config.get(CONF_VEHICLE_TYPE)
units = config.get(CONF_UNITS)
if units is None:
units = hass.config.units.name
data = WazeTravelTimeData(None, None, region, incl_filter,
excl_filter, realtime, units,
vehicle_type)
sensor = WazeTravelTime(name, origin, destination, data)
add_entities([sensor])
# Wait until start event is sent to load this component.
hass.bus.listen_once(
EVENT_HOMEASSISTANT_START, lambda _: sensor.update())
def _get_location_from_attributes(state):
"""Get the lat/long string from an states attributes."""
attr = state.attributes
return '{},{}'.format(attr.get(ATTR_LATITUDE), attr.get(ATTR_LONGITUDE))
class WazeTravelTime(Entity):
"""Representation of a Waze travel time sensor."""
def __init__(self, name, origin, destination, waze_data):
"""Initialize the Waze travel time sensor."""
self._name = name
self._waze_data = waze_data
self._state = None
self._origin_entity_id = None
self._destination_entity_id = None
# Attempt to find entity_id without finding address with period.
pattern = "(?<![a-zA-Z0-9 ])[a-z_]+[.][a-zA-Z0-9_]+"
if re.fullmatch(pattern, origin):
_LOGGER.debug("Found origin source entity %s", origin)
self._origin_entity_id = origin
else:
self._waze_data.origin = origin
if re.fullmatch(pattern, destination):
_LOGGER.debug("Found destination source entity %s", destination)
self._destination_entity_id = destination
else:
self._waze_data.destination = destination
@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._waze_data.duration is not None:
return round(self._waze_data.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._waze_data.duration is None:
return None
res = {ATTR_ATTRIBUTION: ATTRIBUTION}
res[ATTR_DURATION] = self._waze_data.duration
res[ATTR_DISTANCE] = self._waze_data.distance
res[ATTR_ROUTE] = self._waze_data.route
return res
def _get_location_from_entity(self, entity_id):
"""Get the location from the entity_id."""
state = self.hass.states.get(entity_id)
if state is None:
_LOGGER.error("Unable to find entity %s", entity_id)
return None
# Check if the entity has location attributes.
if location.has_location(state):
_LOGGER.debug("Getting %s location", entity_id)
return _get_location_from_attributes(state)
# Check if device is inside a zone.
zone_state = self.hass.states.get('zone.{}'.format(state.state))
if location.has_location(zone_state):
_LOGGER.debug(
"%s is in %s, getting zone location",
entity_id, zone_state.entity_id
)
return _get_location_from_attributes(zone_state)
# If zone was not found in state then use the state as the location.
if entity_id.startswith('sensor.'):
return state.state
# When everything fails just return nothing.
return None
def _resolve_zone(self, friendly_name):
"""Get a lat/long from a zones friendly_name."""
states = self.hass.states.all()
for state in states:
if state.domain == 'zone' and state.name == friendly_name:
return _get_location_from_attributes(state)
return friendly_name
def update(self):
"""Fetch new state data for the sensor."""
_LOGGER.debug("Fetching Route for %s", self._name)
# Get origin latitude and longitude from entity_id.
if self._origin_entity_id is not None:
self._waze_data.origin = self._get_location_from_entity(
self._origin_entity_id)
# Get destination latitude and longitude from entity_id.
if self._destination_entity_id is not None:
self._waze_data.destination = self._get_location_from_entity(
self._destination_entity_id)
# Get origin from zone name.
self._waze_data.origin = self._resolve_zone(
self._waze_data.origin)
# Get desination from zone name.
self._waze_data.destination = self._resolve_zone(
self._waze_data.destination)
self._waze_data.update()
class WazeTravelTimeData():
"""WazeTravelTime Data object."""
def __init__(self, origin, destination, region, include, exclude,
realtime, units, vehicle_type):
"""Set up WazeRouteCalculator."""
import WazeRouteCalculator
self._calc = WazeRouteCalculator
self.origin = origin
self.destination = destination
self.region = region
self.include = include
self.exclude = exclude
self.realtime = realtime
self.units = units
self.duration = None
self.distance = None
self.route = None
# Currently WazeRouteCalc only supports PRIVATE, TAXI, MOTORCYCLE.
if vehicle_type.upper() == 'CAR':
# Empty means PRIVATE for waze which translates to car.
self.vehicle_type = ''
else:
self.vehicle_type = vehicle_type.upper()
def update(self):
"""Update WazeRouteCalculator Sensor."""
if self.origin is not None and self.destination is not None:
try:
params = self._calc.WazeRouteCalculator(
self.origin, self.destination, self.region,
self.vehicle_type, log_lvl=logging.DEBUG)
routes = params.calc_all_routes_info(real_time=self.realtime)
if self.include is not None:
routes = {k: v for k, v in routes.items() if
self.include.lower() in k.lower()}
if self.exclude is not None:
routes = {k: v for k, v in routes.items() if
self.exclude.lower() in k.lower()}
route = sorted(routes, key=(lambda key: routes[key][0]))[0]
self.duration, distance = routes[route]
if self.units == CONF_UNIT_SYSTEM_IMPERIAL:
# Convert to miles.
self.distance = distance / 1.609
else:
self.distance = distance
self.route = route
except self._calc.WRCError as exp:
_LOGGER.warning("Error on retrieving data: %s", exp)
return
except KeyError:
_LOGGER.error("Error retrieving data from server")
return
thanks. I am still on 84.3 here though, so I should be using the previous settings for custom_components… I think that would imply I have to use this as waze_travel_time.py, in /config/custom_components/sensor/ ?
Or wouldn’t that be possible, because of specifics in the sensor.py file.
Yes,
/config/custom_components/sensor/waze_travel_time.py
can report: not a single startup error left.
Have a feeling the system has some lag now though, and many of my waze sensors were rather late in the frontend after startup. They are all there now, so maybe the new sensor had to be initialized somehow? we’ll see what happens.
There hasn’t been a fix for the startup warnings. Only the empty response during run. I’m not entirely convinced that the test I posted is using the PR version yet.
On my dev version, this is my current logs for the past 2 hours:
2019-03-10 11:14:26 WARNING (SyncWorker_12) [homeassistant.components.sensor.waze_travel_time] Error on retrieving data: Empty Response
2019-03-10 11:20:30 WARNING (SyncWorker_18) [homeassistant.components.sensor.waze_travel_time] Error on retrieving data: Empty Response
2019-03-10 11:20:30 WARNING (SyncWorker_0) [homeassistant.components.sensor.waze_travel_time] Error on retrieving data: Empty Response
2019-03-10 11:21:31 WARNING (SyncWorker_2) [homeassistant.components.sensor.waze_travel_time] Error on retrieving data: Empty Response
and these errors coincide with me attempting to use the updates in my non-dev home-asstant that runs house.
well what can I say, Ive always had many errors during startup an now see this:
which means I don’t have errors at startup, and no errors during runtime.
Empty response is unknown to me, I have never seen that (I think)
Interesting. Well, don’t bother using this then. They are frequent in new versions.
deleted your CC and the errors are back again:
giving it another shot now to see if I tested correctly
update
can confirm again: using the testing CC, all my startup errors are gone. Not a single waze reference in the log. Note: I havent set logging to debug, if that might be necessary for your Empty repose error, id have to change that and start once more?