diff options
author | Kevron Rees <tripzero.kev@gmail.com> | 2014-12-23 23:50:50 -0800 |
---|---|---|
committer | Kevron Rees <tripzero.kev@gmail.com> | 2014-12-23 23:50:50 -0800 |
commit | c6b73df909bcf61fc6f5ae19cd9a693d55e69651 (patch) | |
tree | c8b5987c02a5f8e53bd42cc692ba2a855aef7014 | |
parent | 045f1495022da6773cc4c86c1abeaba466eea8a4 (diff) | |
download | automotive-message-broker-c6b73df909bcf61fc6f5ae19cd9a693d55e69651.tar.gz |
[tools] ambctl test script
-rw-r--r-- | RELEASE | 1 | ||||
-rw-r--r-- | TODO | 8 | ||||
-rw-r--r-- | lib/abstractpropertytype.h | 2 | ||||
-rw-r--r-- | lib/ambpluginimpl.cpp | 9 | ||||
-rw-r--r-- | lib/ambpluginimpl.h | 2 | ||||
-rw-r--r-- | plugins/database/CMakeLists.txt | 3 | ||||
-rw-r--r-- | plugins/database/databasesink.cpp | 34 | ||||
-rw-r--r-- | plugins/dbus/abstractdbusinterface.cpp | 7 | ||||
-rw-r--r-- | plugins/dbus/dbusplugin.cpp | 1 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 2 | ||||
-rwxr-xr-x | tests/gendb.sh | 15 | ||||
-rw-r--r-- | tools/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tools/ambctl.py | 105 |
13 files changed, 160 insertions, 30 deletions
@@ -6,6 +6,7 @@ New features: - [OpenCV plugin] driver drowsiness detection test code - [Bluemonkey plugin] support for zones in JS API. - [Bluemonkey plugin] database module. +- [tools] new ambctl. replaces amb-get, amb-set, etc Changes: - OpenCV plugin experimental options for cuda and kinect are removed @@ -1,14 +1,10 @@ - Refactor obd2 plugin with AsyncQueue. Use thread safe-update property. -- update json protocol to support rangerequests with PropertyList instead of a signel property (Verify) -- update database to support zone column -- general support for source and zone filtering in database plugin +- update json protocol to support rangerequests with PropertyList instead of a singel property (Verify) +- source export from database plugin does not reflect the source in the database - no reason for pluginloader to track sources. core already does it. - create docs for all plugins (README) - handle badly formed messages properly (ie not crash) in websocketsink -- GetHistory must filter on source - grep all the TODOs in the code and do them - investigate and enable use of provisioning in ssl websockets - enable ambd/plugins.d/ -- finish implementing openxc plugin (needs testing) -- Document internal source/sink plugin API diff --git a/lib/abstractpropertytype.h b/lib/abstractpropertytype.h index 1d299bbc..6efbee13 100644 --- a/lib/abstractpropertytype.h +++ b/lib/abstractpropertytype.h @@ -87,7 +87,7 @@ public: AbstractPropertyType(std::string property) : name(property), timestamp(amb::currentTime()), sequence(-1), zone(Zone::None), priority(Normal) { - void*(name); + } virtual ~AbstractPropertyType() diff --git a/lib/ambpluginimpl.cpp b/lib/ambpluginimpl.cpp index dc646857..7bf7e712 100644 --- a/lib/ambpluginimpl.cpp +++ b/lib/ambpluginimpl.cpp @@ -133,8 +133,10 @@ AbstractPropertyType* AmbPluginImpl::findPropertyType(const VehicleProperty::Pro return nullptr; } -std::shared_ptr<AbstractPropertyType> AmbPluginImpl::addPropertySupport(Zone::Type zone, std::function<AbstractPropertyType* (void)> typeFactory) +std::shared_ptr<AbstractPropertyType> AmbPluginImpl::addPropertySupport(Zone::Type zone, std::function<AbstractPropertyType* (void)> typeFactory, std::string sourceUuid) { + if(sourceUuid.empty()) + sourceUuid = uuid(); std::shared_ptr<AbstractPropertyType> propertyType(typeFactory()); if(!propertyType) return propertyType; @@ -154,9 +156,10 @@ std::shared_ptr<AbstractPropertyType> AmbPluginImpl::addPropertySupport(Zone::Ty propertyType.swap(registeredPropertyType); } propertyType->zone = zone; - propertyType->sourceUuid = uuid(); + propertyType->sourceUuid = sourceUuid; + propertyType->timestamp = amb::currentTime(); ZonePropertyType& zonePropType = properties[name]; - zonePropType.insert( make_pair(zone, propertyType)); + zonePropType.insert(make_pair(zone, propertyType)); return propertyType; } diff --git a/lib/ambpluginimpl.h b/lib/ambpluginimpl.h index d9482f0f..96080379 100644 --- a/lib/ambpluginimpl.h +++ b/lib/ambpluginimpl.h @@ -145,7 +145,7 @@ protected: * \param typeFactory Function to be used to create instance of the AbstractPropertyType for registered property * \return AbstractPropertyType* if signal exits otherwise nullptr(in this case we do not know its datatype) */ - std::shared_ptr<AbstractPropertyType> addPropertySupport(Zone::Type zone, std::function<AbstractPropertyType* (void)> typeFactory); + std::shared_ptr<AbstractPropertyType> addPropertySupport(Zone::Type zone, std::function<AbstractPropertyType* (void)> typeFactory, std::string sourceUuid=""); template <class T> std::shared_ptr<AbstractPropertyType> addPropertySupport(Zone::Type zone) diff --git a/plugins/database/CMakeLists.txt b/plugins/database/CMakeLists.txt index 2564ff2c..041fb01f 100644 --- a/plugins/database/CMakeLists.txt +++ b/plugins/database/CMakeLists.txt @@ -6,6 +6,9 @@ pkg_check_modules(sqlite REQUIRED sqlite3) include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${sqlite_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/plugins/common) +set(database_table_create "CREATE TABLE IF NOT EXISTS data (key TEXT, value BLOB, source TEXT, zone INTEGER, time REAL, sequence REAL, tripId TEXT)" CACHE INTERNAL "database plugin table create command") +add_definitions(-Ddatabase_table_create="${database_table_create}") + set(databasesinkplugin_headers databasesink.h utils.h basedb.hpp baseobject.h sqlitedatabase.h sqlitequery.h) set(databasesinkplugin_sources databasesink.cpp utils.cpp sqlitedatabase.cpp sqlitequery.cpp basedb.hpp) add_library(databasesinkplugin MODULE ${databasesinkplugin_sources}) diff --git a/plugins/database/databasesink.cpp b/plugins/database/databasesink.cpp index f7ed7cf7..9bfe5b25 100644 --- a/plugins/database/databasesink.cpp +++ b/plugins/database/databasesink.cpp @@ -140,7 +140,7 @@ DatabaseSink::DatabaseSink(AbstractRoutingEngine *engine, map<std::string, std:: :AmbPluginImpl(engine, config, parent), shared(nullptr), playback(false), playbackShared(nullptr), playbackMultiplier(1) { tablename = "data"; - tablecreate = "CREATE TABLE IF NOT EXISTS data (key TEXT, value BLOB, source TEXT, zone INTEGER, time REAL, sequence REAL, tripId TEXT)"; + tablecreate = database_table_create; if(config.find("bufferLength") != config.end()) { @@ -341,7 +341,7 @@ void DatabaseSink::setDatabaseFileName(string filename) { initDb(); - vector<vector<string> > supportedStr = shared->db->select("SELECT DISTINCT key, zone FROM " + tablename); + vector<vector<string> > supportedStr = shared->db->select("SELECT DISTINCT key, zone, source FROM " + tablename); for(int i=0; i < supportedStr.size(); i++) { @@ -350,11 +350,13 @@ void DatabaseSink::setDatabaseFileName(string filename) if(!contains(supported(), name)) { std::string zoneStr = supportedStr[i][1]; + std::string sourceStr = supportedStr[i][2]; - DebugOut() << "adding property " << name << " in zone: " << zoneStr << endl; + DebugOut() << "adding property " << name << " in zone: " << zoneStr << "for source: " << sourceStr << endl; Zone::Type zone = boost::lexical_cast<Zone::Type>(zoneStr); - addPropertySupport(zone, [name]() { return VehicleProperty::getPropertyTypeForPropertyNameValue(name); }); + auto property = addPropertySupport(zone, [name]() { return VehicleProperty::getPropertyTypeForPropertyNameValue(name); }); + property->sourceUuid = sourceStr; } } @@ -417,17 +419,18 @@ void DatabaseSink::getRangePropertyAsync(AsyncRangePropertyReply *reply) for(auto itr = reply->properties.begin(); itr != reply->properties.end(); itr++) { + DebugOut() << "prop: " << (*itr) << endl; if(itr != reply->properties.begin()) query<<" OR "; query<<"key='"<<(*itr)<<"'"; } - query<<") AND"; + query<<")"; - if(reply->timeBegin && reply->timeEnd) + if(reply->timeEnd) { - query<<" time BETWEEN "<<reply->timeBegin<<" AND "<<reply->timeEnd; + query<<" AND time BETWEEN "<<reply->timeBegin<<" AND "<<reply->timeEnd; } if(reply->sequenceBegin >= 0 && reply->sequenceEnd >=0) @@ -444,9 +447,19 @@ void DatabaseSink::getRangePropertyAsync(AsyncRangePropertyReply *reply) DebugOut()<<"Dataset size "<<data.size()<<endl; - for(auto i=0;i<data.size();i++) + if(!data.size()) { - if(data[i].size() != 6) + reply->success = false; + reply->error = AsyncPropertyReply::InvalidOperation; + } + else + { + reply->success = true; + } + + for(auto i=0; i<data.size(); i++) + { + if(data[i].size() != 7) continue; DBObject dbobj; @@ -456,6 +469,7 @@ void DatabaseSink::getRangePropertyAsync(AsyncRangePropertyReply *reply) dbobj.zone = boost::lexical_cast<double>(data[i][3]); dbobj.time = boost::lexical_cast<double>(data[i][4]); dbobj.sequence = boost::lexical_cast<double>(data[i][5]); + dbobj.tripId = data[i][6]; AbstractPropertyType* property = VehicleProperty::getPropertyTypeForPropertyNameValue(dbobj.key, dbobj.value); if(property) @@ -467,7 +481,7 @@ void DatabaseSink::getRangePropertyAsync(AsyncRangePropertyReply *reply) } } - reply->success = true; + reply->completed(reply); delete db; diff --git a/plugins/dbus/abstractdbusinterface.cpp b/plugins/dbus/abstractdbusinterface.cpp index dce2888b..c8dcdf17 100644 --- a/plugins/dbus/abstractdbusinterface.cpp +++ b/plugins/dbus/abstractdbusinterface.cpp @@ -103,7 +103,8 @@ static void handleMyMethodCall(GDBusConnection *connection, { AbstractProperty* prop = (*itr).second; - propertyList.push_back(prop->ambPropertyName()); + if(!contains(propertyList, prop->ambPropertyName())) + propertyList.push_back(prop->ambPropertyName()); } std::string ifaceName = iface->interfaceName(); @@ -114,7 +115,7 @@ static void handleMyMethodCall(GDBusConnection *connection, request.timeBegin = beginTime; request.timeEnd = endTime; request.zone = iface->zone(); - request.sourceUuid = iface->source(); + //request.sourceUuid = iface->source(); request.completed = [&invocation,&ifaceName](AsyncRangePropertyReply* reply) { @@ -247,7 +248,7 @@ void AbstractDBusInterface::addProperty(AbstractProperty* property) "</method>" "<signal name='" + pn + "Changed' >" " <arg type='v' name='" + nameToLower + "' direction='out' />" - " <arg type='d' name='timestamp' direction='out' />" + " <arg type='d' name='imestamp' direction='out' />" "</signal>" "<property type='i' name='" + property->name() + "Sequence' access='read' />"; diff --git a/plugins/dbus/dbusplugin.cpp b/plugins/dbus/dbusplugin.cpp index da84c5d5..ed950268 100644 --- a/plugins/dbus/dbusplugin.cpp +++ b/plugins/dbus/dbusplugin.cpp @@ -70,6 +70,7 @@ void DBusSink::supportedChanged(const PropertyList &supportedProperties) routingEngine->subscribeToProperty(p, mSourceFilter, this); addProperty(prop); supported = true; + mTime = amb::currentTime(); } } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e54f797b..8fab3da2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,7 +6,7 @@ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/amb-get.py ${CMAKE_CURRENT_BINARY_DI configure_file (${CMAKE_CURRENT_SOURCE_DIR}/amb-set.py ${CMAKE_CURRENT_BINARY_DIR}/amb-set @ONLY) configure_file (${CMAKE_CURRENT_SOURCE_DIR}/amb-get-history.py ${CMAKE_CURRENT_BINARY_DIR}/amb-get-history @ONLY) configure_file (${CMAKE_CURRENT_SOURCE_DIR}/amb-listen.py ${CMAKE_CURRENT_BINARY_DIR}/amb-listen @ONLY) -configure_file (${CMAKE_CURRENT_SOURCE_DIR}/gen-set.py ${CMAKE_CURRENT_BINARY_DIR}/gen-set @ONLY) +configure_file (${CMAKE_CURRENT_SOURCE_DIR}/gendb.sh ${CMAKE_CURRENT_SOURCE_DIR}/gendb @ONLY) install (PROGRAMS ${amb_tests} DESTINATION bin) diff --git a/tests/gendb.sh b/tests/gendb.sh index 34a1978d..9830d82d 100755 --- a/tests/gendb.sh +++ b/tests/gendb.sh @@ -1,23 +1,28 @@ #!/bin/bash -TABLE="CREATE TABLE IF NOT EXISTS data (key TEXT, value BLOB, source TEXT, time REAL, sequence REAL);" +TABLE="@database_table_create@;" + +if [ -f generated.db ]; + then + rm generated.db +fi -rm generated.db -rm generated.db.sql echo $TABLE > generated.db.sql echo "BEGIN IMMEDIATE TRANSACTION;" >> generated.db.sql -for (( i=0; i<120; i++ )) +for (( i=0; i<130; i++ )) do T=$(echo 1385571956 + $i) for (( n=1; n<1000; n++ )) do MS=$(echo $n \* 0.001 | bc) TIME=$(echo $T + $MS | bc) - echo "insert into data values('VehicleSpeed',$(( ( RANDOM % 300 ) + 1 )),'test', $TIME, -1);" >> generated.db.sql + echo "insert into data values('VehicleSpeed', $(( ( RANDOM % 300 ) + 1 )),'test', 0, $TIME, -1, 'alskejroanpnfansadfasdfa');" >> generated.db.sql done done echo "END TRANSACTION;" >> generated.db.sql sqlite3 generated.db < generated.db.sql + +exit diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 64f35086..ddba598f 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1 +1,2 @@ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/genmapping.py ${CMAKE_CURRENT_SOURCE_DIR}/genmapping @ONLY) +configure_file (${CMAKE_CURRENT_SOURCE_DIR}/ambctl.py ${CMAKE_CURRENT_SOURCE_DIR}/ambctl @ONLY) diff --git a/tools/ambctl.py b/tools/ambctl.py new file mode 100644 index 00000000..e3850645 --- /dev/null +++ b/tools/ambctl.py @@ -0,0 +1,105 @@ +#!/usr/bin/python + +import argparse +import dbus +import sys +import json +import gobject +from dbus.mainloop.glib import DBusGMainLoop + +def changed(interface, properties, invalidated): + print json.dumps(properties, indent=2) + +parser = argparse.ArgumentParser(description='Process DBus mappings.') +parser.add_argument('command', metavar='COMMAND [help]', help='amb dbus command') + +parser.add_argument('commandArgs', metavar='ARG', nargs='*', + help='amb dbus command arguments') + +args = parser.parse_args() + +dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) +bus = dbus.SystemBus() +managerObject = bus.get_object("org.automotive.message.broker", "/"); +managerInterface = dbus.Interface(managerObject, "org.automotive.Manager") + +if args.command == "list" : + supportedList = managerInterface.List(); + for objectName in supportedList: + print objectName + sys.exit() + +elif args.command == "get": + if args.commandArgs[0] == "help": + print "ObjectName [ObjectName...]" + sys.exit() + + for objectName in args.commandArgs: + objects = managerInterface.FindObject(objectName); + print objectName + for o in objects: + propertiesInterface = dbus.Interface(bus.get_object("org.automotive.message.broker", o),"org.freedesktop.DBus.Properties") + print json.dumps(propertiesInterface.GetAll("org.automotive."+objectName), indent=2) + sys.exit() + +elif args.command == "listen": + if args.commandArgs[0] == "help": + print "ObjectName [ObjectName...]" + sys.exit() + for objectName in args.commandArgs: + objects = managerInterface.FindObject(objectName); + for o in objects: + bus.add_signal_receiver(changed, + dbus_interface="org.freedesktop.DBus.Properties", + signal_name="PropertiesChanged", path=o) +elif args.command == "set": + if args.commandArgs[0] == "help": + print "ObjectName PropertyName VALUE [ZONE]" + sys.exit() + if len(args.commandArgs) < 3: + print "set requires more arguments (see set help)" + sys.exit() + objectName = args.commandArgs[0] + propertyName = args.commandArgs[1] + value = args.commandArgs[2] + zone = 0 + if len(args.commandArgs) == 4: + zone = int(args.commandArgs[3]) + object = managerInterface.FindObjectForZone(objectName, zone) + propertiesInterface = dbus.Interface(bus.get_object("org.automotive.message.broker", object),"org.freedesktop.DBus.Properties") + property = propertiesInterface.Get("org.automotive."+objectName, propertyName) + realValue = property.__class__(value) + propertiesInterface.Set("org.automotive."+objectName, propertyName, realValue) + property = propertiesInterface.Get("org.automotive."+objectName, propertyName) + if property == realValue: + print propertyName + " = ", property + else: + print "Error setting property" + sys.exit() +elif args.command == "getHistory": + if args.commandArgs[0] == "help": + print "ObjectName [STARTTIME] [ENDTIME] [ZONE]" + sys.exit() + if len(args.commandArgs) < 1: + print "getHistory requires more arguments (see getHistory help)" + sys.exit() + objectName = args.commandArgs[0] + start = 1 + if len(args.commandArgs) >= 2: + start = float(args.commandArgs[1]) + end = 9999999999 + if len(args.commandArgs) >= 3: + end = float(args.commandArgs[2]) + zone = 0 + if len(args.commandArgs) == 4: + zone = int(args.commandArgs[3]) + + object = managerInterface.FindObjectForZone(objectName, zone); + propertiesInterface = dbus.Interface(bus.get_object("org.automotive.message.broker", object),"org.automotive."+objectName) + print json.dumps(propertiesInterface.GetHistory(start, end), indent=2) + sys.exit() +else: + print "unknown command" + sys.exit() +loop = gobject.MainLoop() +loop.run() |