File size: 5,900 Bytes
63ec258 187a965 63ec258 e5f444f 5baa807 e5f444f 63ec258 5baa807 e5f444f 5baa807 63ec258 e5f444f 63ec258 e5f444f cb47347 e5f444f 3ae3815 e5f444f 63ec258 cb47347 63ec258 cb47347 187a965 cc1b4c0 63ec258 cc1b4c0 63ec258 cb47347 63ec258 cb47347 cc1b4c0 63ec258 cb47347 63ec258 7b96044 63ec258 247bc50 63ec258 e5f444f 63ec258 cb47347 63ec258 cb47347 63ec258 cb47347 7b96044 cc1b4c0 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
from datetime import datetime
import requests
from .common import config, vehicle
def find_coordinates(address):
"""
Find the coordinates of a specific address.
:param address (string): Required. The address
"""
# https://developer.tomtom.com/geocoding-api/documentation/geocode
url = f"https://api.tomtom.com/search/2/geocode/{address}.json?key={config.TOMTOM_API_KEY}"
response = requests.get(url)
data = response.json()
lat = data["results"][0]["position"]["lat"]
lon = data["results"][0]["position"]["lon"]
return lat, lon
def plot_route(points):
import plotly.express as px
lats = []
lons = []
for point in points:
lats.append(point["latitude"])
lons.append(point["longitude"])
# fig = px.line_geo(lat=lats, lon=lons)
# fig.update_geos(fitbounds="locations")
fig = px.line_mapbox(
lat=lats, lon=lons, zoom=12, height=600, color_discrete_sequence=["red"]
)
fig.update_layout(
mapbox_style="open-street-map",
# mapbox_zoom=12,
)
fig.update_geos(fitbounds="locations")
fig.update_layout(margin={"r": 20, "t": 20, "l": 20, "b": 20})
return fig
def calculate_route(origin, destination):
"""This function is called when the origin or destination is updated in the GUI. It calculates the route between the origin and destination."""
print(f"calculate_route(origin: {origin}, destination: {destination})")
origin_coords = find_coordinates(origin)
destination_coords = find_coordinates(destination)
orig_coords_str = ",".join(map(str, origin_coords))
dest_coords_str = ",".join(map(str, destination_coords))
print(f"origin_coords: {origin_coords}, destination_coords: {destination_coords}")
vehicle.destination = destination
vehicle.location_coordinates = origin_coords
vehicle.location = origin
# origin = "49.631997,6.171029"
# destination = "49.586745,6.140002"
url = f"https://api.tomtom.com/routing/1/calculateRoute/{orig_coords_str}:{dest_coords_str}/json?key={config.TOMTOM_API_KEY}"
response = requests.get(url)
data = response.json()
points = data["routes"][0]["legs"][0]["points"]
return plot_route(points), vehicle.model_dump_json(), points
def find_route_tomtom(
lat_depart="0",
lon_depart="0",
lat_dest="0",
lon_dest="0",
depart_datetime="",
**kwargs,
):
"""
Return the distance and the estimated time to go to a specific destination from the current place, at a specified depart time.
:param lat_depart (string): latitude of depart
:param lon_depart (string): longitude of depart
:param lat_dest (string): latitude of destination
:param lon_dest (string): longitude of destination
:param depart_time (string): departure hour, in the format '08:00:20'.
"""
# https://developer.tomtom.com/routing-api/documentation/routing/calculate-route
# https://developer.tomtom.com/routing-api/documentation/routing/guidance-instructions
url = f"https://api.tomtom.com/routing/1/calculateRoute/{lat_depart},{lon_depart}:{lat_dest},{lon_dest}/json?key={config.TOMTOM_API_KEY}&departAt={depart_datetime}"
print(f"Calling TomTom API: {url}")
r = requests.get(
url,
timeout=5,
)
# Parse JSON from the response
response = r.json()
try:
result = response["routes"][0]["summary"]
except KeyError:
print(f"Failed to find a route: {response}")
return "Failed to find a route", response
distance_m = result["lengthInMeters"]
duration_s = result["travelTimeInSeconds"]
arrival_time = result["arrivalTime"]
# Convert string to datetime object
arrival_time = datetime.fromisoformat(arrival_time)
return {
"distance_m": distance_m,
"duration_s": duration_s,
"arrival_time": arrival_time,
}, response
def find_route(destination=""):
"""This function finds a route to a destination and returns the distance and the estimated time to go to a specific destination\
from the current location.
:param destination (string): Required. The destination
"""
if not destination:
destination = vehicle.destination
# lat, lon, city = check_city_coordinates(lat_depart,lon_depart,city_depart)
lat_dest, lon_dest = find_coordinates(destination)
print(f"lat_dest: {lat_dest}, lon_dest: {lon_dest}")
# Extract the latitude and longitude of the vehicle
vehicle_coordinates = getattr(vehicle, "location_coordinates")
lat_depart, lon_depart = vehicle_coordinates
print(f"lat_depart: {lat_depart}, lon_depart: {lon_depart}")
date = getattr(vehicle, "date")
time = getattr(vehicle, "time")
departure_time = f"{date}T{time}"
trip_info, raw_response = find_route_tomtom(
lat_depart, lon_depart, lat_dest, lon_dest, departure_time
)
distance, duration, arrival_time = (
trip_info["distance_m"],
trip_info["duration_s"],
trip_info["arrival_time"],
)
# Calculate distance in kilometers (1 meter = 0.001 kilometers)
distance_km = distance * 0.001
# Calculate travel time in minutes (1 second = 1/60 minutes)
time_minutes = duration / 60
if time_minutes < 60:
time_display = f"{time_minutes:.0f} minutes"
else:
hours = int(time_minutes / 60)
minutes = int(time_minutes % 60)
time_display = f"{hours} hours" + (
f" and {minutes} minutes" if minutes > 0 else ""
)
# Extract and display the arrival hour in HH:MM format
arrival_hour_display = arrival_time.strftime("%H:%M")
# return the distance and time
return f"The route to {destination} is {distance_km:.2f} km which takes {time_display}. Leaving now, the arrival time is estimated at {arrival_hour_display}."
# raw_response["routes"][0]["legs"][0]["points"]
|