initial commit
commit
7f52695a08
|
|
@ -0,0 +1,16 @@
|
|||
FROM python:3.9.9-slim-buster
|
||||
LABEL maintainer="Yann Feunteun <yann.feunteun@protonmail.com>"
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY requirements.txt /app/
|
||||
|
||||
RUN pip install --upgrade pip
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
COPY ./ /app/
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
# command to run on container start
|
||||
CMD [ "uvicorn", "app.main:app", "--host", "0.0.0.0", "--reload" ]
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
from pydantic import BaseSettings
|
||||
|
||||
class Settings(BaseSettings):
|
||||
grpc_server_host: str = "127.0.0.1"
|
||||
grpc_server_port: str = "50051"
|
||||
|
||||
# Defines the maximum allowed distance in meters
|
||||
# of a route. Above this threshold, a 404 response code
|
||||
# will be returned meaning no route correspond to the request.
|
||||
max_route_length_allowed: int = 20000
|
||||
|
||||
# Maximum allowed distance in meters between a requested route
|
||||
# start/end point and the closest point on our graph
|
||||
closest_point_tolerance: int = 150
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
|
||||
# reads env variables (case insensitive) and validate against schema
|
||||
settings = Settings()
|
||||
|
|
@ -0,0 +1,262 @@
|
|||
import sys
|
||||
import json
|
||||
import time
|
||||
import hashlib
|
||||
from fastapi import FastAPI, Body
|
||||
from pydantic import BaseModel, Field
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
import requests
|
||||
from .config import settings
|
||||
|
||||
import numpy as np
|
||||
from scipy.spatial import KDTree
|
||||
from scipy.spatial import ConvexHull
|
||||
|
||||
import grpc
|
||||
from . import route_service_pb2
|
||||
from . route_service_pb2_grpc import RouteServiceStub
|
||||
from .schemas import (
|
||||
Message,
|
||||
Point,
|
||||
LineString,
|
||||
Polygon,
|
||||
PolygonGeometry,
|
||||
RouteRequest,
|
||||
CoverageResponse,
|
||||
RouteResponsePath
|
||||
)
|
||||
|
||||
from andyamo import types
|
||||
|
||||
from geopy import distance as geo_distance
|
||||
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.openapi.utils import get_openapi
|
||||
|
||||
from fastapi import Security, Depends, FastAPI, HTTPException
|
||||
from fastapi.openapi.docs import get_swagger_ui_html
|
||||
from fastapi.openapi.utils import get_openapi
|
||||
|
||||
from starlette.status import HTTP_403_FORBIDDEN
|
||||
from starlette.responses import RedirectResponse, JSONResponse
|
||||
|
||||
channel = grpc.insecure_channel(f"{settings.grpc_server_host}:{settings.grpc_server_port}")
|
||||
grpc_client = RouteServiceStub(channel)
|
||||
|
||||
|
||||
|
||||
def get_hash(data: str):
|
||||
return hashlib.md5(f"{data}".encode("utf-8")).hexdigest()
|
||||
|
||||
with open("export_clean_splitted.json", "r") as f:
|
||||
data = [json.loads(x.strip()) for x in f.readlines()]
|
||||
|
||||
hash_to_type = {}
|
||||
|
||||
for feature in data:
|
||||
hash_to_type[feature["feature"]["properties"]["index"]] = feature["feature"]["properties"]["type"]
|
||||
|
||||
|
||||
|
||||
datastore = {}
|
||||
|
||||
for _profile in ["foot", "manual_wheelchair", "electric_wheelchair"]:#, "visually_impaired_cane", "cognitive_disability", "elderly", "hearing_impaired"]:
|
||||
datastore[_profile] = {}
|
||||
datastore[_profile]["points"] = []
|
||||
datastore[_profile]["ids"] = []
|
||||
|
||||
req_data = {"profile": types.Profile(_profile).name}
|
||||
request = route_service_pb2.Profile(**req_data)
|
||||
|
||||
for node in grpc_client.ListNodes(request):
|
||||
#print(node.index, node.longitude, node.latitude)
|
||||
datastore[_profile]["points"].append([node.longitude, node.latitude])
|
||||
datastore[_profile]["ids"].append(node.index)
|
||||
|
||||
datastore[_profile]["kdtree"] = KDTree(datastore[_profile]["points"])
|
||||
|
||||
nodeid_to_coords = {}
|
||||
for feature in data:
|
||||
nodeid_to_coords["d_" + feature['feature']["properties"]["nodes"][0]] = \
|
||||
feature['feature']["geometry"]['coordinates'][0]
|
||||
nodeid_to_coords["d_" + feature['feature']["properties"]["nodes"][1]] = \
|
||||
feature['feature']["geometry"]['coordinates'][1]
|
||||
|
||||
def compute_convex_hull():
|
||||
_points = np.array(datastore["foot"]["points"])
|
||||
hull = ConvexHull(_points)
|
||||
|
||||
hull_geojson = {
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
l = []
|
||||
for vertex in hull.vertices:
|
||||
l.append(list(datastore["foot"]["points"][vertex]))
|
||||
|
||||
l.append(list(datastore["foot"]["points"][hull.vertices[0]]))
|
||||
hull_geojson["geometry"]["coordinates"] = [l]
|
||||
|
||||
return hull_geojson
|
||||
|
||||
hull_geojson = compute_convex_hull()
|
||||
|
||||
|
||||
def compute_coverage(features: list) -> tuple:
|
||||
"""Return bounding box of the geographical area covered by this instance."""
|
||||
|
||||
min_lon = sys.maxsize
|
||||
min_lat = sys.maxsize
|
||||
max_lon = 0
|
||||
max_lat = 0
|
||||
|
||||
for feature in data:
|
||||
for (lon, lat) in feature["feature"]["geometry"]["coordinates"]:
|
||||
if lon < min_lon:
|
||||
min_lon = lon
|
||||
if lon > max_lon:
|
||||
max_lon = lon
|
||||
|
||||
if lat < min_lat:
|
||||
min_lat = lat
|
||||
if lat > max_lat:
|
||||
max_lat = lat
|
||||
|
||||
|
||||
return min_lon,min_lat,max_lon,max_lat
|
||||
|
||||
|
||||
def get_point_from_nodeid(nodeid):
|
||||
return nodeid_to_coords[nodeid]
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class ConvexHullResponse(BaseModel):
|
||||
polygon: Polygon = Field(..., title="polygon", description="Similar to /coverage, returns the convex hull corresponding to the geographical area covered as a GeoJSON polygon.")
|
||||
|
||||
|
||||
|
||||
@app.get("/healthz", summary="Check if API is up or not")
|
||||
def healthz():
|
||||
return { "healthy": "OK" }
|
||||
|
||||
|
||||
@app.get("/coverage", summary="Coverage information (bounding box)", response_model=CoverageResponse)
|
||||
def coverage():
|
||||
bbox = compute_coverage(data)
|
||||
return { "bbox": bbox }
|
||||
|
||||
|
||||
@app.get("/convex", summary="Coverage information (convex hull)", response_model=ConvexHullResponse)
|
||||
def coverage():
|
||||
return { "polygon": hull_geojson }
|
||||
|
||||
|
||||
@app.post(
|
||||
"/route",
|
||||
summary="Pedestrian routing",
|
||||
response_model=RouteResponsePath,
|
||||
responses={
|
||||
400: {"model": Message},
|
||||
404: {"model": Message}
|
||||
}
|
||||
)
|
||||
def route(route: RouteRequest = Body(...)) -> RouteResponsePath:
|
||||
|
||||
|
||||
if route.profile.value not in ["foot", "manual_wheelchair", "electric_wheelchair"]:
|
||||
return JSONResponse(
|
||||
status_code=404, content={
|
||||
"message": "Profile not available yet. Available profiles are: foot, manual_wheelchair and electric_wheelchair"
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
_, idx_start = datastore[route.profile.value]["kdtree"]\
|
||||
.query([route.start.lon, route.start.lat])
|
||||
_, idx_end = datastore[route.profile.value]["kdtree"]\
|
||||
.query([route.end.lon, route.end.lat])
|
||||
|
||||
too_far_from_graph = False
|
||||
|
||||
if geo_distance.distance(
|
||||
get_point_from_nodeid(str(datastore[route.profile.value]["ids"][idx_start])[1:]),
|
||||
[route.start.lon, route.start.lat]
|
||||
).m > settings.closest_point_tolerance:
|
||||
too_far_from_graph = True
|
||||
|
||||
if geo_distance.distance(
|
||||
get_point_from_nodeid(str(datastore[route.profile.value]["ids"][idx_end])[1:]),
|
||||
[route.end.lon, route.end.lat]
|
||||
).m > settings.closest_point_tolerance:
|
||||
too_far_from_graph = True
|
||||
|
||||
if too_far_from_graph:
|
||||
|
||||
return JSONResponse(
|
||||
status_code=400, content={
|
||||
"message": "Start and or end point outside covered perimeter"
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
req_data = {
|
||||
"start": str(datastore[route.profile.value]["ids"][idx_start]),
|
||||
"end": str(datastore[route.profile.value]["ids"][idx_end]),
|
||||
"profile": route_service_pb2.Profile(profile=route.profile.name)
|
||||
}
|
||||
|
||||
|
||||
request = route_service_pb2.RouteRequest(**req_data)
|
||||
response = grpc_client.ShortestPath(request)
|
||||
route = response.route
|
||||
distance = response.distance
|
||||
|
||||
if distance > settings.max_route_length_allowed:
|
||||
return JSONResponse(status_code=404, content={"message": "No route found."})
|
||||
|
||||
route_points = [get_point_from_nodeid(x[1:]) for x in route]
|
||||
|
||||
segment_types = []
|
||||
|
||||
for i in range(len(route_points) - 1):
|
||||
segment_hash0 = get_hash([route_points[i], route_points[i+1]])
|
||||
segment_hash1 = get_hash([route_points[i+1], route_points[i]])
|
||||
|
||||
if segment_hash0 in hash_to_type.keys():
|
||||
segment_types.append(hash_to_type[segment_hash0])
|
||||
elif segment_hash1 in hash_to_type.keys():
|
||||
segment_types.append(hash_to_type[segment_hash1])
|
||||
|
||||
if len(segment_types) < i+1:
|
||||
segment_types.append("unknown")
|
||||
|
||||
|
||||
min_lon = min([x[0] for x in route_points])
|
||||
min_lat = min([x[1] for x in route_points])
|
||||
max_lon = max([x[0] for x in route_points])
|
||||
max_lat = max([x[1] for x in route_points])
|
||||
|
||||
walking_speed = 4000 / 3600 ## 4km/h == 4000 / 3600 m / s
|
||||
return {
|
||||
"distance": distance,
|
||||
"duration": distance * walking_speed,
|
||||
"points": {
|
||||
"type": "LineString",
|
||||
"coordinates": route_points
|
||||
},
|
||||
"segment_types": segment_types,
|
||||
"bbox": [min_lon, min_lat, max_lon, max_lat]
|
||||
|
||||
}
|
||||
|
||||
|
||||
return JSONResponse(status_code=404, content={"message": "No route found."})
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: route_service.proto
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf.internal import builder as _builder
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13route_service.proto\"E\n\x0cRouteRequest\x12\r\n\x05start\x18\x01 \x01(\t\x12\x0b\n\x03\x65nd\x18\x02 \x01(\t\x12\x19\n\x07profile\x18\x03 \x01(\x0b\x32\x08.Profile\"q\n\x07Profile\x12!\n\x07profile\x18\x01 \x01(\x0e\x32\x10.Profile.Profile\"C\n\x07Profile\x12\x08\n\x04\x46OOT\x10\x00\x12\x15\n\x11MANUAL_WHEELCHAIR\x10\x01\x12\x17\n\x13\x45LECTRIC_WHEELCHAIR\x10\x02\"0\n\rRouteResponse\x12\r\n\x05route\x18\x01 \x03(\t\x12\x10\n\x08\x64istance\x18\x02 \x01(\x05\":\n\x04Node\x12\r\n\x05index\x18\x01 \x01(\t\x12\x10\n\x08latitude\x18\x02 \x01(\x02\x12\x11\n\tlongitude\x18\x03 \x01(\x02\x32\x61\n\x0cRouteService\x12/\n\x0cShortestPath\x12\r.RouteRequest\x1a\x0e.RouteResponse\"\x00\x12 \n\tListNodes\x12\x08.Profile\x1a\x05.Node\"\x00\x30\x01\x62\x06proto3')
|
||||
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'route_service_pb2', globals())
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
|
||||
DESCRIPTOR._options = None
|
||||
_ROUTEREQUEST._serialized_start=23
|
||||
_ROUTEREQUEST._serialized_end=92
|
||||
_PROFILE._serialized_start=94
|
||||
_PROFILE._serialized_end=207
|
||||
_PROFILE_PROFILE._serialized_start=140
|
||||
_PROFILE_PROFILE._serialized_end=207
|
||||
_ROUTERESPONSE._serialized_start=209
|
||||
_ROUTERESPONSE._serialized_end=257
|
||||
_NODE._serialized_start=259
|
||||
_NODE._serialized_end=317
|
||||
_ROUTESERVICE._serialized_start=319
|
||||
_ROUTESERVICE._serialized_end=416
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
|
||||
import route_service_pb2 as route__service__pb2
|
||||
|
||||
|
||||
class RouteServiceStub(object):
|
||||
"""Interface exported by the server.
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.ShortestPath = channel.unary_unary(
|
||||
'/RouteService/ShortestPath',
|
||||
request_serializer=route__service__pb2.RouteRequest.SerializeToString,
|
||||
response_deserializer=route__service__pb2.RouteResponse.FromString,
|
||||
)
|
||||
self.ListNodes = channel.unary_stream(
|
||||
'/RouteService/ListNodes',
|
||||
request_serializer=route__service__pb2.Profile.SerializeToString,
|
||||
response_deserializer=route__service__pb2.Node.FromString,
|
||||
)
|
||||
|
||||
|
||||
class RouteServiceServicer(object):
|
||||
"""Interface exported by the server.
|
||||
"""
|
||||
|
||||
def ShortestPath(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def ListNodes(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_RouteServiceServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'ShortestPath': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.ShortestPath,
|
||||
request_deserializer=route__service__pb2.RouteRequest.FromString,
|
||||
response_serializer=route__service__pb2.RouteResponse.SerializeToString,
|
||||
),
|
||||
'ListNodes': grpc.unary_stream_rpc_method_handler(
|
||||
servicer.ListNodes,
|
||||
request_deserializer=route__service__pb2.Profile.FromString,
|
||||
response_serializer=route__service__pb2.Node.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'RouteService', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class RouteService(object):
|
||||
"""Interface exported by the server.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def ShortestPath(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/RouteService/ShortestPath',
|
||||
route__service__pb2.RouteRequest.SerializeToString,
|
||||
route__service__pb2.RouteResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def ListNodes(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_stream(request, target, '/RouteService/ListNodes',
|
||||
route__service__pb2.Profile.SerializeToString,
|
||||
route__service__pb2.Node.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
from andyamo import types
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
class Message(BaseModel):
|
||||
message: str
|
||||
|
||||
class Point(BaseModel):
|
||||
lon: float
|
||||
lat: float
|
||||
|
||||
class Config:
|
||||
schema_extra = {
|
||||
"example": {
|
||||
"lon": 3.127781750469675,
|
||||
"lat": 45.76400009445323
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class LineString(BaseModel):
|
||||
type: str
|
||||
coordinates: list[list[float]]
|
||||
|
||||
|
||||
class RouteRequest(BaseModel):
|
||||
start: Point = Field(..., description="The starting point for which the route should be calculated.")
|
||||
end: Point = Field(..., description="The ending point for which the route should be calculated.")
|
||||
profile: types.Profile = Field(..., description="See [availables profiles](#section/Routing-Profiles)")
|
||||
|
||||
|
||||
class CoverageResponse(BaseModel):
|
||||
bbox: list[float] = Field(..., title="bbox", description="The bounding box of the geographical area covered. Format: [minLon,minLat,maxLon,maxLat]")
|
||||
|
||||
class Config:
|
||||
schema_extra = {
|
||||
"example": {
|
||||
"bbox": [
|
||||
3.073747158050537,
|
||||
45.77367083508177,
|
||||
3.075887560844421,
|
||||
45.77517870042004
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class RouteResponsePath(BaseModel):
|
||||
distance: int = Field(..., description="Total distance in meters for the route returned")
|
||||
duration: int = Field(..., description="Estimated travel time in seconds. Depends on the chosen [profile](#section/Routing-Profiles)")
|
||||
points: LineString = Field(..., description="The geometry of the route in [GeoJSON format](https://datatracker.ietf.org/doc/html/rfc7946)")
|
||||
bbox: list[float] = Field(..., title="bbox", description="The bounding box of the route geometry. Format: [minLon,minLat,maxLon,maxLat]")
|
||||
segment_types: list[str] = Field(..., description="Segment types in the returned route result. Can be sidewalk, stair, crosswalk or unknown")
|
||||
|
||||
class Config:
|
||||
schema_extra = {
|
||||
"example": {
|
||||
"distance": 280,
|
||||
"duration": 201,
|
||||
"points": {
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[
|
||||
3.073747158050537,
|
||||
45.77517870042004
|
||||
],
|
||||
[
|
||||
3.0739670991897583,
|
||||
45.77472597094132
|
||||
],
|
||||
[
|
||||
3.0742889642715454,
|
||||
45.77413105636887
|
||||
],
|
||||
[
|
||||
3.0747556686401367,
|
||||
45.77379056781466
|
||||
],
|
||||
[
|
||||
3.074975609779358,
|
||||
45.77367083508177
|
||||
],
|
||||
[
|
||||
3.0753082036972046,
|
||||
45.77374940971673
|
||||
],
|
||||
[
|
||||
3.0754369497299194,
|
||||
45.77386540064218
|
||||
],
|
||||
[
|
||||
3.0756354331970215,
|
||||
45.77381301767344
|
||||
],
|
||||
[
|
||||
3.075887560844421,
|
||||
45.773872883919395
|
||||
]
|
||||
]
|
||||
},
|
||||
"segment_types": ["sidewalk", "sidewalk", "crosswalk", "sidewalk", "sidewalk", "stair", "sidewalk", "sidewalk"],
|
||||
"bbox": [3.073747158050537, 45.77367083508177, 3.075887560844421, 45.77517870042004]
|
||||
}
|
||||
}
|
||||
|
||||
class PolygonGeometry(BaseModel):
|
||||
type: str
|
||||
coordinates: list[list[list[float]]]
|
||||
|
||||
class Config:
|
||||
schema_extra = {
|
||||
"example": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
3.4716796874999996,
|
||||
47.37603463349758
|
||||
],
|
||||
[
|
||||
3.49639892578125,
|
||||
47.33603074146188
|
||||
],
|
||||
[
|
||||
3.6488342285156246,
|
||||
47.429945332976125
|
||||
],
|
||||
[
|
||||
3.4716796874999996,
|
||||
47.37603463349758
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
class Polygon(BaseModel):
|
||||
type: str
|
||||
properties: dict
|
||||
geometry: PolygonGeometry
|
||||
|
||||
class Config:
|
||||
schema_extra = {
|
||||
"example": {
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
3.4716796874999996,
|
||||
47.37603463349758
|
||||
],
|
||||
[
|
||||
3.49639892578125,
|
||||
47.33603074146188
|
||||
],
|
||||
[
|
||||
3.6488342285156246,
|
||||
47.429945332976125
|
||||
],
|
||||
[
|
||||
3.4716796874999996,
|
||||
47.37603463349758
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,13 @@
|
|||
-i https://pypi.andyamo.fr/simple
|
||||
andyamo==0.1.2
|
||||
fastapi==0.71.0
|
||||
geopy==2.2.0
|
||||
uvicorn==0.15.0
|
||||
requests==2.27.1
|
||||
grpcio-tools==1.43.0
|
||||
opentracing==2.4.0
|
||||
scipy==1.8.0
|
||||
opentelemetry-sdk==1.10.0
|
||||
opentelemetry-api==1.10.0
|
||||
opentelemetry-exporter-jaeger==1.10.0
|
||||
numpy==1.22.2
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: route_service.proto
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf.internal import builder as _builder
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13route_service.proto\"E\n\x0cRouteRequest\x12\r\n\x05start\x18\x01 \x01(\t\x12\x0b\n\x03\x65nd\x18\x02 \x01(\t\x12\x19\n\x07profile\x18\x03 \x01(\x0b\x32\x08.Profile\"q\n\x07Profile\x12!\n\x07profile\x18\x01 \x01(\x0e\x32\x10.Profile.Profile\"C\n\x07Profile\x12\x08\n\x04\x46OOT\x10\x00\x12\x15\n\x11MANUAL_WHEELCHAIR\x10\x01\x12\x17\n\x13\x45LECTRIC_WHEELCHAIR\x10\x02\"0\n\rRouteResponse\x12\r\n\x05route\x18\x01 \x03(\t\x12\x10\n\x08\x64istance\x18\x02 \x01(\x05\":\n\x04Node\x12\r\n\x05index\x18\x01 \x01(\t\x12\x10\n\x08latitude\x18\x02 \x01(\x02\x12\x11\n\tlongitude\x18\x03 \x01(\x02\x32\x61\n\x0cRouteService\x12/\n\x0cShortestPath\x12\r.RouteRequest\x1a\x0e.RouteResponse\"\x00\x12 \n\tListNodes\x12\x08.Profile\x1a\x05.Node\"\x00\x30\x01\x62\x06proto3')
|
||||
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'route_service_pb2', globals())
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
|
||||
DESCRIPTOR._options = None
|
||||
_ROUTEREQUEST._serialized_start=23
|
||||
_ROUTEREQUEST._serialized_end=92
|
||||
_PROFILE._serialized_start=94
|
||||
_PROFILE._serialized_end=207
|
||||
_PROFILE_PROFILE._serialized_start=140
|
||||
_PROFILE_PROFILE._serialized_end=207
|
||||
_ROUTERESPONSE._serialized_start=209
|
||||
_ROUTERESPONSE._serialized_end=257
|
||||
_NODE._serialized_start=259
|
||||
_NODE._serialized_end=317
|
||||
_ROUTESERVICE._serialized_start=319
|
||||
_ROUTESERVICE._serialized_end=416
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
|
||||
import route_service_pb2 as route__service__pb2
|
||||
|
||||
|
||||
class RouteServiceStub(object):
|
||||
"""Interface exported by the server.
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.ShortestPath = channel.unary_unary(
|
||||
'/RouteService/ShortestPath',
|
||||
request_serializer=route__service__pb2.RouteRequest.SerializeToString,
|
||||
response_deserializer=route__service__pb2.RouteResponse.FromString,
|
||||
)
|
||||
self.ListNodes = channel.unary_stream(
|
||||
'/RouteService/ListNodes',
|
||||
request_serializer=route__service__pb2.Profile.SerializeToString,
|
||||
response_deserializer=route__service__pb2.Node.FromString,
|
||||
)
|
||||
|
||||
|
||||
class RouteServiceServicer(object):
|
||||
"""Interface exported by the server.
|
||||
"""
|
||||
|
||||
def ShortestPath(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def ListNodes(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_RouteServiceServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'ShortestPath': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.ShortestPath,
|
||||
request_deserializer=route__service__pb2.RouteRequest.FromString,
|
||||
response_serializer=route__service__pb2.RouteResponse.SerializeToString,
|
||||
),
|
||||
'ListNodes': grpc.unary_stream_rpc_method_handler(
|
||||
servicer.ListNodes,
|
||||
request_deserializer=route__service__pb2.Profile.FromString,
|
||||
response_serializer=route__service__pb2.Node.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'RouteService', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class RouteService(object):
|
||||
"""Interface exported by the server.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def ShortestPath(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/RouteService/ShortestPath',
|
||||
route__service__pb2.RouteRequest.SerializeToString,
|
||||
route__service__pb2.RouteResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def ListNodes(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_stream(request, target, '/RouteService/ListNodes',
|
||||
route__service__pb2.Profile.SerializeToString,
|
||||
route__service__pb2.Node.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
Loading…
Reference in New Issue