1#!/usr/bin/env ruby 2 3# Copyright 2015 gRPC authors. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17# Sample app that connects to a Route Guide service. 18# 19# Usage: $ path/to/route_guide_client.rb path/to/route_guide_db.json & 20 21this_dir = File.expand_path(File.dirname(__FILE__)) 22lib_dir = File.join(File.dirname(this_dir), 'lib') 23$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) 24 25require 'grpc' 26require 'multi_json' 27require 'route_guide_services_pb' 28 29include Routeguide 30 31GET_FEATURE_POINTS = [ 32 Point.new(latitude: 409_146_138, longitude: -746_188_906), 33 Point.new(latitude: 0, longitude: 0) 34] 35 36# runs a GetFeature rpc. 37# 38# - once with a point known to be present in the sample route database 39# - once with a point that is not in the sample database 40def run_get_feature(stub) 41 p 'GetFeature' 42 p '----------' 43 GET_FEATURE_POINTS.each do |pt| 44 resp = stub.get_feature(pt) 45 if resp.name != '' 46 p "- found '#{resp.name}' at #{pt.inspect}" 47 else 48 p "- found nothing at #{pt.inspect}" 49 end 50 end 51end 52 53LIST_FEATURES_RECT = Rectangle.new( 54 lo: Point.new(latitude: 400_000_000, longitude: -750_000_000), 55 hi: Point.new(latitude: 420_000_000, longitude: -730_000_000)) 56 57# runs a ListFeatures rpc. 58# 59# - the rectangle to chosen to include most of the known features 60# in the sample db. 61def run_list_features(stub) 62 p 'ListFeatures' 63 p '------------' 64 resps = stub.list_features(LIST_FEATURES_RECT) 65 resps.each do |r| 66 p "- found '#{r.name}' at #{r.location.inspect}" 67 end 68end 69 70# RandomRoute provides an Enumerable that yields a random 'route' of points 71# from a list of Features. 72class RandomRoute 73 def initialize(features, size) 74 @features = features 75 @size = size 76 end 77 78 # yields a point, waiting between 0 and 1 seconds between each yield 79 # 80 # @return an Enumerable that yields a random point 81 def each 82 return enum_for(:each) unless block_given? 83 @size.times do 84 json_feature = @features[rand(0..@features.length)] 85 next if json_feature.nil? 86 location = json_feature['location'] 87 pt = Point.new( 88 Hash[location.each_pair.map { |k, v| [k.to_sym, v] }]) 89 p "- next point is #{pt.inspect}" 90 yield pt 91 sleep(rand(0..1)) 92 end 93 end 94end 95 96# runs a RecordRoute rpc. 97# 98# - the rectangle to chosen to include most of the known features 99# in the sample db. 100def run_record_route(stub, features) 101 p 'RecordRoute' 102 p '-----------' 103 points_on_route = 10 # arbitrary 104 reqs = RandomRoute.new(features, points_on_route) 105 resp = stub.record_route(reqs.each) 106 p "summary: #{resp.inspect}" 107end 108 109ROUTE_CHAT_NOTES = [ 110 RouteNote.new(message: 'doh - a deer', 111 location: Point.new(latitude: 0, longitude: 0)), 112 RouteNote.new(message: 'ray - a drop of golden sun', 113 location: Point.new(latitude: 0, longitude: 1)), 114 RouteNote.new(message: 'me - the name I call myself', 115 location: Point.new(latitude: 1, longitude: 0)), 116 RouteNote.new(message: 'fa - a longer way to run', 117 location: Point.new(latitude: 1, longitude: 1)), 118 RouteNote.new(message: 'soh - with needle and a thread', 119 location: Point.new(latitude: 0, longitude: 1)) 120] 121 122# runs a RouteChat rpc. 123# 124# sends a canned set of route notes and prints out the responses. 125def run_route_chat(stub) 126 p 'Route Chat' 127 p '----------' 128 sleeping_enumerator = SleepingEnumerator.new(ROUTE_CHAT_NOTES, 1) 129 stub.route_chat(sleeping_enumerator.each_item) { |r| p "received #{r.inspect}" } 130end 131 132# SleepingEnumerator yields through items, and sleeps between each one 133class SleepingEnumerator 134 def initialize(items, delay) 135 @items = items 136 @delay = delay 137 end 138 def each_item 139 return enum_for(:each_item) unless block_given? 140 @items.each do |item| 141 sleep @delay 142 p "next item to send is #{item.inspect}" 143 yield item 144 end 145 end 146end 147 148def main 149 stub = RouteGuide::Stub.new('localhost:50051', :this_channel_is_insecure) 150 run_get_feature(stub) 151 run_list_features(stub) 152 run_route_chat(stub) 153 if ARGV.length == 0 154 p 'no feature database; skipping record_route' 155 exit 156 end 157 raw_data = [] 158 File.open(ARGV[0]) do |f| 159 raw_data = MultiJson.load(f.read) 160 end 161 run_record_route(stub, raw_data) 162end 163 164main 165