From e4b87e0873359337ea4d923112bb4be75b70ee6f Mon Sep 17 00:00:00 2001 From: Kevron Rees Date: Fri, 2 Nov 2012 14:08:43 -0700 Subject: [PATCH] added getHistory support to websocket sink plugin and added api to test api.js --- lib/abstractroutingengine.h | 21 +++- plugins/websocketsink/test/api.js | 30 +++++- plugins/websocketsink/websocketsinkmanager.cpp | 132 +++++++++++++++++++------ plugins/websocketsink/websocketsinkmanager.h | 1 + 4 files changed, 151 insertions(+), 33 deletions(-) diff --git a/lib/abstractroutingengine.h b/lib/abstractroutingengine.h index f39503e..cca57b1 100644 --- a/lib/abstractroutingengine.h +++ b/lib/abstractroutingengine.h @@ -40,8 +40,13 @@ typedef std::function GetRangedPropertyComplete class PropertyValueTime { public: + ~PropertyValueTime() + { + delete value; + } + AbstractPropertyType* value; - time_t timestamp; + double timestamp; }; class AsyncPropertyRequest @@ -122,8 +127,8 @@ public: VehicleProperty::Property property; GetRangedPropertyCompletedSignal completed; - time_t begin; - time_t end; + double begin; + double end; }; class AsyncRangePropertyReply: public AsyncRangePropertyRequest @@ -135,6 +140,16 @@ public: } + ~AsyncRangePropertyReply() + { + for(auto itr = values.begin(); itr != values.end(); itr++) + { + delete (*itr); + } + + values.clear(); + } + std::list values; bool success; }; diff --git a/plugins/websocketsink/test/api.js b/plugins/websocketsink/test/api.js index 3a6f335..5c0d836 100644 --- a/plugins/websocketsink/test/api.js +++ b/plugins/websocketsink/test/api.js @@ -44,6 +44,19 @@ * form of data[n].name/data[n].value * errorCB: error callback, called with error message string * +* Function name: getHistory(event, startTime, endTime, successCB, errorCB) +* Description: +* Retrieves a list of event/value pairs for a target list of event names +* Required arguments: +* event: event to read +* startTime: start date/time +* endTime: end date/time +* successCB: success callback, gets called with the event/value pair list +* for all requested events. 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(eventlist, valuelist, successCB, errorCB) * Description: * Sets a gourp of event's values (triggers error on read-only events) @@ -245,6 +258,19 @@ Vehicle.prototype.get = function(namelist, successCB, errorCB) this.send(obj, successCB, errorCB); } +Vehicle.prototype.getHistory = function(event, startTime, endTime, successCB, errorCB) +{ + var obj = { + "type" : "method", + "name": "getHistory", + "transactionid" : this.generateTransactionId(), + "data" : [event, (startTime.getTime()/1000).toString(), (endTime.getTime()/1000).toString()] + }; + + this.send(obj, successCB, errorCB); + +} + Vehicle.prototype.set = function(namelist, valuelist, successCB, errorCB) { if((namelist.length != valuelist.length)||(namelist.length <= 0)) @@ -312,8 +338,8 @@ Vehicle.prototype.receive = function(msg) return; } - if((event == undefined)||(event.type == undefined)|| - (event.name == undefined)) + if((event === undefined)||(event.type === undefined)|| + (event.name === undefined)) { self.iErrorCB("BADLY FORMED MESSAGE: "+msg); return; diff --git a/plugins/websocketsink/websocketsinkmanager.cpp b/plugins/websocketsink/websocketsinkmanager.cpp index 3875501..e189ae2 100644 --- a/plugins/websocketsink/websocketsinkmanager.cpp +++ b/plugins/websocketsink/websocketsinkmanager.cpp @@ -80,6 +80,7 @@ void WebSocketSinkManager::setConfiguration(map config) } context = libwebsocket_create_context(port, interface.c_str(), protocollist,libwebsocket_internal_extensions,ssl_cert_path, ssl_key_path, -1, -1, options); } + void WebSocketSinkManager::addSingleShotSink(libwebsocket* socket, VehicleProperty::Property property,string id) { AsyncPropertyRequest velocityRequest; @@ -136,11 +137,88 @@ void WebSocketSinkManager::addSingleShotSink(libwebsocket* socket, VehicleProper //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); } + +void WebSocketSinkManager::addSingleShotRangedSink(libwebsocket* socket, VehicleProperty::Property property, double start, double end, string id) +{ + AsyncRangePropertyRequest rangedRequest; + + rangedRequest.begin = start; + rangedRequest.end = end; + + if (property == "running_status_speedometer") + { + rangedRequest.property = VehicleProperty::VehicleSpeed; + } + else if (property == "running_status_engine_speed") + { + rangedRequest.property = VehicleProperty::EngineSpeed; + } + else if (property == "running_status_steering_wheel_angle") + { + rangedRequest.property = VehicleProperty::SteeringWheelAngle; + } + else if (property == "running_status_transmission_gear_status") + { + rangedRequest.property = VehicleProperty::TransmissionShiftPosition; + } + else + { + PropertyList foo = VehicleProperty::capabilities(); + if (ListPlusPlus(&foo).contains(property)) + { + rangedRequest.property = property; + } + else + { + DebugOut(0)<<"websocketsink: Invalid property requested: "< values = reply->values; + for(auto itr = values.begin(); itr != values.end(); itr++) + { + if(itr != values.begin()) + { + data<<","; + } + + data << "{ \"value\" : " << "\"" << (*itr)->value->toString() << "\", \"time\" : \"" << (*itr)->timestamp << "\" }"; + } + + data<<"]"; + + s << "{\"type\":\"methodReply\",\"name\":\"getHistory\",\"data\":"<getRangePropertyAsync(rangedRequest); +} + void WebSocketSinkManager::removeSink(libwebsocket* socket,VehicleProperty::Property property, string uuid) { if (m_sinkMap.find(property) != m_sinkMap.end()) @@ -397,7 +475,7 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb name = json_reader_get_string_value(reader); json_reader_end_member(reader); - list data; + vector data; list key; list value; json_reader_read_member(reader,"data"); @@ -471,30 +549,6 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb //GetProperty is going to be a singleshot sink. //string arg = arguments.front(); sinkManager->addSingleShotSink(wsi,data.front(),id); - /*if (data.front()== "running_status_speedometer") - { - sinkManager->addSingleShotSink(wsi,VehicleProperty::VehicleSpeed,id); - } - else if (data.front() == "running_status_engine_speed") - { - sinkManager->addSingleShotSink(wsi,VehicleProperty::EngineSpeed,id); - } - else if (data.front() == "running_status_steering_wheel_angle") - { - sinkManager->addSingleShotSink(wsi,VehicleProperty::SteeringWheelAngle,id); - } - else if (data.front() == "running_status_transmission_gear_status") - { - sinkManager->addSingleShotSink(wsi,VehicleProperty::TransmissionShiftPosition,id); - } - else - { - PropertyList foo = VehicleProperty::capabilities(); - if (ListPlusPlus(&foo).contains(data.front())) - { - sinkManager->addSingleShotSink(wsi,data.front(),id); - } - }*/ } else { @@ -531,7 +585,7 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb else if (name == "subscribe") { //Websocket wants to subscribe to an event, data.front(); - for (list::iterator i=data.begin();i!=data.end();i++) + for (auto i=data.begin();i!=data.end();i++) { sinkManager->addSink(wsi,(*i),id); } @@ -539,11 +593,29 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb else if (name == "unsubscribe") { //Websocket wants to unsubscribe to an event, data.front(); - for (list::iterator i=data.begin();i!=data.end();i++) + for (auto i=data.begin();i!=data.end();i++) { sinkManager->removeSink(wsi,(*i),id); } } + else if (name == "getHistory") + { + if(data.size() == 3) + { + std::string property = data[0]; + std::string startStr = data[1]; + std::string endStr = data[2]; + + sinkManager->addSingleShotRangedSink(wsi,property, + boost::lexical_cast(startStr), + boost::lexical_cast(endStr), id); + } + + else + { + //TODO: error, "invalid arguments" should be sent in reply to this. + } + } else if (name == "getSupportedEventTypes") { //If data.front() dosen't contain a property name, return a list of properties supported. @@ -602,6 +674,10 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb libwebsocket_write(wsi, (unsigned char*)new_response, strlen(new_response), LWS_WRITE_TEXT); delete (char*)(new_response-LWS_SEND_BUFFER_PRE_PADDING); } + else + { + DebugOut(0)<<"Unknown method called."< config); void addSingleShotSink(libwebsocket* socket, VehicleProperty::Property property,string id); + void addSingleShotRangedSink(libwebsocket* socket, VehicleProperty::Property property,double start, double end, string id); void addSink(libwebsocket* socket, VehicleProperty::Property property,string uuid); void disconnectAll(libwebsocket* socket); void removeSink(libwebsocket* socket,VehicleProperty::Property property,string uuid); -- 2.7.4