From ae069ef031b1da5af505485a25731b86f8d37c96 Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Tue, 27 Apr 2021 09:56:56 +0100 Subject: [PATCH] add directions endpoint to routing service --- routing/README.md | 4 +- routing/handler/osrm.go | 145 ++++++- routing/main.go | 6 +- routing/proto/routing.pb.go | 653 +++++++++++++++++++++++++++--- routing/proto/routing.pb.micro.go | 19 + routing/proto/routing.proto | 54 ++- 6 files changed, 796 insertions(+), 85 deletions(-) diff --git a/routing/README.md b/routing/README.md index cba695d..45b75f3 100644 --- a/routing/README.md +++ b/routing/README.md @@ -9,5 +9,5 @@ The routing service provides point to point directions The following config must be set - **routing.mode**: "google" or "osrm" -- **google.api.key**: google maps api key if using google -- **osrm.api.address"**: location of osrm api +- **routing.address"**: location of osrm api if used +- **google.apikey**: google maps api key if using google diff --git a/routing/handler/osrm.go b/routing/handler/osrm.go index 4f29df4..b212f16 100644 --- a/routing/handler/osrm.go +++ b/routing/handler/osrm.go @@ -18,6 +18,121 @@ type OSRM struct { Client *osrm.OSRM } +func (o *OSRM) Directions(ctx context.Context, req *pb.DirectionsRequest, rsp *pb.DirectionsResponse) error { + // validate the request + if req.Origin == nil { + return ErrMissingOrigin + } + if req.Destination == nil { + return ErrMissingDestination + } + if err := validatePoint(req.Origin); err != nil { + return err + } + if err := validatePoint(req.Destination); err != nil { + return err + } + + orig := req.Origin + dest := req.Destination + + if o.Client == nil { + u, _ := url.Parse(o.Address) + if u.Scheme == "" { + u.Scheme = "http" + } + o.Client = osrm.NewFromURL(u.String()) + } + + ctx, cancelFn := context.WithTimeout(context.Background(), time.Second) + defer cancelFn() + + resp, err := o.Client.Route(ctx, osrm.RouteRequest{ + Profile: "car", + Coordinates: osrm.NewGeometryFromPointSet(geo.PointSet{ + {orig.Longitude, orig.Latitude}, + {dest.Longitude, dest.Latitude}, + }), + Steps: osrm.StepsTrue, + Annotations: osrm.AnnotationsFalse, + Overview: osrm.OverviewFalse, + }) + if err != nil { + return errors.InternalServerError("routing.eta", "failed to get route: %v", err.Error()) + } + + if len(resp.Routes) == 0 { + return nil + } + + // set the estimated duration and distance + rsp.Duration = float64(resp.Routes[0].Duration) + rsp.Distance = float64(resp.Routes[0].Distance) + + for _, leg := range resp.Routes[0].Legs { + for _, step := range leg.Steps { + // set the waypoints for the route + for _, intersect := range step.Intersections { + rsp.Waypoints = append(rsp.Waypoints, &pb.Waypoint{ + Name: step.Name, + Location: &pb.Point{ + Latitude: intersect.Location.Lat(), + Longitude: intersect.Location.Lng(), + }, + }) + } + + instruction := step.Maneuver.Modifier + + switch step.Maneuver.Type { + case "new name": + instruction = "go " + step.Maneuver.Modifier + default: + instruction = step.Maneuver.Type + " " + step.Maneuver.Modifier + } + + var intersections []*pb.Intersection + + for _, is := range step.Intersections { + var bearings []float64 + + for _, bearing := range is.Bearings { + bearings = append(bearings, float64(bearing)) + } + + intersections = append(intersections, &pb.Intersection{ + Bearings: bearings, + Location: &pb.Point{ + Latitude: is.Location.Lat(), + Longitude: is.Location.Lng(), + }, + }) + } + + // set the directions for the route + rsp.Directions = append(rsp.Directions, &pb.Direction{ + Name: step.Name, + Instruction: instruction, + Distance: float64(step.Distance), + Duration: float64(step.Duration), + Maneuver: &pb.Maneuver{ + BearingBefore: float64(step.Maneuver.BearingBefore), + BearingAfter: float64(step.Maneuver.BearingAfter), + Location: &pb.Point{ + Latitude: float64(step.Maneuver.Location.Lat()), + Longitude: float64(step.Maneuver.Location.Lng()), + }, + Action: step.Maneuver.Type, + Direction: step.Maneuver.Modifier, + }, + Intersections: intersections, + }) + } + } + + return nil +} + func (o *OSRM) Eta(ctx context.Context, req *pb.EtaRequest, rsp *pb.EtaResponse) error { // validate the request if req.Origin == nil { @@ -126,18 +241,24 @@ func (o *OSRM) Route(ctx context.Context, req *pb.RouteRequest, rsp *pb.RouteRes return errors.InternalServerError("routing.route", "failed to get route: %v", err.Error()) } - for _, routes := range resp.Routes { - for _, leg := range routes.Legs { - for _, step := range leg.Steps { - for _, intersect := range step.Intersections { - rsp.Waypoints = append(rsp.Waypoints, &pb.Waypoint{ - Name: step.Name, - Location: &pb.Point{ - Latitude: intersect.Location.Lat(), - Longitude: intersect.Location.Lng(), - }, - }) - } + if len(resp.Routes) == 0 { + return nil + } + + // set distance and duration + rsp.Duration = float64(resp.Routes[0].Duration) + rsp.Distance = float64(resp.Routes[0].Distance) + + for _, leg := range resp.Routes[0].Legs { + for _, step := range leg.Steps { + for _, intersect := range step.Intersections { + rsp.Waypoints = append(rsp.Waypoints, &pb.Waypoint{ + Name: step.Name, + Location: &pb.Point{ + Latitude: intersect.Location.Lat(), + Longitude: intersect.Location.Lng(), + }, + }) } } } diff --git a/routing/main.go b/routing/main.go index f66e4e4..7cb6f01 100644 --- a/routing/main.go +++ b/routing/main.go @@ -28,7 +28,7 @@ func main() { switch mode { case "google": // Setup google maps - c, err := config.Get("google.api.key") + c, err := config.Get("google.apikey") if err != nil { logger.Fatalf("Error loading config: %v", err) } @@ -43,7 +43,7 @@ func main() { // Register handler pb.RegisterRoutingHandler(srv.Server(), &handler.Google{m}) - case "osrm": + case "osrm", "": // todo // Setup google maps c, err := config.Get("routing.address") @@ -52,7 +52,7 @@ func main() { } apiAddr := c.String("http://router.project-osrm.org") if len(apiAddr) == 0 { - logger.Fatalf("Missing required config: osrm.api.address") + logger.Fatalf("Missing required config: routing.address") } // Register handler pb.RegisterRoutingHandler(srv.Server(), &handler.OSRM{Address: apiAddr}) diff --git a/routing/proto/routing.pb.go b/routing/proto/routing.pb.go index 5d6bfca..23c1b35 100644 --- a/routing/proto/routing.pb.go +++ b/routing/proto/routing.pb.go @@ -132,6 +132,372 @@ func (x *Waypoint) GetLocation() *Point { return nil } +type Maneuver struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BearingBefore float64 `protobuf:"fixed64,1,opt,name=bearing_before,json=bearingBefore,proto3" json:"bearing_before,omitempty"` + BearingAfter float64 `protobuf:"fixed64,2,opt,name=bearing_after,json=bearingAfter,proto3" json:"bearing_after,omitempty"` + Location *Point `protobuf:"bytes,3,opt,name=location,proto3" json:"location,omitempty"` + Action string `protobuf:"bytes,4,opt,name=action,proto3" json:"action,omitempty"` + Direction string `protobuf:"bytes,5,opt,name=direction,proto3" json:"direction,omitempty"` +} + +func (x *Maneuver) Reset() { + *x = Maneuver{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_routing_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Maneuver) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Maneuver) ProtoMessage() {} + +func (x *Maneuver) ProtoReflect() protoreflect.Message { + mi := &file_proto_routing_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Maneuver.ProtoReflect.Descriptor instead. +func (*Maneuver) Descriptor() ([]byte, []int) { + return file_proto_routing_proto_rawDescGZIP(), []int{2} +} + +func (x *Maneuver) GetBearingBefore() float64 { + if x != nil { + return x.BearingBefore + } + return 0 +} + +func (x *Maneuver) GetBearingAfter() float64 { + if x != nil { + return x.BearingAfter + } + return 0 +} + +func (x *Maneuver) GetLocation() *Point { + if x != nil { + return x.Location + } + return nil +} + +func (x *Maneuver) GetAction() string { + if x != nil { + return x.Action + } + return "" +} + +func (x *Maneuver) GetDirection() string { + if x != nil { + return x.Direction + } + return "" +} + +type Intersection struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Location *Point `protobuf:"bytes,1,opt,name=location,proto3" json:"location,omitempty"` + Bearings []float64 `protobuf:"fixed64,2,rep,packed,name=bearings,proto3" json:"bearings,omitempty"` +} + +func (x *Intersection) Reset() { + *x = Intersection{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_routing_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Intersection) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Intersection) ProtoMessage() {} + +func (x *Intersection) ProtoReflect() protoreflect.Message { + mi := &file_proto_routing_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Intersection.ProtoReflect.Descriptor instead. +func (*Intersection) Descriptor() ([]byte, []int) { + return file_proto_routing_proto_rawDescGZIP(), []int{3} +} + +func (x *Intersection) GetLocation() *Point { + if x != nil { + return x.Location + } + return nil +} + +func (x *Intersection) GetBearings() []float64 { + if x != nil { + return x.Bearings + } + return nil +} + +type Direction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // street name or location + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // alternative reference + Reference string `protobuf:"bytes,2,opt,name=reference,proto3" json:"reference,omitempty"` + // human readable instruction + Instruction string `protobuf:"bytes,3,opt,name=instruction,proto3" json:"instruction,omitempty"` + // distance to travel in meters + Distance float64 `protobuf:"fixed64,4,opt,name=distance,proto3" json:"distance,omitempty"` + // duration to travel in seconds + Duration float64 `protobuf:"fixed64,5,opt,name=duration,proto3" json:"duration,omitempty"` + // maneuver to take + Maneuver *Maneuver `protobuf:"bytes,6,opt,name=maneuver,proto3" json:"maneuver,omitempty"` + // intersections on route + Intersections []*Intersection `protobuf:"bytes,7,rep,name=intersections,proto3" json:"intersections,omitempty"` +} + +func (x *Direction) Reset() { + *x = Direction{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_routing_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Direction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Direction) ProtoMessage() {} + +func (x *Direction) ProtoReflect() protoreflect.Message { + mi := &file_proto_routing_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Direction.ProtoReflect.Descriptor instead. +func (*Direction) Descriptor() ([]byte, []int) { + return file_proto_routing_proto_rawDescGZIP(), []int{4} +} + +func (x *Direction) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Direction) GetReference() string { + if x != nil { + return x.Reference + } + return "" +} + +func (x *Direction) GetInstruction() string { + if x != nil { + return x.Instruction + } + return "" +} + +func (x *Direction) GetDistance() float64 { + if x != nil { + return x.Distance + } + return 0 +} + +func (x *Direction) GetDuration() float64 { + if x != nil { + return x.Duration + } + return 0 +} + +func (x *Direction) GetManeuver() *Maneuver { + if x != nil { + return x.Maneuver + } + return nil +} + +func (x *Direction) GetIntersections() []*Intersection { + if x != nil { + return x.Intersections + } + return nil +} + +type DirectionsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Origin *Point `protobuf:"bytes,1,opt,name=origin,proto3" json:"origin,omitempty"` + Destination *Point `protobuf:"bytes,2,opt,name=destination,proto3" json:"destination,omitempty"` +} + +func (x *DirectionsRequest) Reset() { + *x = DirectionsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_routing_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DirectionsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DirectionsRequest) ProtoMessage() {} + +func (x *DirectionsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_routing_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DirectionsRequest.ProtoReflect.Descriptor instead. +func (*DirectionsRequest) Descriptor() ([]byte, []int) { + return file_proto_routing_proto_rawDescGZIP(), []int{5} +} + +func (x *DirectionsRequest) GetOrigin() *Point { + if x != nil { + return x.Origin + } + return nil +} + +func (x *DirectionsRequest) GetDestination() *Point { + if x != nil { + return x.Destination + } + return nil +} + +type DirectionsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Turn by turn directions + Directions []*Direction `protobuf:"bytes,1,rep,name=directions,proto3" json:"directions,omitempty"` + // The waypoints on the route + Waypoints []*Waypoint `protobuf:"bytes,2,rep,name=waypoints,proto3" json:"waypoints,omitempty"` + // Estimated distance of the route in meters + Distance float64 `protobuf:"fixed64,3,opt,name=distance,proto3" json:"distance,omitempty"` + // Estimated duration of the route in seconds + Duration float64 `protobuf:"fixed64,4,opt,name=duration,proto3" json:"duration,omitempty"` +} + +func (x *DirectionsResponse) Reset() { + *x = DirectionsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_routing_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DirectionsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DirectionsResponse) ProtoMessage() {} + +func (x *DirectionsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_routing_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DirectionsResponse.ProtoReflect.Descriptor instead. +func (*DirectionsResponse) Descriptor() ([]byte, []int) { + return file_proto_routing_proto_rawDescGZIP(), []int{6} +} + +func (x *DirectionsResponse) GetDirections() []*Direction { + if x != nil { + return x.Directions + } + return nil +} + +func (x *DirectionsResponse) GetWaypoints() []*Waypoint { + if x != nil { + return x.Waypoints + } + return nil +} + +func (x *DirectionsResponse) GetDistance() float64 { + if x != nil { + return x.Distance + } + return 0 +} + +func (x *DirectionsResponse) GetDuration() float64 { + if x != nil { + return x.Duration + } + return 0 +} + type EtaRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -148,7 +514,7 @@ type EtaRequest struct { func (x *EtaRequest) Reset() { *x = EtaRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_routing_proto_msgTypes[2] + mi := &file_proto_routing_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -161,7 +527,7 @@ func (x *EtaRequest) String() string { func (*EtaRequest) ProtoMessage() {} func (x *EtaRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_routing_proto_msgTypes[2] + mi := &file_proto_routing_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -174,7 +540,7 @@ func (x *EtaRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use EtaRequest.ProtoReflect.Descriptor instead. func (*EtaRequest) Descriptor() ([]byte, []int) { - return file_proto_routing_proto_rawDescGZIP(), []int{2} + return file_proto_routing_proto_rawDescGZIP(), []int{7} } func (x *EtaRequest) GetOrigin() *Point { @@ -217,7 +583,7 @@ type EtaResponse struct { func (x *EtaResponse) Reset() { *x = EtaResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_routing_proto_msgTypes[3] + mi := &file_proto_routing_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -230,7 +596,7 @@ func (x *EtaResponse) String() string { func (*EtaResponse) ProtoMessage() {} func (x *EtaResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_routing_proto_msgTypes[3] + mi := &file_proto_routing_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -243,7 +609,7 @@ func (x *EtaResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EtaResponse.ProtoReflect.Descriptor instead. func (*EtaResponse) Descriptor() ([]byte, []int) { - return file_proto_routing_proto_rawDescGZIP(), []int{3} + return file_proto_routing_proto_rawDescGZIP(), []int{8} } func (x *EtaResponse) GetDuration() float64 { @@ -267,7 +633,7 @@ type RouteRequest struct { func (x *RouteRequest) Reset() { *x = RouteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_routing_proto_msgTypes[4] + mi := &file_proto_routing_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -280,7 +646,7 @@ func (x *RouteRequest) String() string { func (*RouteRequest) ProtoMessage() {} func (x *RouteRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_routing_proto_msgTypes[4] + mi := &file_proto_routing_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -293,7 +659,7 @@ func (x *RouteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RouteRequest.ProtoReflect.Descriptor instead. func (*RouteRequest) Descriptor() ([]byte, []int) { - return file_proto_routing_proto_rawDescGZIP(), []int{4} + return file_proto_routing_proto_rawDescGZIP(), []int{9} } func (x *RouteRequest) GetOrigin() *Point { @@ -315,14 +681,18 @@ type RouteResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // estimated distance in meters + Distance float64 `protobuf:"fixed64,1,opt,name=distance,proto3" json:"distance,omitempty"` + // estimated duration in seconds + Duration float64 `protobuf:"fixed64,2,opt,name=duration,proto3" json:"duration,omitempty"` // waypoints on the route - Waypoints []*Waypoint `protobuf:"bytes,2,rep,name=waypoints,proto3" json:"waypoints,omitempty"` + Waypoints []*Waypoint `protobuf:"bytes,3,rep,name=waypoints,proto3" json:"waypoints,omitempty"` } func (x *RouteResponse) Reset() { *x = RouteResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_routing_proto_msgTypes[5] + mi := &file_proto_routing_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -335,7 +705,7 @@ func (x *RouteResponse) String() string { func (*RouteResponse) ProtoMessage() {} func (x *RouteResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_routing_proto_msgTypes[5] + mi := &file_proto_routing_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -348,7 +718,21 @@ func (x *RouteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RouteResponse.ProtoReflect.Descriptor instead. func (*RouteResponse) Descriptor() ([]byte, []int) { - return file_proto_routing_proto_rawDescGZIP(), []int{5} + return file_proto_routing_proto_rawDescGZIP(), []int{10} +} + +func (x *RouteResponse) GetDistance() float64 { + if x != nil { + return x.Distance + } + return 0 +} + +func (x *RouteResponse) GetDuration() float64 { + if x != nil { + return x.Duration + } + return 0 } func (x *RouteResponse) GetWaypoints() []*Waypoint { @@ -371,39 +755,99 @@ var file_proto_routing_proto_rawDesc = []byte{ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x90, 0x01, - 0x0a, 0x0a, 0x45, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, - 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, - 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x6f, 0x72, - 0x69, 0x67, 0x69, 0x6e, 0x12, 0x30, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x6f, 0x75, 0x74, - 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, - 0x65, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, - 0x22, 0x29, 0x0a, 0x0b, 0x45, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x01, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x68, 0x0a, 0x0c, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x6f, + 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb8, 0x01, + 0x0a, 0x08, 0x4d, 0x61, 0x6e, 0x65, 0x75, 0x76, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x65, + 0x61, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x01, 0x52, 0x0d, 0x62, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x42, 0x65, 0x66, 0x6f, 0x72, + 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x66, 0x74, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x69, 0x6e, + 0x67, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, + 0x6e, 0x67, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x56, 0x0a, 0x0c, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x6f, 0x75, + 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x01, 0x52, 0x08, 0x62, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x73, + 0x22, 0x83, 0x02, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1a, + 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, + 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x08, 0x6d, 0x61, + 0x6e, 0x65, 0x75, 0x76, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, + 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4d, 0x61, 0x6e, 0x65, 0x75, 0x76, 0x65, 0x72, 0x52, + 0x08, 0x6d, 0x61, 0x6e, 0x65, 0x75, 0x76, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x0d, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x6d, 0x0a, 0x11, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x30, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x40, 0x0a, 0x0d, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x77, 0x61, 0x79, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x6f, 0x75, 0x74, - 0x69, 0x6e, 0x67, 0x2e, 0x57, 0x61, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x09, 0x77, 0x61, - 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x32, 0x77, 0x0a, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x69, - 0x6e, 0x67, 0x12, 0x38, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x15, 0x2e, 0x72, 0x6f, - 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x32, 0x0a, 0x03, - 0x45, 0x74, 0x61, 0x12, 0x13, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x74, - 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, - 0x6e, 0x67, 0x2e, 0x45, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x42, 0x11, 0x5a, 0x0f, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x72, 0x6f, 0x75, 0x74, - 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb1, 0x01, 0x0a, 0x12, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x0a, + 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x2f, 0x0a, 0x09, 0x77, 0x61, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x57, 0x61, + 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x09, 0x77, 0x61, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x01, 0x52, 0x08, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1a, 0x0a, + 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, + 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x90, 0x01, 0x0a, 0x0a, 0x45, 0x74, + 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, + 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, + 0x6e, 0x67, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, + 0x12, 0x30, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, + 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x22, 0x29, 0x0a, 0x0b, + 0x45, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x64, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x68, 0x0a, 0x0c, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, + 0x67, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, + 0x30, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x50, + 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x22, 0x78, 0x0a, 0x0d, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1a, + 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, + 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x09, 0x77, 0x61, + 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x57, 0x61, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x52, 0x09, 0x77, 0x61, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x32, 0xc0, 0x01, 0x0a, 0x07, + 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x38, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x12, 0x15, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, + 0x67, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x32, 0x0a, 0x03, 0x45, 0x74, 0x61, 0x12, 0x13, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, + 0x6e, 0x67, 0x2e, 0x45, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, + 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0a, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1b, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x11, + 0x5a, 0x0f, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, + 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -418,31 +862,46 @@ func file_proto_routing_proto_rawDescGZIP() []byte { return file_proto_routing_proto_rawDescData } -var file_proto_routing_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_proto_routing_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_proto_routing_proto_goTypes = []interface{}{ - (*Point)(nil), // 0: routing.Point - (*Waypoint)(nil), // 1: routing.Waypoint - (*EtaRequest)(nil), // 2: routing.EtaRequest - (*EtaResponse)(nil), // 3: routing.EtaResponse - (*RouteRequest)(nil), // 4: routing.RouteRequest - (*RouteResponse)(nil), // 5: routing.RouteResponse + (*Point)(nil), // 0: routing.Point + (*Waypoint)(nil), // 1: routing.Waypoint + (*Maneuver)(nil), // 2: routing.Maneuver + (*Intersection)(nil), // 3: routing.Intersection + (*Direction)(nil), // 4: routing.Direction + (*DirectionsRequest)(nil), // 5: routing.DirectionsRequest + (*DirectionsResponse)(nil), // 6: routing.DirectionsResponse + (*EtaRequest)(nil), // 7: routing.EtaRequest + (*EtaResponse)(nil), // 8: routing.EtaResponse + (*RouteRequest)(nil), // 9: routing.RouteRequest + (*RouteResponse)(nil), // 10: routing.RouteResponse } var file_proto_routing_proto_depIdxs = []int32{ - 0, // 0: routing.Waypoint.location:type_name -> routing.Point - 0, // 1: routing.EtaRequest.origin:type_name -> routing.Point - 0, // 2: routing.EtaRequest.destination:type_name -> routing.Point - 0, // 3: routing.RouteRequest.origin:type_name -> routing.Point - 0, // 4: routing.RouteRequest.destination:type_name -> routing.Point - 1, // 5: routing.RouteResponse.waypoints:type_name -> routing.Waypoint - 4, // 6: routing.Routing.Route:input_type -> routing.RouteRequest - 2, // 7: routing.Routing.Eta:input_type -> routing.EtaRequest - 5, // 8: routing.Routing.Route:output_type -> routing.RouteResponse - 3, // 9: routing.Routing.Eta:output_type -> routing.EtaResponse - 8, // [8:10] is the sub-list for method output_type - 6, // [6:8] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 0, // 0: routing.Waypoint.location:type_name -> routing.Point + 0, // 1: routing.Maneuver.location:type_name -> routing.Point + 0, // 2: routing.Intersection.location:type_name -> routing.Point + 2, // 3: routing.Direction.maneuver:type_name -> routing.Maneuver + 3, // 4: routing.Direction.intersections:type_name -> routing.Intersection + 0, // 5: routing.DirectionsRequest.origin:type_name -> routing.Point + 0, // 6: routing.DirectionsRequest.destination:type_name -> routing.Point + 4, // 7: routing.DirectionsResponse.directions:type_name -> routing.Direction + 1, // 8: routing.DirectionsResponse.waypoints:type_name -> routing.Waypoint + 0, // 9: routing.EtaRequest.origin:type_name -> routing.Point + 0, // 10: routing.EtaRequest.destination:type_name -> routing.Point + 0, // 11: routing.RouteRequest.origin:type_name -> routing.Point + 0, // 12: routing.RouteRequest.destination:type_name -> routing.Point + 1, // 13: routing.RouteResponse.waypoints:type_name -> routing.Waypoint + 9, // 14: routing.Routing.Route:input_type -> routing.RouteRequest + 7, // 15: routing.Routing.Eta:input_type -> routing.EtaRequest + 5, // 16: routing.Routing.Directions:input_type -> routing.DirectionsRequest + 10, // 17: routing.Routing.Route:output_type -> routing.RouteResponse + 8, // 18: routing.Routing.Eta:output_type -> routing.EtaResponse + 6, // 19: routing.Routing.Directions:output_type -> routing.DirectionsResponse + 17, // [17:20] is the sub-list for method output_type + 14, // [14:17] is the sub-list for method input_type + 14, // [14:14] is the sub-list for extension type_name + 14, // [14:14] is the sub-list for extension extendee + 0, // [0:14] is the sub-list for field type_name } func init() { file_proto_routing_proto_init() } @@ -476,7 +935,7 @@ func file_proto_routing_proto_init() { } } file_proto_routing_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EtaRequest); i { + switch v := v.(*Maneuver); i { case 0: return &v.state case 1: @@ -488,7 +947,7 @@ func file_proto_routing_proto_init() { } } file_proto_routing_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EtaResponse); i { + switch v := v.(*Intersection); i { case 0: return &v.state case 1: @@ -500,7 +959,7 @@ func file_proto_routing_proto_init() { } } file_proto_routing_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RouteRequest); i { + switch v := v.(*Direction); i { case 0: return &v.state case 1: @@ -512,6 +971,66 @@ func file_proto_routing_proto_init() { } } file_proto_routing_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DirectionsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_routing_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DirectionsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_routing_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EtaRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_routing_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EtaResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_routing_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_routing_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RouteResponse); i { case 0: return &v.state @@ -530,7 +1049,7 @@ func file_proto_routing_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_routing_proto_rawDesc, NumEnums: 0, - NumMessages: 6, + NumMessages: 11, NumExtensions: 0, NumServices: 1, }, diff --git a/routing/proto/routing.pb.micro.go b/routing/proto/routing.pb.micro.go index 7b9297f..2724dcc 100644 --- a/routing/proto/routing.pb.micro.go +++ b/routing/proto/routing.pb.micro.go @@ -46,6 +46,8 @@ type RoutingService interface { Route(ctx context.Context, in *RouteRequest, opts ...client.CallOption) (*RouteResponse, error) // Eta returns an estimated time of arrival for a route Eta(ctx context.Context, in *EtaRequest, opts ...client.CallOption) (*EtaResponse, error) + // Directions provides turn by turn directions + Directions(ctx context.Context, in *DirectionsRequest, opts ...client.CallOption) (*DirectionsResponse, error) } type routingService struct { @@ -80,6 +82,16 @@ func (c *routingService) Eta(ctx context.Context, in *EtaRequest, opts ...client return out, nil } +func (c *routingService) Directions(ctx context.Context, in *DirectionsRequest, opts ...client.CallOption) (*DirectionsResponse, error) { + req := c.c.NewRequest(c.name, "Routing.Directions", in) + out := new(DirectionsResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Routing service type RoutingHandler interface { @@ -87,12 +99,15 @@ type RoutingHandler interface { Route(context.Context, *RouteRequest, *RouteResponse) error // Eta returns an estimated time of arrival for a route Eta(context.Context, *EtaRequest, *EtaResponse) error + // Directions provides turn by turn directions + Directions(context.Context, *DirectionsRequest, *DirectionsResponse) error } func RegisterRoutingHandler(s server.Server, hdlr RoutingHandler, opts ...server.HandlerOption) error { type routing interface { Route(ctx context.Context, in *RouteRequest, out *RouteResponse) error Eta(ctx context.Context, in *EtaRequest, out *EtaResponse) error + Directions(ctx context.Context, in *DirectionsRequest, out *DirectionsResponse) error } type Routing struct { routing @@ -112,3 +127,7 @@ func (h *routingHandler) Route(ctx context.Context, in *RouteRequest, out *Route func (h *routingHandler) Eta(ctx context.Context, in *EtaRequest, out *EtaResponse) error { return h.RoutingHandler.Eta(ctx, in, out) } + +func (h *routingHandler) Directions(ctx context.Context, in *DirectionsRequest, out *DirectionsResponse) error { + return h.RoutingHandler.Directions(ctx, in, out) +} diff --git a/routing/proto/routing.proto b/routing/proto/routing.proto index a59364d..75f665c 100644 --- a/routing/proto/routing.proto +++ b/routing/proto/routing.proto @@ -8,6 +8,8 @@ service Routing { rpc Route(RouteRequest) returns (RouteResponse) {} // Eta returns an estimated time of arrival for a route rpc Eta(EtaRequest) returns (EtaResponse) {} + // Directions provides turn by turn directions + rpc Directions(DirectionsRequest) returns (DirectionsResponse) {} } message Point { @@ -22,6 +24,52 @@ message Waypoint { Point location = 2; } +message Maneuver { + double bearing_before = 1; + double bearing_after = 2; + Point location = 3; + string action = 4; + string direction = 5; +} + +message Intersection { + Point location = 1; + repeated double bearings = 2; +} + +message Direction { + // street name or location + string name = 1; + // alternative reference + string reference = 2; + // human readable instruction + string instruction = 3; + // distance to travel in meters + double distance = 4; + // duration to travel in seconds + double duration = 5; + // maneuver to take + Maneuver maneuver = 6; + // intersections on route + repeated Intersection intersections = 7; +} + +message DirectionsRequest { + Point origin = 1; + Point destination = 2; +} + +message DirectionsResponse { + // Turn by turn directions + repeated Direction directions = 1; + // The waypoints on the route + repeated Waypoint waypoints = 2; + // Estimated distance of the route in meters + double distance = 3; + // Estimated duration of the route in seconds + double duration = 4; +} + message EtaRequest { Point origin = 1; Point destination = 2; @@ -44,6 +92,10 @@ message RouteRequest { } message RouteResponse { + // estimated distance in meters + double distance = 1; + // estimated duration in seconds + double duration = 2; // waypoints on the route - repeated Waypoint waypoints = 2; + repeated Waypoint waypoints = 3; }