summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevron Rees <tripzero.kev@gmail.com>2014-12-23 09:52:00 -0800
committerKevron Rees <tripzero.kev@gmail.com>2014-12-23 09:52:00 -0800
commit2bdd66ead71810213900523cac7d3b4abd1592db (patch)
tree0df2c3905d4ca8f50db6d63b02f0b4d29392f115
parent5f66d2e3e2bc77fed33a9069a8f02fd2142d218f (diff)
parentbbbf257a0c9c8449250804b6a805f6d41750f7ea (diff)
downloadautomotive-message-broker-2bdd66ead71810213900523cac7d3b4abd1592db.tar.gz
Merge pull request #36 from tripzero/master0.12.901
Documentation updates. Fixes to several plugins.
-rw-r--r--CMakeLists.txt2
-rw-r--r--RELEASE4
-rw-r--r--TODO3
-rw-r--r--ambd/core.cpp8
-rw-r--r--ambd/main.cpp8
-rw-r--r--docs/README2
-rw-r--r--docs/amb.in.idl14
-rw-r--r--examples/CMakeLists.txt1
-rw-r--r--examples/databaseconfig.in28
-rw-r--r--examples/opencvdbusconfig.in2
-rw-r--r--examples/websocketsource2.in4
-rw-r--r--lib/abstractpropertytype.h22
-rw-r--r--lib/abstractsink.h2
-rw-r--r--lib/abstractsource.cpp29
-rw-r--r--lib/abstractsource.h2
-rw-r--r--lib/debugout.h11
-rw-r--r--lib/propertyinfo.hpp7
-rw-r--r--lib/vehicleproperty.h3
-rw-r--r--plugins/bluemonkey/bluemonkey.cpp3
-rw-r--r--plugins/bluemonkey/config.js5
-rw-r--r--plugins/common/CMakeLists.txt2
-rw-r--r--plugins/common/ambpluginimpl.cpp2
-rw-r--r--plugins/common/ambpluginimpl.h13
-rw-r--r--plugins/common/bluetooth5.cpp2
-rw-r--r--plugins/database/CMakeLists.txt6
-rw-r--r--plugins/database/basedb.hpp80
-rw-r--r--plugins/database/databasesink.cpp185
-rw-r--r--plugins/database/databasesink.h45
-rw-r--r--plugins/dbus/CMakeLists.txt2
-rw-r--r--plugins/dbus/abstractdbusinterface.cpp25
-rw-r--r--plugins/dbus/abstractdbusinterface.h2
-rw-r--r--plugins/dbus/automotivemanager.cpp18
-rw-r--r--plugins/dbus/dbusinterfacemanager.cpp9
-rw-r--r--plugins/dbus/varianttype.cpp10
-rw-r--r--plugins/exampleplugin.cpp2
-rw-r--r--plugins/gpsnmea/gpsnmea.cpp2
-rw-r--r--plugins/gpsnmea/gpsnmea.h2
-rw-r--r--plugins/murphyplugin/murphysource.cpp8
-rw-r--r--plugins/murphyplugin/murphysource.h59
-rw-r--r--plugins/obd2plugin/obd2source.cpp14
-rw-r--r--plugins/obd2plugin/obd2source.h2
-rw-r--r--plugins/obd2plugin/obdlib.cpp4
-rw-r--r--plugins/obd2plugin/obdpid.h4
-rw-r--r--plugins/opencvlux/CMakeLists.txt6
-rw-r--r--plugins/opencvlux/README29
-rw-r--r--plugins/opencvlux/opencvluxplugin.cpp163
-rw-r--r--plugins/opencvlux/opencvluxplugin.h33
-rw-r--r--plugins/websocket/CMakeLists.txt4
-rw-r--r--plugins/websocket/common.cpp93
-rw-r--r--plugins/websocket/common.h35
-rw-r--r--plugins/websocket/protocol16
-rw-r--r--plugins/websocket/test/events.js5
-rw-r--r--plugins/websocket/test/test.js29
-rw-r--r--plugins/websocket/test/vehicle.js54
-rw-r--r--plugins/websocket/websocketsink.cpp18
-rw-r--r--plugins/websocket/websocketsink.h4
-rw-r--r--plugins/websocket/websocketsinkmanager.cpp150
-rw-r--r--plugins/websocket/websocketsinkmanager.h12
-rw-r--r--plugins/websocket/websocketsource.cpp208
-rw-r--r--plugins/websocket/websocketsource.h11
-rw-r--r--plugins/wheel/wheelplugin.cpp7
-rw-r--r--plugins/wheel/wheelplugin.h10
-rwxr-xr-xtests/amb-set.py9
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")
diff --git a/RELEASE b/RELEASE
index d7a921d1..42c800e1 100644
--- a/RELEASE
+++ b/RELEASE
@@ -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
diff --git a/TODO b/TODO
index 3a0f68c3..64ebecf7 100644
--- a/TODO
+++ b/TODO
@@ -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", "/");