Merge remote-tracking branch 'origin/master' into wheelsource
authorJames Ausmus <james.ausmus@intel.com>
Thu, 23 Aug 2012 19:24:04 +0000 (12:24 -0700)
committerJames Ausmus <james.ausmus@intel.com>
Thu, 23 Aug 2012 19:24:04 +0000 (12:24 -0700)
15 files changed:
config
plugins/dbus/CMakeLists.txt
plugins/dbus/dbusplugin.h
plugins/dbus/properties.cpp [new file with mode: 0644]
plugins/dbus/properties.h [new file with mode: 0644]
plugins/websocketsink/CMakeLists.txt
plugins/websocketsink/test/api.js
plugins/websocketsink/test/servertest/client.html [new file with mode: 0644]
plugins/websocketsink/test/servertest/server.html [moved from plugins/websocketsink/test/server.html with 89% similarity]
plugins/websocketsink/test/servertest/server.js [moved from plugins/websocketsink/test/server.js with 97% similarity]
plugins/websocketsink/test/test.js
plugins/websocketsink/websocketsink.cpp
plugins/websocketsink/websocketsink.h
plugins/websocketsink/websocketsinkmanager.cpp
plugins/websocketsink/websocketsinkmanager.h

diff --git a/config b/config
index 44830c7..bc39085 100644 (file)
--- a/config
+++ b/config
@@ -1,5 +1,5 @@
 {
        "sources" : [ "../plugins/examplesourceplugin.so" ],
-       "sinks": [ "../plugins/examplesinkplugin.so", "../plugins/dbus/dbussinkplugin.so" ,"../plugins/tcpsink/websocketsinkplugin.so" ]
+       "sinks": [ "../plugins/examplesinkplugin.so", "../plugins/dbus/dbussinkplugin.so" ,"../plugins/websocketsink/websocketsinkplugin.so" ]
 }
 
index a688c79..07464f3 100644 (file)
@@ -3,8 +3,8 @@ include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs})
 
 pkg_check_modules(gio REQUIRED gio-2.0)
 
-set(dbussinkplugin_headers dbusplugin.h abstractproperty.h abstractdbusinterface.h dbusinterfacemanager.h accelerationproperty.h basicproperty.h)
-set(dbussinkplugin_sources dbusplugin.cpp abstractproperty.cpp abstractdbusinterface.cpp dbusinterfacemanager.cpp accelerationproperty.cpp basicproperty.cpp)
+set(dbussinkplugin_headers dbusplugin.h abstractproperty.h abstractdbusinterface.h dbusinterfacemanager.h accelerationproperty.h basicproperty.h properties.h)
+set(dbussinkplugin_sources dbusplugin.cpp abstractproperty.cpp abstractdbusinterface.cpp dbusinterfacemanager.cpp accelerationproperty.cpp basicproperty.cpp properties.cpp)
 
 add_library(dbussinkplugin MODULE ${dbussinkplugin_sources})
 set_target_properties(dbussinkplugin PROPERTIES PREFIX "")
index abb7416..8007ec4 100644 (file)
@@ -35,6 +35,12 @@ public:
        virtual std::string uuid();
 
 protected:
+       template <typename T>
+       void wantProperty(VehicleProperty::Property)
+       {
+
+       }
+
        PropertyDBusMap propertyDBusMap;
 };
 
diff --git a/plugins/dbus/properties.cpp b/plugins/dbus/properties.cpp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/plugins/dbus/properties.h b/plugins/dbus/properties.h
new file mode 100644 (file)
index 0000000..de7efed
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+       Copyright (C) 2012  Intel Corporation
+
+       This library is free software; you can redistribute it and/or
+       modify it under the terms of the GNU Lesser General Public
+       License as published by the Free Software Foundation; either
+       version 2.1 of the License, or (at your option) any later version.
+
+       This library is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+       Lesser General Public License for more details.
+
+       You should have received a copy of the GNU Lesser General Public
+       License along with this library; if not, write to the Free Software
+       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PROPERTIES_H_H_H_
+#define _PROPERTIES_H_H_H_
+
+#include "dbusplugin.h"
+#include "abstractdbusinterface.h"
+
+class VehicleSpeedProperty: public AbstractDBusInterface, public DBusSink
+{
+public:
+       AccelerationPropertyInterface(AbstractRoutingEngine* re, GDBusConnection* connection)
+               :AbstractDBusInterface("org.automotive.acceleration","/org/automotive/acceleration", connection),
+                 DBusSink(re)
+       {
+               supportedChanged(re->supported());
+       }
+
+       void supportedChanged(PropertyList supportedProperties)
+       {
+               for(PropertyDBusMap itr = propertyDBusMap.begin(); itr != propertyDBusMap.end(); itr++)
+               {
+                       if(ListPlusPlus<VehicleProperty::Property>(&supportedProperties).contains((*itr)))
+                       {
+                               routingEngine->subscribeToProperty((*itr), this);
+
+                       }
+               }
+       }
+};
+
+#endif
index 2aac74c..eb1284b 100644 (file)
@@ -1,6 +1,8 @@
-
+include(CheckIncludeFiles)
 include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs})
 
