summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus <mfeuer@jaguarlandrover.com>2014-08-11 14:10:55 -0700
committerMagnus <mfeuer@jaguarlandrover.com>2014-08-11 14:10:55 -0700
commitb928375c535c8d239c77938dd87d63dc3ad9af75 (patch)
tree57a1b1a11f3266ab444686010b652e96c29aa01a
parent90ed8e6400d09654f0e2b7969c5bd9cb743235c4 (diff)
downloadrvi_core-b928375c535c8d239c77938dd87d63dc3ad9af75.tar.gz
Temp
Signed-off-by: Magnus <mfeuer@jaguarlandrover.com>
-rw-r--r--Makefile30
-rw-r--r--README.md1
-rw-r--r--TODO15
-rw-r--r--hvac_demo/README.md75
-rwxr-xr-xhvac_demo/hvac_emulator.py59
-rwxr-xr-xhvac_demo/hvac_subscription_service.py93
-rw-r--r--hvac_demo/rvi_json_rpc_server.py28
-rw-r--r--setup_rvi_node.sh43
8 files changed, 269 insertions, 75 deletions
diff --git a/Makefile b/Makefile
index 74fa5e7..dd52378 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,14 @@
+#
+# Makefile for the RVI node.
+#
+#
+
.PHONY: all deps compile setup clean doc setup_backend setup_device
NAME=rvi
-export KVDB_BACKENDS=ets
+SETUP_GEN=./deps/setup/setup_gen
-SETUP_GEN=$(shell ./find_setup_gen.sh)
all: deps compile
@@ -18,17 +22,10 @@ compile:
recomp:
./rebar compile skip_deps=true
-setup_device:
- ERL_LIBS=$(PWD)/deps:$(ERL_LIBS):$(PWD) \
- $(SETUP_GEN) $(NAME) priv/setup_device.config setup_device
-
-setup_backend:
- ERL_LIBS=$(PWD)/deps:$(ERL_LIBS):$(PWD) \
- $(SETUP_GEN) $(NAME) priv/setup_backend.config setup_backend
target_backend:
ERL_LIBS=$(PWD)/deps:$(ERL_LIBS) \
- $(SETUP_GEN) $(NAME) priv/setup_backend.config setup -pz $(PWD)/ebin \
+ $(SETUP_GEN) $(NAME) priv/backend.config setup -pz $(PWD)/ebin \
-target rel_backend -vsn 0.1
target_device:
@@ -36,19 +33,6 @@ target_device:
$(SETUP_GEN) $(NAME) priv/setup_device.config setup -pz $(PWD)/ebin \
-target rel_device -vsn 0.1
-#
-# Start the backend server
-#
-run_backend: setup_backend
- erl -boot setup_backend/start -config setup_backend/sys
-
-
-#
-# Start the backend device.
-#
-run_device: setup_device
- erl -boot setup_device/start -config setup_device/sys
-
doc:
./REBAR_DOC=1 ./rebar skip_deps=true get-deps doc
diff --git a/README.md b/README.md
index f888c3c..7e8e156 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
# TOP LEVEL RVI PROJECT
+
Better documentation coming soon.
Preqequisites.
diff --git a/TODO b/TODO
index 614d6c3..8c8d0cf 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,17 @@
In doc and code, convert JSON-RPC param "parameters" to "arguments" in order to avoid
confusion with JSON-RPC "params"
-In doc and code, rename "target" "service" or potentially "target service"
+In doc and code, rename "target" "service" or potentially "target
+ service"
+
+In HLD, update data_link_up use case (Step 10) to involve service
+ discovery
+
+In HLD, schedule, data link, and service discovery - Fix code so that
+ service availability is managed by service discovery only. Today
+ the network address of a given service (set by data_link_up calls
+ from data_link_device) are received by schedule, which maintains a
+ redundant copy of all service availability states. This should be
+ moved to Servide Discovery, which should forward the call to
+ schedule. HLD
-
diff --git a/hvac_demo/README.md b/hvac_demo/README.md
index 01821d2..9c9be51 100644
--- a/hvac_demo/README.md
+++ b/hvac_demo/README.md
@@ -1,11 +1,72 @@
-The HVAC service is a test service that registers with the backend server to handle a very simple pub/sub setup.
+# HVAC DEMO
-Accepted commands are:
-subscribe(vin, subscriber) -> Any updates to the given vin should be sent as publish command to the given subscriber (a service running on a device).
-unsubscribe(vin, subscriber) -> Remove subscription conenction between subscriber and vin.
+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/
+
+# BACKGROUND
+The remote HVAC control demo is a part of the Automotive Grade Linux
+project where the Tizen IVI climate control (HVAC) screen can be
+remotely controlled from a mobile device. Updates made to the IVI HVAC
+screen are sent in real time to the mobile device, and vice versa.
+
+An initial release of the remote HVAC demo was done using the MQTT
+protocol (mqtt.org). The first milestone of the RVI project will
+migrate the HVAC demo to the RVI technology.
+
+# CONTENT
+This directory contains a simple subscription service
+(hvac\_subscription\_service.py) replacing the MQTT broker. The
+subscription service lets the IVI and mobile devices setup
+subscriptions so that they receive notifications when the HVAC values
+for a specific VIN (Vehicle Identification Number) have been
+updated. The service is, in effect, a standard publish/subscribe
+setup.
+
+In order to test the RVI milestone 1 and the subscription service
+without having to bring up a complete Tizen IVI and mobile device
+environment, a simple emulator for these two components have been
+providedin hvac_emulator.py.
+
+The emulator can be started in IVI or mobile device mode. Please run
+./hvac_emulator.py for usage details.
+
+# TEST SETUP
+
+Two RVI nodes will be involved in the test:
+
+The backend node will host the subscription service (hvac\_subscription\_service.py), and will also
+receive requests from the mobile device emultor (hvac_emulator.py).
+
+The IVI node will host the IVI emulator.
+
+## CREATE THE MOBILE DEVICE NODE
+
+From the rvi root directory, setup the mobile device node:
+
+ ./setup_rvi_node ivi priv/setup_ivi.config
+
+In a similar manner, setup the IVI backend node:
+
+ ./setup_rvi_node backend priv/setup_backend.config
+
+The result will be two new directories, ivi and backend, created under the rvi root directory.
+
+Since both rvi nodes will execute on the same machine, each node will have to specify their
+own port range, which is handled through the -p
+
+
+In antoer window, launch the backend node:
+
+
+ ./rvi_node -n backend -p 23070
+
+
+Launch the IVI rvi node in its own window:
+
+ ./rvi_node -n ivi -p 23050 -b localhost:23070
-publish(vin, key, value) -> A given vin is updating a key with a new value. All subscribers to the vin will be notified.
-Dependencies:
-pip install jsonrpclib
diff --git a/hvac_demo/hvac_emulator.py b/hvac_demo/hvac_emulator.py
index a9cc863..4b42c08 100755
--- a/hvac_demo/hvac_emulator.py
+++ b/hvac_demo/hvac_emulator.py
@@ -1,6 +1,14 @@
#!/usr/bin/python
#
+# 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/
+#
+
+#
# Emulate a mobile device or an IVI.
#
# This emulator connects to an RVI Service Edge as a service and
@@ -90,7 +98,6 @@ import threading
#
SUBSCRIPTION_SERVICE_BASE='jlr.com/backend/subscription_service'
SUBSCRIBE_SERVICE=SUBSCRIPTION_SERVICE_BASE+'/subscribe'
-UNSUBSCRIBE_SERVICE=SUBSCRIPTION_SERVICE_BASE+'/unsubscribe'
PUBLISH_SERVICE=SUBSCRIPTION_SERVICE_BASE+'/publish'
#
@@ -100,7 +107,7 @@ PUBLISH_SERVICE=SUBSCRIPTION_SERVICE_BASE+'/publish'
#
def publish(vin, key, value):
print "Publish invoked!"
- print "vin:", viny
+ print "vin:", vin
print "key:", key
print "value:", value
return ['ok']
@@ -115,6 +122,9 @@ def usage():
print "The RVI Service Edge URL can be found in"
print "priv/setup_[backend,device].config as"
print "env -> rvi -> components -> service_edge -> url"
+ print
+ print "The RVI Service Edge URL can can also be specified"
+ print "on the command line of the rvi_node.sh script."
sys.exit(255)
@@ -127,7 +137,7 @@ def usage():
#
emulator_service_host = 'localhost'
emulator_service_port = random.randint(20001, 59999)
-
+emulator_service_url = 'http://'+emulator_service_host + ':' + str(emulator_service_port)
@@ -152,10 +162,24 @@ if len(sys.argv) == 5:
# The complete service name will be: jlr.com/backend/mobile/<phone_nr>/hvac/publish
emulator_service_name = '/mobile/'+phone_number+'/hvac/publish'
+
+ # Setup an outbound JSON-RPC connection to the RVI Service Edeg.
+ rvi_server = jsonrpclib.Server(rvi_url)
+
+ # Register our HVAC mobile emulator service with the RVI Service Edge,
+ # allowing the RVI to forward requests to the service name to the
+ # given network addresss (URL):
+ print "Emulator service URL", emulator_service_url
+ res = rvi_server.register_service(service = emulator_service_name,
+ network_address = emulator_service_url)
+
+ full_emulator_service_name = res['service']
+
print "Will run in mobile device mode."
print "Backend server node URL: ", rvi_url
print "Phone Number: ", phone_number
print "VIN: ", vin
+ print "Full Service Name: ", full_emulator_service_name
elif len(sys.argv) == 3:
[ progname, rvi_url, mode ] = sys.argv
@@ -173,21 +197,20 @@ elif len(sys.argv) == 3:
# Setup an outbound JSON-RPC connection to the RVI Service Edeg.
rvi_server = jsonrpclib.Server(rvi_url)
- # Register our HVAC IVI/mobile emulator service with the RVI Service Edge,
+ # Register our HVAC IVI emulator service with the RVI Service Edge,
# allowing the RVI to forward requests to the service name to the
# given network addresss (URL):
+
res = rvi_server.register_service(service = emulator_service_name,
- network_address =
- 'http://'+emulator_service_host + ':' + str(emulator_service_port))
+ network_address = emulator_service_url)
# The returned full service name contains the VIN number that we want:
# jlr.com/vin/<vin>/hvac/publish
# We need to dig out the <vin> bit
- print "res = ", res
- svc_name = res['service']
+ full_emulator_service_name = res['service']
- [ t1, t2, vin, t3, t4] = svc_name.split('/')
+ [ t1, t2, vin, t3, t4] = full_emulator_service_name.split('/')
print "vin:", vin,
# We are in mobile device mode. Setup the vin numbers for publish
@@ -215,7 +238,7 @@ rvi_server.message(calling_service = emulator_service_name,
target = SUBSCRIBE_SERVICE,
timeout = 0,
parameters = [{ u'vin': sub_vin,
- u'subscribing_service': emulator_service_name}])
+ u'subscribing_service': full_emulator_service_name}])
# Create a thread to handle incoming stuff so that we can do input
# in order to get new values
@@ -223,15 +246,25 @@ thr = threading.Thread(target=emulator_service.serve_forever)
thr.start()
while True:
+ line = raw_input('Enter <key> <val> or "q" for quit: ')
+ if line == 'q':
+ emulator_service.shutdown()
+ sys.exit(0)
+
# Read a line and split it into a key val pair
- [k, v] = raw_input('Enter <key> <val>: ').split(' ')
+ lst = line.split(' ')
+ if len(lst) != 2:
+ print "Nope", len(lst), lst
+ continue
+
+ [k, v] = line.split(' ')
# Send out update to the subscriber
- rvi_server.message(calling_service=emulator_service_name,
+ rvi_server.message(calling_service= emulator_service_name,
target = PUBLISH_SERVICE,
timeout = 0,
parameters = [{ u'vin': pub_vin,
u'key': k,
- u'val': v}])
+ u'value': v}])
print('Key {} set to {} for vin{}'. format(k, v, vin))
diff --git a/hvac_demo/hvac_subscription_service.py b/hvac_demo/hvac_subscription_service.py
index 88c8435..27c9d05 100755
--- a/hvac_demo/hvac_subscription_service.py
+++ b/hvac_demo/hvac_subscription_service.py
@@ -1,4 +1,60 @@
#!/usr/bin/python
+#
+# 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/
+#
+
+#
+# This is an extremely simple subscription service that connects to
+# a central backend RVI node. The node is well known by all
+# other RVI nodes in a network, who has the backedn node configured
+# as a "static" node. See priv/setup_device.config for an example.
+#
+# The subscription service will register the following services
+# with the backend RVI node:
+#
+# /subscription_service/subscribe
+# (Full name: jlr.com/backend/subscription_service/subscribe)
+# Parameters:
+# vin - The VIN number for which updates are subscribed to.
+# subscribing_service - The service to send a message to when
+# the given vin is updated.
+#
+# Adds the given service to the list of subscribers to notify
+#
+# When a message is recieved by the /subscribing_service/publish
+# service, all subscribers who have specified a vin
+# matching that provided with the publish message will have
+# the message forwarded to them.
+#
+# /subscription_service/unsubscribe
+# (Full name: jlr.com/backend/subscription_service/unsubscribe)
+# Parameters:
+# vin - The VIN number from which the service unsubscribes.
+# subscribing_service - The service that unsubscribes.,
+#
+# Removes a service, previously subscribing to the service through
+# a subscribe command, from the given vin. Future updates
+# to the vin will not be forwarded to the given service.
+#
+# /subscription_service/publish
+# (Full name: jlr.com/backend/subscription_service/publish)
+# Parameters:
+# vin - The VIN number from which the service unsubscribes.
+# key - The key that has an updated value
+# value - The new value assigned to key
+#
+# Distributes the key/value pair to all services that have previosuly
+# subscribed to updates for the given vin.
+#
+# For RVI Milestone 1, the mobile and Tizen IVI UI remains to be
+# integrated with the RVI system itself. Meanwhile, hvac_emulator.py
+# is provded as a simple tester that can emulate either an IVI or
+# a mobile device.
+#
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer
import jsonrpclib
@@ -15,7 +71,7 @@ HVAC_SERVER=('localhost', 8901)
#
# Thus:
# { '1234': [ 'jlr.com/vin/5555/hvac_update_ui', 'jlr.com/vin/4711/hvac_update_ui']
-vin_subs = []
+vin_subs = {}
def subscribe(vin, subscribing_service):
print "Subscribe"
@@ -23,13 +79,14 @@ def subscribe(vin, subscribing_service):
print "subscribing_service:", subscribing_service
# Delete any existing service with the same name
- try:
- vin_subs[vin].remove(subscribing_service)
- except Err:
- pass
-
# Add the subscribing service
- vin_subs[vin].append(subscribing_service)
+ if not vin in vin_subs:
+ vin_subs[vin] = [subscribing_service]
+ else:
+ if vin_subs[vin].count(subscribing_service) == 0:
+ vin_subs[vin].append(subscribing_service)
+
+ print "Result: ",vin_subs
return ['ok']
@@ -39,10 +96,9 @@ def unsubscribe(vin, subscribing_service):
print "subscribing_service:", subscribing_service
# Delete any existing service with the same name
- try:
+
+ if vin in vin_subs and vin_subs[vin].count(subscribing_service) > 0:
vin_subs[vin].remove(subscribing_service)
- except Err:
- pass
return ['ok']
@@ -52,28 +108,29 @@ def publish(vin, key, value):
print "key:", key
print "value:", value
- # Delete any existing service with the same name
+ # Distribute
try:
subs = vin_subs[vin]
except Err:
print "No subscribers for vin:", vin
return ['ok']
+ print "subs:", subs
for sub in subs:
print "Sending publish to", sub
rvi_server.message(calling_service = '/hvac/publish',
target = sub,
timeout = 0,
- parameters = [{ u'key': key}, {u'value': value }])
+ parameters = [{ u'vin': vin, u'key': key}, {u'value': value }])
# Setup self's server that we will receive incoming calls from service edge on.
hvac_server = RVIJSONRPCServer(HVAC_SERVER)
# hvac_server = SimpleJSONRPCServer(HVAC_SERVER)
-hvac_server.register_function(subscribe, '/hvac/subscriber_service/subscribe')
-hvac_server.register_function(unsubscribe, '/hvac/subscriber_service/unsubscribe')
-hvac_server.register_function(publish, '/hvac/subscriber_service/publish')
+hvac_server.register_function(subscribe, '/subscription_service/subscribe')
+hvac_server.register_function(unsubscribe, '/subscription_service/unsubscribe')
+hvac_server.register_function(publish, '/subscription_service/publish')
# Register our services with the service edge and have
@@ -83,17 +140,17 @@ rvi_server = jsonrpclib.Server(RVI_SERVICE_EDGE)
res = rvi_server.register_service(service = '/subscription_service/subscribe',
network_address = 'http://localhost:8901')
-print "Registered service /subscription_service/subscribe as", res['service']
+print "Registered service", res['service']
res = rvi_server.register_service(service = '/subscription_service/unsubscribe',
network_address = 'http://localhost:8901')
-print "Registered service /subscription_service/unsubscribe as", res['service']
+print "Registered service", res['service']
res = rvi_server.register_service(service = '/subscription_service/publish',
network_address = 'http://localhost:8901')
-print "Registered service /subscription_service/publish as", res['service']
+print "Registered service", res['service']
hvac_server.serve_forever()
diff --git a/hvac_demo/rvi_json_rpc_server.py b/hvac_demo/rvi_json_rpc_server.py
index 7235756..e29fbb4 100644
--- a/hvac_demo/rvi_json_rpc_server.py
+++ b/hvac_demo/rvi_json_rpc_server.py
@@ -1,3 +1,10 @@
+#
+# 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/
+#
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer
import jsonrpclib
@@ -5,29 +12,26 @@ class RVIJSONRPCServer(SimpleJSONRPCServer):
# Check if method is 'message', if so dispatch on
# name 'target' instead.
def _dispatch(self, method, params):
- print "dispatch:", params
+ # print "dispatch:", params
if method == 'message':
- print "Will dispatch message to: " + params['target']
+ # print "Will dispatch message to: " + params['target']
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 params['parameters']
+ # print "Parameters:", params['parameters']
msg_params = params['parameters']
for i in range(0, len(msg_params)):
- print "params ", msg_params[i].keys()[0], " = ", msg_params[i].values()[0]
- dict_param[msg_params[i].keys()[0]] = msg_params[i].values()[0]
+ 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 "DICT: ", dict_param
+ # print "Parameter disctionary: ", dict_param
+ # print
# Ship the processed dispatch info upward.
return SimpleJSONRPCServer._dispatch(self, params['target'], dict_param)
- print "Method:", method
- for x in params:
- print "params ", x, " = ",params[x]
- return SimpleJSONRPCServer._dispatch(self,message, params)
-
- print "---"
+ return SimpleJSONRPCServer._dispatch(self,message, params)
diff --git a/setup_rvi_node.sh b/setup_rvi_node.sh
new file mode 100644
index 0000000..8cefbd1
--- /dev/null
+++ b/setup_rvi_node.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+#
+# 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/
+#
+
+#
+# Setup an RVI release with a configuration file.
+#
+# This script will setup a directory with with the same name
+# as the release name. The script uses Ulf Wiger's setup application
+# (github.com/Feuerlabs/setup) to generate the release.
+#
+# Once setup, the RVI node can be started with ./rvi_node <release_na,e?
+#
+# Please note that the generated release will depend on the built
+#
+# In order to create a standalone release, use create_rvi_release.sh
+#
+SETUP_GEN=./deps/setup/setup_gen # Ulf's kitchen sink setup utility
+
+if [ "$#" != "2" ]
+then
+ echo "Usage: $0 <release_name> <config_file>"
+ echo "Will create a subdirectory named <release_name> which contains"
+ echo "all configuration and boot files necessary to bring up an rvi node."
+ echo
+ echo "Launch the node with ./rvi_node <release_name>"
+ echo
+ echo "See priv/sample.config for example configuration file"
+ echo
+ exit 1
+fi
+
+export ERL_LIBS=$PWD/deps:$ERL_LIBS:$PWD
+
+$SETUP_GEN $1 $2 $1
+
+echo "RVI Node $1 has been setup. Launch with ./rvi_node $1"
+exit 0