diff options
author | Magnus Feuer <mfeuer@jaguarlandrover.com> | 2015-02-12 11:32:59 -0800 |
---|---|---|
committer | Magnus Feuer <mfeuer@jaguarlandrover.com> | 2015-02-12 11:32:59 -0800 |
commit | c3804481dc7f615584f74fb94626b7f900a4ce24 (patch) | |
tree | 059c9f191d08d85e8399f7ecac41508351f31818 /python/rvilib.py | |
parent | 8586ccb7554c19b6ebe8eadf4fd622b68f5fced7 (diff) | |
download | rvi_core-c3804481dc7f615584f74fb94626b7f900a4ce24.tar.gz |
Added simplified RVI integration
Diffstat (limited to 'python/rvilib.py')
-rw-r--r-- | python/rvilib.py | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/python/rvilib.py b/python/rvilib.py new file mode 100644 index 0000000..700e032 --- /dev/null +++ b/python/rvilib.py @@ -0,0 +1,144 @@ +# +# Copyright (C) 2014, Jaguar Land Rover +# +# This program is licensed under the terms and conditions of the +# Mozilla Public License, version 2.0. The full text of the +# Mozilla Public License is at https://www.mozilla.org/MPL/2.0/ +# +# rbilib.py 0.3.0 +# +# This moduke +from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer +from jsonrpclib import Server +import random +import time +import threading + +class RVI(SimpleJSONRPCServer): + # address is either localhost or the ip address of self. + # 0.0.0.0 should work to listen to all addresses, but haven't been tested + # Port is either a fixed port (integer) or a tuple with a start and stop + # port that should be used as a random interval to pick the port from + def __init__(self, rvi_node_url, address='localhost', port=(20001,59999)): + if isinstance(port, tuple) == True: + (start_port, stop_port) = port + self.rvi_port = random.randint(start_port, stop_port) + else: + self.rvi_port = port + + self.rvi_address = address + print self.rvi_address + print self.rvi_port + SimpleJSONRPCServer.__init__(self,addr=((self.rvi_address, self.rvi_port)), logRequests=False) + self.rvi_client = Server(rvi_node_url) + self.serve_thread = False + + # Set the callback to invoke when RVI reports that one or more new + # services are available for invocation somewhere in the network. + # Arguments will be an array of fully qualified service available. + def set_services_available_callback(self, function): + self.register_function(function, 'services_available') + + # Set the callback to invoke when RVI reports that one or more previously + # available services are no longer available for invocation + # + # Arguments will be an array of fully qualified service names no longer available. + def set_services_unavailable_callback(self, function): + self.register_function(function, 'services_unavailable') + + # Register a service in this python program that should + # be reached from the rest of the network. + # + # service_name is the local service name ('/my_stuff/set_fan_speed') + # + # function is a python function reference to invoke when an + # JSON-RPC call for service_nameis received from RVI. + # + # This function will return the fully qualified name of the registered service. + # + # Thus, if you call: + # + # register_service('/my_stuff/set_fan_speed', set_fan_speed) + # + # you will get back the fully qualified service name assigned: + # + # "jlr.com/vin/YV1TS32G54F123456/my_stuff/set_fan_speed" + # + # This is the globally accessible name for the service that can be used anywhere + # in an RVI network to access your service. + # + def register_service(self, service_name, function): + # Register service_name within SimpleJSONRPCServer so that + # when it gets invoked with the given URL suffic, it will call 'function'. + # + # I.e. when self.url() + service_name gets called by the RVI node, we + # will dispatch that call to 'function'. + # + print "Will register {} to function {}".format(service_name, function) + self.register_function(function, service_name) + + # Register the service name with the RVI node so that we get called + # at the URL we are listening on (self.url()). + # + res = self.rvi_client.register_service(service=service_name, network_address=self.url()) + + # Check if we have a thread going + if self.serve_thread == False: + print "No thread started, will do so now" + self.start_serve_thread() + + + # Return the fully qualified service name + return res['service'] + + def start_serve_thread(self): + self.serve_thread = threading.Thread(target=self.serve_forever) + self.serve_thread.start() + + # + # Return the URL that we've setup for incoming JSON-RPC calls + # from the RVI node. + # + def url(self): + return 'http://' + self.rvi_address + ':' + str(self.rvi_port) + + + # + # Send a message to the RVI node to be forwarded to the + # service that registered 'service_name' in the network. + # + def message(self, service_name, parameters, timeout = int(time.time()) + 60 ): + print "message({}, {}, {})".format(service_name, parameters, timeout) + self.rvi_client.message(calling_service= "not_used", + service_name = service_name, + timeout = timeout, + parameters = parameters) + + # + # Check if method is 'message', if so dispatch on + # name 'service_name' instead. + # + def _dispatch(self, method, params): + if method == 'message': + print "Will dispatch message to: " + params['service_name'] + dict_param = {} + # Extract the 'parameters' element from the top level JSON-RPC + # 'param'. + # Convert 'parameters' from [{'vin': 1234}, {hello: 'world'}] to + # a regular dictionary: {'vin': 1234, hello: 'world'} + + # print "Parameters:", params['parameters'] + msg_params = params['parameters'] + for i in range(0, len(msg_params)): + for j in range(0, len(msg_params[i].keys())): + print "params", msg_params[i].keys()[j], "=", msg_params[i].values()[j] + dict_param[msg_params[i].keys()[j]] = msg_params[i].values()[j] + + # print "Parameter disctionary: ", dict_param + # print + # Ship the processed dispatch info upward. + return SimpleJSONRPCServer._dispatch(self, params['service_name'], dict_param) + + # Fallthrough to all other methods. + # Will handle service_re3 + return SimpleJSONRPCServer._dispatch(self,method, params) |