+check_include_files(libwebsockets.h HAVE_WEBSOCKETS)
+
 set(websocketsinkplugin_headers websocketsink.h websocketmanager.h)
 set(websocketsinkplugin_sources websocketsinkmanager.cpp websocketsink.cpp)
 add_library(websocketsinkplugin MODULE ${websocketsinkplugin_sources})
index b4e2a8e..48fb4f4 100644 (file)
@@ -7,25 +7,85 @@
  *
  */
 
-/* ------------------------ vehicle interface ----------------------------- */
+/*****************************************************************************
+* Class name: Vehicle
+* Description:
+*    A javascript implementation of the IVI vehicle API that communicates
+*    to the automotive message broker through a websocket
+* Optional constructor arguments:
+*    sCB: success callback, called when socket is connected, argument is 
+*         success message string
+*    eCB: error callback, called on socket close or error, argument is error
+*         message string
+*    url: the URL to use for the websocket, in the form "ws://host:port/script"
+*    protocol: the protocol to use for the websocket, default is "http-only"
+*
+* [Public Member functions]
+*  Function name: getSupportedEventTypes(type, writeable, successCB, errorCB)
+*    Description:
+*        Retrieves a list of vehicle events for the requested type
+*    Required arguments:
+*        type: target event or group to query (use empty string for all events)
+*        writeable: if true, return only writeable events, otherwise get all
+*        successCB: success callback, gets called with a string list of names
+*              for all the events and event groups that are children of the 
+*              target. e.g. "vehicle_info" returns all events/groups with the 
+*              vehicle_info prefix. If the target is an event group, it's
+*              omitted from the returned list
+*        errorCB: error callback, called with error message string
+*
+*  Function name: get(type, successCB, errorCB)
+*    Description:
+*        Retrieves a list of event/value pairs for a target event or event group
+*    Required arguments:
+*        type: target event group to query (use empty string for all events)
+*        successCB: success callback, gets called with the event/value pair list
+*                   for all event children of the target. The list is the in the 
+*                   form of data[n].name/data[n].value
+*        errorCB: error callback, called with error message string
+*
+*  Function name: set(type, value, successCB, errorCB)
+*    Description:
+*        Sets a single event's value (triggers error if it's read-only)
+*    Required arguments:
+*        type: target event to set (an event group will trigger an error)
+*        successCB: success callback, gets called with the event/value pair
+*                   that was successfully set in the form data.name/data.value
+*        errorCB: error callback, called with error message string
+*
+******************************************************************************/
 
