diff options
author | Kevron Rees <tripzero.kev@gmail.com> | 2014-12-23 09:52:00 -0800 |
---|---|---|
committer | Kevron Rees <tripzero.kev@gmail.com> | 2014-12-23 09:52:00 -0800 |
commit | 2bdd66ead71810213900523cac7d3b4abd1592db (patch) | |
tree | 0df2c3905d4ca8f50db6d63b02f0b4d29392f115 | |
parent | 5f66d2e3e2bc77fed33a9069a8f02fd2142d218f (diff) | |
parent | bbbf257a0c9c8449250804b6a805f6d41750f7ea (diff) | |
download | automotive-message-broker-2bdd66ead71810213900523cac7d3b4abd1592db.tar.gz |
Merge pull request #36 from tripzero/master0.12.901
Documentation updates. Fixes to several plugins.
63 files changed, 739 insertions, 815 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d62d3408..fbbc5afc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_BUILD_TYPE, Debug) include(FindPkgConfig) set(PROJECT_NAME "automotive-message-broker") -set(PROJECT_VERSION "0.12.900") +set(PROJECT_VERSION "0.12.901") set(PROJECT_CODENAME "agera") set(PROJECT_QUALITY "beta") @@ -10,8 +10,12 @@ New features: Changes: - OpenCV plugin experimental options for cuda and kinect are removed - Removed unmaintained plugins: tpms, websocket{sink,source} +- AbstractSource::getPropertyInfo() is now mandatory +- [websocket plugin] protocol changes: getSupportedEventTypes is getSupported. 'data' changed type to array of objects + instead of array of strings. See plugins/websocket/protocol Fixes: - [DBus plugin] Fix exporting properties in zones that really don't have support - [xwalk extension] fixed set() for some types did not work because of invalid GVariant creation. - [websocket plugin] Updated html test page. Fixed protocol usage. +- [websocket plugin] Source zones properly supported @@ -1,9 +1,6 @@ - Refactor obd2 plugin with AsyncQueue. Use thread safe-update property. -- Rewrite websocket test html -- update json protocol to include getPropertyInfo calls - update json protocol to support rangerequests with PropertyList instead of a signel property (Verify) -- update json protocol to support zones - update database to support zone column - general support for source and zone filtering in database plugin - no reason for pluginloader to track sources. core already does it. diff --git a/ambd/core.cpp b/ambd/core.cpp index 645e6307..4402bfff 100644 --- a/ambd/core.cpp +++ b/ambd/core.cpp @@ -130,9 +130,8 @@ void Core::updateSupported(PropertyList added, PropertyList removed, AbstractSou if(!s.size()) return; - for(auto itr = mSinks.begin(); itr != mSinks.end(); ++itr) + for(auto sink : mSinks) { - AbstractSink* sink = *itr; sink->supportedChanged(s); } } @@ -501,6 +500,11 @@ void Core::handleAddSupported(const PropertyList& added, AbstractSource* source) if(!source) throw std::runtime_error("Core::handleAddSupported passed a null source"); + if(!contains(mSources, source)) + { + mSources.insert(source); + } + for(auto property : added) { if(!sourceForProperty(property, source->uuid())) diff --git a/ambd/main.cpp b/ambd/main.cpp index f6f1b407..58a8abde 100644 --- a/ambd/main.cpp +++ b/ambd/main.cpp @@ -155,7 +155,7 @@ int main(int argc, char **argv) if(getuid() == 0) { - DebugOut(DebugOut::Error)<<"Running as root. This is dangerous."<<endl; + DebugOut(DebugOut::Warning)<<"Running as root. This is dangerous."<<endl; } #ifndef GLIB_VERSION_2_36 @@ -207,9 +207,9 @@ void daemonize() close(i); // close all descriptors } { // handle standard I/O - i = open("/dev/null", O_RDWR); - dup(i); - dup(i); + i = open("/dev/null", O_RDWR); + dup(i); + dup(i); } // first instance continues } diff --git a/docs/README b/docs/README index 18e1b1f9..e60609fe 100644 --- a/docs/README +++ b/docs/README @@ -6,4 +6,4 @@ cmake -Denable_docs=ON .. The internal AMB class and interface documentation is generated in the docs/amb folder. DBus API documentation is generated in the docs/dbus folder. - +Specific plugin documentation can be found in the plugins/${plugin}/README (ie plugins/dbus/README). diff --git a/docs/amb.in.idl b/docs/amb.in.idl index 0d57e836..ded521e5 100644 --- a/docs/amb.in.idl +++ b/docs/amb.in.idl @@ -40,7 +40,7 @@ map Dictionary { interface VehiclePropertyType { /*! - * \brief time stamp marking the last time a property in the interface updated + * \brief time in seconds since system start when a property in the interface updated. */ attribute Double Time readonly @@ -71,10 +71,8 @@ enumeration Zone { } /*! org.automotive.Manager - * \brief Manager is a helper interface for discovering and finding available objects - * Manager is a helper interface that helps inform of supported data types and find - * specified data type objects' path on DBus - * DBus Path: / + * \brief Manager is a helper interface for discovering and finding available objects. + * Objects represent interfaces to data types. */ interface org.automotive.Manager { @@ -82,7 +80,7 @@ interface org.automotive.Manager { * \brief return supported properties */ method List { - out { String[] } + out {array of String objectNames} } /*! @@ -102,7 +100,7 @@ interface org.automotive.Manager { String objectName } out { - String[] objectPaths + array of String objectPaths } } @@ -138,7 +136,7 @@ interface org.automotive.Manager { String objectName } out { - UInt32[] zones + array of UInt32 zones } } diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 28ff5a33..4313156e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -4,7 +4,6 @@ set(amb_examples configwheel databaseconfig databasesource dbusconfig examplecon configure_file (${CMAKE_CURRENT_SOURCE_DIR}/configwheel.in ${CMAKE_CURRENT_SOURCE_DIR}/configwheel @ONLY) -configure_file (${CMAKE_CURRENT_SOURCE_DIR}/databaseconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/databaseconfig @ONLY) configure_file (${CMAKE_CURRENT_SOURCE_DIR}/databasesource.in ${CMAKE_CURRENT_SOURCE_DIR}/databasesource @ONLY) configure_file (${CMAKE_CURRENT_SOURCE_DIR}/dbusconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/dbusconfig @ONLY) configure_file (${CMAKE_CURRENT_SOURCE_DIR}/exampleconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/exampleconfig @ONLY) diff --git a/examples/databaseconfig.in b/examples/databaseconfig.in deleted file mode 100644 index 577c82ee..00000000 --- a/examples/databaseconfig.in +++ /dev/null @@ -1,28 +0,0 @@ -{ - "sources" : [ - { - "name" : "ExampleSouce", - "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so" - } - ], - "sinks": [ - { - "name" : "Database", - "path" : "@PLUGIN_INSTALL_PATH@/databasesinkplugin.so", - "properties" : "{ 'properties' : ['VehicleSpeed','EngineSpeed'] }", - "databaseFile" : "/tmp/storage", - "startOnLoad" : "true", - "bufferLength" : "1", - "frequency" : "1" - }, - { - "name" : "Example Sink", - "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so" - }, - { - "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so" - } - - ] -} - diff --git a/examples/opencvdbusconfig.in b/examples/opencvdbusconfig.in index 0040e1a5..7634c755 100644 --- a/examples/opencvdbusconfig.in +++ b/examples/opencvdbusconfig.in @@ -4,7 +4,7 @@ { "name" : "OpenCV LUX", "path" : "@PLUGIN_INSTALL_PATH@/opencvluxplugin.so", - "threaded" : "false", + "threaded" : "true", "opencl" : "true", "fps" : "30", "pixelLowerBound" : "18", diff --git a/examples/websocketsource2.in b/examples/websocketsource2.in index c537fb45..053b1ab8 100644 --- a/examples/websocketsource2.in +++ b/examples/websocketsource2.in @@ -12,6 +12,10 @@ ], "sinks": [ { + "name" : "DBusSink", + "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so" + }, + { "name" : "ExampleSink", "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so" } diff --git a/lib/abstractpropertytype.h b/lib/abstractpropertytype.h index 0157b530..1d299bbc 100644 --- a/lib/abstractpropertytype.h +++ b/lib/abstractpropertytype.h @@ -63,7 +63,7 @@ static const Zone::Type MiddleLeft; static const Zone::Type RearRight; static const Zone::Type RearLeft; -typedef std::list<Zone::Type> ZoneList; +typedef std::vector<Zone::Type> ZoneList; }; @@ -222,6 +222,22 @@ public: return mValue; } + /*! + * \brief signature + * \return gvariant signature + */ + virtual const string signature() + { + auto var = amb::make_super(toVariant()); + if(!var) return ""; + + const string s = g_variant_get_type_string(var.get()); + + DebugOut() << "returning signature: " << s << " for "<< name << endl; + + return s; + } + /** * @brief destroyed is called if this property is destroyed. */ @@ -266,7 +282,9 @@ public: static int value(GVariant* v) { - return g_variant_get_int32(v); + int val = 0; + g_variant_get(v, signature(), &val); + return val; } static std::string stringize(std::string v) diff --git a/lib/abstractsink.h b/lib/abstractsink.h index 6494adec..1b4ed9db 100644 --- a/lib/abstractsink.h +++ b/lib/abstractsink.h @@ -73,7 +73,7 @@ protected: }; -/// TODO: deprecate in 0.13. +/// TODO: deprecate in 0.14. class AbstractSinkManager { public: diff --git a/lib/abstractsource.cpp b/lib/abstractsource.cpp index 26fc07c8..5e78c363 100644 --- a/lib/abstractsource.cpp +++ b/lib/abstractsource.cpp @@ -1,19 +1,19 @@ /* - Copyright (C) 2012 Intel Corporation + Copyright (C) 2012 Intel Corporation - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -31,10 +31,5 @@ AbstractSource::~AbstractSource() } -PropertyInfo AbstractSource::getPropertyInfo(const VehicleProperty::Property & property) -{ - return PropertyInfo::invalid(); -} - diff --git a/lib/abstractsource.h b/lib/abstractsource.h index 5868dbf1..ebeaebdc 100644 --- a/lib/abstractsource.h +++ b/lib/abstractsource.h @@ -106,7 +106,7 @@ public: * \param property the property to get info for. * \return a PropertyInfo object. */ - virtual PropertyInfo getPropertyInfo(const VehicleProperty::Property & property); + virtual PropertyInfo getPropertyInfo(const VehicleProperty::Property & property) = 0; /*! * \brief supported diff --git a/lib/debugout.h b/lib/debugout.h index 4644ef73..b8030ee9 100644 --- a/lib/debugout.h +++ b/lib/debugout.h @@ -30,11 +30,18 @@ using namespace std; void debugOut(const string &message); -class DebugOut +class DebugOut { public: + /*! + * \brief Error use when essential functionality is blocked + */ static const int Error; + + /*! + * \brief Warning use when non-essential functionality is bocked, or when workarounds exist. + */ static const int Warning; DebugOut(int debugLevel = 4) @@ -85,7 +92,7 @@ public: } return *this; } - + DebugOut const & operator << (double val) const { if(mDebugLevel <= debugThreshhold || mDebugLevel == Error || mDebugLevel == Warning) diff --git a/lib/propertyinfo.hpp b/lib/propertyinfo.hpp index 600c90ff..ae229a45 100644 --- a/lib/propertyinfo.hpp +++ b/lib/propertyinfo.hpp @@ -2,7 +2,6 @@ #define PROPERTYINFO_H_ #include "abstractpropertytype.h" -#include <list> class PropertyInfo { @@ -18,7 +17,7 @@ public: * @arg updateFrequency * @arg zonesList */ - PropertyInfo(uint updateFreq, std::list<Zone::Type> zonesList) + PropertyInfo(uint updateFreq, Zone::ZoneList zonesList) :mUpdateFrequency(updateFreq), mZones(zonesList), mIsValid(true) { @@ -38,7 +37,7 @@ public: * Number of different zones supported by this property. * */ - std::list<Zone::Type> zones() + Zone::ZoneList zones() { return mZones; } @@ -65,7 +64,7 @@ public: private: uint mUpdateFrequency; - std::list<Zone::Type> mZones; + Zone::ZoneList mZones; bool mIsValid; }; diff --git a/lib/vehicleproperty.h b/lib/vehicleproperty.h index 08792cdf..e1bd0ed6 100644 --- a/lib/vehicleproperty.h +++ b/lib/vehicleproperty.h @@ -30,6 +30,7 @@ #include "abstractpropertytype.h" #include "mappropertytype.hpp" +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" namespace ButtonEvents { enum ButtonEventType { @@ -541,7 +542,7 @@ public: /**< Button Event @see ButtonEvents::ButtonEventType */ ///TODO: deprecated. Use ButtonEventW3C. Remove in 0.14 - [[deprecated("Depricated in 0.14. Use ButtonEventW3C")]] + [[deprecated("Deprecated in 0.14. Use ButtonEventW3C")]] static const Property ButtonEvent; PROPERTYTYPE(ButtonEvent, ButtonEventType, BasicPropertyType<ButtonEvents::ButtonEventType>, ButtonEvents::ButtonEventType) diff --git a/plugins/bluemonkey/bluemonkey.cpp b/plugins/bluemonkey/bluemonkey.cpp index 38d39a6d..b8c98168 100644 --- a/plugins/bluemonkey/bluemonkey.cpp +++ b/plugins/bluemonkey/bluemonkey.cpp @@ -127,7 +127,8 @@ AbstractPropertyType* qVariantToAbstractPropertyType(QString name, QVariant var) return nullptr; } -BluemonkeySink::BluemonkeySink(AbstractRoutingEngine* e, map<string, string> config, AbstractSource &parent): QObject(0), AmbPluginImpl(e, config, parent), engine(nullptr), mSilentMode(false) +BluemonkeySink::BluemonkeySink(AbstractRoutingEngine* e, map<string, string> config, AbstractSource &parent) + : QObject(0), AmbPluginImpl(e, config, parent), engine(nullptr), mSilentMode(false) { QTimer::singleShot(1,this,SLOT(reloadEngine())); diff --git a/plugins/bluemonkey/config.js b/plugins/bluemonkey/config.js index a1dfd572..6f48d8f3 100644 --- a/plugins/bluemonkey/config.js +++ b/plugins/bluemonkey/config.js @@ -239,6 +239,11 @@ bluemonkey.createCustomProperty("LaneDepartureStatus", "running"); bluemonkey.createCustomProperty("AlarmStatus", "prearmed"); bluemonkey.createCustomProperty("ParkingBrakeStatusW3C", "inactive"); +bluemonkey.createCustomProperty("Altitude", 200); +bluemonkey.createCustomProperty("Latitude", 45.541174); +bluemonkey.createCustomProperty("Longitude", -122.958967); + + var speedProperty = bluemonkey.subscribeTo("VehicleSpeed"); var testTimer = bluemonkey.createTimer(); diff --git a/plugins/common/CMakeLists.txt b/plugins/common/CMakeLists.txt index 7f123ab8..8a2311ac 100644 --- a/plugins/common/CMakeLists.txt +++ b/plugins/common/CMakeLists.txt @@ -1,5 +1,5 @@ set(plugins_common_sources abstractio.hpp serialport.hpp bluetoothadapterproxy.c bluetooth.hpp bluetoothmanagerproxy.c bluetoothserialproxy.c bluetooth5.cpp canadapter.cpp cansocket.cpp cansocketreader.cpp - canbusimpl.cpp cansocketadapter.cpp logger.cpp mutex.cpp thread.cpp ambpluginimpl.cpp) + canbusimpl.cpp cansocketadapter.cpp logger.cpp mutex.cpp thread.cpp ambpluginimpl.cpp ambplugin.h) set(plugins_common_headers_install abstractio.hpp serialport.hpp bluetooth.hpp bluetoothadapterproxy.h bluetoothmanagerproxy.h bluetoothserialproxy.h bluetooth5.h canbus.h canadapter.h cansocket.h cansocketreader.h canbusimpl.h cansocketadapter.h canobserver.h logger.h mutex.h thread.h ambplugin.h ambpluginimpl.h) diff --git a/plugins/common/ambpluginimpl.cpp b/plugins/common/ambpluginimpl.cpp index ec678f7b..dc646857 100644 --- a/plugins/common/ambpluginimpl.cpp +++ b/plugins/common/ambpluginimpl.cpp @@ -164,7 +164,7 @@ PropertyInfo AmbPluginImpl::getPropertyInfo(const VehicleProperty::Property & pr { auto it = properties.find(property); if(it != properties.end()) { - std::list<Zone::Type> zones; + Zone::ZoneList zones; for(auto itZonePropType = it->second.begin(); itZonePropType != it->second.end(); ++itZonePropType) zones.push_back(itZonePropType->first); diff --git a/plugins/common/ambpluginimpl.h b/plugins/common/ambpluginimpl.h index 070b6d10..d9482f0f 100644 --- a/plugins/common/ambpluginimpl.h +++ b/plugins/common/ambpluginimpl.h @@ -138,14 +138,23 @@ protected: * \param zone Zone of the property to be found. * \return AbstractPropertyType* if signal exits otherwise nullptr(in this case we do not know its datatype) */ - virtual AbstractPropertyType* findPropertyType(const VehicleProperty::Property& propertyName, const Zone::Type& zone); + virtual AbstractPropertyType* findPropertyType(const VehicleProperty::Property& propertyName, const Zone::Type& zone = Zone::None); /*! Registers property in AMB * \param zone Zone of the property to be registered. * \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) */ - virtual 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); + + template <class T> + std::shared_ptr<AbstractPropertyType> addPropertySupport(Zone::Type zone) + { + auto typeFactory = [](){ + return new T; + }; + return addPropertySupport(zone, typeFactory); + } // // data: diff --git a/plugins/common/bluetooth5.cpp b/plugins/common/bluetooth5.cpp index 06f0e0f1..f836b422 100644 --- a/plugins/common/bluetooth5.cpp +++ b/plugins/common/bluetooth5.cpp @@ -331,7 +331,7 @@ void Bluetooth5::connect(ConnectedCallback onconnectedCallback) if(errorPtr) { - DebugOut(DebugOut::Error) << "error trying to connect profile: " << errorPtr->message << endl; + DebugOut(DebugOut::Warning) << "error trying to connect profile: " << errorPtr->message << endl; } }, this); diff --git a/plugins/database/CMakeLists.txt b/plugins/database/CMakeLists.txt index 3db25adb..8f977d25 100644 --- a/plugins/database/CMakeLists.txt +++ b/plugins/database/CMakeLists.txt @@ -4,14 +4,16 @@ include(CheckIncludeFiles) pkg_check_modules(sqlite REQUIRED sqlite3) -include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${sqlite_INCLUDE_DIRS}) +include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${sqlite_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/plugins/common) 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}) set_target_properties(databasesinkplugin PROPERTIES PREFIX "") -target_link_libraries(databasesinkplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${sqlite_LIBRARIES}) +target_link_libraries(databasesinkplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${sqlite_LIBRARIES} amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common) install(TARGETS databasesinkplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_SOURCE_DIR}/README @ONLY) + endif(database_plugin) diff --git a/plugins/database/basedb.hpp b/plugins/database/basedb.hpp index 49a84ae3..353b3284 100644 --- a/plugins/database/basedb.hpp +++ b/plugins/database/basedb.hpp @@ -12,7 +12,7 @@ * more details. * * You should have received a copy of the GNU Lesser General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., + * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * */ @@ -52,50 +52,50 @@ class BaseDB public: BaseDB():db(NULL),q(NULL) { - + } - - + + virtual ~BaseDB() { DebugOut()<<"BaseDB: Destroying db object. Table: "<<table<<endl; delete q; delete db; } - + void setTable(string tablename) { if(tablename == "") return; table = tablename; - + if(!tableExists()) reloadTable(); } - + virtual void init(string dbname, string tablename, string tablestring) { DebugOut()<<"BaseDB: Initializing db object. Table: "<<tablename.c_str()<<endl; tableString = tablestring; - + db = new sqlitedatabase(); - + db->init(dbname); - + DebugOut()<<"BaseDB: Using db/db-file: "<<dbname.c_str()<<endl; - + if(! db->Connected()) { DebugOut(0)<<"BaseDB: database not found "<<dbname<<endl; throw -1; } q = new sqlitequery(); - + q->init(db); setTable(tablename); } - + virtual void reloadTable() { @@ -103,7 +103,7 @@ public: dropTable(); createTable(); } - + virtual bool tableExists() { bool exists=false; @@ -119,7 +119,7 @@ public: q->freeResult(); return exists; } - + virtual void renameTable(string newname) { @@ -127,7 +127,7 @@ public: string query = "ALTER TABLE "+table+" RENAME TO "+newname; q->execute(query); } - + template<typename T> void insert(DictionaryList<T> params) { @@ -142,7 +142,7 @@ public: endquery<<"'"<<fixInvalids(tempval.str())<<"'"; if(i < params.size()-1) { - query+=","; + query+=","; endquery<<","; } } @@ -151,7 +151,7 @@ public: DebugOut()<<"BaseDB: "<<query<<endl; q->execute(query); } - + template<typename T> void insert(NameValuePair<T> param) @@ -168,13 +168,13 @@ public: DebugOut()<<"BaseDB: "<<query<<endl; q->execute(query); } - + virtual void insert(DictionaryList<string> params) { insert<string>(params); } - + template<typename T, typename TT, typename T3> void update(T col, TT colval, NameValuePair<T3> qualifier) @@ -187,17 +187,17 @@ public: query << "UPDATE "<< table << " SET `"<<col<<"` = '"<<fixInvalids(tempcolval.str())<< "' WHERE `"<<fixInvalids(qualifier.name)<<"` = '"<<fixInvalids(tempval.str())<<"'"; - printf("BaseDB: Update: %s",query.str().c_str()); + DebugOut() << "BaseDB: Update: " << query.str() << endl; q->execute(query.str()); } - + template<typename T, typename TT> - void + void update(NameValuePair<T> param, NameValuePair<TT> qualifier) { update<string,T,TT>(param.name, param.value, qualifier); } - + template<typename T, typename TT> void update(DictionaryList<T> params, NameValuePair<TT> qualifier) @@ -207,12 +207,12 @@ public: update<T,TT>(params[i],qualifier); } } - + virtual void update(NameValuePair<string> param, NameValuePair<string> qualifier) { update<string,string>(param,qualifier); } - + template<typename T> void deleteRow(NameValuePair<T> qualifier) { @@ -221,30 +221,30 @@ public: tempval<<qualifier.value; query << "DELETE FROM "<< table<< " WHERE `"<<qualifier.name<<"` = '"<<fixInvalids(tempval.str())<<"'"; - printf("BaseDB: %s: %s",__FUNCTION__, query.str().c_str()); + DebugOut() << "BaseDB: " << __FUNCTION__ << " : " << query.str() << endl; q->execute(query.str()); } - - virtual void + + virtual void deleteRow(NameValuePair<string> qualifier) { deleteRow<string>(qualifier); } - + virtual void dropTable() { dropTable(table); } - + virtual void dropTable(string tablename) { string query="DROP TABLE IF EXISTS "+tablename; - printf("BaseDB: Dropping Table %s with query:? %s",tablename.c_str(),query.c_str()); + DebugOut() << "BaseDB: Dropping Table " << tablename <<" with query: " << query << endl; q->execute(query); } - + virtual void createTable() { @@ -253,18 +253,18 @@ public: string::size_type i=t.find("%s",0); if(i!=string::npos) query=t.replace(i, 2, table); else query = t; - printf("BaseDB: Creating Table %s with query:? %s",table.c_str(),query.c_str()); + DebugOut() << "BaseDB: Creating Table" << table << " with query: " << query << endl; q->execute(query); } - - + + string fixInvalids(string filename) { return filename; } - + vector<vector<string> > select(string query) { DebugOut()<<query<<endl; @@ -305,7 +305,7 @@ public: } protected: - + void fixFilename(string* filename) { @@ -332,9 +332,9 @@ protected: filename->replace(i,1,""); unfixFilename(filename); } - + } - + sqlitedatabase *db; sqlitequery *q; string table; diff --git a/plugins/database/databasesink.cpp b/plugins/database/databasesink.cpp index 75d7033e..f7ed7cf7 100644 --- a/plugins/database/databasesink.cpp +++ b/plugins/database/databasesink.cpp @@ -3,18 +3,22 @@ #include "listplusplus.h" #include "superptr.hpp" #include "uuidhelper.h" +#include "ambplugin.h" #include <thread> int bufferLength = 100; int timeout=1000; -extern "C" AbstractSinkManager * create(AbstractRoutingEngine* routingengine, map<string, string> config) +extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, map<string, string> config) { - return new DatabaseSinkManager(routingengine, config); + auto plugin = new AmbPlugin<DatabaseSink>(routingengine, config); + plugin->init(); + + return plugin; } -void * cbFunc(Shared* shared) +static void * cbFunc(Shared* shared) { if(!shared) { @@ -132,21 +136,15 @@ int getNextEvent(gpointer data) return 0; } -DatabaseSink::DatabaseSink(AbstractRoutingEngine *engine, map<std::string, std::string> config) - :AbstractSource(engine,config),shared(nullptr),playback(false),playbackShared(nullptr), playbackMultiplier(1) +DatabaseSink::DatabaseSink(AbstractRoutingEngine *engine, map<std::string, std::string> config, AbstractSource &parent) + :AmbPluginImpl(engine, config, parent), shared(nullptr), playback(false), playbackShared(nullptr), playbackMultiplier(1) { - databaseName = "storage"; tablename = "data"; - tablecreate = "CREATE TABLE IF NOT EXISTS data (key TEXT, value BLOB, source TEXT, zone REAL, time REAL, sequence REAL, tripId TEXT)"; - - if(config.find("databaseFile") != config.end()) - { - setDatabaseFileName(config["databaseFile"]); - } + tablecreate = "CREATE TABLE IF NOT EXISTS data (key TEXT, value BLOB, source TEXT, zone INTEGER, time REAL, sequence REAL, tripId TEXT)"; if(config.find("bufferLength") != config.end()) { - bufferLength = atoi(config["bufferLength"].c_str()); + bufferLength = boost::lexical_cast<int>(config["bufferLength"]); } if(config.find("frequency") != config.end()) @@ -159,8 +157,6 @@ DatabaseSink::DatabaseSink(AbstractRoutingEngine *engine, map<std::string, std:: { DebugOut(DebugOut::Error)<<"Failed to parse frequency: Invalid value "<<config["frequency"]<<endl; } - - } if(config.find("properties") != config.end()) @@ -168,20 +164,18 @@ DatabaseSink::DatabaseSink(AbstractRoutingEngine *engine, map<std::string, std:: parseConfig(); } - for(auto itr=propertiesToSubscribeTo.begin();itr!=propertiesToSubscribeTo.end();itr++) + for(auto itr : propertiesToSubscribeTo) { - engine->subscribeToProperty(*itr,this); + engine->subscribeToProperty(itr, &parent); } - mSupported.push_back(DatabaseFile); - mSupported.push_back(DatabaseLogging); - mSupported.push_back(DatabasePlayback); - - routingEngine->updateSupported(supported(), PropertyList(), this); + databaseName = addPropertySupport(Zone::None, [](){ return new DatabaseFileType("storage"); }); + playback = addPropertySupport(Zone::None, [](){ return new DatabasePlaybackType(false); }); + databaseLogging = addPropertySupport(Zone::None, [](){ return new DatabaseLoggingType(false); }); if(config.find("startOnLoad")!= config.end()) { - setLogging(config["startOnLoad"] == "true"); + databaseLogging->setValue(config["startOnLoad"] == "true"); } if(config.find("playbackMultiplier")!= config.end()) @@ -191,10 +185,8 @@ DatabaseSink::DatabaseSink(AbstractRoutingEngine *engine, map<std::string, std:: if(config.find("playbackOnLoad")!= config.end()) { - setPlayback(config["playbackOnLoad"] == "true"); + playback->setValue(config["playbackOnLoad"] == "true"); } - - } DatabaseSink::~DatabaseSink() @@ -216,17 +208,6 @@ void DatabaseSink::supportedChanged(const PropertyList &supportedProperties) } -PropertyList DatabaseSink::supported() -{ - return mSupported; -} - -PropertyInfo DatabaseSink::getPropertyInfo(VehicleProperty::Property property) -{ - /// TODO: Compute update frequency for properties in the database - return PropertyInfo::invalid(); -} - void DatabaseSink::parseConfig() { json_object *rootobject; @@ -273,7 +254,8 @@ void DatabaseSink::stopDb() obj.quit = true; shared->queue.append(obj); - thread.join(); + if(thread && thread->joinable()) + thread->join(); delete shared; shared = NULL; @@ -281,7 +263,7 @@ void DatabaseSink::stopDb() void DatabaseSink::startDb() { - if(playback.basicValue()) + if(playback->value<bool>()) { DebugOut(0)<<"ERROR: tried to start logging during playback. Only logging or playback can be used at one time"<<endl; return; @@ -295,15 +277,18 @@ void DatabaseSink::startDb() initDb(); - thread = std::thread(cbFunc, shared); + if(thread && thread->joinable()) + thread->detach(); + + thread = amb::make_unique(new std::thread(cbFunc, shared)); } void DatabaseSink::startPlayback() { - if(playback.basicValue()) + if(playback->value<bool>()) return; - playback = true; + playback->setValue(true); initDb(); @@ -334,7 +319,7 @@ void DatabaseSink::startPlayback() obj.key = results[i][0]; obj.value = results[i][1]; obj.source = results[i][2]; - obj.zone = boost::lexical_cast<double>(results[i][3]); + obj.zone = boost::lexical_cast<int>(results[i][3]); obj.time = boost::lexical_cast<double>(results[i][4]); obj.sequence = boost::lexical_cast<double>(results[i][5]); @@ -349,46 +334,34 @@ void DatabaseSink::initDb() if(shared) delete shared; shared = new Shared; - shared->db->init(databaseName.value<std::string>(), tablename, tablecreate); -} - -void DatabaseSink::setPlayback(bool v) -{ - AsyncSetPropertyRequest request; - request.property = DatabasePlayback; - request.value = new DatabasePlaybackType(v); - - setProperty(request); -} - -void DatabaseSink::setLogging(bool b) -{ - databaseLogging = b; - AsyncSetPropertyRequest request; - request.property = DatabaseLogging; - request.value = &databaseLogging; - - setProperty(request); + shared->db->init(databaseName->value<std::string>(), tablename, tablecreate); } void DatabaseSink::setDatabaseFileName(string filename) { - databaseName = filename; - initDb(); - vector<vector<string> > supportedStr = shared->db->select("SELECT DISTINCT key FROM "+tablename); + vector<vector<string> > supportedStr = shared->db->select("SELECT DISTINCT key, zone FROM " + tablename); for(int i=0; i < supportedStr.size(); i++) { - if(!contains(mSupported, supportedStr[i][0])) - mSupported.push_back(supportedStr[i][0]); + std::string name = supportedStr[i][0]; + + if(!contains(supported(), name)) + { + std::string zoneStr = supportedStr[i][1]; + + DebugOut() << "adding property " << name << " in zone: " << zoneStr << endl; + + Zone::Type zone = boost::lexical_cast<Zone::Type>(zoneStr); + addPropertySupport(zone, [name]() { return VehicleProperty::getPropertyTypeForPropertyNameValue(name); }); + } } delete shared; shared = NULL; - routingEngine->updateSupported(mSupported, PropertyList(), this); + routingEngine->updateSupported(supported(), PropertyList(), &source); } void DatabaseSink::propertyChanged(AbstractPropertyType *value) @@ -398,10 +371,10 @@ void DatabaseSink::propertyChanged(AbstractPropertyType *value) if(!shared) return; - if(!contains(mSupported, property)) + if(!contains(supported(), property)) { - mSupported.push_back(property); - routingEngine->updateSupported(mSupported, PropertyList(), this); + addPropertySupport(value->zone, [property]() { return VehicleProperty::getPropertyTypeForPropertyNameValue(property);}); + routingEngine->updateSupported(supported(), PropertyList(), &source); } DBObject obj; @@ -416,53 +389,26 @@ void DatabaseSink::propertyChanged(AbstractPropertyType *value) } -const string DatabaseSink::uuid() +const std::string DatabaseSink::uuid() const { return "9f88156e-cb92-4472-8775-9c08addf50d3"; } -void DatabaseSink::getPropertyAsync(AsyncPropertyReply *reply) +void DatabaseSink::init() { - reply->success = false; - - if(reply->property == DatabaseFile) - { - DatabaseFileType temp(databaseName); - reply->value = &temp; - - reply->success = true; - reply->completed(reply); - - return; - } - else if(reply->property == DatabaseLogging) - { - databaseLogging = shared != nullptr; - - reply->value = &databaseLogging; - reply->success = true; - reply->completed(reply); - - return; - } - - else if(reply->property == DatabasePlayback) + if(configuration.find("databaseFile") != configuration.end()) { - DatabasePlaybackType temp = playback; - reply->value = &temp; - reply->success = true; - reply->completed(reply); - - return; + databaseName->setValue(configuration["databaseFile"]); + setDatabaseFileName(configuration["databaseFile"]); } - reply->completed(reply); + routingEngine->updateSupported(supported(), PropertyList(), &source); } void DatabaseSink::getRangePropertyAsync(AsyncRangePropertyReply *reply) { BaseDB * db = new BaseDB(); - db->init(databaseName.value<std::string>(), tablename, tablecreate); + db->init(databaseName->value<std::string>(), tablename, tablecreate); ostringstream query; query.precision(15); @@ -529,46 +475,28 @@ void DatabaseSink::getRangePropertyAsync(AsyncRangePropertyReply *reply) AsyncPropertyReply *DatabaseSink::setProperty(AsyncSetPropertyRequest request) { - AsyncPropertyReply* reply = new AsyncPropertyReply(request); - reply->success = false; + AsyncPropertyReply* reply = AmbPluginImpl::setProperty(request); if(request.property == DatabaseLogging) { if(request.value->value<bool>()) { - setPlayback(false); startDb(); - reply->success = true; - databaseLogging = true; - routingEngine->updateProperty(&databaseLogging,uuid()); } else { stopDb(); - reply->success = true; - databaseLogging = false; - routingEngine->updateProperty(&databaseLogging,uuid()); } } - else if(request.property == DatabaseFile) { - std::string fname = request.value->toString(); - - databaseName = fname; - - routingEngine->updateProperty(&databaseName,uuid()); - - reply->success = true; + setDatabaseFileName(databaseName->value<std::string>()); } else if( request.property == DatabasePlayback) { if(request.value->value<bool>()) { - setLogging(false); startPlayback(); - - routingEngine->updateProperty(&playback,uuid()); } else { @@ -576,11 +504,7 @@ AsyncPropertyReply *DatabaseSink::setProperty(AsyncSetPropertyRequest request) playbackShared->stop = true; playback = false; - - routingEngine->updateProperty(&playback,uuid()); } - - reply->success = true; } return reply; @@ -594,3 +518,4 @@ void DatabaseSink::subscribeToPropertyChanges(VehicleProperty::Property ) void DatabaseSink::unsubscribeToPropertyChanges(VehicleProperty::Property ) { } + diff --git a/plugins/database/databasesink.h b/plugins/database/databasesink.h index 6933612c..2e9709d9 100644 --- a/plugins/database/databasesink.h +++ b/plugins/database/databasesink.h @@ -25,6 +25,7 @@ #include "basedb.hpp" #include <asyncqueue.hpp> #include "listplusplus.h" +#include "ambpluginimpl.h" #include <glib.h> @@ -136,26 +137,24 @@ PROPERTYTYPEBASIC(DatabaseLogging, bool) PROPERTYTYPEBASIC(DatabasePlayback, bool) PROPERTYTYPE(DatabaseFile, DatabaseFileType, StringPropertyType, std::string) -class DatabaseSink : public AbstractSource +class DatabaseSink : public AmbPluginImpl { public: - DatabaseSink(AbstractRoutingEngine* engine, map<string, string> config); + DatabaseSink(AbstractRoutingEngine* engine, map<string, string> config, AbstractSource &parent); ~DatabaseSink(); virtual void supportedChanged(const PropertyList & supportedProperties); virtual void propertyChanged(AbstractPropertyType *value); - const std::string uuid(); + const std::string uuid() const; + + void init(); ///source role: - virtual void getPropertyAsync(AsyncPropertyReply *reply); virtual void getRangePropertyAsync(AsyncRangePropertyReply *reply); virtual AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request); virtual void subscribeToPropertyChanges(VehicleProperty::Property property); virtual void unsubscribeToPropertyChanges(VehicleProperty::Property property); - virtual PropertyList supported(); - int supportedOperations() { return GetRanged | Get | Set;} - - PropertyInfo getPropertyInfo(VehicleProperty::Property property); + int supportedOperations() const { return AbstractSource::GetRanged | AbstractSource::Get | AbstractSource::Set;} private: //methods: @@ -164,38 +163,20 @@ private: //methods: void startDb(); void startPlayback(); void initDb(); - void setPlayback(bool v); - void setLogging(bool b); - void setDatabaseFileName(std::string filename); + void setDatabaseFileName(std::string filename); private: PropertyList mSubscriptions; Shared *shared; - std::thread thread; - //std::string databaseName; + std::unique_ptr<std::thread> thread; std::string tablename; std::string tablecreate; - std::list<VehicleProperty::Property> propertiesToSubscribeTo; - PropertyList mSupported; + PropertyList propertiesToSubscribeTo; PlaybackShared* playbackShared; uint playbackMultiplier; - DatabasePlaybackType playback; - DatabaseFileType databaseName; - DatabaseLoggingType databaseLogging; -}; - - -class DatabaseSinkManager: public AbstractSinkManager -{ -public: - DatabaseSinkManager(AbstractRoutingEngine* engine, map<string, string> config) - :AbstractSinkManager(engine, config) - { - new DatabaseSink(routingEngine, config); - VehicleProperty::registerProperty(DatabaseLogging, [](){return new DatabaseLoggingType(false);}); - VehicleProperty::registerProperty(DatabasePlayback, [](){return new DatabasePlaybackType(false);}); - VehicleProperty::registerProperty(DatabaseFile, [](){return new DatabaseFileType("storage");}); - } + std::shared_ptr<AbstractPropertyType> playback; + std::shared_ptr<AbstractPropertyType> databaseName; + std::shared_ptr<AbstractPropertyType> databaseLogging; }; #endif // DATABASESINK_H diff --git a/plugins/dbus/CMakeLists.txt b/plugins/dbus/CMakeLists.txt index aab7e90f..7bc4fd79 100644 --- a/plugins/dbus/CMakeLists.txt +++ b/plugins/dbus/CMakeLists.txt @@ -15,4 +15,6 @@ target_link_libraries(dbussinkplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${lin install (TARGETS dbussinkplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH}) install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/amb.conf DESTINATION /etc/dbus-1/system.d ) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/amb.conf ${CMAKE_CURRENT_SOURCE_DIR}/amb.conf) + add_subdirectory(amb-qt) diff --git a/plugins/dbus/abstractdbusinterface.cpp b/plugins/dbus/abstractdbusinterface.cpp index 86739c0a..dce2888b 100644 --- a/plugins/dbus/abstractdbusinterface.cpp +++ b/plugins/dbus/abstractdbusinterface.cpp @@ -223,7 +223,7 @@ void AbstractDBusInterface::addProperty(AbstractProperty* property) { string nameToLower = property->name(); boost::algorithm::to_lower<string>(nameToLower); - + string access; if(property->access() == AbstractProperty::Read) @@ -250,7 +250,7 @@ void AbstractDBusInterface::addProperty(AbstractProperty* property) " <arg type='d' name='timestamp' direction='out' />" "</signal>" "<property type='i' name='" + property->name() + "Sequence' access='read' />"; - + properties[property->name()] = property; if(!contains(mimplementedProperties, property->ambPropertyName())) @@ -266,7 +266,7 @@ void AbstractDBusInterface::registerObject() { throw std::runtime_error("forgot to call setDBusConnection on AbstractDBusInterface"); } - + if(introspectionXml.empty()) { cerr<<"no interface to export: "<<mInterfaceName<<endl; @@ -278,11 +278,11 @@ void AbstractDBusInterface::registerObject() introspectionXml += "</interface>" "</node>"; } - + GError* error=NULL; GDBusNodeInfo* introspection = g_dbus_node_info_new_for_xml(introspectionXml.c_str(), &error); - + if(!introspection || error) { @@ -312,7 +312,7 @@ void AbstractDBusInterface::registerObject() DebugOut(DebugOut::Error)<<error2->message<<endl; g_error_free(error2); } - + if(regId == 0) { DebugOut(DebugOut::Error)<<"We failed to register on DBus"<<endl; @@ -365,6 +365,19 @@ list<AbstractDBusInterface *> AbstractDBusInterface::interfaces() return ifaces; } +std::vector<std::string> AbstractDBusInterface::supportedInterfaces() +{ + std::vector<std::string> ifaces; + + for(auto itr : objectMap) + { + if(itr.second->isSupported()) + ifaces.push_back(itr.second->objectName()); + } + + return ifaces; +} + bool AbstractDBusInterface::implementsProperty(string property) { for(auto itr = properties.begin(); itr != properties.end(); itr++) diff --git a/plugins/dbus/abstractdbusinterface.h b/plugins/dbus/abstractdbusinterface.h index 7b13a57d..2223ea4f 100644 --- a/plugins/dbus/abstractdbusinterface.h +++ b/plugins/dbus/abstractdbusinterface.h @@ -62,6 +62,8 @@ public: static list<AbstractDBusInterface*> interfaces(); + static std::vector<string> supportedInterfaces(); + std::string interfaceName() { return mInterfaceName; } bool implementsProperty(std::string property); diff --git a/plugins/dbus/automotivemanager.cpp b/plugins/dbus/automotivemanager.cpp index 6a77bc42..a6b1ca25 100644 --- a/plugins/dbus/automotivemanager.cpp +++ b/plugins/dbus/automotivemanager.cpp @@ -206,29 +206,27 @@ static void handleMethodCall(GDBusConnection *connection, else if(method == "List") { - std::list<AbstractDBusInterface*> list = AbstractDBusInterface::interfaces(); + std::vector<std::string> supportedProperties = AbstractDBusInterface::supportedInterfaces(); - if(!list.size()) + if(!supportedProperties.size()) { g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.Error", "No supported objects"); return; } + std::sort(supportedProperties.begin(), supportedProperties.end()); + auto itr = std::unique(supportedProperties.begin(), supportedProperties.end()); + + supportedProperties.erase(itr, supportedProperties.end()); + GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); - - for(auto itr = list.begin(); itr != list.end(); itr++) + for(auto objectName : supportedProperties) { - if(!(*itr)->isSupported()) - continue; - - std::string objectName = (*itr)->objectName(); - g_variant_builder_add(&builder, "s", objectName.c_str()); } - g_dbus_method_invocation_return_value(invocation,g_variant_new("(as)",&builder)); } else if(method == "SourcesForObjectName") diff --git a/plugins/dbus/dbusinterfacemanager.cpp b/plugins/dbus/dbusinterfacemanager.cpp index d70e1d29..e17800cf 100644 --- a/plugins/dbus/dbusinterfacemanager.cpp +++ b/plugins/dbus/dbusinterfacemanager.cpp @@ -42,15 +42,12 @@ std::unordered_map<std::string, std::unordered_set<Zone::Type>> getUniqueSources { std::unordered_map<std::string, std::unordered_set<Zone::Type>> uniqueSourcesList; - for(auto itr = implementedProperties.begin(); itr != implementedProperties.end(); itr++) + for(auto property : implementedProperties) { - VehicleProperty::Property property = *itr; std::vector<std::string> sources = re->sourcesForProperty(property); - for(auto itr2 = sources.begin(); itr2 != sources.end(); itr2++) + for(auto source : sources) { - std::string source = *itr2; - PropertyInfo info = re->getPropertyInfo(property, source); std::unordered_set<Zone::Type> uniqueZoneList; @@ -60,7 +57,7 @@ std::unordered_map<std::string, std::unordered_set<Zone::Type>> getUniqueSources uniqueZoneList = uniqueSourcesList[source]; } - std::list<Zone::Type> zoneList = info.zones(); + Zone::ZoneList zoneList = info.zones(); if(!zoneList.size()) { diff --git a/plugins/dbus/varianttype.cpp b/plugins/dbus/varianttype.cpp index 6af9d03d..4f3bce82 100644 --- a/plugins/dbus/varianttype.cpp +++ b/plugins/dbus/varianttype.cpp @@ -21,16 +21,15 @@ void VariantType::initialize() request.zoneFilter = mZoneFilter; using namespace std::placeholders; - request.completed = [this](AsyncPropertyReply* reply) + request.completed = [this](AsyncPropertyReply* r) { + auto reply = amb::make_unique(r); if(reply->success) setValue(reply->value->copy()); else DebugOut(DebugOut::Error)<<"get request unsuccessful for "<<reply->property<<" : "<<reply->error<<endl; mInitialized = true; - - delete reply; }; /// do not request if not supported: @@ -61,15 +60,14 @@ void VariantType::fromGVariant(GVariant *val) request.property = mAmbPropertyName; request.value = v; request.zoneFilter = mZoneFilter; - request.completed = [&](AsyncPropertyReply* reply) + request.completed = [&](AsyncPropertyReply* r) { + auto reply = amb::make_unique(r); /// TODO: throw dbus exception if(!reply->success) { DebugOut(DebugOut::Error)<<"SetProperty fail: "<<reply->error<<endl; } - - delete reply; }; routingEngine->setProperty(request); diff --git a/plugins/exampleplugin.cpp b/plugins/exampleplugin.cpp index ecfefaba..f94a0739 100644 --- a/plugins/exampleplugin.cpp +++ b/plugins/exampleplugin.cpp @@ -395,7 +395,7 @@ void ExampleSourcePlugin::addPropertySupport(VehicleProperty::Property property, { mSupported.push_back(property); - std::list<Zone::Type> zones; + Zone::ZoneList zones; zones.push_back(zone); diff --git a/plugins/gpsnmea/gpsnmea.cpp b/plugins/gpsnmea/gpsnmea.cpp index 2791bff2..695e15df 100644 --- a/plugins/gpsnmea/gpsnmea.cpp +++ b/plugins/gpsnmea/gpsnmea.cpp @@ -692,7 +692,7 @@ void GpsNmeaSource::addPropertySupport(VehicleProperty::Property property, Zone: { mSupported.push_back(property); - std::list<Zone::Type> zones; + Zone::ZoneList zones; zones.push_back(zone); diff --git a/plugins/gpsnmea/gpsnmea.h b/plugins/gpsnmea/gpsnmea.h index 9212224a..caf5c932 100644 --- a/plugins/gpsnmea/gpsnmea.h +++ b/plugins/gpsnmea/gpsnmea.h @@ -49,7 +49,7 @@ public: void supportedChanged(const PropertyList &) {} - PropertyInfo getPropertyInfo(VehicleProperty::Property property) + PropertyInfo getPropertyInfo(VehicleProperty::Property const & property) { if(propertyInfoMap.find(property) != propertyInfoMap.end()) return propertyInfoMap[property]; diff --git a/plugins/murphyplugin/murphysource.cpp b/plugins/murphyplugin/murphysource.cpp index f3f59a57..dc319914 100644 --- a/plugins/murphyplugin/murphysource.cpp +++ b/plugins/murphyplugin/murphysource.cpp @@ -270,6 +270,14 @@ int MurphySource::connectToMurphy() return 0; } +PropertyInfo MurphySource::getPropertyInfo(const VehicleProperty::Property &property) +{ + Zone::ZoneList zones; + zones.push_back(murphyProperties[property]->zone); + + return PropertyInfo(0, zones); +} + MurphySource::MurphySource(AbstractRoutingEngine *re, map<string, string> config) : AbstractSource(re, config) { diff --git a/plugins/murphyplugin/murphysource.h b/plugins/murphyplugin/murphysource.h index 620b1d0e..6ed5519f 100644 --- a/plugins/murphyplugin/murphysource.h +++ b/plugins/murphyplugin/murphysource.h @@ -36,54 +36,55 @@ class MurphySource : public AbstractSource { public: - MurphySource(AbstractRoutingEngine* re, map<string, string> config); - ~MurphySource(); + MurphySource(AbstractRoutingEngine* re, map<string, string> config); + ~MurphySource(); const string uuid() { return "murphy"; } - void getPropertyAsync(AsyncPropertyReply *reply); - void getRangePropertyAsync(AsyncRangePropertyReply *reply); - AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request); - void subscribeToPropertyChanges(VehicleProperty::Property property); - void unsubscribeToPropertyChanges(VehicleProperty::Property property); - PropertyList supported(); + void getPropertyAsync(AsyncPropertyReply *reply); + void getRangePropertyAsync(AsyncRangePropertyReply *reply); + AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request); + void subscribeToPropertyChanges(VehicleProperty::Property property); + void unsubscribeToPropertyChanges(VehicleProperty::Property property); + PropertyList supported(); - int supportedOperations(); + int supportedOperations(); void supportedChanged(const PropertyList &) {} - void processValue(string propertyName, AbstractPropertyType *value); + void processValue(string propertyName, AbstractPropertyType *value); - bool hasProperty(string propertyName); + bool hasProperty(string propertyName); - void setState(mrp_process_state_t state); - mrp_process_state_t getState(); + void setState(mrp_process_state_t state); + mrp_process_state_t getState(); - void setConnected(bool connected); + void setConnected(bool connected); - int connectToMurphy(); + int connectToMurphy(); + PropertyInfo getPropertyInfo(const VehicleProperty::Property &property); private: - void checkSubscriptions(); - void setConfiguration(map<string, string> config); - void readyToConnect(mrp_mainloop_t *ml); + void checkSubscriptions(); + void setConfiguration(map<string, string> config); + void readyToConnect(mrp_mainloop_t *ml); - PropertyList m_supportedProperties; + PropertyList m_supportedProperties; - MurphySource *m_source; - AbstractRoutingEngine *m_re; + MurphySource *m_source; + AbstractRoutingEngine *m_re; - // known properties + // known properties - map<string, AbstractPropertyType *> murphyProperties; + map<string, AbstractPropertyType *> murphyProperties; - // murphy integration + // murphy integration - mrp_mainloop_t *m_ml; - mrp_transport_t *m_tport; - string m_address; // transport address - mrp_process_state_t m_state; - bool m_connected; + mrp_mainloop_t *m_ml; + mrp_transport_t *m_tport; + string m_address; // transport address + mrp_process_state_t m_state; + bool m_connected; }; #endif // MURPHYSOURCE_H diff --git a/plugins/obd2plugin/obd2source.cpp b/plugins/obd2plugin/obd2source.cpp index 1be11126..4aa6b7ba 100644 --- a/plugins/obd2plugin/obd2source.cpp +++ b/plugins/obd2plugin/obd2source.cpp @@ -681,6 +681,14 @@ PropertyList OBD2Source::supported() return m_supportedProperties; } +PropertyInfo OBD2Source::getPropertyInfo(const VehicleProperty::Property &) +{ + Zone::ZoneList zones; + zones.push_back(0); + + return PropertyInfo(0, zones); +} + int OBD2Source::supportedOperations() { return Get | Set; @@ -733,7 +741,7 @@ void OBD2Source::subscribeToPropertyChanges(VehicleProperty::Property property) g_async_queue_push(subscriptionAddQueue, pid); CommandRequest *req = new CommandRequest(); req->req = "connectifnot"; - g_async_queue_push(commandQueue,req); + g_async_queue_push(commandQueue, req); } } @@ -799,13 +807,13 @@ AsyncPropertyReply *OBD2Source::setProperty(AsyncSetPropertyRequest request ) { CommandRequest *req = new CommandRequest(); req->req = "connectifnot"; - g_async_queue_push(commandQueue,req); + g_async_queue_push(commandQueue, req); } else { CommandRequest *req = new CommandRequest(); req->req = "disconnect"; - g_async_queue_push(commandQueue,req); + g_async_queue_push(commandQueue, req); } } diff --git a/plugins/obd2plugin/obd2source.h b/plugins/obd2plugin/obd2source.h index ba8cc2bf..8ca4ed45 100644 --- a/plugins/obd2plugin/obd2source.h +++ b/plugins/obd2plugin/obd2source.h @@ -152,6 +152,8 @@ public: void unsubscribeToPropertyChanges(VehicleProperty::Property property); PropertyList supported(); + PropertyInfo getPropertyInfo(const VehicleProperty::Property &property); + int supportedOperations(); PropertyList queuedRequests; diff --git a/plugins/obd2plugin/obdlib.cpp b/plugins/obd2plugin/obdlib.cpp index 3a1e9ec0..e223ea10 100644 --- a/plugins/obd2plugin/obdlib.cpp +++ b/plugins/obd2plugin/obdlib.cpp @@ -58,7 +58,7 @@ int obdLib::openPort(const int fd, int baudrate) //struct termios oldtio;
struct termios newtio;
//bzero(&newtio,sizeof(newtio));
- tcgetattr(portHandle,&newtio);
+ tcgetattr(portHandle, &newtio);
long BAUD = B9600;
switch (baudrate)
{
@@ -107,7 +107,7 @@ int obdLib::openPort(const int fd, int baudrate) debug(obdLib::DEBUG_VERBOSE,"Setting baud rate to %i\n",baudrate);
}
fcntl(portHandle, F_SETFL, 0); //Set to blocking
- tcsetattr(portHandle,TCSANOW,&newtio);
+ tcsetattr(portHandle, TCSANOW, &newtio);
return 0;
}
diff --git a/plugins/obd2plugin/obdpid.h b/plugins/obd2plugin/obdpid.h index 12eb20ca..20db314a 100644 --- a/plugins/obd2plugin/obdpid.h +++ b/plugins/obd2plugin/obdpid.h @@ -33,9 +33,9 @@ public: static ByteArray compress(ByteArray replyVector) { ByteArray tmp; - for (int i=0;i<replyVector.size();i++) + for (int i=0;i<replyVector.size()-1;i++) { - tmp.push_back(obdLib::byteArrayToByte(replyVector[i],replyVector[i+1])); + tmp.push_back(obdLib::byteArrayToByte(replyVector[i], replyVector[i+1])); i++; } return tmp; diff --git a/plugins/opencvlux/CMakeLists.txt b/plugins/opencvlux/CMakeLists.txt index f7ef01c7..a4c6d852 100644 --- a/plugins/opencvlux/CMakeLists.txt +++ b/plugins/opencvlux/CMakeLists.txt @@ -46,15 +46,17 @@ if(Qt5Core_FOUND) endif(Qt5Core_FOUND) set(CMAKE_AUTOMOC ON) -include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${OpenCV_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${QT_INCLUDE_DIRS}) +include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${OpenCV_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${QT_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/plugins/common) set(opencvluxplugin_headers opencvluxplugin.h) set(opencvluxplugin_sources opencvluxplugin.cpp) add_library(opencvluxplugin MODULE ${opencvluxplugin_sources}) set_target_properties(opencvluxplugin PROPERTIES PREFIX "") -target_link_libraries(opencvluxplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${OpenCV_LIBS} ${Boost_LIBRARIES} ${QT_LIBRARIES}) +target_link_libraries(opencvluxplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${OpenCV_LIBS} ${Boost_LIBRARIES} ${QT_LIBRARIES} amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common) install(TARGETS opencvluxplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_SOURCE_DIR}/README @ONLY) + endif(opencvlux_plugin) diff --git a/plugins/opencvlux/README b/plugins/opencvlux/README index f8db1d2f..3dcb32ba 100644 --- a/plugins/opencvlux/README +++ b/plugins/opencvlux/README @@ -1,6 +1,6 @@ OpenCV "lux" plugin -This plugin simulates the ExteriorBrigtness property using a traditional webcamera. It works +This plugin simulates the ExteriorBrigtness property using a traditional webcamera. It works by taking the mean pixel intensity of the web camera image and estimating lux. The particular can be calibrated using the "pixelUpperBound" and "pixelLowerBound" variables. @@ -13,14 +13,14 @@ Currently, this plugin has been tested with OpenCV 2.4.4. To use the OpenCV plugin, add the following to the "sources" array in /etc/ambd/config: { - "name" : "OpenCV LUX", - "path" : "/usr/lib/automotive-message-broker/opencvluxplugin.so", - "threaded" : "true", - "pixelLowerBound" : "0", - "pixelUpperBound" : "255", - "fps" : "30", - "opencl" : "false", - "device" : "0" + "name" : "OpenCV LUX", + "path" : "/usr/lib/automotive-message-broker/opencvluxplugin.so", + "threaded" : "true", + "pixelLowerBound" : "0", + "pixelUpperBound" : "255", + "fps" : "30", + "opencl" : "false", + "device" : "0" } NOTE: some features require the qtmainloop to be running. see the main README for details. @@ -50,13 +50,13 @@ How many times per second to poll image data from the camera. Default: "30" "pixelLowerBound" -Lowest calibration value for a camera. This is the average pixel intensity value the camera reports when +Lowest calibration value for a camera. This is the average pixel intensity value the camera reports when it is completely covered. Default: "0" "pixelUpperBound" -The highest calibration value for camera. This is the average pixel intensity value when a very bright +The highest calibration value for camera. This is the average pixel intensity value when a very bright light (like the sun) is being projected at the camera. Default: "255" @@ -89,16 +89,19 @@ open or closed. If closed for a period of time, DriverDrowsiness will change to Default: "false" -AMB Properties: +Properties: VideoLogging Turn on and off video logging - Type: bool Access: readwrite DriverDrowsiness True if the driver has been detected drowsy. +Type: bool +Access: readonly +OpenCL +True if OpenCL acceleration is enabled. Type: bool Access: readonly diff --git a/plugins/opencvlux/opencvluxplugin.cpp b/plugins/opencvlux/opencvluxplugin.cpp index ea4f2e12..c23ec775 100644 --- a/plugins/opencvlux/opencvluxplugin.cpp +++ b/plugins/opencvlux/opencvluxplugin.cpp @@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include "timestamp.h" #include <listplusplus.h> #include <superptr.hpp> +#include <ambplugin.h> #include <iostream> #include <thread> @@ -45,26 +46,28 @@ const std::string OpenCL = "OpenCL"; extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, map<string, string> config) { - VehicleProperty::registerProperty(VideoLogging, [](){ + auto plugin = new AmbPlugin<OpenCvLuxPlugin>(routingengine, config); + plugin->init(); + + return plugin; +} + +OpenCvLuxPlugin::OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string> config, AbstractSource &parent) + :AmbPluginImpl(re, config, parent), lastLux(0), speed(0), latitude(0), longitude(0) +{ + videoLogging = addPropertySupport(Zone::None, [](){ return new BasicPropertyType<bool>(VideoLogging, false); }); - VehicleProperty::registerProperty(DriverDrowsiness, [](){ + driverDrowsiness = addPropertySupport(Zone::None, [](){ return new OpenCvLuxPlugin::DriverDrowsinessType(DriverDrowsiness, false); }); - VehicleProperty::registerProperty(OpenCL, [](){ + openCl = addPropertySupport(Zone::None, [](){ return new BasicPropertyType<bool>(OpenCL, false); }); - return new OpenCvLuxPlugin(routingengine, config); -} - -OpenCvLuxPlugin::OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string> config) - :AbstractSource(re, config), lastLux(0), speed(0), latitude(0), longitude(0), extBrightness(new VehicleProperty::ExteriorBrightnessType(0)) -{ - driverDrowsiness = amb::make_unique(new DriverDrowsinessType(DriverDrowsiness, false)); - openCl = amb::make_unique(new BasicPropertyType<bool>(OpenCL, false)); + extBrightness = addPropertySupport<VehicleProperty::ExteriorBrightnessType>(Zone::None); shared = amb::make_unique(new Shared); shared->parent = this; @@ -131,7 +134,9 @@ OpenCvLuxPlugin::OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string> openCl->setValue(cv::ocl::useOpenCL()); } else + { DebugOut(DebugOut::Warning) << "You really don't have openCL support." << endl; + } } if(config.find("ddd") != config.end()) @@ -167,9 +172,9 @@ OpenCvLuxPlugin::OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string> } - routingEngine->subscribeToProperty(VehicleProperty::VehicleSpeed, this); - routingEngine->subscribeToProperty(VehicleProperty::Latitude, this); - routingEngine->subscribeToProperty(VehicleProperty::Longitude, this); + routingEngine->subscribeToProperty(VehicleProperty::VehicleSpeed, &parent); + routingEngine->subscribeToProperty(VehicleProperty::Latitude, &parent); + routingEngine->subscribeToProperty(VehicleProperty::Longitude, &parent); } OpenCvLuxPlugin::~OpenCvLuxPlugin() @@ -177,7 +182,7 @@ OpenCvLuxPlugin::~OpenCvLuxPlugin() } -const string OpenCvLuxPlugin::uuid() +const string OpenCvLuxPlugin::uuid() const { return "3c7a1ea0-7d2e-11e2-9e96-0800200c9a66"; } @@ -192,28 +197,11 @@ void OpenCvLuxPlugin::getPropertyAsync(AsyncPropertyReply *reply) { /// we want to turn on the camera for one shot to get an image and determine the intensity - if(init()) - grabImage(shared.get()); + init(); + grabImage(shared.get()); } - if(reply->property == VehicleProperty::ExteriorBrightness) - { - replyQueue.push_back(reply); - } - else if(reply->property == VideoLogging) - { - BasicPropertyType<bool> tmp(VideoLogging, shared->loggingOn); - reply->value = &tmp; - reply->success = true; - reply->completed(reply); - } - else ///We don't support what you are asking for. Reply false - { - reply->value = nullptr; - reply->success = false; - reply->error = AsyncPropertyReply::InvalidOperation; - reply->completed(reply); - } + AmbPluginImpl::getPropertyAsync(reply); } void OpenCvLuxPlugin::getRangePropertyAsync(AsyncRangePropertyReply *reply) @@ -223,29 +211,25 @@ void OpenCvLuxPlugin::getRangePropertyAsync(AsyncRangePropertyReply *reply) AsyncPropertyReply *OpenCvLuxPlugin::setProperty(AsyncSetPropertyRequest request ) { - AsyncPropertyReply *reply = new AsyncPropertyReply(request); - - reply->success = false; - reply->error = AsyncPropertyReply::InvalidOperation; - if(request.property == VideoLogging) { shared->loggingOn = request.value->value<bool>(); - reply->success = true; - reply->error = AsyncPropertyReply::NoError; + } + if(request.property == OpenCL) + { + QMutexLocker lock(&mutex); + cv::ocl::setUseOpenCL(request.value->value<bool>()); } - reply->completed(reply); - - return reply; + return AmbPluginImpl::setProperty(request);; } void OpenCvLuxPlugin::subscribeToPropertyChanges(VehicleProperty::Property property) { if(!shared->mRequests.size()) { - if(init()) - g_timeout_add(1000 / shared->fps, grabImage, shared.get()); + init(); + g_timeout_add(1000 / shared->fps, grabImage, shared.get()); } shared->mRequests.push_back(property); @@ -256,21 +240,6 @@ void OpenCvLuxPlugin::unsubscribeToPropertyChanges(VehicleProperty::Property pro removeOne(&shared->mRequests,property); } -PropertyList OpenCvLuxPlugin::supported() -{ - PropertyList props; - props.push_back(VehicleProperty::ExteriorBrightness); - props.push_back(DriverDrowsiness); - props.push_back(VideoLogging); - - return props; -} - -int OpenCvLuxPlugin::supportedOperations() -{ - return Get | Set; -} - void OpenCvLuxPlugin::propertyChanged(AbstractPropertyType *value) { QMutexLocker lock(&mutex); @@ -326,7 +295,7 @@ static int grabImage(void *data) } } - /*if(shared->threaded) + if(shared->threaded) { QFutureWatcher<uint> *watcher = new QFutureWatcher<uint>(); QObject::connect(watcher, &QFutureWatcher<uint>::finished, shared->parent, &OpenCvLuxPlugin::imgProcResult); @@ -338,10 +307,11 @@ static int grabImage(void *data) } else { - shared->parent->writeVideoFrame(m_image); + if(shared->parent->videoLogging->value<bool>()) + shared->parent->writeVideoFrame(m_image); try { - int lux = evalImage(m_image, shared); + uint16_t lux = evalImage(m_image, shared); shared->parent->updateProperty(lux); } catch(...) @@ -350,7 +320,7 @@ static int grabImage(void *data) } //detectLight(m_image,shared); - }*/ + } if(shared->mRequests.size()) { @@ -386,7 +356,7 @@ static uint evalImage(cv::UMat qImg, OpenCvLuxPlugin::Shared *shared) } -bool OpenCvLuxPlugin::init() +void OpenCvLuxPlugin::init() { if(!shared->m_capture) { @@ -398,13 +368,11 @@ bool OpenCvLuxPlugin::init() if(!shared->m_capture->isOpened()) { - DebugOut()<<"we failed to open camera device ("<<device<<") or no camera found"<<endl; - return false; + DebugOut() << "we failed to open camera device (" << device << ") or no camera found" << endl; + return; } - if(configuration.find("logging") != configuration.end() && - configuration["logging"] == "true" && - (!shared->mWriter || !shared->mWriter->isOpened())) + if(!shared->mWriter || !shared->mWriter->isOpened()) { cv::Size s = cv::Size((int) shared->m_capture->get(cv::CAP_PROP_FRAME_WIDTH), (int) shared->m_capture->get(cv::CAP_PROP_FRAME_HEIGHT)); @@ -413,7 +381,7 @@ bool OpenCvLuxPlugin::init() if(codec.empty() || codec.size() != 4) { - DebugOut(DebugOut::Warning)<<"Invalid codec. Using default: MJPG"<<endl; + DebugOut(DebugOut::Warning)<<"Invalid codec: "<<codec <<". Using default: MJPG"<<endl; codec = "MJPG"; } @@ -430,7 +398,7 @@ bool OpenCvLuxPlugin::init() DebugOut()<<"camera frame height: "<<shared->m_capture->get(cv::CAP_PROP_FRAME_HEIGHT)<<endl; DebugOut()<<"camera frame fps: "<<shared->m_capture->get(cv::CAP_PROP_FPS)<<endl; - return true; + return; } @@ -485,33 +453,15 @@ void OpenCvLuxPlugin::writeVideoFrame(cv::UMat f) } } -void OpenCvLuxPlugin::updateProperty(uint lux) +void OpenCvLuxPlugin::updateProperty(uint16_t lux) { - extBrightness->setValue(lux); - - for(auto reply : replyQueue) - { - reply->value = extBrightness.get(); - reply->success = true; - try{ - if(reply->completed) - reply->completed(reply); - } - catch(...) - { - DebugOut(DebugOut::Warning)<<"reply failed"<<endl; - } - } - - replyQueue.clear(); + extBrightness->setValue(lux); if(lux != lastLux && shared->mRequests.size()) { lastLux = lux; routingEngine->updateProperty(extBrightness.get(), uuid()); } - - } void OpenCvLuxPlugin::imgProcResult() @@ -531,10 +481,10 @@ void OpenCvLuxPlugin::imgProcResult() } } -TrafficLight::Color detectLight(cv::Mat img, OpenCvLuxPlugin::Shared *shared) +TrafficLight::Color detectLight(cv::UMat img, OpenCvLuxPlugin::Shared *shared) { - cv::Mat gray; + cv::UMat gray; cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY); cv::GaussianBlur(gray, gray, cv::Size(9,9), 2, 2); @@ -554,11 +504,11 @@ TrafficLight::Color detectLight(cv::Mat img, OpenCvLuxPlugin::Shared *shared) try { - cv::Mat light(img, rect); + cv::UMat light(img, rect); - cv::circle( img, center, radius, cv::Scalar(0,0,255), 3, 8, 0 ); + cv::circle(img, center, radius, cv::Scalar(0,0,255), 3, 8, 0 ); - cv::rectangle(img, rect,cv::Scalar(255,0,0)); + cv::rectangle(img, rect.tl(), rect.br(), cv::Scalar(255,0,0)); cv::Scalar avgPixel = cv::mean(light); @@ -624,14 +574,19 @@ void OpenCvLuxPlugin::detectEyes(cv::UMat frame) hasEyes = true; DebugOut() << "Number of eyes: " << eyes.size() << endl; - driverDrowsiness->setValue(false); - routingEngine->updateProperty(driverDrowsiness.get(), this->uuid()); + if(driverDrowsiness->value<bool>()) + { + driverDrowsiness->setValue(false); + routingEngine->updateProperty(driverDrowsiness.get(), this->uuid()); + } } else { - DebugOut() << "No eyes!!!" << endl; - driverDrowsiness->setValue(true); - routingEngine->updateProperty(driverDrowsiness.get(), this->uuid()); + if(!driverDrowsiness->value<bool>()) + { + driverDrowsiness->setValue(true); + routingEngine->updateProperty(driverDrowsiness.get(), this->uuid()); + } } } } diff --git a/plugins/opencvlux/opencvluxplugin.h b/plugins/opencvlux/opencvluxplugin.h index 550a9fb9..aecd08e2 100644 --- a/plugins/opencvlux/opencvluxplugin.h +++ b/plugins/opencvlux/opencvluxplugin.h @@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #define OPENCVLUXPLUGIN_H #include <abstractsource.h> +#include <ambpluginimpl.h> #include <string> #include <memory> @@ -31,7 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA using namespace std; -class OpenCvLuxPlugin: public QObject, public AbstractSource +class OpenCvLuxPlugin: public QObject, public AmbPluginImpl { Q_OBJECT public: @@ -57,40 +58,35 @@ public: int frameCount; }; - OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string> config); + OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string> config, AbstractSource& parent); ~OpenCvLuxPlugin(); - const string uuid(); + const string uuid() const; void getPropertyAsync(AsyncPropertyReply *reply); void getRangePropertyAsync(AsyncRangePropertyReply *reply); AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request); void subscribeToPropertyChanges(VehicleProperty::Property property); void unsubscribeToPropertyChanges(VehicleProperty::Property property); - PropertyList supported(); - - int supportedOperations(); void propertyChanged(AbstractPropertyType* value); void supportedChanged(const PropertyList &); - void updateProperty(uint lux); + void updateProperty(uint16_t lux); void writeVideoFrame(cv::UMat frame); void detectEyes(cv::UMat frame); -public Q_SLOTS: - void imgProcResult(); + void init(); + std::shared_ptr<AbstractPropertyType> videoLogging; -private: /// methods: - bool init(); +public Q_SLOTS: + void imgProcResult(); private: - - uint speed; uint latitude; uint longitude; @@ -99,7 +95,7 @@ private: std::string device; std::list<AsyncPropertyReply*> replyQueue; - std::unique_ptr<VehicleProperty::ExteriorBrightnessType> extBrightness; + std::shared_ptr<AbstractPropertyType> extBrightness; std::unique_ptr<Shared> shared; QMutex mutex; @@ -107,13 +103,12 @@ private: std::unique_ptr<cv::CascadeClassifier> faceCascade; std::unique_ptr<cv::CascadeClassifier> eyeCascade; - std::unique_ptr<DriverDrowsinessType> driverDrowsiness; - - std::unique_ptr<BasicPropertyType<bool>> openCl; + std::shared_ptr<AbstractPropertyType> driverDrowsiness; + std::shared_ptr<AbstractPropertyType> openCl; }; static int grabImage(void *data); -static uint evalImage(cv::Mat qImg, OpenCvLuxPlugin::Shared *shared); +static uint evalImage(cv::UMat qImg, OpenCvLuxPlugin::Shared *shared); namespace TrafficLight { @@ -126,7 +121,7 @@ enum Color }; } -TrafficLight::Color detectLight(cv::Mat img, OpenCvLuxPlugin::Shared* shared); +TrafficLight::Color detectLight(cv::UMat img, OpenCvLuxPlugin::Shared* shared); #endif // EXAMPLEPLUGIN_H diff --git a/plugins/websocket/CMakeLists.txt b/plugins/websocket/CMakeLists.txt index d594cad3..0e290353 100644 --- a/plugins/websocket/CMakeLists.txt +++ b/plugins/websocket/CMakeLists.txt @@ -41,6 +41,10 @@ add_library(websocketsource MODULE ${websocketsource_sources}) set_target_properties(websocketsource PROPERTIES PREFIX "") target_link_libraries(websocketsource amb ${websockets_LIBRARIES} -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${QT_LIBRARIES}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test/vehicle.js ${CMAKE_CURRENT_SOURCE_DIR}/test/vehicle.js) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test/test.js ${CMAKE_CURRENT_SOURCE_DIR}/test/test.js) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test/events.js ${CMAKE_CURRENT_SOURCE_DIR}/test/events.js) + install(TARGETS websocketsource LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH}) endif(websocket_plugin) diff --git a/plugins/websocket/common.cpp b/plugins/websocket/common.cpp index 8021be48..5088620e 100644 --- a/plugins/websocket/common.cpp +++ b/plugins/websocket/common.cpp @@ -1,42 +1,45 @@ #include "common.h" #include "debugout.h" #include <math.h> +#include <glib.h> + +#include <QVariantMap> bool doBinary = false; -int lwsWrite(libwebsocket *lws, QByteArray d, int len) +const char * amb::BasicTypes::UInt16Str = "UInt16"; +const char * amb::BasicTypes::UInt32Str = "UInt32"; +const char * amb::BasicTypes::Int16Str = "Int16"; +const char * amb::BasicTypes::Int32Str = "Int32"; +const char * amb::BasicTypes::StringStr = "String"; +const char * amb::BasicTypes::DoubleStr = "Double"; +const char * amb::BasicTypes::BooleanStr = "Boolean"; + +int lwsWrite(libwebsocket *lws, QByteArray d) { if(!lws) { - DebugOut(DebugOut::Error)<<__FUNCTION__<<": libwebsockets is not valid. Perhaps it has not been initialized?"<<endl; + DebugOut(DebugOut::Error)<<__FUNCTION__<<": libwebsockets is not valid. Perhaps it has not been initialized?" << endl; return -1; } + DebugOut() << "Writing to websocket: " << d.constData() << endl; + int retval = -1; QByteArray temp = d; int numframes = 1; - int framesize = 512; + int framesize = 5012; if(d.length() > framesize) { - numframes = ceil((double)d.length() / 122.0); + numframes = ceil((double)d.length() / double(framesize)); QVariantMap multiFrameMessage; multiFrameMessage["type"] = "multiframe"; multiFrameMessage["frames"] = numframes; - QByteArray msg; - - if(doBinary) - msg = QJsonDocument::fromVariant(multiFrameMessage).toBinaryData(); - else - { - msg = QJsonDocument::fromVariant(multiFrameMessage).toJson(); - cleanJson(msg); - } - - lwsWrite(lws, msg, msg.length()); + lwsWriteVariant(lws, multiFrameMessage); } while(numframes--) @@ -57,7 +60,7 @@ int lwsWrite(libwebsocket *lws, QByteArray d, int len) } else { - std::unique_ptr<char[]> buffer(new char[LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING]); + std::unique_ptr<char[]> buffer(new char[LWS_SEND_BUFFER_PRE_PADDING + toWrite.length() + LWS_SEND_BUFFER_POST_PADDING]); char *buf = buffer.get() + LWS_SEND_BUFFER_PRE_PADDING; memcpy(buf, strToWrite, toWrite.length()); @@ -65,9 +68,21 @@ int lwsWrite(libwebsocket *lws, QByteArray d, int len) } } return retval; - } +int lwsWriteVariant(libwebsocket *lws, QVariant d) +{ + QByteArray replystr; + if(doBinary) + replystr = QJsonDocument::fromVariant(d).toBinaryData(); + else + { + replystr = QJsonDocument::fromVariant(d).toJson(); + cleanJson(replystr); + } + + lwsWrite(lws, replystr); +} void cleanJson(QByteArray &json) { @@ -75,3 +90,47 @@ void cleanJson(QByteArray &json) json.replace("\n", ""); json.replace("\t", ""); } + +const std::string amb::BasicTypes::fromSignature(const string &sig) +{ + if(sig.empty()) return ""; + + char c = sig[0]; + + if(c == G_VARIANT_CLASS_BOOLEAN) + return BooleanStr; + + else if(c == G_VARIANT_CLASS_BYTE) + return ""; + + else if(c == G_VARIANT_CLASS_INT16) + return Int16Str; + + else if(c == G_VARIANT_CLASS_UINT16) + return UInt16Str; + + else if(c == G_VARIANT_CLASS_INT32) + return Int32Str; + + else if(c == G_VARIANT_CLASS_UINT32) + return UInt32Str; + + else if(c == G_VARIANT_CLASS_INT64) + return ""; + + else if(c == G_VARIANT_CLASS_UINT64) + return ""; + + else if(c == G_VARIANT_CLASS_DOUBLE) + return DoubleStr; + + else if(c == G_VARIANT_CLASS_STRING) + return StringStr; + + else if(c == G_VARIANT_CLASS_ARRAY) + { + ///TODO support array and map + return ""; + } + return ""; +} diff --git a/plugins/websocket/common.h b/plugins/websocket/common.h index 95fb7bb4..b246e1bb 100644 --- a/plugins/websocket/common.h +++ b/plugins/websocket/common.h @@ -1,10 +1,8 @@ #ifndef COMMON_WEBSOCKET_H_ #define COMMON_WEBSOCKET_H_ -#include <libwebsockets.h> -#include <QByteArray> -#include <QVariantMap> #include <QJsonDocument> +#include <libwebsockets.h> #include <memory> extern bool doBinary; @@ -12,6 +10,35 @@ extern bool doBinary; void cleanJson(QByteArray &json); // libwebsocket_write helper function -int lwsWrite(struct libwebsocket *lws, QByteArray d, int len); +int lwsWrite(struct libwebsocket *lws, QByteArray d); +int lwsWriteVariant(struct libwebsocket *lws, QVariant d); + +namespace amb +{ +namespace BasicTypes +{ +enum BasicTypeEnum +{ + UInt16, + UInt32, + Int16, + Int32, + String, + Double, + Boolean +}; + +extern const char * UInt16Str; +extern const char * UInt32Str; +extern const char * Int16Str; +extern const char * Int32Str; +extern const char * StringStr; +extern const char * DoubleStr; +extern const char * BooleanStr; + +const std::string fromSignature(std::string const & sig); + +} // BasicTypes +} // amb #endif diff --git a/plugins/websocket/protocol b/plugins/websocket/protocol index d7089c9f..2d723a0f 100644 --- a/plugins/websocket/protocol +++ b/plugins/websocket/protocol @@ -1,7 +1,7 @@ Example protocol messages Property changed event: -{"type":"valuechanged","name":"VehicleSpeed","data":{"value":"217","zone": 0, "timestamp":"1354521964.60253","sequence":"0"}, "transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66", } +{"type":"valuechanged","name":"VehicleSpeed","data":{"value": "217","zone": 0, 'type' : 'UInt16', "timestamp":"1354521964.60253","sequence":"0"}, "transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66", } Get property request: {"type":"method","name":"get","data": { "property" : "VehicleSpeed", "zone" : 0 }, "transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"} @@ -10,16 +10,22 @@ Get property reply: {"type":"methodReply","name":"get","data":{"property":"VehicleSpeed","value":"17", "timestamp" : "1354521964.24962", "sequence": "0" },"transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"} Get supported request: -{"type":"method","name":"getSupportedEventTypes","transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"} +{"type":"method","name":"getSupported","transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"} Get supported reply: -{"type":"methodReply","name":"getSupportedEventTypes","data":[EngineSpeed","VehicleSpeed"],"transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"} +{"type":"methodReply","name":"getSupported","data":[{'name' :'EngineSpeed', 'zone' : 0, 'type' : 'UInt16'}, "{'name' :'VehicleSpeed', 'zone' : 0, 'type' : 'UInt16'}],"transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"} + +Supported Changed +{"type":"methodReply","name":"supportedChanged","data":[{'name' :'EngineSpeed', 'zone' : 0, 'type' : 'UInt16'}, "{'name' :'VehicleSpeed', 'zone' : 0, 'type' : 'UInt16'}],"transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"} Subscribe to data: -{"type":"method","name":"subscribe","data": {"property":"EngineSpeed", "zone": 0},"transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"} +{"type":"method","name":"subscribe","property":"EngineSpeed","transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"} Subscribe to data reply: -{"type":"methodReply","name":"subscribe","data":"EngineSpeed","transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"} +{"type":"methodReply","name":"subscribe","property":"EngineSpeed","transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"} + +Unsubscribe to data: +{"type":"method", "name":"unsubscribe", "property":"EngineSpeed", "transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"} Get History request: {"type":"method","name":"getRange","data": {"property":"VehicleSpeed", "timeBegin":"1368825008.35948","timeEnd":"1368825018.35948","sequenceBegin":"-1","sequenceEnd":"-1"},"transactionid":"b07589ba-417c-4604-80c6-01c0dcbd524d"} diff --git a/plugins/websocket/test/events.js b/plugins/websocket/test/events.js index cb0cfd52..18fa6e12 100644 --- a/plugins/websocket/test/events.js +++ b/plugins/websocket/test/events.js @@ -17,14 +17,13 @@ function VehicleEventType() "AirRecirculation", "AirflowDirection", "AvgKW", -"BatteryStatus", +"BatteryVoltage", "ChildLock", "Defrost", "ExteriorBrightness", "ExteriorTemperature", "FanSpeed", "FrontWheelRadius", -"FullBatteryRange", "InteriorTemperature", "LightHazard", "LightHead", @@ -50,7 +49,7 @@ function VehicleEventType() VehicleEventType.prototype.getSupportedEventList = function(val) { /* for undefined just assume everything */ - if((val == undefined)||(val === "")) + if((val === undefined)||(val === "")) return this.event; /* grab every event with case insensitive prefix of val */ diff --git a/plugins/websocket/test/test.js b/plugins/websocket/test/test.js index 67c942dd..db4befee 100644 --- a/plugins/websocket/test/test.js +++ b/plugins/websocket/test/test.js @@ -48,14 +48,9 @@ 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:"); + PRINT.pass(event + " is a set of " + data.length + " objects:"); 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) { - PRINT.log(data[i]); + PRINT.log(JSON.stringify(data[i])); } } else { PRINT.fail(event + " unexcepted empty data field"); @@ -79,19 +74,21 @@ function updateInput(input, value) { function getValue(event) { var zone = getZone(event); var types = window.vehicle.get(event, zone, - function(data) { - if (data) { + function(propertyValue) { + if (propertyValue) { PRINT.pass("values received:"); - PRINT.log(data.property + ": " + data.value + ", zone: " + data.zone); + PRINT.log(propertyValue.data.property + ": " + propertyValue.data.value + ", zone: " + propertyValue.data.zone); 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 zone = elements[i].getElementsByTagName('input')[1]; - updateInput(zone, zone.value); + if(zone) + updateInput(zone, zone.value); var input = elements[i].getElementsByTagName('input')[0]; - updateInput(input, data.value); + if(input) + updateInput(input, propertyValue.value); } } else { PRINT.fail("no values retrieved for " + eventlist); @@ -124,7 +121,7 @@ function setValue(eventlist) { } } - var types = window.vehicle.set(eventlist, valuelist, zoneList, + var types = window.vehicle.set(eventlist, valuelist, zoneList, function(msg) { PRINT.pass("Set success for: " + JSON.stringify(msg)); }, @@ -135,7 +132,7 @@ function setValue(eventlist) { } function eventListener(e) { - PRINT.log(e.name + " update: " + JSON.stringify(e.value)); + 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]; @@ -153,8 +150,8 @@ function subscribe(event) { var zoneList = getZone(event); window.vehicle.subscribe(event, zoneList, function(data) { - PRINT.pass("Subscribe success for: " + data); - document.addEventListener(data, eventListener, false); + PRINT.pass("Subscribe success for: " + data.property); + document.addEventListener(data.property, eventListener, false); }, function(msg) { PRINT.fail("Subscribe failed for: " + msg); diff --git a/plugins/websocket/test/vehicle.js b/plugins/websocket/test/vehicle.js index 86a266e5..706fb698 100644 --- a/plugins/websocket/test/vehicle.js +++ b/plugins/websocket/test/vehicle.js @@ -13,7 +13,7 @@ * A javascript implementation of the IVI vehicle API that communicates * to the automotive message broker through a websocket * Optional constructor arguments: -* sCB: success callback, called when socket is connected, argument is +* sCB: success callback, called when socket is connected, argument is * success message string * eCB: error callback, called on socket close or error, argument is error * message string @@ -28,8 +28,8 @@ * type: target event or group to query (use empty string for all events) * writeable: if true, return only writeable events, otherwise get all * successCB: success callback, gets called with a string list of names -* for all the events and event groups that are children of the -* target. e.g. "vehicle_info" returns all events/groups with the +* for all the events and event groups that are children of the +* target. e.g. "vehicle_info" returns all events/groups with the * vehicle_info prefix. If the target is an event group, it's * omitted from the returned list * errorCB: error callback, called with error message string @@ -40,7 +40,7 @@ * Required arguments: * eventlist[]: list of events to read (use empty string for all events) * successCB: success callback, gets called with the event/value pair list -* for all requested events. The list is the in the +* 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 * @@ -71,7 +71,7 @@ * Description: * Subscribe to a list of events so you can listen to value changes, they * can be monitored with document.addEventListener(eventname, callback, false); -* The Event object passed to the callback has two parameters, e.name and +* The Event object passed to the callback has two parameters, e.name and * e.value. Events are sent to the handler individually. * Required arguments: * eventlist: target events to listen to @@ -81,7 +81,7 @@ * * Function name: unsubscribe(eventlist, successCB, errorCB) * Description: -* Unsubscribe to a list of events to let the server know you're not listening, +* Unsubscribe to a list of events to let the server know you're not listening, * they should stop being sent from the server if no other clients are using them, * but will at least stop being triggered in your app. * Required arguments: @@ -186,7 +186,7 @@ function Vehicle(sCB, eCB, url, protocol) { self.iErrorCB(e.data); }; - self.socket.onmessage = function (e) + self.socket.onmessage = function (e) { self.receive(e.data); }; @@ -225,7 +225,7 @@ Vehicle.prototype.send = function(obj, successCB, errorCB) } var i = this.methodIdx; this.methodIdx = (this.methodIdx + 1)%100; - this.methodCalls[i] = new this.VehicleMethodCall(obj.transactionid, + this.methodCalls[i] = new this.VehicleMethodCall(obj.transactionid, obj.name, successCB, errorCB); this.socket.send(JSON.stringify(obj)); this.methodCalls[i].start(); @@ -236,7 +236,7 @@ Vehicle.prototype.getSupportedEventTypes = function(type, writeable, successCB, { var obj = { "type" : "method", - "name" : "getSupportedEventTypes", + "name" : "getSupported", "writeable" : writeable, "transactionid" : this.generateTransactionId(), "data" : type @@ -247,7 +247,7 @@ Vehicle.prototype.getSupportedEventTypes = function(type, writeable, successCB, Vehicle.prototype.get = function(name, zone, successCB, errorCB) { property = {"property" : name, "zone" : zone}; - + var obj = { "type" : "method", "name": "get", @@ -288,7 +288,7 @@ Vehicle.prototype.subscribe = function(name, zone, successCB, errorCB) "type" : "method", "name": "subscribe", "transactionid" : this.generateTransactionId(), - "data" : {"property" : name, "zone" : zone } + "property" : name }; this.send(obj, successCB, errorCB); @@ -300,7 +300,7 @@ Vehicle.prototype.unsubscribe = function(name, zone, successCB, errorCB) "type" : "method", "name": "unsubscribe", "transactionid" : this.generateTransactionId(), - "data" : {"property" : name, "zone" : zone } + "property" : name }; this.send(obj, successCB, errorCB); @@ -342,16 +342,16 @@ Vehicle.prototype.receive = function(msg) for(var i = 0; i < calls.length; i++) { var call = calls[i]; - if(call&&(!call.done)&&(call.transactionid === event.transactionid)) + if(call && (!call.done) && (call.transactionid === event.transactionid)) { call.finish(); if(event.error !== undefined) { call.errorCB(event.error); } - else if(event.data !== undefined && call.successCB !== undefined) + else if(call.successCB !== undefined) { - call.successCB(event.data); + call.successCB(event); } return; } @@ -364,26 +364,4 @@ 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 - }; - } -})(); -*/ + diff --git a/plugins/websocket/websocketsink.cpp b/plugins/websocket/websocketsink.cpp index d74eaf6b..5cdfb72b 100644 --- a/plugins/websocket/websocketsink.cpp +++ b/plugins/websocket/websocketsink.cpp @@ -34,14 +34,13 @@ #include <QJsonDocument> #include <QVariantMap> -WebSocketSink::WebSocketSink(AbstractRoutingEngine* re, libwebsocket *wsi, string uuid, VehicleProperty::Property property, std::string ambdproperty, Zone::Type zone) +WebSocketSink::WebSocketSink(AbstractRoutingEngine* re, libwebsocket *wsi, string uuid, VehicleProperty::Property property, std::string ambdproperty) : AbstractSink(re,map<string, string> ()) { m_amdbproperty = ambdproperty; m_uuid = uuid; m_wsi = wsi; m_property = property; - mZone = zone; m_re = re; re->subscribeToProperty(ambdproperty, this); } @@ -53,9 +52,6 @@ void WebSocketSink::propertyChanged(AbstractPropertyType *value) { VehicleProperty::Property property = value->name; - if(value->zone != mZone) - return; - QVariantMap data; QVariantMap reply; @@ -63,22 +59,14 @@ void WebSocketSink::propertyChanged(AbstractPropertyType *value) data["zone"] = value->zone; data["timestamp"]=value->timestamp; data["sequence"]=value->sequence; + data["type"] = amb::BasicTypes::fromSignature(amb::make_unique(VehicleProperty::getPropertyTypeForPropertyNameValue(property))->signature()).c_str(); reply["data"]=data; reply["type"]="valuechanged"; reply["name"]=property.c_str(); reply["transactionid"]=m_uuid.c_str(); - QByteArray replystr; - if(doBinary) - replystr = QJsonDocument::fromVariant(reply).toBinaryData(); - else - { - replystr = QJsonDocument::fromVariant(reply).toJson(); - cleanJson(replystr); - } - - lwsWrite(m_wsi, replystr,replystr.length()); + lwsWriteVariant(m_wsi, reply); } WebSocketSink::~WebSocketSink() { diff --git a/plugins/websocket/websocketsink.h b/plugins/websocket/websocketsink.h index 5b5502fc..1ddd73b2 100644 --- a/plugins/websocket/websocketsink.h +++ b/plugins/websocket/websocketsink.h @@ -29,14 +29,13 @@ class WebSocketSink : public AbstractSink { public: - WebSocketSink(AbstractRoutingEngine* re, libwebsocket *wsi, string uuid, VehicleProperty::Property property, std::string ambdproperty, Zone::Type zone); + WebSocketSink(AbstractRoutingEngine* re, libwebsocket *wsi, string uuid, VehicleProperty::Property property, std::string ambdproperty); ~WebSocketSink(); const string uuid() ; void propertyChanged(AbstractPropertyType *value); void supportedChanged(const PropertyList & supportedProperties); PropertyList subscriptions(); libwebsocket *socket() { return m_wsi; } - Zone::Type zone() { return mZone; } private: char *webSocketBuffer; @@ -45,7 +44,6 @@ private: libwebsocket *m_wsi; string m_uuid; string m_property; - Zone::Type mZone; }; #endif // WEBSOCKETSINK_H diff --git a/plugins/websocket/websocketsinkmanager.cpp b/plugins/websocket/websocketsinkmanager.cpp index 1c8a7e16..10d064d3 100644 --- a/plugins/websocket/websocketsinkmanager.cpp +++ b/plugins/websocket/websocketsinkmanager.cpp @@ -16,7 +16,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - #include "websocketsinkmanager.h" #include "websocketsink.h" #include "common.h" @@ -58,6 +57,7 @@ WebSocketSinkManager::WebSocketSinkManager(AbstractRoutingEngine* engine, map<st } + void WebSocketSinkManager::init() { //Protocol list for libwebsockets. @@ -67,10 +67,12 @@ void WebSocketSinkManager::init() setConfiguration(configuration); } + PropertyList WebSocketSinkManager::getSupportedProperties() { return m_engine->supported(); } + void WebSocketSinkManager::setConfiguration(map<string, string> config) { // //Config has been passed, let's start stuff up. @@ -149,17 +151,8 @@ void WebSocketSinkManager::setConfiguration(map<string, string> config) void WebSocketSinkManager::addSingleShotSink(libwebsocket* socket, VehicleProperty::Property property, Zone::Type zone, string id) { AsyncPropertyRequest request; - PropertyList foo = VehicleProperty::capabilities(); - if (contains(foo,property)) - { - request.property = property; - } - else - { - DebugOut(0)<<"websocketsink: Invalid property requested: "<<property; - return; - } + request.property = property; request.zoneFilter = zone; request.completed = [socket,id,property](AsyncPropertyReply* reply) { @@ -185,17 +178,7 @@ void WebSocketSinkManager::addSingleShotSink(libwebsocket* socket, VehicleProper replyvar["data"]= data; replyvar["transactionid"]=id.c_str(); - QByteArray replystr; - - if(doBinary) - replystr = QJsonDocument::fromVariant(replyvar).toBinaryData(); - else - { - replystr = QJsonDocument::fromVariant(replyvar).toJson(); - cleanJson(replystr); - } - - lwsWrite(socket, replystr, replystr.length()); + lwsWriteVariant(socket, replyvar); delete reply; }; @@ -233,17 +216,7 @@ void WebSocketSinkManager::addSingleShotRangedSink(libwebsocket* socket, Propert replyvar["data"]=list; replyvar["transactionid"]=id.c_str(); - QByteArray replystr; - - if(doBinary) - replystr = QJsonDocument::fromVariant(replyvar).toBinaryData(); - else - { - replystr = QJsonDocument::fromVariant(replyvar).toJson(); - cleanJson(replystr); - } - - lwsWrite(socket, replystr, replystr.length()); + lwsWriteVariant(socket, replyvar); delete reply; }; @@ -251,7 +224,7 @@ void WebSocketSinkManager::addSingleShotRangedSink(libwebsocket* socket, Propert AsyncRangePropertyReply* reply = routingEngine->getRangePropertyAsync(rangedRequest); } -void WebSocketSinkManager::removeSink(libwebsocket* socket,VehicleProperty::Property property, string uuid, Zone::Type zone) +void WebSocketSinkManager::removeSink(libwebsocket* socket,VehicleProperty::Property property, string uuid) { if (m_sinkMap.find(property) != m_sinkMap.end()) { @@ -259,30 +232,17 @@ void WebSocketSinkManager::removeSink(libwebsocket* socket,VehicleProperty::Prop for(auto i : sinks) { - if(i->zone() == zone) - { - m_sinkMap[property].remove(i); - delete i; - } + m_sinkMap[property].remove(i); + delete i; } QVariantMap reply; reply["type"]="methodReply"; reply["name"]="unsubscribe"; - reply["data"]=property.c_str(); + reply["property"]=property.c_str(); reply["transactionid"]= uuid.c_str(); - QByteArray replystr; - - if(doBinary) - replystr = QJsonDocument::fromVariant(reply).toBinaryData(); - else - { - replystr = QJsonDocument::fromVariant(reply).toJson(); - cleanJson(replystr); - } - - lwsWrite(socket, replystr, replystr.length()); + lwsWriteVariant(socket, reply); } } void WebSocketSinkManager::setValue(libwebsocket* socket,VehicleProperty::Property property,string value,Zone::Type zone,string uuid) @@ -307,17 +267,7 @@ void WebSocketSinkManager::setValue(libwebsocket* socket,VehicleProperty::Proper replyvar["data"]= data; replyvar["transactionid"]=uuid.c_str(); - QByteArray replystr; - - if(doBinary) - replystr = QJsonDocument::fromVariant(replyvar).toBinaryData(); - else - { - replystr = QJsonDocument::fromVariant(replyvar).toJson(); - cleanJson(replystr); - } - - lwsWrite(socket, replystr, replystr.length()); + lwsWriteVariant(socket, replyvar); delete reply; }; @@ -327,35 +277,18 @@ void WebSocketSinkManager::setValue(libwebsocket* socket,VehicleProperty::Proper delete type; } -void WebSocketSinkManager::addSink(libwebsocket* socket, VehicleProperty::Property property, string uuid, Zone::Type zone) +void WebSocketSinkManager::addSink(libwebsocket* socket, VehicleProperty::Property property, string uuid) { - PropertyList foo = VehicleProperty::capabilities(); - if (!contains(foo,property)) - { - DebugOut(DebugOut::Warning)<<"Invalid property requested: "<<property<<endl; - return; - } - QVariantMap reply; reply["type"] = "methodReply"; reply["name"] = "subscribe"; - reply["data"] = property.c_str(); + reply["property"] = property.c_str(); reply["transactionid"] = uuid.c_str(); - QByteArray replystr; - - if(doBinary) - replystr = QJsonDocument::fromVariant(reply).toBinaryData(); - else - { - replystr = QJsonDocument::fromVariant(reply).toJson(); - cleanJson(replystr); - } + lwsWriteVariant(socket, reply); - lwsWrite(socket, replystr, replystr.length()); - - WebSocketSink *sink = new WebSocketSink(m_engine, socket, uuid, property, property, zone); + WebSocketSink *sink = new WebSocketSink(m_engine, socket, uuid, property, property); m_sinkMap[property].push_back(sink); } extern "C" AbstractSinkManager * create(AbstractRoutingEngine* routingengine, map<string, string> config) @@ -570,44 +503,51 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb } else if (name == "subscribe") { - QVariantMap data = call["data"].toMap(); - int zone = data["zone"].toInt(); - sinkManager->addSink(wsi, data["property"].toString().toStdString(), id, zone); - + std::string property = call["property"].toString().toStdString(); + sinkManager->addSink(wsi, property, id); } else if (name == "unsubscribe") { - QVariantMap data = call["data"].toMap(); - sinkManager->removeSink(wsi, data["property"].toString().toStdString(), id, data["zone"].toInt()); - + sinkManager->removeSink(wsi, call["property"].toString().toStdString(), id); } - else if (name == "getSupportedEventTypes") + else if (name == "getSupportedEventTypes" || name == "getSupported") { QVariantMap reply; - QStringList list; + QVariantList list; PropertyList supported = sinkManager->getSupportedProperties(); + DebugOut() << "we support " << supported.size() << " properties" << endl; for(VehicleProperty::Property i : supported) { - list.append(i.c_str()); + std::vector<std::string> sources = sinkManager->router()->sourcesForProperty(i); + for(auto source : sources) + { + PropertyInfo info = sinkManager->router()->getPropertyInfo(i, source); + + for(auto zone : info.zones()) + { + auto property = amb::make_unique(VehicleProperty::getPropertyTypeForPropertyNameValue(i)); + + std::string signature = property->signature(); + const std::string basicType = amb::BasicTypes::fromSignature(signature); + + QVariantMap map; + map["zone"] = zone; + map["name"] = i.c_str(); + map["type"] = basicType.c_str(); + map["source"] = source.c_str(); + + list.append(map); + } + } } reply["type"] = "methodReply"; - reply["name"] = "getSupportedEventTypes"; + reply["name"] = "getSupported"; reply["transactionid"] = id.c_str(); reply["data"] = list; - QByteArray replystr; - - if(doBinary) - replystr = QJsonDocument::fromVariant(reply).toBinaryData(); - else - { - replystr = QJsonDocument::fromVariant(reply).toJson(); - cleanJson(replystr); - } - - lwsWrite(wsi, replystr, replystr.length()); + lwsWriteVariant(wsi, reply); } else { diff --git a/plugins/websocket/websocketsinkmanager.h b/plugins/websocket/websocketsinkmanager.h index e4d98211..9ffd3e34 100644 --- a/plugins/websocket/websocketsinkmanager.h +++ b/plugins/websocket/websocketsinkmanager.h @@ -37,24 +37,26 @@ public: WebSocketSinkManager(AbstractRoutingEngine* engine, map<string, string> config); 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, Zone::Type zone); + void addSink(libwebsocket* socket, VehicleProperty::Property property, string uuid); void disconnectAll(libwebsocket* socket); - void removeSink(libwebsocket* socket, VehicleProperty::Property property, string uuid, Zone::Type zone); + void removeSink(libwebsocket* socket, VehicleProperty::Property property, string uuid); void addPoll(int fd); void removePoll(int fd); void init(); - map<std::string, list<WebSocketSink*> > m_sinkMap; + std::map<std::string, list<WebSocketSink*> > m_sinkMap; void setConfiguration(map<string, string> config); void setValue(libwebsocket* socket,VehicleProperty::Property property,string value, Zone::Type zone, string uuid); PropertyList getSupportedProperties(); + AbstractRoutingEngine * router() { return routingEngine; } + int partialMessageIndex; QByteArray incompleteMessage; int expectedMessageFrames; private: - map<int,GIOChannel*> m_ioChannelMap; - map<int,guint> m_ioSourceMap; + std::map<int, GIOChannel*> m_ioChannelMap; + std::map<int, guint> m_ioSourceMap; AbstractRoutingEngine *m_engine; struct libwebsocket_protocols protocollist[2]; diff --git a/plugins/websocket/websocketsource.cpp b/plugins/websocket/websocketsource.cpp index 8b8de3d9..eb0211a5 100644 --- a/plugins/websocket/websocketsource.cpp +++ b/plugins/websocket/websocketsource.cpp @@ -51,7 +51,7 @@ class UniquePropertyCache public: bool hasProperty(std::string name, std::string source, Zone::Type zone) { - for(auto i : properties) + for(auto i : mProperties) { if(i->name == name && i->sourceUuid == source && @@ -63,9 +63,9 @@ public: return false; } - std::shared_ptr<AbstractPropertyType> append(std::string name, std::string source, Zone::Type zone) + std::shared_ptr<AbstractPropertyType> append(std::string name, std::string source, Zone::Type zone, std::string type) { - for(auto i : properties) + for(auto i : mProperties) { if(i->name == name && i->sourceUuid == source && @@ -79,20 +79,55 @@ public: if(!t) { - throw std::runtime_error(name + "name is not a known type"); + VehicleProperty::registerProperty(name, [name, type]() -> AbstractPropertyType* { + if(type == amb::BasicTypes::UInt16Str) + { + return new BasicPropertyType<uint16_t>(name, 0); + } + else if(type == amb::BasicTypes::Int16Str) + { + return new BasicPropertyType<int16_t>(name, 0); + } + else if(type == amb::BasicTypes::UInt32Str) + { + return new BasicPropertyType<uint32_t>(name, 0); + } + else if(type == amb::BasicTypes::Int32Str) + { + return new BasicPropertyType<int32_t>(name, 0); + } + else if(type == amb::BasicTypes::StringStr) + { + return new StringPropertyType(name); + } + else if(type == amb::BasicTypes::DoubleStr) + { + return new BasicPropertyType<double>(name, 0); + } + else if(type == amb::BasicTypes::BooleanStr) + { + return new BasicPropertyType<bool>(name, false); + } + DebugOut(DebugOut::Warning) << "Unknown or unsupported type: " << type << endl; + return nullptr; + }); + t = VehicleProperty::getPropertyTypeForPropertyNameValue(name); } - t->sourceUuid = source; - t->zone = zone; + if(t)/// check again to see if registration succeeded + { + t->sourceUuid = source; + t->zone = zone; - properties.emplace_back(t); + mProperties.emplace_back(t); + } - return property(name, source, zone); + return property(name, source, zone); /// will return nullptr if t didn't register } std::shared_ptr<AbstractPropertyType> property(std::string name, std::string source, Zone::Type zone) { - for(auto i : properties) + for(auto i : mProperties) { if(i->name == name && i->sourceUuid == source && @@ -105,8 +140,10 @@ public: return nullptr; } + std::vector<std::shared_ptr<AbstractPropertyType>> properties() { return mProperties; } + private: - std::vector<std::shared_ptr<AbstractPropertyType>> properties; + std::vector<std::shared_ptr<AbstractPropertyType>> mProperties; }; UniquePropertyCache properties; @@ -144,20 +181,10 @@ void WebSocketSource::checkSubscriptions() reply["type"] = "method"; reply["name"] = "subscribe"; - reply["data"] = prop.c_str(); + reply["property"] = prop.c_str(); reply["transactionid"] = "d293f670-f0b3-11e1-aff1-0800200c9a66"; - QByteArray replystr; - - if(doBinary) - replystr = QJsonDocument::fromVariant(reply).toBinaryData(); - else - { - replystr = QJsonDocument::fromVariant(reply).toJson(); - cleanJson(replystr); - } - - lwsWrite(clientsocket, replystr, replystr.length()); + lwsWriteVariant(clientsocket, reply); } } void WebSocketSource::setConfiguration(map<string, string> config) @@ -205,14 +232,21 @@ void WebSocketSource::setConfiguration(map<string, string> config) sslval = 2; } - clientsocket = libwebsocket_client_connect(context, ip.c_str(), port, sslval,"/", "localhost", "websocket",protocols[0].name, -1); - - + clientsocket = libwebsocket_client_connect(context, ip.c_str(), port, sslval,"/", "localhost", "websocket", protocols[0].name, -1); } -PropertyInfo WebSocketSource::getPropertyInfo(VehicleProperty::Property property) +PropertyInfo WebSocketSource::getPropertyInfo(const VehicleProperty::Property &property) { - return PropertyInfo::invalid(); + Zone::ZoneList zones; + for(auto i : properties.properties()) + { + if(i->name == property) + { + zones.push_back(i->zone); + } + } + + return PropertyInfo(0, zones); } bool gioPollingFunc(GIOChannel *source, GIOCondition condition, gpointer data) @@ -310,26 +344,16 @@ static int callback_http_only(libwebsocket_context *context, struct libwebsocket QVariantMap toSend; toSend["type"] = "method"; - toSend["name"] = "getSupportedEventTypes"; + toSend["name"] = "getSupported"; toSend["transactionid"] = amb::createUuid().c_str(); - QByteArray replystr; - - if(doBinary) - replystr = QJsonDocument::fromVariant(toSend).toBinaryData(); - else - { - replystr = QJsonDocument::fromVariant(toSend).toJson(); - cleanJson(replystr); - } - - lwsWrite(wsi, replystr, replystr.length()); + lwsWriteVariant(wsi, toSend); break; } case LWS_CALLBACK_CLIENT_RECEIVE: { - QByteArray d((char*)in,len); + QByteArray d((char*)in, len); WebSocketSource * manager = source; @@ -357,7 +381,7 @@ static int callback_http_only(libwebsocket_context *context, struct libwebsocket if(doc.isNull()) { - DebugOut(DebugOut::Error)<<"Invalid message"<<endl; + DebugOut(DebugOut::Warning)<<"Invalid message"<<endl; break; } @@ -384,18 +408,26 @@ static int callback_http_only(libwebsocket_context *context, struct libwebsocket double timestamp = data["timestamp"].toDouble(); int sequence = data["sequence"].toInt(); Zone::Type zone = data["zone"].toInt(); + string type = data["type"].toString().toStdString(); DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Value changed:" << name << value << endl; try { - auto type = properties.append(name, source->uuid(), zone); + auto property = properties.append(name, source->uuid(), zone, type); + + if(!property) + { + DebugOut(DebugOut::Warning) << "We either don't have this or don't support it (" + << name << "," << zone << "," << type << ")" << endl; + } - type->timestamp = timestamp; - type->sequence = sequence; - type->fromString(value); + property->timestamp = timestamp; + property->sequence = sequence; + property->fromString(value); + + m_re->updateProperty(property.get(), source->uuid()); - m_re->updateProperty(type.get(), source->uuid()); double currenttime = amb::currentTime(); /** This is now the latency between when something is available to read on the socket, until @@ -403,12 +435,12 @@ static int callback_http_only(libwebsocket_context *context, struct libwebsocket * JSON parsing in this section. */ - DebugOut(2)<<"websocket network + parse latency: "<<(currenttime - type->timestamp)*1000<<"ms"<<endl; + DebugOut()<<"websocket network + parse latency: "<<(currenttime - property->timestamp)*1000<<"ms"<<endl; totalTime += (currenttime - oldTimestamp)*1000; numUpdates ++; averageLatency = totalTime / numUpdates; - DebugOut(2)<<"Average parse latency: "<<averageLatency<<endl; + DebugOut()<<"Average parse latency: "<<averageLatency<<endl; } catch (exception ex) { @@ -418,23 +450,29 @@ static int callback_http_only(libwebsocket_context *context, struct libwebsocket } else if (type == "methodReply") { - if (name == "getSupportedEventTypes") + if (name == "getSupported" || name == "supportedChanged") { QVariant data = call["data"]; - QStringList supported = data.toStringList(); + QVariantList supported = data.toList(); + + DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Got getSupported request"<<endl; - DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Got getSupportedEventTypes request"<<endl; - PropertyList props; - Q_FOREACH(QString p, supported) + Q_FOREACH(QVariant p, supported) { - props.push_back(p.toStdString()); + QVariantMap d = p.toMap(); + Zone::Type zone = d["zone"].toInt(); + std::string name = d["name"].toString().toStdString(); + std::string proptype = d["type"].toString().toStdString(); + std::string source = d["source"].toString().toStdString(); + + properties.append(name, source, zone, proptype); } - source->setSupported(props); - //m_re->updateSupported(m_supportedProperties,PropertyList()); + source->updateSupported(); + } else if (name == "getRanged") { @@ -451,7 +489,7 @@ static int callback_http_only(libwebsocket_context *context, struct libwebsocket double timestamp = obj["timestamp"].toDouble(); int sequence = obj["sequence"].toInt(); - AbstractPropertyType* type = VehicleProperty::getPropertyTypeForPropertyNameValue(name,value); + AbstractPropertyType* type = VehicleProperty::getPropertyTypeForPropertyNameValue(name, value); type->timestamp = timestamp; type->sequence = sequence; @@ -540,11 +578,16 @@ static int callback_http_only(libwebsocket_context *context, struct libwebsocket return 0; } } -void WebSocketSource::setSupported(PropertyList list) +void WebSocketSource::updateSupported() { - DebugOut() <<__SMALLFILE__ << ":" << __LINE__ <<" "<< __FUNCTION__ <<endl; - m_supportedProperties = list; - m_re->updateSupported(list,PropertyList(),this); + PropertyList list; + for(auto i : properties.properties()) + { + if(!contains(list, i->name)) + list.push_back(i->name); + } + + m_re->updateSupported(list, PropertyList(), this); } WebSocketSource::WebSocketSource(AbstractRoutingEngine *re, map<string, string> config) : AbstractSource(re, config), partialMessageIndex(0),expectedMessageFrames(0) @@ -578,7 +621,12 @@ WebSocketSource::WebSocketSource(AbstractRoutingEngine *re, map<string, string> } PropertyList WebSocketSource::supported() { - return m_supportedProperties; + PropertyList list; + for(auto i : properties.properties()) + { + list.push_back(i->name); + } + return list; } int WebSocketSource::supportedOperations() @@ -629,17 +677,7 @@ void WebSocketSource::getPropertyAsync(AsyncPropertyReply *reply) replyvar["data"] = data; replyvar["transactionid"] = uuid.c_str(); - QByteArray replystr; - - if(doBinary) - replystr = QJsonDocument::fromVariant(replyvar).toBinaryData(); - else - { - replystr = QJsonDocument::fromVariant(replyvar).toJson(); - cleanJson(replystr); - } - - lwsWrite(clientsocket, replystr, replystr.length()); + lwsWriteVariant(clientsocket, replyvar); } void WebSocketSource::getRangePropertyAsync(AsyncRangePropertyReply *reply) @@ -671,17 +709,7 @@ void WebSocketSource::getRangePropertyAsync(AsyncRangePropertyReply *reply) replyvar["data"] = properties; - QByteArray replystr; - - if(doBinary) - replystr = QJsonDocument::fromVariant(replyvar).toBinaryData(); - else - { - replystr = QJsonDocument::fromVariant(replyvar).toJson(); - cleanJson(replystr); - } - - lwsWrite(clientsocket, replystr, replystr.length()); + lwsWriteVariant(clientsocket, replyvar); } AsyncPropertyReply * WebSocketSource::setProperty( AsyncSetPropertyRequest request ) @@ -700,17 +728,7 @@ AsyncPropertyReply * WebSocketSource::setProperty( AsyncSetPropertyRequest reque replyvar["data"] = data; replyvar["transactionid"] = amb::createUuid().c_str(); - QByteArray replystr; - - if(doBinary) - replystr = QJsonDocument::fromVariant(replyvar).toBinaryData(); - else - { - replystr = QJsonDocument::fromVariant(replyvar).toJson(); - cleanJson(replystr); - } - - lwsWrite(clientsocket, replystr, replystr.length()); + lwsWriteVariant(clientsocket, replyvar); ///TODO: we should actually wait for a response before we simply complete the call reply->success = true; diff --git a/plugins/websocket/websocketsource.h b/plugins/websocket/websocketsource.h index 4a318955..c19a6e86 100644 --- a/plugins/websocket/websocketsource.h +++ b/plugins/websocket/websocketsource.h @@ -48,11 +48,10 @@ public: void checkSubscriptions(); PropertyList activeRequests; PropertyList removeRequests; - void setSupported(PropertyList list); + void updateSupported(); void supportedChanged(const PropertyList &) {} void setConfiguration(std::map<std::string, std::string> config); - //map<VehicleProperty::Property,AsyncPropertyReply*> propertyReplyMap; - //map<VehicleProperty::Property,AsyncRangePropertyReply*> rangedPropertyReplyMap; + std::map<std::string,AsyncPropertyReply*> uuidReplyMap; std::map<std::string,double> uuidTimeoutMap; std::map<std::string, AsyncRangePropertyReply*> uuidRangedReplyMap; @@ -61,11 +60,7 @@ public: QByteArray incompleteMessage; int expectedMessageFrames; - PropertyInfo getPropertyInfo(VehicleProperty::Property property); - -private: - PropertyList m_supportedProperties; - + PropertyInfo getPropertyInfo(const VehicleProperty::Property & property); }; #endif // WEBSOCKETSOURCE_H diff --git a/plugins/wheel/wheelplugin.cpp b/plugins/wheel/wheelplugin.cpp index 0ddfd799..6958bb92 100644 --- a/plugins/wheel/wheelplugin.cpp +++ b/plugins/wheel/wheelplugin.cpp @@ -179,6 +179,13 @@ int WheelSourcePlugin::supportedOperations() return Get | Set; } +PropertyInfo WheelSourcePlugin::getPropertyInfo(const VehicleProperty::Property &property) +{ + Zone::ZoneList zones; + zones.push_back(0); + return PropertyInfo(0, zones); +} + void WheelSourcePlugin::unsubscribeToPropertyChanges(VehicleProperty::Property property) { mRequests.erase(property); diff --git a/plugins/wheel/wheelplugin.h b/plugins/wheel/wheelplugin.h index 4a5b54b8..4bfa11a7 100644 --- a/plugins/wheel/wheelplugin.h +++ b/plugins/wheel/wheelplugin.h @@ -32,7 +32,7 @@ class WheelSourcePlugin: public AbstractSource public: WheelSourcePlugin(AbstractRoutingEngine* re, map<string, string> config); ~WheelSourcePlugin(); - + const string uuid(); void getPropertyAsync(AsyncPropertyReply *reply); void getRangePropertyAsync(AsyncRangePropertyReply *reply){} @@ -42,13 +42,15 @@ public: PropertyList supported(); int supportedOperations(); - + void supportedChanged(const PropertyList &) {} map<string, string> getConfiguration() { return configuration; } - friend class WheelPrivate; - + PropertyInfo getPropertyInfo(const VehicleProperty::Property &property); + + friend class WheelPrivate; + private: WheelPrivate *mWheel; diff --git a/tests/amb-set.py b/tests/amb-set.py index 59d7b7fa..1c7e02c5 100755 --- a/tests/amb-set.py +++ b/tests/amb-set.py @@ -16,24 +16,23 @@ args = parser.parse_args() objectName = args.objectName propertyToSet = args.property value = args.value -valueType = args.valueType +valueType = args.valueType.lower() zone = int(args.zone) realValue = 0 -print "valueType: " + valueType - if valueType == "boolean": realValue = value == "true" elif valueType == "integer": - realValue = int(value) + realValue = dbus.Int32(value) elif valueType == "string": realValue = value elif valueType == "double": realValue = double(value) elif valueType == "UInt16": - print "can has UInt16!!!" realValue = dbus.UInt16(value) +else: + raise Exception("Unknown type: " + valueType) bus = dbus.SystemBus() managerObject = bus.get_object("org.automotive.message.broker", "/"); |