summaryrefslogtreecommitdiff
path: root/python/rvi_ws.py
blob: 14ccfcdb28759e18708f0f97aa259860c4a3a87c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#
# Copyright (C) 2016, 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/
#
# rvi_ws 0.1.0
#  
# This module is the websocket implementation of for RVI services. 

# To use this code you will follow these steps.
# 1. Import the rvi_ws class using "import rvi_ws"
# 2. Instantiate a rvi_ws_client class object specifying the bundle_id, debug params, host, and services.
#    services will be a dictionary where the key will be the service_name to register and value will be the service's callback function
#     ex. 
#         rvi_client = rvi_ws.rvi_ws_client(host = <string host url>, bundle_id = <string bundle name>,  services = <dict of callbacks> [,debug = <True|False>])
#
# 3. Register and run the services by invoking the services_run() function in the rvi_ws_client class. This will block all other code
#    execution until the websocket connection closes in which case will return a None value.
#    ex.
#         rvi_client.run_forever()
#

import websocket
import json

# rvi_ws_client will be in charge of handling all communication via websockets between the service bundle and RVI.

class rvi_ws_client(websocket.WebSocketApp):

    def __init__(self, host, bundle_id, services, debug = False):
        super(rvi_ws_client, self).__init__(host)

        self.host = host
        self.DEBUG = debug
        self.service_bundle_id = bundle_id
        self.callback_funcs = services
        self.reg_services = []

        self.on_close = self._on_close
        self.on_open = self._on_open
        self.on_message = self._on_message

        websocket.enableTrace(debug)

        if self.service_bundle_id == None or len(self.service_bundle_id) <= 0:
            raise NameError('rvi_ws_client - No Specified bundle_id')
        if len(self.callback_funcs) <= 0:
            raise EnvironmentError('rvi_ws_client - No services to register')

    # Unregister service for clean close of websocket, for time being will just print out debug
    def _on_close(self, ws):
        unreg_ws = websocket.create_connection(self.host)
        payload = {}
        payload['json-rpc'] = "2.0"
        payload['id'] = "0"
        payload['method'] = "unregister_service"
        
        for unsub in self.reg_services:
            payload['params'] = {
                                'service_name' : unsub
            }
            unreg_ws.send(json.dumps(payload))

    # What to do on the open of the application. Note we must register_services for this to do anything.
    def _on_open(self, ws):

        payload = {}
        payload['json-rpc'] = "2.0"
        payload['id'] = "0"
        payload['method'] = "register_service"

        for service_name, callback in self.callback_funcs.items():
            payload['params'] = {"service_name":self.service_bundle_id+"/"+service_name}        
            self.send(json.dumps(payload))

    # on_message will route the message from the websocket to it's corresponding callback function that registered the service
    def _on_message(self, ws, message):

        message_dict = json.loads(message)

        try:
            if (message_dict['method'] == 'message') and (message_dict['params']['service_name'][(2+len(self.service_bundle_id)):] in self.callback_funcs):
                self.callback_funcs[message_dict['params']['service_name'][(2+len(self.service_bundle_id)):]](**message_dict['params']['parameters'])
            elif message_dict['method'] == 'register_service':
                self.reg_services.append(message_dict['service'])

        except:
            pass

def get_available_services(host):
    ws = websocket.create_connection(host)
    payload = {'json-rpc':'2.0', 'id':0, 'method':'get_available_services', 'params':[]}
    ws.send(json.dumps(payload))
    return json.loads(ws.recv())['services']