TIVI-1465 Update websocket plugin and protocol to handle zones and sources
authorMarek Timko <marek.timko@ixonos.com>
Mon, 11 Nov 2013 12:20:10 +0000 (13:20 +0100)
committerKevron Rees <kevron.m.rees@intel.com>
Wed, 13 Nov 2013 19:02:22 +0000 (11:02 -0800)
Websocket plugin with zone support
MapPropertyType::fromString fixed

Change-Id: I4993e015a31d91a4ac3bfda45ca41d5a2e9485a3
Signed-off-by: Marek Timko <marek.timko@ixonos.com>
lib/mappropertytype.hpp
plugins/websocketsink/test/events.js
plugins/websocketsink/test/index.html
plugins/websocketsink/test/style.css
plugins/websocketsink/test/test.js
plugins/websocketsink/test/vehicle.js [moved from plugins/websocketsink/test/api.js with 88% similarity]
plugins/websocketsink/websocketsink.cpp
plugins/websocketsink/websocketsinkmanager.cpp
plugins/websocketsink/websocketsinkmanager.h
plugins/websocketsourceplugin/websocketsource.cpp

index 35bcffb..694400b 100644 (file)
@@ -78,7 +78,7 @@ public:
                json_object_object_foreach(rootobject, key, val)
                {
                        T one(key);
-                       N two(json_object_get_string(val));
+                       N two(std::string(json_object_get_string(val)));
                        append(one,two);
 
                }
index a669f09..cb0cfd5 100644 (file)
 function VehicleEventType()
 {
     this.event = [
-        "vehicle_info",
-        "vehicle_info_wmi",
-        "vehicle_info_vin",
-        "vehicle_info_vehicle_type",
-        "vehicle_info_door_type",
-        "vehicle_info_door_type_1st_row",
-        "vehicle_info_door_type_2nd_row",
-        "vehicle_info_door_type_3rd_row",
-        "vehicle_info_fuel_type",
-        "vehicle_info_transmission_gear_type",
-        "vehicle_info_wheel_info",
-        "vehicle_info_wheel_info_radius",
-        "vehicle_info_wheel_info_track",
-        "running_status",
-        "running_status_vehicle_power_mode",
-        "running_status_speedometer",
-        "running_status_engine_speed",
-        "running_status_trip_meter",
-        "running_status_trip_meter_1",
-        "running_status_trip_meter_2",
-        "running_status_trip_meter_1_mileage",
-        "running_status_trip_meter_2_mileage",
-        "running_status_trip_meter_1_average_speed",
-        "running_status_trip_meter_2_average_speed",
-        "running_status_trip_meter_1_fuel_consumption",
-        "running_status_trip_meter_2_fuel_consumption",
-        "running_status_transmission_gear_status",
-        "running_status_cruise_control",
-        "running_status_cruise_control_status",
-        "running_status_cruise_control_speed",
-        "running_status_wheel_brake",
-        "running_status_lights_status",
-        "running_status_lights_status_head",
-        "running_status_lights_status_high_beam",
-        "running_status_lights_status_turn_left",
-        "running_status_lights_status_turn_right",
-        "running_status_lights_status_brake",
-        "running_status_lights_status_fog_front",
-        "running_status_lights_status_fog_rear",
-        "running_status_lights_status_hazard",
-        "running_status_lights_status_parking",
-        "running_status_interior_lights_status",
-        "running_status_interior_lights_status_driver",
-        "running_status_interior_lights_status_passenger",
-        "running_status_interior_lights_status_center",
-        "running_status_automatic_headlights",
-        "running_status_dynamic_high_beam",
-        "running_status_horn",
-        "running_status_chime",
-        "running_status_fuel",
-        "running_status_estimated_range",
-        "running_status_engine_oil",
-        "running_status_engine_oil_remaining",
-        "running_status_engine_oil_change",
-        "running_status_engine_oil_temp",
-        "running_status_engine_coolant",
-        "running_status_engine_coolant_level",
-        "running_status_engine_coolant_temp",
-        "running_status_steering_wheel_angle",
-        "maintenance",
-        "maintenance_odometer",
-        "maintenance_transmission_oil",
-        "maintenance_transmission_oil_life_level",
-        "maintenance_transmission_oil_temp",
-        "maintenance_brake_fluid_level",
-        "maintenance_washer_fluid_level",
-        "maintenance_malfunction_indicator_lamp",
-        "maintenance_battery",
-        "maintenance_battery_voltage",
-        "maintenance_battery_current",
-        "maintenance_tire_pressure",
-        "maintenance_tire_pressure_front_left",
-        "maintenance_tire_pressure_front_right",
-        "maintenance_tire_pressure_rear_left",
-        "maintenance_tire_pressure_rear_right",
-        "maintenance_tire_pressure_status",
-        "maintenance_tire_pressure_status_front_left",
-        "maintenance_tire_pressure_status_front_right",
-        "maintenance_tire_pressure_status_rear_left",
-        "maintenance_tire_pressure_status_rear_right",
-        "personalization",
-        "personalization_key_id",
-        "personalization_language",
-        "personalization_measurement_system",
-        "personalization_measurement_system_string",
-        "personalization_measurement_system_string_fuel",
-        "personalization_measurement_system_string_distance",
-        "personalization_measurement_system_string_speed",
-        "personalization_measurement_system_string_consumption",
-        "personalization_mirror",
-        "personalization_mirror_driver",
-        "personalization_mirror_passenger",
-        "personalization_mirror_inside",
-        "personalization_steering_wheel_position",
-        "personalization_steering_wheel_position_slide",
-        "personalization_steering_wheel_position_tilt",
-        "personalization_driving_mode",
-        "personalization_driver_seat_position",
-        "personalization_driver_seat_position_recline_seatback",
-        "personalization_driver_seat_position_slide",
-        "personalization_driver_seat_position_cushion_height",
-        "personalization_driver_seat_position_headrest",
-        "personalization_driver_seat_position_back_cushion",
-        "personalization_driver_seat_position_side_cushion",
-        "personalization_passenger_seat_position",
-        "personalization_passenger_seat_position_recline_seatback",
-        "personalization_passenger_seat_position_slide",
-        "personalization_passenger_seat_position_cushion_height",
-        "personalization_passenger_seat_position_headrest",
-        "personalization_passenger_seat_position_back_cushion",
-        "personalization_passenger_seat_position_side_cushion",
-        "personalization_dashboard_illumination",
-        "personalization_generated_vehicle_sound_mode",
-        "driving_safety",
-        "driving_safety_antilock_braking_system",
-        "driving_safety_traction_control_system",
-        "driving_safety_electronic_stability_control",
-        "driving_safety_vehicle_top_speed_limit",
-        "driving_safety_airbag_status",
-        "driving_safety_airbag_status_driver",
-        "driving_safety_airbag_status_passenger",
-        "driving_safety_airbag_status_side",
-        "driving_safety_door_open_status",
-        "driving_safety_door_open_status_driver",
-        "driving_safety_door_open_status_passenger",
-        "driving_safety_door_open_status_rear_left",
-        "driving_safety_door_open_status_rear_right",
-        "driving_safety_door_open_status_trunk",
-        "driving_safety_door_open_status_fuel_filter_cap",
-        "driving_safety_door_open_status_hood",
-        "driving_safety_door_lock_status",
-        "driving_safety_door_lock_status_driver",
-        "driving_safety_door_lock_status_passenger",
-        "driving_safety_door_lock_status_rear_left",
-        "driving_safety_door_lock_status_rear_right",
-        "driving_safety_child_safety_lock",
-        "driving_safety_occupants_status",
-        "driving_safety_occupants_status_driver",
-        "driving_safety_occupants_status_passenger",
-        "driving_safety_occupants_status_rear_left",
-        "driving_safety_occupants_status_rear_right",
-        "driving_safety_seat_belt",
-        "driving_safety_seat_belt_driver",
-        "driving_safety_seat_belt_passenger",
-        "driving_safety_seat_belt_rear_left",
-        "driving_safety_seat_belt_rear_right",
-        "driving_safety_window_lock",
-        "driving_safety_window_lock_driver",
-        "driving_safety_window_lock_passenger",
-        "driving_safety_window_lock_rear_left",
-        "driving_safety_window_lock_rear_right",
-        "driving_safety_obstacle_distance",
-        "driving_safety_obstacle_distance_sensor_status",
-        "driving_safety_obstacle_distance_front_center",
-        "driving_safety_obstacle_distance_rear_center",
-        "driving_safety_obstacle_distance_front_left",
-        "driving_safety_obstacle_distance_front_right",
-        "driving_safety_obstacle_distance_middle_left",
-        "driving_safety_obstacle_distance_middle_right",
-        "driving_safety_obstacle_distance_rear_left",
-        "driving_safety_obstacle_distance_rear_right",
-        "driving_safety_front_collision_detection",
-        "driving_safety_front_collision_detection_status",
-        "driving_safety_front_collision_detection_distance",
-        "driving_safety_front_collision_detection_time",
-        "vision_system",
-        "vision_system_lane_departure_detection_status",
-        "vision_system_lane_departed",
-        "parking",
-        "parking_security_alert",
-        "parking_parking_brake",
-        "parking_parking_lights",
-        "climate_environment_interior_temp",
-        "climate_environment_exterior_temp",
-        "climate_environment_exterior_brightness",
-        "climate_environment_rain_sensor",
-        "climate_environment_windshield_wiper",
-        "climate_environment_rear_wiper",
-        "climate_environment_hvac_fan",
-        "climate_environment_hvac_fan_direction",
-        "climate_environment_hvac_fan_speed",
-        "climate_environment_hvac_fan_target_temp",
-        "climate_environment_air_conditioning",
-        "climate_environment_air_recirculation",
-        "climate_environment_heater",
-        "climate_environment_defrost",
-        "climate_environment_defrost_windshield",
-        "climate_environment_defrost_rear_window",
-        "climate_environment_defrost_side_mirrors",
-        "climate_environment_steering_wheel_heater",
-        "climate_environment_seat_heater",
-        "climate_environment_seat_cooler",
-        "climate_environment_window",
-        "climate_environment_window_driver",
-        "climate_environment_window_passenger",
-        "climate_environment_window_rear_left",
-        "climate_environment_window_rear_right",
-        "climate_environment_sunroof",
-        "climate_environment_sunroof_openness",
-        "climate_environment_sunroof_tilt",
-        "climate_environment_convertible_roof"
+"Randomize",
+"AirConditioning",
+"AirRecirculation",
+"AirflowDirection",
+"AvgKW",
+"BatteryStatus",
+"ChildLock",
+"Defrost",
+"ExteriorBrightness",
+"ExteriorTemperature",
+"FanSpeed",
+"FrontWheelRadius",
+"FullBatteryRange",
+"InteriorTemperature",
+"LightHazard",
+"LightHead",
+"LightParking",
+"NightMode",
+"Odometer",
+"SeatHeater",
+"TargetTemperature",
+"TransmissionShiftPosition",
+"VehicleSpeed",
+"Weather"
     ];
     this.value = [];
 
index a94ee39..9a5daef 100644 (file)
@@ -4,7 +4,7 @@
     <title>IVI API Tester</title>
     <meta charset="utf-8">
     <link rel="stylesheet" href="style.css"/>
-    <script src="api.js"></script>
+    <script src="vehicle.js"></script>
 </head>
 <body onload="init()">
     <div id="result">
index a3bf655..8456fd1 100644 (file)
     top: 0px;
     left: 0%;
     height: 100%;
-    width: 520px;
+    width: 620px;
     overflow-y: auto;
 }
 
 #result {
     position: absolute;
     top: 0px;