-function Vehicle(socketUrl, sCB, eCB, calltimeout)
+function Vehicle(sCB, eCB, url, protocol)
 {
+    /* store a copy of Vehicle this for reference in callbacks */
     var self = this;
+
     this.iSuccessCB = sCB;
     this.iErrorCB = eCB;
-    this.retries = 5;
-    this.connected = false;
-    this.transactionid = 0;
-    this.methodCalls = [];
-    this.methodIdx = 0;
-    this.timeouttime = (calltimeout == undefined)?5000:calltimeout;
 
+    /* variables for call management, supports up to 100 simultaneously */
+    this.methodIdx = 0;
+    this.methodCalls = [];
     for(var i = 0; i < 100; i++)
     {
         this.methodCalls[i] = null;
     }
 
+    /* number of connection retries to attempt if the socket closes */
+    this.retries = 5;
+    this.connected = false;
+
+    /* timeout for method calls in milliseconds */
+    this.timeouttime = 5000;
+
+    /* default values for WebSocket */
+    this.socketUrl = "ws://localhost:23000/vehicle";
+    this.socketProtocol = "http-only";
+
+    /* override the websocket address if parameters are given */
+    if(url != undefined) this.socketUrl = url;
+    if(protocol != undefined) this.socketProtocol = protocol;
+
     this.VehicleMethodCall = function(id, name, successCB, errorCB)
     {
         var me = this;
@@ -57,11 +117,17 @@ function Vehicle(socketUrl, sCB, eCB, calltimeout)
     function init() {
         if ("WebSocket" in window)
         {
-            self.socket = new WebSocket(socketUrl);
+            if(self.socketProtocol.length > 0)
+            {
+                self.socket = new WebSocket(self.socketUrl, self.socketProtocol);
+            }
+            else
+            {
+                self.socket = new WebSocket(self.socketUrl);
+            }
             self.socket.onopen = function()
             {
                 self.connected = true;
-                this.send("client");
                 self.iSuccessCB((self.retries < 5)?"(RECONNECTED)":"");
                 self.retries = 5;
             };
@@ -94,9 +160,22 @@ function Vehicle(socketUrl, sCB, eCB, calltimeout)
     init();
 }
 
+Vehicle.prototype.generateTransactionId = function()
+{
+    var i, val = [];
+    for(i = 0; i < 8; i++)
+    {
+       var num = Math.floor((Math.random()+1)*65536);
+       val[i] = num.toString(16).substring(1);
+    }
+    var uuid = val[0]+val[1]+"-"+
+               val[2]+"-"+val[3]+"-"+val[4]+"-"+
+               val[5]+val[6]+val[7];
+    return uuid;
+}
+
 Vehicle.prototype.send = function(obj, successCB, errorCB)
 {
-    obj.transactionid = this.transactionid++;
     if(!this.connected)
     {
         if(errorCB != undefined)
@@ -120,7 +199,7 @@ Vehicle.prototype.getSupportedEventTypes = function(type, writeable, successCB,
         "type" : "method",
         "name" : "getSupportedEventTypes",
         "writeable" : writeable,
-        "transactionid" : 0,
+        "transactionid" : this.generateTransactionId(),
         "data" : type
     };
     this.send(obj, successCB, errorCB);
@@ -131,7 +210,7 @@ Vehicle.prototype.get = function(type, successCB, errorCB)
     var obj = {
         "type" : "method",
         "name": "get",
-        "transactionid" : 0,
+        "transactionid" : this.generateTransactionId(),
         "data" : type
     };
     this.send(obj, successCB, errorCB);
@@ -142,7 +221,7 @@ Vehicle.prototype.set = function(type, value, successCB, errorCB)
     var obj = {
         "type" : "method",
         "name": "set",
-        "transactionid" : 0,
+        "transactionid" : this.generateTransactionId(),
         "data" : {"property" : type, "value" : value}
     };
     this.send(obj, successCB, errorCB);
diff --git a/plugins/websocketsink/test/servertest/client.html b/plugins/websocketsink/test/servertest/client.html
new file mode 100644 (file)
index 0000000..9ef2ee3
--- /dev/null
@@ -0,0 +1,17 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <title>IVI API Tester</title>
+    <meta charset="utf-8">
+    <link rel="stylesheet" href="../style.css"/>
+    <script src="../api.js"></script>
+</head>
+<body onload='init("ws://localhost:23023/vehicle?client", "")'>
+    <div id="result">
+    </div>
+    <div id="tester">
+    </div>
+    <script src="../events.js"></script>
+    <script src="../test.js"></script>
+</body>
+</html>
similarity index 89%
rename from plugins/websocketsink/test/server.html
rename to plugins/websocketsink/test/servertest/server.html
index 0e5d50c..43dc72a 100644 (file)
@@ -12,7 +12,7 @@
     word-wrap: break-word;
 }
     </style>
-    <script src="events.js"></script>
+    <script src="../events.js"></script>
     <script src="server.js"></script>
 </head>
 <body>
similarity index 97%
rename from plugins/websocketsink/test/server.js
rename to plugins/websocketsink/test/servertest/server.js
index 54b5ee4..180c23f 100644 (file)
@@ -59,7 +59,6 @@ function VehicleServer(socketUrl)
             self.socket.onopen = function()
             {
                 PRINT.pass("Server READY");
-                this.send("server");
             };
             self.socket.onclose = function()
             {
@@ -173,5 +172,5 @@ VehicleServer.prototype.receive = function(msg)
 window.addEventListener('load', function () {
     "use strict";
     PRINT.init("result");
-    var server = new VehicleServer("ws://localhost:23000/vehicle");
+    var server = new VehicleServer("ws://localhost:23023/vehicle?server");
 });
index db4f8e2..ebeb4be 100644 (file)
@@ -150,8 +150,7 @@ function error(msg)
     PRINT.fail(msg);
 }
 
-function init() {
+function init(url, protocol) {
     PRINT.init("result");
-    window.vehicle = new Vehicle("ws://localhost:23000/vehicle",
-        start, error);
+    window.vehicle = new Vehicle(start, error, url, protocol);
 }
index 587392a..c080ee6 100644 (file)
 
 
 
-WebSocketSink::WebSocketSink(AbstractRoutingEngine* re) : AbstractSink(re)
+WebSocketSink::WebSocketSink(AbstractRoutingEngine* re,libwebsocket *wsi,string uuid) : AbstractSink(re)
 {
-
+       m_uuid = uuid;
 }
 string WebSocketSink::uuid()
 {
-       return "e43f6cad-60e3-4454-9638-01ffa9ab8c8f";
+       return m_uuid;
 }
 void WebSocketSink::propertyChanged(VehicleProperty::Property property, boost::any value, string  uuid)
 {
index 6fb2cdc..e4c2d5e 100644 (file)
 #include <glib.h>
 #include <abstractroutingengine.h>
 #include "abstractsink.h"
+#include <libwebsockets.h>
 class WebSocketSink : public AbstractSink
 {
 
 public:
-       WebSocketSink(AbstractRoutingEngine* re);
+       WebSocketSink(AbstractRoutingEngine* re,libwebsocket *wsi,string uuid);
        string uuid() ;
        void propertyChanged(VehicleProperty::Property property, boost::any value, string  uuid);
        void supportedChanged(PropertyList supportedProperties);
        PropertyList subscriptions();
-
+private:
+       string m_uuid;
 };
 
 #endif // WEBSOCKETSINK_H
index 0dc9912..9f6a992 100644 (file)
@@ -18,6 +18,7 @@
 
 
 #include "websocketsinkmanager.h"
+#include "websocketsink.h"
 #include <sstream>
 #include <json-glib/json-glib.h>
 
@@ -40,7 +41,7 @@ WebSocketSinkManager::WebSocketSinkManager(AbstractRoutingEngine* engine):Abstra
        protocollist[0] = { "http-only", websocket_callback, 0 };
        protocollist[1] = { NULL, NULL, 0 };
 
-       int port = 7681;
+       int port = 23000;
        const char *interface = "lo";
        const char *ssl_cert_path = NULL;
        const char *ssl_key_path = NULL;
@@ -49,20 +50,20 @@ WebSocketSinkManager::WebSocketSinkManager(AbstractRoutingEngine* engine):Abstra
        //Create a listening socket on port 23000 on localhost.
        context = libwebsocket_create_context(port, interface, protocollist,libwebsocket_internal_extensions,ssl_cert_path, ssl_key_path, -1, -1, options);
 }
-void WebSocketSinkManager::addSink(libwebsocket* socket, VehicleProperty::Property property)
+void WebSocketSinkManager::addSingleShotSink(libwebsocket* socket, VehicleProperty::Property property,string id)
 {
        AsyncPropertyRequest velocityRequest;
-       velocityRequest.property = VehicleProperty::VehicleSpeed;
-       velocityRequest.completed = [socket](AsyncPropertyReply* reply) {
+       velocityRequest.property = property;
+       velocityRequest.completed = [socket,id](AsyncPropertyReply* reply) {
                printf("Got property:%i\n",boost::any_cast<uint16_t>(reply->value));
                uint16_t velocity = boost::any_cast<uint16_t>(reply->value);
                stringstream s;
                
                //TODO: Dirty hack hardcoded stuff, jsut to make it work.
-               s << "{\"type\":\"reply\",\"name\":\"Velocity\",\"arguments\":\"[\"" << velocity << "\"],\"transactionid\":\"aeff0345defaa03c132\"}";
+               s << "{\"type\":\"methodReply\",\"name\":\"get\",\"data\":[{\"name\":\"running_status_speedometer\",\"value\":\"" << velocity << "\"}],\"transactionid\":\"" << id << "\"}";
                
                string replystr = s.str();
-               
+               printf("Reply: %s\n",replystr.c_str());
 
                char *new_response = new char[LWS_SEND_BUFFER_PRE_PADDING + strlen(replystr.c_str()) + LWS_SEND_BUFFER_POST_PADDING];
                new_response+=LWS_SEND_BUFFER_PRE_PADDING;
@@ -76,6 +77,10 @@ void WebSocketSinkManager::addSink(libwebsocket* socket, VehicleProperty::Proper
 
        AsyncPropertyReply* reply = routingEngine->getPropertyAsync(velocityRequest);
 }
+void WebSocketSinkManager::addSink(libwebsocket* socket, VehicleProperty::Property property,string uuid)
+{
+       WebSocketSink *sink = new WebSocketSink(m_engine,socket,uuid);
+}
 
 extern "C" AbstractSinkManager * create(AbstractRoutingEngine* routingengine)
 {
@@ -109,8 +114,8 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
                }
                case LWS_CALLBACK_HTTP:
                {
+                       //TODO: Verify that ALL requests get sent via LWS_CALLBACK_HTTP, so we can use that instead of LWS_CALLBACK_RECIEVE
                        printf("requested URI: %s\n", (char*)in);
-                       //This contains the JSON, but so does LWS_CALLBACK_RECEIVE...
                        
                        /*{
                          "type":"method",
@@ -124,6 +129,7 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
                        if (!json_parser_load_from_data(parser,(char*)in,len,&error))
                        {
                          printf("Error loading JSON\n");
+                         return 0;
                        }
                        
                        JsonNode* node = json_parser_get_root(parser);
@@ -150,6 +156,7 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
                        string type;
                        string  name;
                        list<string> arguments;
+                       string data;
                        //stringlist arguments
                        string id;
                        json_reader_read_member(reader,"type");
@@ -160,7 +167,7 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
                        name = json_reader_get_string_value(reader);
                        json_reader_end_member(reader);
                        
-                       json_reader_read_member(reader,"Arguments");
+                       /*json_reader_read_member(reader,"Arguments");
                        g_assert(json_reader_is_array(reader));
                        for(int i=0; i < json_reader_count_elements(reader); i++)
                        {
@@ -170,30 +177,69 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
                                json_reader_end_element(reader);
                        }
                        json_reader_end_member(reader);
-                       
+                       */
+                       json_reader_read_member(reader,"data");
+                       printf("Data Type Name: %s\n",g_type_name(json_node_get_value_type(json_reader_get_value(reader))));
+                       data = json_reader_get_string_value(reader);
+                       json_reader_end_member(reader);
+                       //running_status_engine_speed
                        
                        
                        json_reader_read_member(reader,"transactionid");
-                       id = json_reader_get_string_value(reader);
+                       
+                       //JsonNode *node = json_reader_get_value(reader);
+                       //node->
+                       
+                       //printf("Type Name: %s\n",gtype);
+                       printf("Before\n");
+                       //GType gtype = json_reader_get_type();
+                       //json_reader_error_get_type();
+                       if (strcmp("gchararray",g_type_name(json_node_get_value_type(json_reader_get_value(reader)))) == 0)
+                       {
+                         //Type is a string
+                         id = json_reader_get_string_value(reader);
+                       }
+                       else
+                       {
+                         stringstream strstr;
+                         strstr << json_reader_get_int_value(reader);
+                         id = strstr.str();
+                       }
+                       //printf("After\n");
+                       //printf("New %s\n",id.c_str());
+                       //json_reader_get
                        json_reader_end_member(reader);
                        
                        
                        if (type == "method")
                        {
-                         if (name == "GetProperty")
+                         if (name == "get")
                          {
-                           string arg = arguments.front();
-                           if (arg == "Velocity")
+                           //GetProperty is going to be a singleshot sink.
+                           //string arg = arguments.front();
+                           if (data== "running_status_speedometer")
                            {                      
                              printf("Found velocity\n");
                            //m_engine->subscribeToProperty(VehicleProperty::VehicleSpeed,this);
                              
                            
-                           sinkManager->addSink(wsi,VehicleProperty::Property::VehicleSpeed);
+                           sinkManager->addSingleShotSink(wsi,VehicleProperty::Property::VehicleSpeed,id);
                            //libwebsocket_write(wsi, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT);
+                           
                            }
+                           else if (data == "running_status_engine_speed")
+                           {
+                             sinkManager->addSingleShotSink(wsi,VehicleProperty::Property::EngineSpeed,id);
+                           }
+                           //EngineSpeed
+                           //AccelerationX
                            
                          }
+                         else if (name == "Subscribe")
+                         {
+                           //Subscribe is a permanent sink, until unsubscription.
+                           sinkManager->addSink(wsi,VehicleProperty::VehicleSpeed,id);
+                         }
                        }
                        
                        ///TODO: this will probably explode:
index ae5f9ef..a8e6f97 100644 (file)
@@ -28,7 +28,8 @@ class WebSocketSinkManager: public AbstractSinkManager
 {
 public:
        WebSocketSinkManager(AbstractRoutingEngine* engine);
-       void addSink(libwebsocket *socket,VehicleProperty::Property property);
+       void addSingleShotSink(libwebsocket* socket, VehicleProperty::Property property,string id);
+       void addSink(libwebsocket* socket, VehicleProperty::Property property,string uuid);
 private:
   AbstractRoutingEngine *m_engine;
        struct libwebsocket_protocols protocollist[2];