1 # Copyright 2016 gRPC authors. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 """A gRPC server servicing both Greeter and RouteGuide RPCs.""" 15 16 from concurrent import futures 17 import time 18 import math 19 20 import grpc 21 22 import helloworld_pb2 23 import helloworld_pb2_grpc 24 import route_guide_pb2 25 import route_guide_pb2_grpc 26 import route_guide_resources 27 28 _ONE_DAY_IN_SECONDS = 60 * 60 * 24 29 30 31 def _get_feature(feature_db, point): 32 """Returns Feature at given location or None.""" 33 for feature in feature_db: 34 if feature.location == point: 35 return feature 36 return None 37 38 39 def _get_distance(start, end): 40 """Distance between two points.""" 41 coord_factor = 10000000.0 42 lat_1 = start.latitude / coord_factor 43 lat_2 = end.latitude / coord_factor 44 lon_1 = start.longitude / coord_factor 45 lon_2 = end.longitude / coord_factor 46 lat_rad_1 = math.radians(lat_1) 47 lat_rad_2 = math.radians(lat_2) 48 delta_lat_rad = math.radians(lat_2 - lat_1) 49 delta_lon_rad = math.radians(lon_2 - lon_1) 50 51 a = (pow(math.sin(delta_lat_rad / 2), 2) + 52 (math.cos(lat_rad_1) * math.cos(lat_rad_2) * pow( 53 math.sin(delta_lon_rad / 2), 2))) 54 c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) 55 R = 6371000 56 # metres 57 return R * c 58 59 60 class _GreeterServicer(helloworld_pb2_grpc.GreeterServicer): 61 62 def SayHello(self, request, context): 63 return helloworld_pb2.HelloReply( 64 message='Hello, {}!'.format(request.name)) 65 66 67 class _RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer): 68 """Provides methods that implement functionality of route guide server.""" 69 70 def __init__(self): 71 self.db = route_guide_resources.read_route_guide_database() 72 73 def GetFeature(self, request, context): 74 feature = _get_feature(self.db, request) 75 if feature is None: 76 return route_guide_pb2.Feature(name="", location=request) 77 else: 78 return feature 79 80 def ListFeatures(self, request, context): 81 left = min(request.lo.longitude, request.hi.longitude) 82 right = max(request.lo.longitude, request.hi.longitude) 83 top = max(request.lo.latitude, request.hi.latitude) 84 bottom = min(request.lo.latitude, request.hi.latitude) 85 for feature in self.db: 86 if (feature.location.longitude >= left and 87 feature.location.longitude <= right and 88 feature.location.latitude >= bottom and 89 feature.location.latitude <= top): 90 yield feature 91 92 def RecordRoute(self, request_iterator, context): 93 point_count = 0 94 feature_count = 0 95 distance = 0.0 96 prev_point = None 97 98 start_time = time.time() 99 for point in request_iterator: 100 point_count += 1 101 if _get_feature(self.db, point): 102 feature_count += 1 103 if prev_point: 104 distance += _get_distance(prev_point, point) 105 prev_point = point 106 107 elapsed_time = time.time() - start_time 108 return route_guide_pb2.RouteSummary( 109 point_count=point_count, 110 feature_count=feature_count, 111 distance=int(distance), 112 elapsed_time=int(elapsed_time)) 113 114 def RouteChat(self, request_iterator, context): 115 prev_notes = [] 116 for new_note in request_iterator: 117 for prev_note in prev_notes: 118 if prev_note.location == new_note.location: 119 yield prev_note 120 prev_notes.append(new_note) 121 122 123 def serve(): 124 server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) 125 helloworld_pb2_grpc.add_GreeterServicer_to_server(_GreeterServicer(), 126 server) 127 route_guide_pb2_grpc.add_RouteGuideServicer_to_server( 128 _RouteGuideServicer(), server) 129 server.add_insecure_port('[::]:50051') 130 server.start() 131 try: 132 while True: 133 time.sleep(_ONE_DAY_IN_SECONDS) 134 except KeyboardInterrupt: 135 server.stop(0) 136 137 138 if __name__ == '__main__': 139 serve() 140