-    left: 520px;
+    left: 620px;
     height: 98%;
     width: 1380px;
     padding-top: 1%;
@@ -40,7 +40,7 @@
     position: relative;
     left: 0px;
     height: 67px;
-    width: 500px;
+    width: 700px;
     overflow: hidden;
 }
 
     top: 32px;
     left: 0px;
     height: 35px;
-    width: 430px;
+    width: 630px;
 }
 
+.smallText {
+    text-align: left;
+    color: #FFFFFF;
+    font: 18px Arial;
+    display: inline;
+}
 .propinfo {
     position: absolute;
     top: 0px;
     left: 0px;
     height: 67px;
-    width: 500px;
+    width: 600px;
     text-align: left;
     color: #FFFFFF;
     font: 18px Arial;
index 72383ee..90106f2 100644 (file)
 /* --------------------------- utility code ------------------------------- */
 
 var PRINT = {
-    logElement : null,
-    init : function(log_id) {
+    logElement: null,
+    init: function(log_id) {
         this.logElement = document.getElementById(log_id);
     },
 
-    scrollToBottom : function() {
+    scrollToBottom: function() {
         this.logElement.scrollTop = this.logElement.scrollHeight;
     },
 
-    clear : function() {
+    clear: function() {
         this.logElement.innerHTML = "";
     },
 
-    pass : function(msg) {
+    pass: function(msg) {
         this.logElement.innerHTML += "<div class='PassClass'>PASS: " + msg + "</div>";
         this.scrollToBottom();
     },
 
-    fail : function(msg) {
+    fail: function(msg) {
         this.logElement.innerHTML += "<div class='FailClass'>FAIL: " + msg + "</div>";
         this.scrollToBottom();
     },
 
-    log : function(msg) {
+    log: function(msg) {
         this.logElement.innerHTML += "<div class='LogClass'> " + msg + "</div>";
         this.scrollToBottom();
     },
@@ -44,39 +44,30 @@ var PRINT = {
 var vehicleEventType = new VehicleEventType();
 var selected = [];
 
-function getTypes(event)
-{
+function getTypes(event) {
     var types = window.vehicle.getSupportedEventTypes(event, false,
         function(data) {
-            if(data && data.length > 1)
-            {
-                PRINT.pass(event+" is a set of "+data.length+" events:");
-                for(i in data)
-                {
+            if (data && data.length > 1) {
+                PRINT.pass(event + " is a set of " + data.length + " events:");
+                for (i in data) {
                     PRINT.log(data[i]);
                 }
-            }
-            else if(data && data.length > 0)
-            {
-                PRINT.pass(event+" is a single event:");
-                for(i in data)
-                {
+            } else if (data && data.length > 0) {
+                PRINT.pass(event + " is a single event:");
+                for (i in data) {
                     PRINT.log(data[i]);
                 }
-            }
-            else
-            {
-                PRINT.fail(event+" unexcepted empty data field");
+            } else {
+                PRINT.fail(event + " unexcepted empty data field");
             }
         },
         function(msg) {
-            PRINT.fail(((event === "")?"all events":event)+":<br>"+msg);
+            PRINT.fail(((event === "") ? "all events" : event) + ":<br>" + msg);
         }
     );
 }
 
-function updateInput(input, value)
-{
+function updateInput(input, value) {
     input.value = value;
     input.className = "change";
     input.addEventListener('webkitTransitionEnd', function callback(e) {
@@ -85,35 +76,48 @@ function updateInput(input, value)
     }, false);
 }
 
-function getValue(eventlist)
-{
-    var types = window.vehicle.get(eventlist,
+function getValue(eventlist) {
+    var zoneList =  getZone(eventlist);
+    var types = window.vehicle.get(eventlist, zoneList,
         function(data) {
-            if(data && data.length > 0)
-            {
+            if (data) {
                 PRINT.pass("values received:");
-                var list = [];
-                for(var i = 0; i < data.length; i++)
-                {
-                    list[i] = data[i].name;
-                    PRINT.log(data[i].name+": "+data[i].value);
-                }
+                if (eventlist.length > 1 && !! data.length && data.length > 0) {
+                    var list = [];
+                    for (var i = 0; i < data.length; i++) {
+                        list[i] = data[i].property;
+                        //list[i] = data[i].name; ???
+                        PRINT.log(data[i].property + ": " + data[i].value + ", zone: " + data[i].zone);
+                        //PRINT.log(data[i].name+": "+data[i].value); ???
+                    }
 
-                var elements = document.getElementsByClassName('proptest');
-                for (var i = 0; i < elements.length; i++) {
-                    var propinfo = elements[i].getElementsByClassName('propinfo')[0];
-                    var name = propinfo.innerHTML;
-                    var idx = list.indexOf(name);
-                    if(idx >= 0)
-                    {
-                        var input = elements[i].getElementsByTagName('input')[0];
-                        updateInput(input, data[idx].value);
+                    var elements = document.getElementsByClassName('proptest');
+                    for (var i = 0; i < elements.length; i++) {
+                        var propinfo = elements[i].getElementsByClassName('propinfo')[0];
+                        var name = propinfo.innerHTML;
+                        var idx = list.indexOf(name);
+                        if (idx >= 0) {
+                            var zone = elements[i].getElementsByTagName('input')[1];
+                            updateInput(zone, zone.value);
+                            var input = elements[i].getElementsByTagName('input')[0];
+                            updateInput(input, data[idx].value);
+                        }
+                    }
+                } else {
+                    PRINT.log(JSON.stringify(data));
+                    var elements = document.getElementsByClassName('proptest');
+                    for (var i = 0; i < elements.length; i++) {
+                        var propinfo = elements[i].getElementsByClassName('propinfo')[0];
+                        if (data.property == propinfo.innerHTML) {
+                            var zone = elements[i].getElementsByTagName('input')[1];
+                            updateInput(zone, zone.value);
+                            var input = elements[i].getElementsByTagName('input')[0];
+                            updateInput(input, data.value);
+                        }
                     }
                 }
-            }
-            else
-            {
-                PRINT.fail("no values retrieved for "+eventlist);
+            } else {
+                PRINT.fail("no values retrieved for " + eventlist);
             }
         },
         function(msg) {
@@ -122,10 +126,10 @@ function getValue(eventlist)
     );
 }
 
-function setValue(eventlist)
-{
+function setValue(eventlist) {
+    var zoneList =  getZone(eventlist);
     var elements = document.getElementsByClassName('proptest');
-    var i, valuelist = [];
+    var i, valuelist = [] ;
 
     /* initialize the value list */
     for (i = 0; i < eventlist.length; i++) {
@@ -136,154 +140,177 @@ function setValue(eventlist)
         var propinfo = elements[i].getElementsByClassName('propinfo')[0];
         var name = propinfo.innerHTML;
         var idx = eventlist.indexOf(name);
-        if(idx >= 0)
-        {
-           var input = elements[i].getElementsByTagName('input')[0];
-           valuelist[idx] = input.value;
+        if (idx >= 0) {
+
+            var input = elements[i].getElementsByTagName('input')[0];
+            valuelist[idx] = input.value;
         }
     }
 
-    var types = window.vehicle.set(eventlist, valuelist,
+    var types = window.vehicle.set(eventlist, valuelist, zoneList, 
         function(msg) {
-            PRINT.pass(msg);
+            PRINT.pass("Set success for: " + JSON.stringify(msg));
         },
         function(msg) {
-            PRINT.fail(msg);
+            PRINT.fail("Set error: " + JSON.stringify(msg));
         }
     );
 }
 
-function eventListener(e)
-{
+function eventListener(e) {
+       PRINT.log(e.name + " update: " + JSON.stringify(e.value));
     var elements = document.getElementsByClassName('proptest');
     for (var i = 0; i < elements.length; i++) {
         var propinfo = elements[i].getElementsByClassName('propinfo')[0];
         var name = propinfo.innerHTML;
-        if(name === e.name)
-        {
+        if (name === e.name) {
             var input = elements[i].getElementsByTagName('input')[0];
-            updateInput(input, e.value);
+            updateInput(input, e.value.value);
+            var zone = elements[i].getElementsByTagName('input')[1];
+            updateInput(zone, e.value.zone);
         }
     }
 }
 
-function subscribe(eventlist)
-{
-    window.vehicle.subscribe(eventlist,
+function subscribe(eventlist) {
+   var zoneList =  getZone(eventlist);
+    window.vehicle.subscribe(eventlist, zoneList,
         function(data) {
-            PRINT.pass("Subscribe success for: "+data);
-            for(var i = 0; i < data.length; i++)
-            {
-                var sub = data[i]+"_subscribe";
-                var unsub = data[i]+"_unsubscribe";
-//                document.getElementById(sub).className = "testbutton subscribe disable"
-//                document.getElementById(unsub).className = "testbutton unsubscribe";
+            PRINT.pass("Subscribe success for: " + data);
+            for (var i = 0; i < data.length; i++) {
+                var sub = data[i] + "_subscribe";
+                var unsub = data[i] + "_unsubscribe";
+                //                document.getElementById(sub).className = "testbutton subscribe disable"
+                //                document.getElementById(unsub).className = "testbutton unsubscribe";
                 document.addEventListener(data[i], eventListener, false);
             }
         },
         function(msg) {
-            PRINT.fail("Subscribe failed for: "+msg);
+            PRINT.fail("Subscribe failed for: " + msg);
         }
     );
 }
 
-function unsubscribe(eventlist)
-{
+function unsubscribe(eventlist, zoneList) {
+    zoneList =  getZone(eventlist);
     /* kill the handers first, so even if the service fails to acknowledge */
     /* we've stopped listening */
-    for(var i = 0; i < eventlist.length; i++)
-    {
+    for (var i = 0; i < eventlist.length; i++) {
         document.removeEventListener(eventlist[i], eventListener, false);
     }
-    window.vehicle.unsubscribe(eventlist,
+    window.vehicle.unsubscribe(eventlist, zoneList,
         function(data) {
-            PRINT.pass("Unsubscribe success for: "+data);
-            for(var i = 0; i < data.length; i++)
-            {
-                var sub = data[i]+"_subscribe";
-                var unsub = data[i]+"_unsubscribe";
-//                document.getElementById(unsub).className = "testbutton unsubscribe disable";
-//                document.getElementById(sub).className = "testbutton subscribe";
+            PRINT.pass("Unsubscribe success for: " + data);
+            for (var i = 0; i < data.length; i++) {
+                var sub = data[i] + "_subscribe";
+                var unsub = data[i] + "_unsubscribe";
+                //                document.getElementById(unsub).className = "testbutton unsubscribe disable";
+                //                document.getElementById(sub).className = "testbutton subscribe";
             }
         },
         function(msg) {
-            PRINT.fail("Unsubscribe failed for: "+msg);
+            PRINT.fail("Unsubscribe failed for: " + msg);
         }
     );
 }
 
-function select(elem)
-{
+function getZone(eventlist) {
+    var list = [];
+    if (eventlist.length > 1) {
+
+        // for (var i = 0; i < data.length; i++) {
+        //     list[i] = data[i].property;
+        //     //list[i] = data[i].name; ???
+        //     PRINT.log(data[i].property + ": " + data[i].value);
+        //     //PRINT.log(data[i].name+": "+data[i].value); ???
+        // }
+
+        var elements = document.getElementsByClassName('proptest');
+        for (var i = 0; i < elements.length; i++) {
+            var propinfo = elements[i].getElementsByClassName('propinfo')[0];
+            var name = propinfo.innerHTML;
+            var idx = eventlist.indexOf(name);
+            if (idx >= 0) {
+                var zone = elements[i].getElementsByTagName('input')[1];
+                list.push(zone.value);
+            }
+        }
+    } else {
+        var elements = document.getElementsByClassName('proptest');
+        for (var i = 0; i < elements.length; i++) {
+            var propinfo = elements[i].getElementsByClassName('propinfo')[0];
+            if (eventlist[0] == propinfo.innerHTML) {
+                var zone = elements[i].getElementsByTagName('input')[1];
+                list.push(zone.value);
+            }
+        }
+    }
+    return list.join();
+}
+
+function select(elem) {
     var name = elem.innerHTML;
-    if(!vehicleEventType.isValid(name))
+    if (!vehicleEventType.isValid(name))
         return;
 
     var idx = selected.indexOf(name);
-    if(elem.className == "propinfo")
-    {
-        if(idx < 0)
-        {
+    if (elem.className == "propinfo") {
+        if (idx < 0) {
             selected[selected.length] = name;
         }
         elem.className = "propinfo select";
-    }
-    else if(elem.className == "propinfo select")
-    {
-        if(idx >= 0)
-        {
+    } else if (elem.className == "propinfo select") {
+        if (idx >= 0) {
             selected.splice(idx, 1);
         }
         elem.className = "propinfo";
     }
 }
 
-function start(msg)
-{
-    if(window.vehicle && window.vehicle.getSupportedEventTypes)
-    {
-        PRINT.pass("vehicle interface online "+msg);
-    }
-    else
-    {
+function start(msg) {
+    if (window.vehicle && window.vehicle.getSupportedEventTypes) {
+        PRINT.pass("vehicle interface online " + msg);
+    } else {
         PRINT.fail("vehicle interface not found");
         return;
     }
 
     var tester = document.getElementById("tester");
     var part = ['<div class="proptest"><div class="propinfo" onclick=select(this)>',
-                '</div><div class="buttons"><div class="testbutton types" onclick=getTypes("',
-                '")></div><div id="',
-                '_subscribe" class="testbutton subscribe" onclick=subscribe(["',
-                '"])></div><div id="',
-                '_unsubscribe" class="testbutton unsubscribe" onclick=unsubscribe(["',
-                '"])></div><div class="testbutton get" onclick=getValue(["',
-                '"])></div><div class="testbutton set" onclick=setValue(["',
-                '"])></div><input type="text" value="0"/></div></div>'
+        '</div><div class="buttons"><div class="testbutton types" onclick=getTypes("',
+        '")></div><div id="',
+        '_subscribe" class="testbutton subscribe" onclick=subscribe(["',
+        '"])></div><div id="',
+        '_unsubscribe" class="testbutton unsubscribe" onclick=unsubscribe(["',
+        '"])></div><div class="testbutton get" onclick=getValue(["',
+        '"])></div><div class="testbutton set" onclick=setValue(["',
+        '"])></div><input class = "Textvalue" type="text" value="0" placeholder="Value" /><div class = "smallText"> Zone: </div><input class = "zone" type="text" value="0" placeholder="Zone"/></div></div>'
     ];
     var events = vehicleEventType.event;
 
     /* apply on all selected events */
-    var html = '<div class="proptest"><div class="propinfo unselectable">apply on all selected events'+
-               '</div><div class="buttons">'+
-               '<div class="testbutton subscribe" onclick=subscribe(selected)></div>'+
-               '<div class="testbutton unsubscribe" onclick=unsubscribe(selected)></div>'+
-               '<div class="testbutton get" onclick=getValue(selected)></div>'+
-               '<div class="testbutton set" onclick=setValue(selected)></div></div></div>'
+    var html = '<div class="proptest"><div class="propinfo unselectable">apply on all selected events' +
+        '</div><div class="buttons">' +
+        '<div class="testbutton subscribe" onclick=subscribe(selected)></div>' +
+        '<div class="testbutton unsubscribe" onclick=unsubscribe(selected)></div>' +
+        '<div class="testbutton get" onclick=getValue(selected)></div>' +
+        '<div class="testbutton set" onclick=setValue(selected)></div></div></div>';
 
     /* all events */
-    html += '<div class="proptest"><div class="propinfo unselectable">all events'+
-            '</div><div class="buttons"><div class="testbutton types" onclick=getTypes("'+
-            '")></div><div class="testbutton subscribe" onclick=subscribe(["'+
-            '"])></div><div class="testbutton unsubscribe" onclick=unsubscribe(["'+
-            '"])></div><div class="testbutton get" onclick=getValue(["'+
-            '"])></div></div></div>';
+    html += '<div class="proptest"><div class="propinfo unselectable">all events';
+    html +=     '</div><div class="buttons"><div class="testbutton types" onclick=getTypes("' ;
+    html +=     '")></div><div class="testbutton subscribe" onclick=\"subscribe([\'' ;
+    html +=     events.join("','") ;
+    html +=     '\'])\"></div><div class="testbutton unsubscribe" onclick= \"unsubscribe([\'' ;
+    html +=     events.join("','");
+    html +=     '\'])\"></div><div class="testbutton get" onclick=\"getValue([\'' ;
+    html +=     events.join("','");
+    html +=     '\'])\"></div></div></div>';
 
     /* events */
-    for(var i = 0; i < events.length; i++)
-    {
+    for (var i = 0; i < events.length; i++) {
         var piece = "";
-        for(var j = 0; j < part.length - 1; j++)
-        {
+        for (var j = 0; j < part.length - 1; j++) {
             piece += part[j] + events[i];
         }
         html += piece + part[j];
@@ -291,8 +318,7 @@ function start(msg)
     tester.innerHTML = html;
 }
 
-function error(msg)
-{
+function error(msg) {
     PRINT.fail(msg);
 }
 
similarity index 88%
rename from plugins/websocketsink/test/api.js
rename to plugins/websocketsink/test/vehicle.js
index 5c0d836..6b8e600 100644 (file)
@@ -91,7 +91,9 @@
 *        errorCB: error callback, called with the eventlist that failed to unsubscribe
 *
 ******************************************************************************/
-
+/*
+(function () {
+*/
 function Vehicle(sCB, eCB, url, protocol)
 {
     /* store a copy of Vehicle this for reference in callbacks */
@@ -120,8 +122,8 @@ function Vehicle(sCB, eCB, url, protocol)
     this.socketProtocol = "http-only";
 
     /* override the websocket address if parameters are given */
-    if(url != undefined) this.socketUrl = url;
-    if(protocol != undefined) this.socketProtocol = protocol;
+    if(url !== undefined) this.socketUrl = url;
+    if(protocol !== undefined) this.socketProtocol = protocol;
 
     this.VehicleMethodCall = function(id, name, successCB, errorCB)
     {
@@ -134,7 +136,7 @@ function Vehicle(sCB, eCB, url, protocol)
         this.start = function()
         {
             me.timeout = setTimeout(function(){
-                if(me.errorCB != undefined)
+                if(me.errorCB !== undefined)
                 {
                     me.errorCB("\""+me.name+"\" method timed out after "+self.timeouttime+"ms");
                 }
@@ -143,7 +145,7 @@ function Vehicle(sCB, eCB, url, protocol)
         }
         this.finish = function()
         {
-            if(me.timeout != undefined)
+            if(me.timeout !== undefined)
             {
                 clearTimeout(me.timeout);
             }
@@ -215,7 +217,7 @@ Vehicle.prototype.send = function(obj, successCB, errorCB)
 {
     if(!this.connected)
     {
-        if(errorCB != undefined)
+        if(errorCB !== undefined)
         {
             errorCB("\""+obj.name+"\" method failed because socket is closed");
         }
@@ -242,18 +244,24 @@ Vehicle.prototype.getSupportedEventTypes = function(type, writeable, successCB,
     this.send(obj, successCB, errorCB);
 }
 
-Vehicle.prototype.get = function(namelist, successCB, errorCB)
+Vehicle.prototype.get = function(namelist, zone, successCB, errorCB)
 {
     if(namelist.length <= 0)
     {
         return;
     }
 
+       var properties = [];
+
+    for(var i = 0; i < namelist.length; i++)
+    {
+        properties[i] = {"property" : namelist[i], "zone" : zone};
+    }
     var obj = {
         "type" : "method",
         "name": "get",
         "transactionid" : this.generateTransactionId(),
-        "data" : namelist
+        "data" : properties
     };
     this.send(obj, successCB, errorCB);
 }
@@ -271,7 +279,7 @@ Vehicle.prototype.getHistory = function(event, startTime, endTime, successCB, er
 
 }
 
-Vehicle.prototype.set = function(namelist, valuelist, successCB, errorCB)
+Vehicle.prototype.set = function(namelist, valuelist, zoneList, successCB, errorCB)
 {
     if((namelist.length != valuelist.length)||(namelist.length <= 0))
     {
@@ -287,31 +295,33 @@ Vehicle.prototype.set = function(namelist, valuelist, successCB, errorCB)
     var list = [];
     for(var i = 0; i < namelist.length; i++)
     {
-        var val = {"property" : namelist[i], "value" : valuelist[i]};
+        var val = {"property" : namelist[i], "value" : valuelist[i],"zone" : zoneList[i]};
         list[list.length] = val;
     }
     obj.data = list;
     this.send(obj, successCB, errorCB);
 }
 
-Vehicle.prototype.subscribe = function(namelist, successCB, errorCB)
+Vehicle.prototype.subscribe = function(namelist, zoneList, successCB, errorCB)
 {
     var obj = {
         "type" : "method",
         "name": "subscribe",
         "transactionid" : this.generateTransactionId(),
-        "data" : namelist
+        "data" : namelist,
+        "zone" : zoneList
     };
     this.send(obj, successCB, errorCB);
 }
 
-Vehicle.prototype.unsubscribe = function(namelist, successCB, errorCB)
+Vehicle.prototype.unsubscribe = function(namelist, zoneList, successCB, errorCB)
 {
     var obj = {
         "type" : "method",
         "name": "unsubscribe",
         "transactionid" : this.generateTransactionId(),
-        "data" : namelist
+        "data" : namelist,
+        "zone" : zoneList
     };
     this.send(obj, successCB, errorCB);
 }
@@ -355,11 +365,11 @@ Vehicle.prototype.receive = function(msg)
                 if(call&&(!call.done)&&(call.transactionid === event.transactionid))
                 {
                     call.finish();
-                    if(event.error != undefined)
+                    if(event.error !== undefined)
                     {
                         call.errorCB(event.error);
                     }
-                    if(event.data != undefined)
+                    else if(event.data !== undefined && call.successCB !== undefined)
                     {
                         call.successCB(event.data);
                     }
@@ -373,3 +383,27 @@ Vehicle.prototype.receive = function(msg)
         }
     }
 }
+
+/*
+    // AMD / RequireJS
+    if (typeof define !== 'undefined' && define.amd) {
+        define([], function () {
+            return {
+                Vehicle: Vehicle
+            };
+        });
+    }
+    // Node.js
+    else if (typeof module !== 'undefined' && module.exports) {
+        module.exports = {
+                Vehicle: Vehicle
+            };
+    }
+    // included directly via <script> tag
+    else {
+        root.vehicle = {
+                Vehicle: Vehicle
+            };
+    }
+})();
+*/
index a9597a1..21093f5 100644 (file)
@@ -65,7 +65,8 @@ void WebSocketSink::propertyChanged(AbstractPropertyType *value)
        s.precision(15);
        
        s << "{\"type\":\"valuechanged\",\"name\":\"" << tmpstr << "\",\"data\":";
-       s << "{ \"value\":\"" << value->toString() << "\",\"timestamp\":\""<<value->timestamp<<"\",\"sequence\":\""<<value->sequence<<"\"},";
+       s << "{ \"value\":\"" << value->toString() << "\",\"zone\":\""<<value->zone;
+       s << "\",\"timestamp\":\""<<value->timestamp<<"\",\"sequence\":\""<<value->sequence<<"\"},";
        s << "\"transactionid\":\"" << m_uuid << "\"}";
        
        string replystr = s.str();
@@ -77,7 +78,7 @@ void WebSocketSink::propertyChanged(AbstractPropertyType *value)
        new_response+=LWS_SEND_BUFFER_PRE_PADDING;
        strcpy(new_response,replystr.c_str());
        libwebsocket_write(m_wsi, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT);
-       delete (char*)(new_response-LWS_SEND_BUFFER_PRE_PADDING);
+       delete [] (char*)(new_response-LWS_SEND_BUFFER_PRE_PADDING);
 }
 WebSocketSink::~WebSocketSink()
 {
index 7e9d93b..94997f0 100644 (file)
@@ -24,6 +24,8 @@
 #include <json/json_object.h>
 #include <json/json_tokener.h>
 #include <listplusplus.h>
+#include <memory>
+
 #define __SMALLFILE__ std::string(__FILE__).substr(std::string(__FILE__).rfind("/")+1)
 
 //Global variables, these will be moved into the class
@@ -34,7 +36,17 @@ WebSocketSinkManager *sinkManager;
 static int websocket_callback(struct libwebsocket_context *context,struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason, void *user,void *in, size_t len);
 bool gioPollingFunc(GIOChannel *source,GIOCondition condition,gpointer data);
 
+// libwebsocket_write helper function
+static int lwsWrite(struct libwebsocket *lws, const std::string& strToWrite)
+{
+       std::unique_ptr<char[]> buffer(new char[LWS_SEND_BUFFER_PRE_PADDING + strToWrite.length() + LWS_SEND_BUFFER_POST_PADDING]);
+
+       char *buf = buffer.get() + LWS_SEND_BUFFER_PRE_PADDING;
+       strcpy(buf, strToWrite.c_str());
 
+       //NOTE: delete[] on buffer is not needed since std::unique_ptr<char[]> is used
+       return libwebsocket_write(lws, (unsigned char*)buf, strToWrite.length(), LWS_WRITE_TEXT);
+}
 
 WebSocketSinkManager::WebSocketSinkManager(AbstractRoutingEngine* engine, map<string, string> config):AbstractSinkManager(engine, config)
 {
@@ -47,7 +59,7 @@ WebSocketSinkManager::WebSocketSinkManager(AbstractRoutingEngine* engine, map<st
 }
 void WebSocketSinkManager::init()
 {
-       //Protocol list for libwebsockets.
+       //Protocol list for libwebsockets.
        protocollist[0] = { "http-only", websocket_callback, 0 };
        protocollist[1] = { NULL, NULL, 0 };
 
@@ -121,73 +133,48 @@ void WebSocketSinkManager::setConfiguration(map<string, string> config)
        
 }
 
-void WebSocketSinkManager::addSingleShotSink(libwebsocket* socket, VehicleProperty::Property property,string id)
+void WebSocketSinkManager::addSingleShotSink(libwebsocket* socket, VehicleProperty::Property property, Zone::Type zone, string id)
 {
-       AsyncPropertyRequest velocityRequest;
-       if (property == "running_status_speedometer")
-       {
-               velocityRequest.property = VehicleProperty::VehicleSpeed;
-       }
-       else if (property == "running_status_engine_speed")
-       {
-               velocityRequest.property = VehicleProperty::EngineSpeed;
-       }
-       else if (property == "running_status_steering_wheel_angle")
+       AsyncPropertyRequest request;
+       PropertyList foo = VehicleProperty::capabilities();
+       if (ListPlusPlus<VehicleProperty::Property>(&foo).contains(property))
        {
-               velocityRequest.property = VehicleProperty::SteeringWheelAngle;
+               request.property = property;
        }
-       else if (property == "running_status_transmission_gear_status")
+       else
        {
-               velocityRequest.property = VehicleProperty::TransmissionShiftPosition;
+               DebugOut(0)<<"websocketsink: Invalid property requested: "<<property;
+               return;
        }
-       else
+
+       request.zoneFilter = zone;
+       request.completed = [socket,id,property](AsyncPropertyReply* reply)
        {
-               PropertyList foo = VehicleProperty::capabilities();
-               if (ListPlusPlus<VehicleProperty::Property>(&foo).contains(property))
-               {
-                       velocityRequest.property = property;
-               }
-               else
-               {
-                       DebugOut(0)<<"websocketsink: Invalid property requested: "<<property;
+               DebugOut()<<"Got property: "<<reply->property.c_str()<<endl;
+               if(!reply->value){
+                       DebugOut()<<"Property value is null"<<endl;
+                       delete reply;
                        return;
                }
 
-       }
-       velocityRequest.completed = [socket,id,property](AsyncPropertyReply* reply)
-       {
-               DebugOut()<<"Got property: "<<reply->value->toString().c_str()<<endl;
-               //uint16_t velocity = boost::any_cast<uint16_t>(reply->value);
                stringstream s;
                s.precision(15);
-               //TODO: Dirty hack hardcoded stuff, jsut to make it work.
-               string tmpstr = "";
-               tmpstr = property;
-
-               /// TODO: timestamp and sequence need to be inside the "data" object:
 
                s << "{\"type\":\"methodReply\",\"name\":\"get\",\"data\":{";
-               s << "\"property\":\"" << tmpstr << "\",\"value\":\"" << reply->value->toString() << "\",\"timestamp\":\""<<reply->value->timestamp<<"\",";
+               s << "\"property\":\"" << property << "\",\"zone\":\"" << reply->value->zone << "\",\"value\":\"" << reply->value->toString() << "\",\"timestamp\":\""<<reply->value->timestamp<<"\",";
                s <<"\"sequence\": \""<<reply->value->sequence<<"\"}";
                s << ",\"transactionid\":\"" << id << "\"}";
-               
 
                string replystr = s.str();
                //printf("Reply: %s\n",replystr.c_str());
                DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Reply:" << replystr << endl;
 
-               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;
-               strcpy(new_response,replystr.c_str());
-               libwebsocket_write(socket, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT);
+               lwsWrite(socket, replystr);
 
-               //TODO: run valgrind on this. libwebsocket's documentation says NOTHING about this, yet malloc insists it's true.
-               //delete new_response; <- Unneeded. Apparently libwebsocket free's it.
-               delete (char*)(new_response-LWS_SEND_BUFFER_PRE_PADDING); //Needs to subtract pre-padding, to get back to the start of the pointer.
                delete reply;
        };
 
-       AsyncPropertyReply* reply = routingEngine->getPropertyAsync(velocityRequest);
+       AsyncPropertyReply* reply = routingEngine->getPropertyAsync(request);
 }
 
 void WebSocketSinkManager::addSingleShotRangedSink(libwebsocket* socket, PropertyList properties, double start, double end, double seqstart,double seqend, string id)
@@ -203,7 +190,6 @@ void WebSocketSinkManager::addSingleShotRangedSink(libwebsocket* socket, Propert
        {
                stringstream s;
 
-               //TODO: Dirty hack hardcoded stuff, jsut to make it work.
                stringstream data;
                data.precision(15);
                data<< "[";
@@ -226,14 +212,8 @@ void WebSocketSinkManager::addSingleShotRangedSink(libwebsocket* socket, Propert
                //printf("Reply: %s\n",replystr.c_str());
                DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Reply:" << replystr << "\n";
 
-               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;
-               strcpy(new_response,replystr.c_str());
-               libwebsocket_write(socket, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT);
+               lwsWrite(socket, replystr);
 
-               //TODO: run valgrind on this. libwebsocket's documentation says NOTHING about this, yet malloc insists it's true.
-               //delete new_response; <- Unneeded. Apparently libwebsocket free's it.
-               delete (char*)(new_response-LWS_SEND_BUFFER_PRE_PADDING); //Needs to subtract pre-padding, to get back to the start of the pointer.
                delete reply;
        };
 
@@ -260,23 +240,32 @@ void WebSocketSinkManager::removeSink(libwebsocket* socket,VehicleProperty::Prop
                //printf("Reply: %s\n",replystr.c_str());
                DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Reply:" << replystr << "\n";
 
-               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;
-               strcpy(new_response,replystr.c_str());
-               libwebsocket_write(socket, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT);
-               delete (char*)(new_response-LWS_SEND_BUFFER_PRE_PADDING);
+               lwsWrite(socket, replystr);
        }
 }
-void WebSocketSinkManager::setValue(string property,string value)
+void WebSocketSinkManager::setValue(libwebsocket* socket,VehicleProperty::Property property,string value,Zone::Type zone,string uuid)
 {
        AbstractPropertyType* type = VehicleProperty::getPropertyTypeForPropertyNameValue(property,value);
 
        AsyncSetPropertyRequest request;
        request.property = property;
        request.value = type;
-       request.completed = [](AsyncPropertyReply* reply)
+       request.zoneFilter = zone;
+       request.completed = [&](AsyncPropertyReply* reply)
        {
                ///TODO: do something here on !reply->success
+               stringstream s;
+               s << "{\"type\":\"methodReply\",\"name\":\"set\",\"data\":[{\"property\":\"" << property << "\",\"zone\":" << reply->zoneFilter
+                       << "}],\"transactionid\":\"" << uuid << "\"";
+               if(!reply->success)
+                       s << ",\"error\":\"method call failed\"";
+               s << "}";
+
+               string replystr = s.str();
+               DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Reply:" << replystr << "\n";
+
+               lwsWrite(socket, replystr);
+
                delete reply;
        };
 
@@ -289,25 +278,7 @@ void WebSocketSinkManager::addSink(libwebsocket* socket, VehicleProperty::Proper
 {
        stringstream s;
 
-       //TODO: Dirty hack hardcoded stuff, jsut to make it work.
        string tmpstr = "";
-       if (property == "running_status_speedometer")
-       {
-               tmpstr = VehicleProperty::VehicleSpeed;
-       }
-       else if (property == "running_status_engine_speed")
-       {
-               tmpstr = VehicleProperty::EngineSpeed;
-       }
-       else if (property == "running_status_steering_wheel_angle")
-       {
-               tmpstr = VehicleProperty::SteeringWheelAngle;
-       }
-       else if (property == "running_status_transmission_gear_status")
-       {
-               tmpstr = VehicleProperty::TransmissionShiftPosition;
-       }
-       else
        {
                PropertyList foo = VehicleProperty::capabilities();
                if (ListPlusPlus<VehicleProperty::Property>(&foo).contains(property))
@@ -327,11 +298,8 @@ void WebSocketSinkManager::addSink(libwebsocket* socket, VehicleProperty::Proper
        //printf("Reply: %s\n",replystr.c_str());
        DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Reply:" << replystr << "\n";
 
-       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;
-       strcpy(new_response,replystr.c_str());
-       libwebsocket_write(socket, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT);
-       delete (char*)(new_response-LWS_SEND_BUFFER_PRE_PADDING);
+       lwsWrite(socket, replystr);
+
        WebSocketSink *sink = new WebSocketSink(m_engine,socket,uuid,property,tmpstr);
        m_sinkMap[property].push_back(sink);
 }
@@ -348,7 +316,7 @@ void WebSocketSinkManager::disconnectAll(libwebsocket* socket)
        for (auto i=m_sinkMap.begin(); i != m_sinkMap.end();i++)
        {
                std::list<WebSocketSink*> *sinks = & (*i).second;
-               for (auto sinkItr =  sinks->begin(); sinkItr != sinks->end(); sinkItr++)
+               for (auto sinkItr = sinks->begin(); sinkItr != sinks->end(); sinkItr++)
                {
                        if ((*sinkItr)->socket() == socket)
                        {
@@ -570,6 +538,7 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
                                vector<string> data;
                                list<string> key;
                                list<string> value;
+                               list<Zone::Type> zone;
                                json_object *dataobject = json_object_object_get(rootobject,"data");
                                if (json_object_get_type(dataobject) == json_type_array)
                                {
@@ -581,12 +550,21 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
                                                {
                                                        json_object *propobject = json_object_object_get(arrayobject,"property");
                                                        json_object *valueobject = json_object_object_get(arrayobject,"value");
-                                                       string keystr = string(json_object_get_string(propobject));
-                                                       string valuestr = string(json_object_get_string(valueobject));
+                                                       json_object *zoneobject = json_object_object_get(arrayobject,"zone");
+                                                       string keystr = string(propobject ? json_object_get_string(propobject) : "");
+                                                       string valuestr = string(valueobject ? json_object_get_string(valueobject): "");
                                                        key.push_back(keystr);
                                                        value.push_back(valuestr);
+                                                       Zone::Type z(Zone::None);
+                                                       if(zoneobject){
+                                                               try {
+                                                                       z = static_cast<Zone::Type>(boost::lexical_cast<int,std::string>(json_object_get_string(zoneobject)));
+                                                               } catch (...) { }
+                                                       }
+                                                       zone.push_back(z);
                                                        json_object_put(propobject);
                                                        json_object_put(valueobject);
+                                                       json_object_put(zoneobject);
                                                }
                                                else if (json_object_get_type(arrayobject) == json_type_string)
                                                {
@@ -612,8 +590,12 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
                                                if (data.size() > 0)
                                                {
                                                        //GetProperty is going to be a singleshot sink.
-                                                       //string arg = arguments.front();
-                                                       sinkManager->addSingleShotSink(wsi,data.front(),id);
+                                                       sinkManager->addSingleShotSink(wsi,data.front(),Zone::None,id);
+                                               }
+                                               else if (key.size() > 0 && key.size() == zone.size())
+                                               {
+                                                       //GetProperty is going to be a singleshot sink.
+                                                       sinkManager->addSingleShotSink(wsi,key.front(),zone.front(),id);
                                                }
                                                else
                                                {
@@ -624,7 +606,7 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
                                        {
                                                if (data.size() > 0)
                                                {
-                                                 //Should not happen
+                                                       //Should not happen
                                                }
                                                else if (value.size() > 0)
                                                {
@@ -635,13 +617,16 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
                                                        else
                                                        {
                                                                list<string>::iterator d = value.begin();
-                                                               for (list<string>::iterator i=key.begin();i!=key.end();i++)
+                                                               list<Zone::Type>::iterator z = zone.begin();
+                                                               for (list<string>::iterator i=key.begin();i!=key.end();++i)
                                                                {
-                                                                       DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "websocketsinkmanager setting" << (*i) << "to" << (*d) << "\n";
+                                                                       DebugOut() << __SMALLFILE__ << ":" << __LINE__ <<
+                                                                       "websocketsinkmanager setting " << (*i) << "to " << (*d) << "in zone " << (*z) << "\n";
                                                                        //(*i);
-                                                                       sinkManager->setValue((*i),(*d));
+                                                                       sinkManager->setValue(wsi,(*i),(*d),(*z), id);
                                                                        //(*d);
-                                                                       d++;
+                                                                       ++d;
+                                                                       ++z;
                                                                }
 
                                                        }
@@ -671,44 +656,26 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
                                                if (data.size() == 0)
                                                {
                                                        //Send what properties we support
-                                                       typessupported = "\"running_status_speedometer\",\"running_status_engine_speed\",\"running_status_steering_wheel_angle\",\"running_status_transmission_gear_status\"";
-                                                       
                                                        PropertyList foo = sinkManager->getSupportedProperties();
                                                        PropertyList::const_iterator i=foo.cbegin();
                                                        while (i != foo.cend())
                                                        {
-                                                               typessupported.append(",\"").append((*i)).append("\"");
+                                                               if(i==foo.cbegin())
+                                                                       typessupported.append("\"").append((*i)).append("\"");
+                                                               else
+                                                                       typessupported.append(",\"").append((*i)).append("\"");
                                                                i++;
                                                        }
                                                }
                                                else
                                                {
                                                        //Send what events a particular property supports
-                                                       if (data.front()== "running_status_speedometer")
-                                                       {
-                                                               typessupported = "\"get\",\"subscribe\",\"unsubscribe\",\"getSupportedEventTypes\"";
-                                                       }
-                                                       else if (data.front()== "running_status_engine_speed")
-                                                       {
-                                                               typessupported = "\"get\",\"subscribe\",\"unsubscribe\",\"getSupportedEventTypes\"";
-                                                       }
-                                                       else if (data.front() == "running_status_steering_wheel_angle")
-                                                       {
-                                                               typessupported = "\"get\",\"subscribe\",\"unsubscribe\",\"getSupportedEventTypes\"";
-                                                       }
-                                                       else if (data.front() == "running_status_transmission_gear_status")
+                                                       PropertyList foo = sinkManager->getSupportedProperties();
+                                                       if (ListPlusPlus<VehicleProperty::Property>(&foo).contains(data.front()))
                                                        {
+                                                               //sinkManager->addSingleShotSink(wsi,data.front(),id);
                                                                typessupported = "\"get\",\"subscribe\",\"unsubscribe\",\"getSupportedEventTypes\"";
                                                        }
-                                                       else
-                                                       {
-                                                               PropertyList foo = sinkManager->getSupportedProperties();
-                                                               if (ListPlusPlus<VehicleProperty::Property>(&foo).contains(data.front()))
-                                                               {
-                                                                       //sinkManager->addSingleShotSink(wsi,data.front(),id);
-                                                                       typessupported = "\"get\",\"subscribe\",\"unsubscribe\",\"getSupportedEventTypes\"";
-                                                               }
-                                                       }
                                                }
                                                stringstream s;
                                                string s2;
@@ -716,11 +683,7 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
                                                string replystr = s.str();
                                                DebugOut() << __SMALLFILE__ << ":" << __LINE__ << " JSON Reply: " << replystr << "\n";
                                                //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;
-                                               strcpy(new_response,replystr.c_str());
-                                               libwebsocket_write(wsi, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT);
-                                               delete (char*)(new_response-LWS_SEND_BUFFER_PRE_PADDING);
+                                               lwsWrite(wsi, replystr);
                                        }
                                        else
                                        {
index 8fe7008..f7178bd 100644 (file)
@@ -34,7 +34,7 @@ class WebSocketSinkManager: public AbstractSinkManager
 {
 public:
        WebSocketSinkManager(AbstractRoutingEngine* engine, map<string, string> config);
-       void addSingleShotSink(libwebsocket* socket, VehicleProperty::Property property,string id);
+       void addSingleShotSink(libwebsocket* socket, VehicleProperty::Property property, Zone::Type zone, string id);
        void addSingleShotRangedSink(libwebsocket* socket, PropertyList properties,double start, double end, double seqstart,double seqend, string id);
        void addSink(libwebsocket* socket, VehicleProperty::Property property,string uuid);
        void disconnectAll(libwebsocket* socket);
@@ -44,12 +44,12 @@ public:
        void init();
        map<std::string, list<WebSocketSink*> > m_sinkMap;
        void setConfiguration(map<string, string> config);
-       void setValue(string property,string value);
+       void setValue(libwebsocket* socket,VehicleProperty::Property property,string value, Zone::Type zone, string uuid);
        list<VehicleProperty::Property> getSupportedProperties();
 private:
        map<int,GIOChannel*> m_ioChannelMap;
        map<int,guint> m_ioSourceMap;
-  AbstractRoutingEngine *m_engine;
+       AbstractRoutingEngine *m_engine;
        struct libwebsocket_protocols protocollist[2];
 };
 
index 58958df..3d30d2b 100644 (file)
 #include <boost/lexical_cast.hpp>
 #include <glib.h>
 #include <sstream>
-//#include <json-glib/json-glib.h>
 #include <listplusplus.h>
 #include <timestamp.h>
 #include "uuidhelper.h"
 
 #include "debugout.h"
 #define __SMALLFILE__ std::string(__FILE__).substr(std::string(__FILE__).rfind("/")+1)
-libwebsocket_context *context;
+libwebsocket_context *context = NULL;
 WebSocketSource *source;
 AbstractRoutingEngine *m_re;
 
@@ -79,7 +78,8 @@ void WebSocketSource::checkSubscriptions()
                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;
                strcpy(new_response,replystr.c_str());
-               libwebsocket_write(clientsocket, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT);
+               if(clientsocket)
+                       libwebsocket_write(clientsocket, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT);
                delete (char*)(new_response-LWS_SEND_BUFFER_PRE_PADDING);
        }
 }
@@ -233,7 +233,7 @@ static int callback_http_only(libwebsocket_context *context,struct libwebsocket
                        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;
                        strcpy(new_response,replystr.c_str());
-                       libwebsocket_write(wsi, (unsigned char*)(new_response), strlen(new_response), LWS_WRITE_TEXT);  
+                       libwebsocket_write(wsi, (unsigned char*)(new_response), strlen(new_response), LWS_WRITE_TEXT);
                        delete (char*)(new_response-LWS_SEND_BUFFER_PRE_PADDING);
 
                        break;
@@ -272,7 +272,7 @@ static int callback_http_only(libwebsocket_context *context,struct libwebsocket
 
 
                        string type = string(json_object_get_string(typeobject));
-                       string  name = string(json_object_get_string(nameobject));
+                       string name = string(json_object_get_string(nameobject));
                        
                        string id;
                        
@@ -426,7 +426,7 @@ static int callback_http_only(libwebsocket_context *context,struct libwebsocket
                                                json_object_put(valueobject);
                                                json_object_put(timestampobject);
                                                json_object_put(sequenceobject);
-                                             
+                                               
                                                AbstractPropertyType* v = VehicleProperty::getPropertyTypeForPropertyNameValue(property,value);
                                                v->timestamp = boost::lexical_cast<double,std::string>(timestamp);
                                                v->sequence = boost::lexical_cast<double,std::string>(sequence);
@@ -442,6 +442,8 @@ static int callback_http_only(libwebsocket_context *context,struct libwebsocket
                                                {
                                                        DebugOut() << "get methodReply has been recieved, without a request being in!. This is likely due to a request coming in after the timeout has elapsed.\n";
                                                }
+
+                                               delete v;
                                        }
                                        else
                                        {
@@ -465,7 +467,7 @@ static int callback_http_only(libwebsocket_context *context,struct libwebsocket
                }
                case LWS_CALLBACK_ADD_POLL_FD:
                {
-                 DebugOut(5) << __SMALLFILE__ << ":" << __LINE__ << "Adding poll for websocket IO channel" << endl;
+                       DebugOut(5) << __SMALLFILE__ << ":" << __LINE__ << "Adding poll for websocket IO channel" << endl;
                        //Add a FD to the poll list.
                        GIOChannel *chan = g_io_channel_unix_new(libwebsocket_get_socket_fd(wsi));
 
@@ -492,7 +494,7 @@ WebSocketSource::WebSocketSource(AbstractRoutingEngine *re, map<string, string>
        m_sslEnabled = false;
        clientConnected = false;
        source = this;
-       m_re = re;  
+       m_re = re;
        struct lws_context_creation_info info;
        memset(&info, 0, sizeof info);
        info.protocols = protocols;
@@ -555,7 +557,7 @@ void WebSocketSource::getPropertyAsync(AsyncPropertyReply *reply)
        std::string uuid = amb::createUuid();
        uuidReplyMap[uuid] = reply;
        uuidTimeoutMap[uuid] = amb::currentTime() + 10.0; ///TODO: 10 second timeout, make this configurable?
-       stringstream s;  
+       stringstream s;
        
        s << "{\"type\":\"method\",\"name\":\"get\",\"data\":[\"" << reply->property << "\"],\"transactionid\":\"" << uuid << "\"}";
        string replystr = s.str();
@@ -564,7 +566,8 @@ void WebSocketSource::getPropertyAsync(AsyncPropertyReply *reply)
        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;
        strcpy(new_response,replystr.c_str());
-       libwebsocket_write(clientsocket, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT);
+       if(clientsocket)
+               libwebsocket_write(clientsocket, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT);
        delete (char*)(new_response-LWS_SEND_BUFFER_PRE_PADDING);
 }
 
@@ -573,7 +576,7 @@ void WebSocketSource::getRangePropertyAsync(AsyncRangePropertyReply *reply)
        std::string uuid = amb::createUuid();
        uuidRangedReplyMap[uuid] = reply;
        uuidTimeoutMap[uuid] = amb::currentTime() + 60; ///TODO: 60 second timeout, make this configurable?
-       stringstream s;  
+       stringstream s;
        s.precision(15);
        s << "{\"type\":\"method\",\"name\":\"getRanged\",\"data\": {";
 
@@ -604,7 +607,8 @@ void WebSocketSource::getRangePropertyAsync(AsyncRangePropertyReply *reply)
        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;
        strcpy(new_response,replystr.c_str());
-       libwebsocket_write(clientsocket, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT);
+       if(clientsocket)
+               libwebsocket_write(clientsocket, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT);
        delete (char*)(new_response-LWS_SEND_BUFFER_PRE_PADDING);
 }