Skip to content

Commit

Permalink
iCloud3 v2.4.5 - Fix problem with Waze Route Server not returning any…
Browse files Browse the repository at this point in the history
… route data.
  • Loading branch information
gcobb321 committed Oct 6, 2021
1 parent 5d40fc9 commit 8bda2b0
Show file tree
Hide file tree
Showing 13 changed files with 224 additions and 201 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Welcome to iCloud3 v2.4!

[![CurrentVersion](https://img.shields.io/badge/Current_Version-v2.4.4-blue.svg)](https://github.com/gcobb321/icloud3)
[![Released](https://img.shields.io/badge/Released-September,_2021-blue.svg)](https://github.com/gcobb321/icloud3)
[![CurrentVersion](https://img.shields.io/badge/Current_Version-v2.4.5-blue.svg)](https://github.com/gcobb321/icloud3)
[![Released](https://img.shields.io/badge/Released-October,_2021-blue.svg)](https://github.com/gcobb321/icloud3)
[![ProjectStage](https://img.shields.io/badge/Project_Stage-General_Availability-red.svg)](https://github.com/gcobb321/icloud3)
[![Type](https://img.shields.io/badge/Type-Custom_Component-orange.svg)](https://github.com/gcobb321/icloud3)
[![HACS](https://img.shields.io/badge/HACS-Default-orange.svg)](https://github.com/gcobb321/icloud3)
Expand Down
28 changes: 17 additions & 11 deletions custom_components/icloud3/device_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@
#pylint: disable=unused-argument, unused-variable
#pylint: disable=too-many-instance-attributes, too-many-lines

VERSION = '2.4.4'
VERSION = '2.4.5'

'''
v2.4.5 (10/5/2021)
1. Fixed a problem where the Waze Route Calculator was being disabled and the distance method-calc was being used. I think the problem started when the WazeRouteCalculator module in the Home Assistant standard Python library was updated.
v2.4.4 (9/25/2021)
1. Coordindated update with pyicloud_ic3.py to support Apple iCloud url changes to access iCloud+ for location & device info for Find-my-Friends tracking method.
Expand Down Expand Up @@ -83,7 +86,7 @@

#Vailidate that Waze is available and can be used
try:
import WazeRouteCalculator
from .waze_route_calc_ic3 import WazeRouteCalculator, WRCError
WAZE_IMPORT_SUCCESSFUL = True
except ImportError:
WAZE_IMPORT_SUCCESSFUL = False
Expand Down Expand Up @@ -1072,6 +1075,7 @@ def __init__(self, hass, see, config_parameter):
self.see = see
self.polling_5_sec_loop_running = False
self.api = None
self.WazeRouteCalc = None # WazeRouteCalculator object
self.base_zone = HOME
self.verification_inprocess_flag = False
self.verification_code = None
Expand Down Expand Up @@ -1243,7 +1247,7 @@ def _start_icloud3(self):
self.track_devicename_list = ""
for devicename in self.devicename_verified:
error_log_msg = None
self._display_info_status_msg(devicename, "Verifying Device")
self._display_info_status_msg(devicename, "Verifing Device")
#Devicename config parameter is OK, now check to make sure the
#entity for device name has been setup by iosapp correctly.
#If the devicename is valid, it will be tracked
Expand Down Expand Up @@ -6190,6 +6194,8 @@ def _initialize_waze_fields(self, waze_region, waze_min_distance,
self.waze_region = waze_region.upper()
self.waze_realtime = waze_realtime

self.WazeRouteCalc = WazeRouteCalculator(self.waze_region, self.waze_realtime)

min_dist_msg = (f"{waze_min_distance} {self.unit_of_measurement}")
max_dist_msg = (f"{waze_max_distance} {self.unit_of_measurement}")

Expand Down Expand Up @@ -8223,7 +8229,8 @@ def _get_waze_data(self, devicename,
last_long, zone, last_dist_from_zone_km):

try:
if not self.distance_method_waze_flag:
if (not self.distance_method_waze_flag
or self.WazeRouteCalc is None):
return (WAZE_NOT_USED, 0, 0, 0)
elif zone == self.base_zone:
return (WAZE_USED, 0, 0, 0)
Expand Down Expand Up @@ -8274,6 +8281,7 @@ def _get_waze_data(self, devicename,
waze_status = WAZE_OUT_OF_RANGE

except Exception as err:
_LOGGER.exception(err)
log_msg = (f"►INTERNAL ERROR (ProcWazeData)-{err})")
self._log_error_msg(log_msg)

Expand All @@ -8296,6 +8304,7 @@ def _get_waze_data(self, devicename,
waze_dist_last_poll)

except Exception as err:
_LOGGER.exception(err)
self._set_waze_not_available_error(err)

return (WAZE_NO_DATA, 0, 0, 0)
Expand All @@ -8314,19 +8323,14 @@ def _get_waze_distance(self, devicename, from_lat, from_long, to_lat,
"""

try:
from_loc = f"{from_lat},{from_long}"
to_loc = f"{to_lat},{to_long}"

retry_cnt = 0
while retry_cnt < 3:
try:
self.count_waze_locates[devicename] += 1
waze_call_start_time = time.time()
route = WazeRouteCalculator.WazeRouteCalculator(
from_loc, to_loc, self.waze_region)

route_time, route_distance = \
route.calc_route_info(self.waze_realtime)
self.WazeRouteCalc.calc_route_info(from_lat, from_long, to_lat, to_long)

self.time_waze_calls[devicename] += (time.time() - waze_call_start_time)

Expand All @@ -8335,12 +8339,14 @@ def _get_waze_distance(self, devicename, from_lat, from_long, to_lat,

return (WAZE_USED, route_distance, route_time)

except WazeRouteCalculator.WRCError as err:
# except WazeRouteCalculator.WRCError as err:
except WRCError as err:
retry_cnt += 1
log_msg = (f"Waze Server Error (#{retry_cnt}), Retrying, Type-{err}")
self._log_info_msg(log_msg)

except Exception as err:
_LOGGER.exception(err)
self._set_waze_not_available_error(err)

return (WAZE_NO_DATA, 0, 0)
Expand Down
2 changes: 1 addition & 1 deletion custom_components/icloud3/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"dependencies": [],
"codeowners": ["@gcobb321"],
"requirements": [],
"version": "2.4.40"
"version": "2.4.5"
}
149 changes: 149 additions & 0 deletions custom_components/icloud3/waze_route_calc_ic3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
#
# WAZE ROUTE CALCULATOR
#
# This module is a modified version of the WazeRouteCalculator developed by
# Kovács Bálint, Budapest, Hungary, that is part of the Python Standard Library.
#
# The modifications include:
# 1. The WazeRouteCalculator object is initialized one time with the region and
# real time parameters. All other parameters are removed. It only works with
# GPS cordinates.
# 2. The from/to GPS cordinates are passed to the calculator on each request
# rather than a new object being created each time requiring a second request
# to retrieve the distance/time results.
#
# The original code can be found on Kovács Bálint's GitHub repo at
# https://github.com/kovacsbalu/WazeRouteCalculator.
#
#<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>

import logging
import requests
import re


class WRCError(Exception):
def __init__(self, message):
self.message = message

def __str__(self):
return self.message


class WazeRouteCalculator(object):
"""Calculate actual route time and distance with Waze API"""

WAZE_URL = "https://www.waze.com/"
HEADERS = {
"User-Agent": "Mozilla/5.0",
"referer": WAZE_URL,
}
VEHICLE_TYPES = ('TAXI', 'MOTORCYCLE')
BASE_COORDS = {
'US': {"lat": 40.713, "lon": -74.006},
'EU': {"lat": 47.498, "lon": 19.040},
'IL': {"lat": 31.768, "lon": 35.214},
'AU': {"lat": -35.281, "lon": 149.128}
}
COORD_SERVERS = {
'US': 'SearchServer/mozi',
'EU': 'row-SearchServer/mozi',
'IL': 'il-SearchServer/mozi',
'AU': 'row-SearchServer/mozi'
}
ROUTING_SERVERS = {
'US': 'RoutingManager/routingRequest',
'EU': 'row-RoutingManager/routingRequest',
'IL': 'il-RoutingManager/routingRequest',
'AU': 'row-RoutingManager/routingRequest'
}
COORD_MATCH = re.compile(r'^([-+]?)([\d]{1,2})(((\.)(\d+)(,)))(\s*)(([-+]?)([\d]{1,3})((\.)(\d+))?)$')


def __init__(self, region, real_time):
self.log = logging.getLogger(__name__)
self.log.addHandler(logging.NullHandler())

region = region.upper()
if region == 'NA':
region = 'US'
self.region = region

self.real_time = real_time
self.vehicle_type = ''
self.route_options = ['AVOID_TRAILS']
self.avoid_subscription_roads = False
self.start_coords = ''
self.end_coords = ''


def get_route(self, from_lat, from_long, to_lat, to_long,):
"""Get route data from waze"""

routing_server = self.ROUTING_SERVERS[self.region]

url_options = {
"from": f"x:{from_long} y:{from_lat}",
"to": f"x:{to_long} y:{to_lat}",
"at": 0,
"returnJSON": "true",
"returnGeometries": "true",
"returnInstructions": "true",
"timeout": 60000,
"nPaths": 1,
"options": ','.join('%s:t' % route_option for route_option in self.route_options),
}

response = requests.get(self.WAZE_URL + routing_server, params=url_options, headers=self.HEADERS)
response.encoding = 'utf-8'
response_json = self._check_response(response)
if response_json:
if 'error' in response_json:
raise WRCError(response_json.get("error"))
else:
if response_json.get("alternatives"):
return [alt['response'] for alt in response_json['alternatives']]
response_obj = response_json['response']
if isinstance(response_obj, list):
response_obj = response_obj[0]

return response_obj
else:
raise WRCError("empty response")

@staticmethod
def _check_response(response):
"""Check waze server response."""
if response.ok:
try:
return response.json()
except ValueError:
return None

def _add_up_route(self, results, stop_at_bounds=False):
"""Calculate route time and distance."""

time = 0
distance = 0
for segment in results:
if 'crossTime' in segment:
time += segment['crossTime' if self.real_time else 'crossTimeWithoutRealTime']
else:
time += segment['cross_time' if self.real_time else 'cross_time_without_real_time']
distance += segment['length']
route_time = time / 60.0
route_distance = distance / 1000.0

return route_time, route_distance

def calc_route_info(self, from_lat, from_long, to_lat, to_long):
"""Calculate best route info."""

route = self.get_route(from_lat, from_long, to_lat, to_long)

route_time, route_distance = self._add_up_route(route['result'])

self.log.info(f"Location: From-({from_lat:0.5f}, {from_long:0.5f}), To-({to_lat:0.5f}, {to_long:0.5f}), Region-{self.region}")
self.log.info(f"Results : Time-{route_time:0.2f}min, Distance-{route_distance:0.2f}km")
return route_time, route_distance
8 changes: 4 additions & 4 deletions development-v2.4.5/device_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@
#pylint: disable=unused-argument, unused-variable
#pylint: disable=too-many-instance-attributes, too-many-lines

VERSION = '2.4.4'
VERSION = '2.4.5'

'''
v2.4.5 (10/5/2021)
1. Fixed a problem where the Waze Route Calculator was being disabled and the distance method-calc was being used. I think the problem started when the WazeRouteCalculator module in the Home Assistant standard Python library was updated.
v2.4.4 (9/25/2021)
1. Coordindated update with pyicloud_ic3.py to support Apple iCloud url changes to access iCloud+ for location & device info for Find-my-Friends tracking method.
Expand Down Expand Up @@ -8320,9 +8323,6 @@ def _get_waze_distance(self, devicename, from_lat, from_long, to_lat,
"""

try:
from_loc = f"{from_lat},{from_long}"
to_loc = f"{to_lat},{to_long}"

retry_cnt = 0
while retry_cnt < 3:
try:
Expand Down
Binary file modified development-v2.4.5/iCloud3-v2.4.5.zip
Binary file not shown.
23 changes: 20 additions & 3 deletions development-v2.4.5/waze_route_calc_ic3.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# -*- coding: utf-8 -*-
"""Waze route calculator"""
#<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
#
# WAZE ROUTE CALCULATOR
#
# This module is a modified version of the WazeRouteCalculator developed by
# Kovács Bálint, Budapest, Hungary, that is part of the Python Standard Library.
#
# The modifications include:
# 1. The WazeRouteCalculator object is initialized one time with the region and
# real time parameters. All other parameters are removed. It only works with
# GPS cordinates.
# 2. The from/to GPS cordinates are passed to the calculator on each request
# rather than a new object being created each time requiring a second request
# to retrieve the distance/time results.
#
# The original code can be found on Kovács Bálint's GitHub repo at
# https://github.com/kovacsbalu/WazeRouteCalculator.
#
#<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>

import logging
import requests
Expand Down Expand Up @@ -127,6 +144,6 @@ def calc_route_info(self, from_lat, from_long, to_lat, to_long):

route_time, route_distance = self._add_up_route(route['result'])

self.log.info(f"Location: From-({from_lat:0.5f}, {from_long:0.5f}) To-({to_lat:0.5f}, {to_long:0.5f}), Region-{self.region}")
self.log.info(f"Location: From-({from_lat:0.5f}, {from_long:0.5f}), To-({to_lat:0.5f}, {to_long:0.5f}), Region-{self.region}")
self.log.info(f"Results : Time-{route_time:0.2f}min, Distance-{route_distance:0.2f}km")
return route_time, route_distance
Loading

0 comments on commit 8bda2b0

Please sign in to comment.