summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevron Rees <tripzero.kev@gmail.com>2015-01-14 15:36:24 -0800
committerKevron Rees <tripzero.kev@gmail.com>2015-01-14 15:36:24 -0800
commit89216a903083efa20969ba4f47c6560b2d9773a8 (patch)
tree080a9993f5c9fbf704f5d7e3ae6e1cb5c9c55b26
parentbf4ba5f6aff0d12b1b1524b452f9743bc284298b (diff)
parentacfe65e70189b99b37f6c0a4d00ff8915de6a3be (diff)
downloadautomotive-message-broker-89216a903083efa20969ba4f47c6560b2d9773a8.tar.gz
Merge pull request #42 from tripzero/master
0.13.801
-rw-r--r--CMakeLists.txt14
-rw-r--r--README80
-rw-r--r--README.md76
-rw-r--r--RELEASE12
-rw-r--r--RELEASE.in.md20
-rw-r--r--RELEASE.md20
-rw-r--r--TODO8
-rw-r--r--ambd/CMakeLists.txt3
-rw-r--r--ambd/config.in19
-rw-r--r--ambd/config.in.json6
-rw-r--r--ambd/pluginloader.cpp283
-rw-r--r--ambd/pluginloader.h11
-rw-r--r--docs/CMakeLists.txt4
-rw-r--r--docs/Doxyfile.mainpage.in2
-rw-r--r--docs/amb.in.fidl26
-rw-r--r--docs/ambd-configuration.in.idl84
-rw-r--r--docs/ambd.in.md76
-rw-r--r--docs/libamb.in5
-rw-r--r--docs/mainpage.in.idl36
-rw-r--r--examples/CMakeLists.txt47
-rw-r--r--examples/bluemonkey/bluemonkeyconfig.in21
-rw-r--r--examples/bluemonkey/bluemonkeyconfig.in.json18
-rw-r--r--examples/cangenconfig.in.json (renamed from examples/cangenconfig.in)6
-rw-r--r--examples/configwheel.in16
-rw-r--r--examples/configwheel.in.json16
-rw-r--r--examples/databaselogging.in.json28
-rw-r--r--examples/databasesource.in16
-rw-r--r--examples/databasesource.in.json16
-rw-r--r--examples/databasewebsocketsink.in.json29
-rw-r--r--examples/dbusconfig.in18
-rw-r--r--examples/dbusconfig.in.json18
-rw-r--r--examples/exampleconfig.in16
-rw-r--r--examples/exampleconfig.in.json16
-rw-r--r--examples/gpsnmea.in16
-rw-r--r--examples/gpsnmea.in.json16
-rw-r--r--examples/obdsourceconfig.in18
-rw-r--r--examples/obdsourceconfig.in.json18
-rw-r--r--examples/opencvdbusconfig.in30
-rw-r--r--examples/opencvdbusconfig.in.json30
-rw-r--r--examples/opencvluxconfig.in24
-rw-r--r--examples/opencvluxconfig.in.json24
-rw-r--r--examples/qtmainloopconfig.in18
-rw-r--r--examples/qtmainloopconfig.in.json18
-rw-r--r--examples/testplugins.d.in.json4
-rw-r--r--examples/testsourceconfig.in15
-rw-r--r--examples/testsourceconfig.in.json15
-rw-r--r--examples/websocketsink2.in21
-rw-r--r--examples/websocketsink2.in.json21
-rw-r--r--examples/websocketsource2.in24
-rw-r--r--examples/websocketsource2.in.json24
-rw-r--r--lib/CMakeLists.txt4
-rw-r--r--lib/abstractpropertytype.h3
-rw-r--r--lib/abstractroutingengine.h82
-rw-r--r--lib/asyncqueue.hpp20
-rw-r--r--lib/debugout.h24
-rw-r--r--lib/picojson.h (renamed from xwalk/common/picojson.h)0
-rw-r--r--lib/superptr.hpp10
-rw-r--r--lib/vehicleproperty.cpp10
-rw-r--r--packaging.in/amb.manifest3
-rw-r--r--packaging.in/automotive-message-broker.spec.in1
-rw-r--r--plugins/CMakeLists.txt5
-rw-r--r--plugins/bluemonkey/bluemonkey.in.idl18
-rw-r--r--plugins/bluemonkey/config.js12
-rw-r--r--plugins/common/abstractdbusinterface.cpp133
-rw-r--r--plugins/common/abstractdbusinterface.h8
-rw-r--r--plugins/common/varianttype.cpp10
-rw-r--r--plugins/common/varianttype.h12
-rw-r--r--plugins/database/databasesink.cpp7
-rw-r--r--plugins/database/databasesink.h4
-rw-r--r--plugins/dbus/CMakeLists.txt4
-rw-r--r--plugins/dbus/automotivemanager.cpp12
-rw-r--r--plugins/dbus/dbus.in.json6
-rw-r--r--plugins/exampleplugin.cpp2
-rw-r--r--plugins/examplesink.cpp3
-rw-r--r--plugins/examplesink.in.json6
-rw-r--r--plugins/examplesource.in.json6
-rw-r--r--plugins/opencvlux/CMakeLists.txt3
-rw-r--r--plugins/testplugin/testplugin.cpp2
-rw-r--r--plugins/websocket/CMakeLists.txt17
-rw-r--r--plugins/websocket/Doxyfile.in4
-rw-r--r--plugins/websocket/protocol37
-rw-r--r--plugins/websocket/protocol.idl440
-rw-r--r--plugins/websocket/test/servertest/client.html17
-rw-r--r--plugins/websocket/test/servertest/server.html22
-rw-r--r--plugins/websocket/test/servertest/server.js312
-rw-r--r--plugins/websocket/websocketsinkmanager.cpp54
-rw-r--r--plugins/websocket/websocketsinkmanager.h2
-rw-r--r--plugins/websocket/websocketsource.cpp76
-rw-r--r--plugins/websocket/websocketsource.h3
-rw-r--r--tools/ambctl.py312
-rwxr-xr-xtools/genmapping.py21
-rw-r--r--xwalk/CMakeLists.txt8
-rw-r--r--xwalk/vehicle.cc41
-rw-r--r--xwalk/vehicle.h2
-rw-r--r--xwalk/vehicle_api.js373
-rw-r--r--xwalk/vehicle_instance.h3
96 files changed, 2224 insertions, 1332 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e95bab52..b8c57dfa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,8 +8,8 @@ include(CMakeDependentOption)
set(PROJECT_NAME "automotive-message-broker")
set(PROJECT_PRETTY_NAME "Automotive Message Broker")
-set(PROJECT_VERSION "0.13.800")
-set(PROJECT_CODENAME "")
+set(PROJECT_VERSION "0.13.801")
+set(PROJECT_CODENAME "74A")
set(PROJECT_QUALITY "alpha")
add_definitions(-DPROJECT_VERSION="${PROJECT_VERSION}")
@@ -21,7 +21,8 @@ set (LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
set (LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/${CMAKE_LIBRARY_ARCHITECTURE}" )
set (PLUGIN_INSTALL_PATH "${LIB_INSTALL_DIR}/${PROJECT_NAME}")
set (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include")
-set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/packages/${PROJECT_NAME}")
+set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/packages/${PROJECT_NAME}/${PROJECT_VERSION}")
+set (PLUGIN_SEGMENT_INSTALL_PATH "/etc/ambd/plugins.d")
option(qtmainloop "Use QCoreApplication mainloop " OFF)
option(websocket_plugin "websocket source and sink plugins" OFF)
@@ -47,11 +48,6 @@ set(XWALK_EXTENSION_PATH "/automotive-message-broker/xwalk" CACHE PATH "director
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpie -pie -std=c++1y")
-if(opencvlux_plugin)
- message(STATUS "OpenCV Lux plugin enabled")
-
-endif(opencvlux_plugin)
-
include (CMakeForceCompiler)
if (enable_icecc)
@@ -86,6 +82,8 @@ add_custom_target(dist COMMAND git archive --prefix=${ARCHIVE_NAME}/ HEAD | bzip
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/RELEASE.in.md" "${CMAKE_CURRENT_SOURCE_DIR}/RELEASE.md" IMMEDIATE @ONLY)
+
# packaging stuff:
# Common things to every type of package
SET(CPACK_PACKAGE_DESCRIPTION "daemon that provides access vehicle data")
diff --git a/README b/README
deleted file mode 100644
index 90916606..00000000
--- a/README
+++ /dev/null
@@ -1,80 +0,0 @@
-Automotive Message Broker is a vehicle network abstraction system. It brokers information from the vehicle
-to applications. It provides application with a rich API for accessing vehicle data.
-
-Automotive Message Broker is built using CMake and requires libltdl (libtool), libjson-c, and boost packages.
-
-
-About the Git Tree:
-master is expected to be unstable and may not even compile. If you want something more stable, checkout one of the
-release branches (ie, 0.9.0, 0.10, etc)
-
-
-To build:
-
-cd automotive-message-broker
-mkdir build
-cd build
-cmake ..
-make
-
-To install:
-
-sudo make install
-
-To run:
-
-ambd
-
-ambd can load different plugins. The config file specifies what plugins to use. The default config located in
-/etc/ambd/config. You can change this or use your own config to have ambd use your own plugins. For example:
-
-# copy the config to your own config
-cp /etc/ambd/config myconfig
-
-# edit myconfig and specify the path to your plugin:
-# change the line:
-"sources" : [ { "path" : "../plugins/examplesourceplugin.so" } ],
-# to:
-"sources" : [ { "path" : "/path/to/mysourceplugin.so" } ],
-
-Now you can run ambd with:
-
-ambd -c /path/to/myconfig
-
-also see ambd -h
-
-Typically, AMB will be used with the DBus plugin. The DBus plugin automatically makes internal AMB properties
-available over DBus. See the DBus plugin documentation for more information (plugins/dbus/README).
-
-
-Running with other plugins
-
-To learn about running AMB with other plugins, please see the plugins/*/README.
-
-
-Running with the Qt mainloop:
-
-Some source and sink plugins may want to use the Qt-based mainloop to take advantage of Qt features. To enable
-the Qt mainloop, run cmake with -Duse_qtcore=On:
-
-cmake .. -Dqtmainloop=On
-
-You will also need to edit your config to enable the Qt-based mainloop:
-
-{
- "mainloop" : "/usr/lib/automotive-message-broker/qtmainloopplugin.so",
- "sources" : [...],
- "sinks" : [...]
-}
-
-NOTE: by default the glib mainloop will be used.
-
-
-
-Questions/Issues/Comments:
-
-Questions or Comments can be emailed to:
-tripzero.kev@gmail.com
-
-Issues can be submitted on our github page:
-https://github.com/otcshare/automotive-message-broker/issues
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..96f46239
--- /dev/null
+++ b/README.md
@@ -0,0 +1,76 @@
+# Automotive Message Broker
+
+Version 0.13.801
+
+## Introduction
+
+Automotive Message Broker is a vehicle network abstraction system. It brokers information from the vehicle
+to applications. It provides application with a rich API for accessing vehicle data.
+
+Automotive Message Broker is built using CMake and requires libltdl (libtool), libjson-c, and boost packages.
+
+## Git
+About the Git Tree:
+master is expected to be unstable and may not even compile. If you want something more stable, checkout one of the
+release branches (ie, 0.9.0, 0.10, etc)
+
+## Building
+
+To build:
+
+~~~~~~~~~~~~~{.bash}
+cd automotive-message-broker
+mkdir build
+cd build
+cmake ..
+make
+~~~~~~~~~~~~~
+
+## Installing
+
+To install:
+
+~~~~~~~~~~~~~{.bash}
+sudo make install
+~~~~~~~~~~~~~
+
+## Running
+To run:
+
+~~~~~~~~~~~~~{.bash}
+ambd
+~~~~~~~~~~~~~
+
+*also see **ambd -h** for additional command line options*
+
+## Configuration
+
+For information on ambd's configuration, please see ambd-configuration.idl.
+
+## Running with the Qt mainloop:
+
+Some source and sink plugins may want to use the Qt-based mainloop to take advantage of Qt features. To enable
+the Qt mainloop, run cmake with -Duse_qtcore=On:
+
+~~~~~~~~~~~~~{.bash}
+cmake .. -Dqtmainloop=On
+~~~~~~~~~~~~~
+
+You will also need to edit your config to enable the Qt-based mainloop:
+
+~~~~~~~~~~~~~{.json}
+{
+ "mainloop" : "/usr/lib/i386-linux-gnu/automotive-message-broker/qtmainloopplugin.so",
+ "plugins" : "/etc/ambd/plugins.d"
+}
+~~~~~~~~~~~~~
+
+NOTE: by default the glib mainloop will be used.
+
+## Questions/Issues/Comments:
+
+Questions or Comments can be emailed to the amb mailing list:
+**amb at lists.01.org**
+
+Issues and Feature requests can be submitted on our github page:
+https://github.com/otcshare/automotive-message-broker/issues
diff --git a/RELEASE b/RELEASE
deleted file mode 100644
index 6caafcf3..00000000
--- a/RELEASE
+++ /dev/null
@@ -1,12 +0,0 @@
-Release notes for release 0.14
-
-New features:
-- [DBus] some classes for exporting custom interfaces moved to plugins-common
-- [Bluemonkey plugin] support for creating custom dbus interfaces: bluemonkey.exportInterface()
-
-Changes:
-- Plugin create() method signature changed.
-- Removed AbstractSinkManager class
-- Removed deprecated dbus interfaces
-
-Fixes:
diff --git a/RELEASE.in.md b/RELEASE.in.md
new file mode 100644
index 00000000..90b5de00
--- /dev/null
+++ b/RELEASE.in.md
@@ -0,0 +1,20 @@
+AMB Release Notes
+Version: @PROJECT_VERSION@
+
+New features:
+- [DBus] some classes for exporting custom interfaces moved to plugins-common
+- [Bluemonkey plugin] support for creating custom dbus interfaces: bluemonkey.exportInterface()
+- [ambctl] support for enabling disabling plugins
+- [ambd] support plugins.d - now plugin segments can be stuck in there and amb will try to load all plugins that
+ are enabled. See the example segments: /etc/ambd/plugins.d/dbus, examplesink, examplesource
+- [xwalk] vehicle extension now dynamically exports all AMB supported objects
+
+Changes:
+- Plugin create() method signature changed.
+- Removed AbstractSinkManager class
+- Removed deprecated dbus interfaces
+- Removed deprecated 'FooChanged' signal introspection description
+- Deprecated 'GetFoo' method. This doesn't contain much more information that cannot already be
+ obtained through the Properties interface.
+
+Fixes:
diff --git a/RELEASE.md b/RELEASE.md
new file mode 100644
index 00000000..73584fa5
--- /dev/null
+++ b/RELEASE.md
@@ -0,0 +1,20 @@
+AMB Release Notes
+Version: 0.13.801
+
+New features:
+- [DBus] some classes for exporting custom interfaces moved to plugins-common
+- [Bluemonkey plugin] support for creating custom dbus interfaces: bluemonkey.exportInterface()
+- [ambctl] support for enabling disabling plugins
+- [ambd] support plugins.d - now plugin segments can be stuck in there and amb will try to load all plugins that
+ are enabled. See the example segments: /etc/ambd/plugins.d/dbus, examplesink, examplesource
+- [xwalk] vehicle extension now dynamically exports all AMB supported objects
+
+Changes:
+- Plugin create() method signature changed.
+- Removed AbstractSinkManager class
+- Removed deprecated dbus interfaces
+- Removed deprecated 'FooChanged' signal introspection description
+- Deprecated 'GetFoo' method. This doesn't contain much more information that cannot already be
+ obtained through the Properties interface.
+
+Fixes:
diff --git a/TODO b/TODO
index 0cc42f1e..699abf63 100644
--- a/TODO
+++ b/TODO
@@ -1,10 +1,4 @@
-
- Refactor obd2 plugin with AsyncQueue. Use thread safe-update property.
-- update json protocol to support rangerequests with PropertyList instead of a singel property (Verify)
- source export from database plugin does not reflect the source in the database
-- no reason for pluginloader to track sources. core already does it.
-- create docs for all plugins (README)
-- handle badly formed messages properly (ie not crash) in websocketsink
- grep all the TODOs in the code and do them
-- investigate and enable use of provisioning in ssl websockets
-- enable ambd/plugins.d/
+
diff --git a/ambd/CMakeLists.txt b/ambd/CMakeLists.txt
index d1af5653..70091458 100644
--- a/ambd/CMakeLists.txt
+++ b/ambd/CMakeLists.txt
@@ -34,8 +34,7 @@ add_executable(ambd ${ambd_sources})
include_directories(${include_dirs} )
target_link_libraries(ambd ${link_libraries} dl amb)
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.in ${CMAKE_CURRENT_BINARY_DIR}/config @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.in.json ${CMAKE_CURRENT_BINARY_DIR}/config @ONLY)
install (TARGETS ambd RUNTIME DESTINATION bin)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/config DESTINATION /etc/ambd)
-
diff --git a/ambd/config.in b/ambd/config.in
deleted file mode 100644
index 850ec786..00000000
--- a/ambd/config.in
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "sources" : [
- {
- "name" : "ExampleSouce",
- "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so"
- }
- ],
- "sinks": [
- {
- "name" : "ExampleSink",
- "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
- },
- {
- "name" : "DBusSink",
- "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so"
- }
- ]
-}
-
diff --git a/ambd/config.in.json b/ambd/config.in.json
new file mode 100644
index 00000000..1e17508a
--- /dev/null
+++ b/ambd/config.in.json
@@ -0,0 +1,6 @@
+{
+ "plugins" : "@PLUGIN_SEGMENT_INSTALL_PATH@",
+ "sources" : [ ],
+ "sinks": [ ]
+}
+
diff --git a/ambd/pluginloader.cpp b/ambd/pluginloader.cpp
index e38547e1..c1e58f1e 100644
--- a/ambd/pluginloader.cpp
+++ b/ambd/pluginloader.cpp
@@ -20,16 +20,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "pluginloader.h"
#include "glibmainloop.h"
#include "core.h"
+
#include <json.h>
+#include <gio/gio.h>
+#include <picojson.h>
+
#include <iostream>
#include <stdexcept>
#include <boost/concept_check.hpp>
std::string get_file_contents(const char *filename)
{
- //FILE *in = fopen(filename,"r");
-
std::ifstream in(filename, std::ios::in);
+ if(!in.is_open())
+ {
+ DebugOut(DebugOut::Error) << "Failed to open file: " << filename << endl;
+ return "";
+ }
+
std::string output;
std::string line;
while(in.good())
@@ -43,36 +51,21 @@ std::string get_file_contents(const char *filename)
PluginLoader::PluginLoader(string configFile, int argc, char** argv): f_create(NULL), routingEngine(nullptr), mMainLoop(nullptr)
{
DebugOut()<<"Loading config file: "<<configFile<<endl;
- json_object *rootobject;
- json_tokener *tokener = json_tokener_new();
std::string configBuffer = get_file_contents(configFile.c_str());
- if(configBuffer == "")
- {
- throw std::runtime_error("No config or config empty");
- }
- enum json_tokener_error err;
- do
- {
- rootobject = json_tokener_parse_ex(tokener, configBuffer.c_str(),configBuffer.length());
- } while ((err = json_tokener_get_error(tokener)) == json_tokener_continue);
- if (err != json_tokener_success)
- {
- fprintf(stderr, "Error: %s\n", json_tokener_error_desc(err));
- // Handle errors, as appropriate for your application.
- throw std::runtime_error("Invalid config");
- }
- if (tokener->char_offset < configFile.length()) // XXX shouldn't access internal fields
+
+ std::string picojsonerr = "";
+ picojson::value v;
+ picojson::parse(v, configBuffer.begin(), configBuffer.end(), &picojsonerr);
+
+ if(!picojsonerr.empty())
{
- // Handle extra characters after parsed object as desired.
- // e.g. issue an error, parse another object from that point, etc...
+ DebugOut(DebugOut::Error) << "Failed to parse main config! " << endl;
+ throw std::runtime_error("Error parsing config");
}
- json_object *coreobject = json_object_object_get(rootobject,"routingEngine");
- if (coreobject)
+ if(v.contains("routingEngine"))
{
- /// there is a mainloop entry. Load the plugin:
-
- string restr = string(json_object_get_string(coreobject));
+ string restr = v.get("routingEngine").to_str();
routingEngine = loadRoutingEngine(restr);
@@ -90,46 +83,33 @@ PluginLoader::PluginLoader(string configFile, int argc, char** argv): f_create(N
/// core wants some specific configuration settings:
std::map<std::string,std::string> settings;
- json_object *lpq = json_object_object_get(rootobject,"lowPriorityQueueSize");
- if (lpq)
- {
- /// there is a mainloop entry. Load the plugin:
-
- string restr = string(json_object_get_string(lpq));
- settings["lowPriorityQueueSize"] = restr;
- }
-
- json_object *npq = json_object_object_get(rootobject,"normalPriorityQueueSize");
- if (npq)
- {
- /// there is a mainloop entry. Load the plugin:
-
- string restr = string(json_object_get_string(npq));
- settings["normalPriorityQueueSize"] = restr;
- }
- json_object *hpq = json_object_object_get(rootobject,"highPriorityQueueSize");
- if (hpq)
+ for (auto q : {"lowPriorityQueueSize", "normalPriorityQueueSize", "highPriorityQueueSize"})
{
- /// there is a mainloop entry. Load the plugin:
-
- string restr = string(json_object_get_string(hpq));
- settings["highPriorityQueueSize"] = restr;
+ if (v.contains(q))
+ {
+ string restr = v.get(q).to_str();
+ settings[q] = restr;
+ }
}
routingEngine = new Core(settings);
}
+ if(v.contains("plugins"))
+ {
+ std::string pluginsPath = v.get("plugins").to_str();
+ scanPluginDir(pluginsPath);
+ }
- json_object *mainloopobject = json_object_object_get(rootobject,"mainloop");
- if (mainloopobject)
+ if(v.contains("mainloop"))
{
/// there is a mainloop entry. Load the plugin:
- string mainloopstr = string(json_object_get_string(mainloopobject));
+ string mainloopstr = v.get("mainloop").to_str();
- mMainLoop = loadMainLoop(mainloopstr,argc, argv);
+ mMainLoop = loadMainLoop(mainloopstr, argc, argv);
if(!mMainLoop)
{
@@ -140,110 +120,169 @@ PluginLoader::PluginLoader(string configFile, int argc, char** argv): f_create(N
{
/// there is no mainloop entry, use default glib
DebugOut()<<"No mainloop specified in config. Using glib by default."<<endl;
- mMainLoop = new GlibMainLoop(argc,argv);
+ mMainLoop = new GlibMainLoop(argc, argv);
}
- json_object *sourcesobject = json_object_object_get(rootobject,"sources");
- if(!sourcesobject)
+ for (auto q : {"sources", "sinks"})
{
- DebugOut()<<"Error getting sources member: "<<endl;
- throw std::runtime_error("Error getting sources member");
- }
+ if(v.contains("sources"))
+ {
+ picojson::array list = v.get(q).get<picojson::array>();
+ if (!list.size())
+ {
+ DebugOut() << "Error getting list for " << q << endl;
+ throw std::runtime_error("Error getting sources list");
+ }
- //g_assert(json_reader_is_array(reader));
- g_assert(json_object_get_type(sourcesobject)==json_type_array);
+ for(auto src : list)
+ {
+ std::map<std::string, std::string> configurationMap;
+ for( auto obj : src.get<picojson::object>())
+ {
+ string valstr = obj.second.to_str();
+ string key = obj.first;
+ DebugOut() << "plugin config key: " << key << "value:" << valstr << endl;
- array_list *sourceslist = json_object_get_array(sourcesobject);
- if (!sourceslist)
- {
- DebugOut() << "Error getting source list" << endl;
- throw std::runtime_error("Error getting sources list");
- }
+ configurationMap[key] = valstr;
+ }
- for(int i=0; i < array_list_length(sourceslist); i++)
- {
- json_object *obj = (json_object*)array_list_get_idx(sourceslist,i); //This is an object
+ string path = configurationMap["path"];
- std::map<std::string, std::string> configurationMap;
- json_object_object_foreach(obj, key, val)
- {
- string valstr = json_object_get_string(val);
- DebugOut() << "plugin config key: " << key << "value:" << valstr << endl;
- configurationMap[key] = valstr;
- }
+ if(!loadPlugin(path, configurationMap))
+ DebugOut(DebugOut::Warning) << "Failed to load plugin: " << path <<endl;
+ }
- string path = configurationMap["path"];
+ }
+ }
- if(!loadPlugin(path,configurationMap))
- DebugOut(DebugOut::Warning) << "Failed to load plugin: " << path <<endl;
+ Core* core = static_cast<Core*>(routingEngine);
+ if( core != nullptr )
+ {
+ core->inspectSupported();
}
+}
- //json_object_put(sourcesobject);
- ///read the sinks:
+PluginLoader::~PluginLoader()
+{
+ for(auto handle : openHandles)
+ dlclose(handle);
+}
- json_object *sinksobject = json_object_object_get(rootobject,"sinks");
+IMainLoop *PluginLoader::mainloop()
+{
+ return mMainLoop;
+}
- if (!sinksobject)
- {
- DebugOut() << "Error getting sink object" << endl;
- throw std::runtime_error("Error getting sink object");
- }
+std::string PluginLoader::errorString()
+{
+ return mErrorString;
+}
+
+void PluginLoader::scanPluginDir(const std::string & dir)
+{
+ DebugOut() << "Scanning plugin directory: " << dir << endl;
- array_list *sinkslist = json_object_get_array(sinksobject);
+ auto pluginsDirectory = amb::make_gobject(g_file_new_for_path(dir.c_str()));
+ GError* enumerateError = nullptr;
- if (!sinkslist)
+ auto enumerator = amb::make_gobject(g_file_enumerate_children(pluginsDirectory.get(), G_FILE_ATTRIBUTE_ID_FILE,
+ G_FILE_QUERY_INFO_NONE, nullptr,
+ &enumerateError));
+ auto enumerateErrorPtr = amb::make_super(enumerateError);
+
+ if(enumerateErrorPtr)
{
- DebugOut() << "Error getting sink list" << endl;
- throw std::runtime_error("Error getting sink list");
+ DebugOut(DebugOut::Error) << "Scanning plugin directory: " << enumerateErrorPtr->message << endl;
+ return;
}
-
- for(int i=0; i < array_list_length(sinkslist); i++)
+ GError* errorGetFile = nullptr;
+ while(auto pluginConfig = amb::make_gobject(g_file_enumerator_next_file(enumerator.get(), nullptr, &errorGetFile)))
{
- json_object *obj = (json_object*)array_list_get_idx(sinkslist,i);
+ std::string name = g_file_info_get_name(pluginConfig.get());
+
+ DebugOut() << "Found file: " << name << endl;
+ std::string fullpath = dir + (boost::algorithm::ends_with(dir, "/") ? "":"/") + name;
+ std::string data = get_file_contents(fullpath.c_str());
- std::map<std::string, std::string> configurationMap;
+ DebugOut() << "data: " << data << endl;
- json_object_object_foreach(obj, key, val)
+ if(!readPluginConfig(data))
{
- string valstr = json_object_get_string(val);
- DebugOut() << "plugin config key: " << key << "value:" << valstr << endl;
- configurationMap[key] = valstr;
+ DebugOut(DebugOut::Error) << "Reading contentds of file: " << name << endl;
}
+ }
+ auto errorGetFilePtr = amb::make_super(errorGetFile);
- string path = configurationMap["path"];
+ if(errorGetFilePtr)
+ {
+ DebugOut(DebugOut::Error) << "enumerating file: " << errorGetFilePtr->message << endl;
+ return;
+ }
+}
+
+bool PluginLoader::readPluginConfig(const string &configData)
+{
+ picojson::value v;
+ std::string err;
- loadPlugin(path, configurationMap);
+ picojson::parse(v, configData.begin(), configData.end(), &err);
+
+ if (!err.empty())
+ {
+ DebugOut(DebugOut::Error) << err << endl;
+ return false;
}
- //json_object_put(sinksobject);
- json_object_put(rootobject);
- json_tokener_free(tokener);
+ std::string pluginName;
+ if(v.contains("name"))
+ {
+ pluginName = v.get("name").to_str();
+ }
- Core* core = static_cast<Core*>(routingEngine);
- if( core != nullptr )
+ std::string pluginPath;
+ if(v.contains("path"))
{
- core->inspectSupported();
+ pluginPath = v.get("path").to_str();
+ }
+ else
+ {
+ DebugOut(DebugOut::Error) << "config missing 'path'." << endl;
+ return false;
}
-}
-PluginLoader::~PluginLoader()
-{
- for(auto handle : openHandles)
- dlclose(handle);
-}
+ bool enabled = false;
+ if(v.contains("enabled"))
+ {
+ enabled = v.get("enabled").get<bool>();
+ }
+ else
+ {
+ DebugOut(DebugOut::Error) << "config missing 'enabled'." << endl;
+ return false;
+ }
-IMainLoop *PluginLoader::mainloop()
-{
- return mMainLoop;
-}
+ DebugOut() << "Plugin: " << pluginName << endl;
+ DebugOut() << "Path: " << pluginPath << endl;
+ DebugOut() << "Enabled: " << enabled << endl;
-std::string PluginLoader::errorString()
-{
- return mErrorString;
+ if(enabled)
+ {
+ std::map<std::string, std::string> otherConfig;
+
+ picojson::object obj = v.get<picojson::object>();
+ for(auto itr : obj)
+ {
+ otherConfig[itr.first] = itr.second.to_str();
+ }
+
+ loadPlugin(pluginPath, otherConfig);
+ }
+
+ return true;
}
diff --git a/ambd/pluginloader.h b/ambd/pluginloader.h
index fb2494da..7700feed 100644
--- a/ambd/pluginloader.h
+++ b/ambd/pluginloader.h
@@ -30,9 +30,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "debugout.h"
#include "imainloop.h"
-
-using namespace std;
-
typedef void create_t(AbstractRoutingEngine*, map<string, string> );
typedef void* create_mainloop_t(int argc, char** argv);
typedef void* createRoutingEngine(void);
@@ -41,17 +38,21 @@ class PluginLoader
{
public:
- PluginLoader(string configFile, int argc, char** argv);
+ PluginLoader(std::string configFile, int argc, char** argv);
~PluginLoader();
IMainLoop* mainloop();
std::string errorString();
+ void scanPluginDir(const std::string &);
+
+ bool readPluginConfig(const std::string & configData);
private: ///methods:
- bool loadPlugin(string pluginName, map<string, string> config)
+
+ bool loadPlugin(string pluginName, std::map<std::string, std::string> config)
{
DebugOut()<<"Loading plugin: "<<pluginName<<endl;
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
index 445856cf..66c97726 100644
--- a/docs/CMakeLists.txt
+++ b/docs/CMakeLists.txt
@@ -33,4 +33,6 @@ endif(enable_docs)
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/amb.in.fidl ${CMAKE_CURRENT_SOURCE_DIR}/amb.fidl @ONLY)
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/mainpage.in.idl ${CMAKE_CURRENT_SOURCE_DIR}/mainpage.idl @ONLY)
-
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/ambd-configuration.in.idl ${CMAKE_CURRENT_SOURCE_DIR}/ambd-configuration.idl @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/ambd.in.md ${CMAKE_CURRENT_SOURCE_DIR}/ambd.md @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/ambd.in.md ${CMAKE_SOURCE_DIR}/README.md @ONLY)
diff --git a/docs/Doxyfile.mainpage.in b/docs/Doxyfile.mainpage.in
index bb8e6882..10fc0604 100644
--- a/docs/Doxyfile.mainpage.in
+++ b/docs/Doxyfile.mainpage.in
@@ -1,4 +1,4 @@
PROJECT_NAME = @PROJECT_NAME@
PROJECT_NUMBER = @PROJECT_VERSION@
-INPUT = @CMAKE_SOURCE_DIR@/docs/mainpage.idl
+INPUT = @CMAKE_SOURCE_DIR@/docs/mainpage.idl @CMAKE_SOURCE_DIR@/docs/ambd-configuration.idl @CMAKE_SOURCE_DIR@/docs/ambd.md @CMAKE_SOURCE_DIR@/RELEASE.md
IMAGE_PATH = @CMAKE_SOURCE_DIR@/docs/images
diff --git a/docs/amb.in.fidl b/docs/amb.in.fidl
index d0381900..2fd78306 100644
--- a/docs/amb.in.fidl
+++ b/docs/amb.in.fidl
@@ -1,5 +1,8 @@
/*!
* \mainpage Automotive Message Broker DBus API Documentation
+* \version @PROJECT_VERSION@
+*
+* <a href="../../html/index.html">Back to AMB Documentation Main</a>
*
* \section intro Introduction
* AMB organizes the API into two general interface categories. First the Manager interface (see manager.txt)
@@ -113,6 +116,27 @@ map Dictionary {
}
/*!
+ * \brief HistoryObject is returned with GetHistory call
+ */
+interface HistoryObject {
+
+ /*!
+ * \brief Name of property
+ */
+ attribute String Name readonly
+
+ /*!
+ * \brief Value of property
+ */
+ attribute Variant Value readonly
+
+ /*!
+ * \brief Time in seconds since unix epoch.
+ */
+ attribute Double Time readonly
+}
+
+/*!
* VehiclePropertyType
* \brief VehiclePropertyType is the base class for all Data types.
*/
@@ -135,7 +159,7 @@ interface VehiclePropertyType {
* \arg endTime time stamp in Seconds since Unix Epoc
*/
method GetHistory(Double beginTime, Double endTime) {
- out{ Dictionary result}
+ out{ array of HistoryObject result }
}
}
diff --git a/docs/ambd-configuration.in.idl b/docs/ambd-configuration.in.idl
new file mode 100644
index 00000000..253459d9
--- /dev/null
+++ b/docs/ambd-configuration.in.idl
@@ -0,0 +1,84 @@
+/*!
+ * \file ambd-configuration.idl
+ * \brief This document describes the ambd (AMB daemon) configuration.
+ * This file is typically located as "/etc/ambd/config". Plugin segments are supported as of 0.14 and should be installed in "@PLUGIN_SEGMENT_INSTALL_PATH@".
+ * \section example Configuration Example
+ * \code
+ * {
+ * "plugins" : "@PLUGIN_SEGMENT_INSTALL_PATH@",
+ * "sources" : [ ],
+ * "sinks": [ ]
+ * }
+ * \endcode
+ */
+
+/*!
+ * \brief Config object is the root JSON object in the config.
+ */
+interface Config {
+
+ /*!
+ * \brief plugins - path to plugin segments.
+ * The AMB Daemon will scan this path for any plugin configuration segments and load them if enabled.
+ */
+ readonly attribute DOMString plugins;
+
+ /*!
+ * \brief mainloop - path to mainloop plugin.
+ * The mainloop plugin is by default glib. AMB also provides a qt-based mainloop so plugins that use Qt mainloop features can be used.
+ */
+ readonly attribute DOMString mainloop;
+
+ /*!
+ * \brief source plugins.
+ * *depricated*. Use plugin configuration segments placed in @PLUGIN_SEGMENT_INSTALL_PATH@.
+ * Plugins defined here will be loaded by AMB.
+ */
+ readonly attribute Plugin[] sources;
+
+ /*!
+ * \brief sink plugins.
+ * *depricated*. Use plugin configuration segments placed in @PLUGIN_SEGMENT_INSTALL_PATH@.
+ * Plugins defined here will be loaded by AMB.
+ */
+ readonly attribute Plugin[] sinks;
+
+}
+
+/*!
+ * \brief the Plugin interface describes the configuration for a plugin.
+ * This interface may be extended with plugin specific options. See the specific plugin's documentation for information on extended attributes.
+ */
+interface Plugin {
+
+ /*!
+ * \brief name of plugin (ie 'ExamplePlugin')
+ */
+ readonly attribute DOMString name;
+
+ /*!
+ * \brief path to the plugins .so file (ie @PLUGIN_INSTALL_PATH@/examplesourceplugin.so)
+ */
+ readonly attribute DOMString path;
+}
+
+/*!
+ * \brief PluginSegment root object for plugin segments.
+ * PluginSegment inherits the attributes from Plugin and adds the "enabled" attribute.
+ * Only plugins that have 'enabled' : true will be loaded by the AMB daemon. PluginSements are usually installed
+ * in @PLUGIN_SEGMENT_INSTALL_PATH@. The following is a basic example of a plugin segment configuration:
+ * \code
+ * {
+ * "name" : "MyPlugin",
+ * "path" : "@PLUGIN_INSTALL_PATH@/myplugin.so",
+ * "enabled" : false
+ * }
+ * \endcode
+ */
+interface PluginSegment : Plugin {
+
+ /*!
+ * \brief enabled - returns true if the plugin is enabled or not.
+ */
+ readonly attribute boolean? enabled;
+}
diff --git a/docs/ambd.in.md b/docs/ambd.in.md
new file mode 100644
index 00000000..bdfe0b08
--- /dev/null
+++ b/docs/ambd.in.md
@@ -0,0 +1,76 @@
+# Automotive Message Broker
+
+Version @PROJECT_VERSION@
+
+## Introduction
+
+Automotive Message Broker is a vehicle network abstraction system. It brokers information from the vehicle
+to applications. It provides application with a rich API for accessing vehicle data.
+
+Automotive Message Broker is built using CMake and requires libltdl (libtool), libjson-c, and boost packages.
+
+## Git
+About the Git Tree:
+master is expected to be unstable and may not even compile. If you want something more stable, checkout one of the
+release branches (ie, 0.9.0, 0.10, etc)
+
+## Building
+
+To build:
+
+~~~~~~~~~~~~~{.bash}
+cd automotive-message-broker
+mkdir build
+cd build
+cmake ..
+make
+~~~~~~~~~~~~~
+
+## Installing
+
+To install:
+
+~~~~~~~~~~~~~{.bash}
+sudo make install
+~~~~~~~~~~~~~
+
+## Running
+To run:
+
+~~~~~~~~~~~~~{.bash}
+ambd
+~~~~~~~~~~~~~
+
+*also see **ambd -h** for additional command line options*
+
+## Configuration
+
+For information on ambd's configuration, please see ambd-configuration.idl.
+
+## Running with the Qt mainloop:
+
+Some source and sink plugins may want to use the Qt-based mainloop to take advantage of Qt features. To enable
+the Qt mainloop, run cmake with -Duse_qtcore=On:
+
+~~~~~~~~~~~~~{.bash}
+cmake .. -Dqtmainloop=On
+~~~~~~~~~~~~~
+
+You will also need to edit your config to enable the Qt-based mainloop:
+
+~~~~~~~~~~~~~{.json}
+{
+ "mainloop" : "@PLUGIN_INSTALL_PATH@/qtmainloopplugin.so",
+ "plugins" : "@PLUGIN_SEGMENT_INSTALL_PATH@"
+}
+~~~~~~~~~~~~~
+
+NOTE: by default the glib mainloop will be used.
+
+## Questions/Issues/Comments:
+
+Questions or Comments can be emailed to the amb mailing list:
+**amb at lists.01.org**
+
+Issues and Feature requests can be submitted on our github page:
+https://github.com/otcshare/automotive-message-broker/issues
diff --git a/docs/libamb.in b/docs/libamb.in
index ace28a9e..f2197dd5 100644
--- a/docs/libamb.in
+++ b/docs/libamb.in
@@ -1,6 +1,9 @@
-/**
+/*!
\mainpage Automotive Message Broker Library Documentation
\version @PROJECT_VERSION@
+
+ <a href="../../html/index.html">Back to AMB Documentation Main</a>
+
\section intro Introduction
Automotive Message Broker (AMB) Library documentation outlines the internal classes and structures for building
plugins for AMB.
diff --git a/docs/mainpage.in.idl b/docs/mainpage.in.idl
index 0e29a6f1..186438ec 100644
--- a/docs/mainpage.in.idl
+++ b/docs/mainpage.in.idl
@@ -2,13 +2,45 @@
* \mainpage Automotive Message Broker Documentation
* \version @PROJECT_VERSION@
* \section links AMB Documentation Sections
-* - <a href="../dbus/html/index.html">DBus API documentation</a>
-* - <a href="../amb/html/index.html">libamb internal API documentation</a>
+* - \ref ambd.md - AMB Daemon Documentation
+* - <a href="../dbus/html/index.html">DBus API documentation</a> - Using AMB with your application
+* - <a href="../amb/html/index.html">libamb internal API documentation</a> - Developing AMB or AMB plugins
* - <a href="../plugins/bluemonkey/html/index.html">Bluemonkey Javascript API documentation</a>
+* - <a href="../plugins/websocket/html/index.html">AMB Websocket protocol documentation</a>
+* - \ref RELEASE.md - Current release notes
*
* \section intro Introduction
* Automotive Message Broker (AMB) is a framework for providing applications with standardized access to vehicle data.
* It uses a plugin architecture to allow customization for different vehicles and devices. Here is a diagram of how
* AMB is architected:
* \image html AMBArchitecture.png
+* AMB works by passing "Properties" from "source" plugins to interested "sink" plugins. These properties represent
+* vehicle data, ie 'VehicleSpeed' represents the vehicle's ground velocity.
+*
+* In General, AMB "source" plugins produce data and AMB "sink" plugins consume them. However, it is possible that a
+* source can also consumes data. AMB supports multiple simultaneous source and sink plugins. This allows for aggregation
+* from multiple vehicle networks, the cloud, or even from other instances of AMB running elsewhere (via the websocket
+* plugins).
+*
+* More information about AMB plugins can be found in the <a href="../amb/html/index.html">library documentation</a>.
+* \section plugins AMB Plugins
+* AMB plugins each have their own usage documentation including any special Properties they define. Below is a description
+* of several AMB plugins and their documenation:
+* - <a href="../plugins/bluemonkey.README">Bluemonkey</a> - Extensible javascript engine plugin for defining plugin behavior in javascript
+* - <a href="../plugins/database.README">Database</a> - Plugin that logs data in a sqlite database and can play back logs
+* - <a href="../plugins/dbus.README">DBus</a> - Exposes AMB Properties on DBus
+* - <a href="../plugins/gpsnmea.README">GPSNmea</a> - GPS Plugin that provides location position data from NMEA compatible devices
+* - <a href="../plugins/obd2.README">OBD-II</a> - Plugin that provides data from OBD-II compatible vehicles
+* - <a href="../plugins/opencvlux.README">OpenCVLux</a> - Plugin that uses OpenCV to produce ADAS data and perform video logging
+* - <a href="../plugins/websocket.README">Websocket</a> - Both source and sink plugin that uses a websocket protocol to communicate
+* - <a href="../plugins/wheel.README">Wheel</a> - Plugin that generates data using the Logitech G27 racing wheel
+* \section crosswalk Crosswalk Vehicle Extension
+* AMB also comes with a <a href="http://crosswalk-project.org">crosswalk</a> extension that implements the W3C Automotive Business group
+* <a href="https://rawgit.com/w3c/automotive-bg/master/vehicle_spec.html">vehicle</a> and <a href="https://rawgit.com/w3c/automotive-bg/master/data_spec.html">data</a> specifications.
+* \section licensing Licensing
+* AMB is licensed LGPL v2. This allows the creation of proprietary plugins.
+* \section previous_versions Previous Versions
+* - <a href="../../0.13/index.html">0.13</a>
+* - <a href="../../0.12/docs/amb/html/index.html">0.12 library Documentation</a>
+* - <a href="../../0.12/docs/dbus/html/index.html">0.12 DBus API Documentation</a>
*/
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 54cea0b6..1100120c 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,21 +1,34 @@
-set(amb_examples configwheel databasesource dbusconfig exampleconfig
- gpsnmea obdsourceconfig opencvluxconfig opencvdbusconfig qtmainloopconfig websocketsink2 websocketsource2
- testsourceconfig bluemonkey/bluemonkeyconfig)
+set(amb_examples ${CMAKE_CURRENT_BINARY_DIR}/configwheel
+ ${CMAKE_CURRENT_BINARY_DIR}/databasesource
+ ${CMAKE_CURRENT_BINARY_DIR}/dbusconfig
+ ${CMAKE_CURRENT_BINARY_DIR}/exampleconfig
+ ${CMAKE_CURRENT_BINARY_DIR}/gpsnmea
+ ${CMAKE_CURRENT_BINARY_DIR}/obdsourceconfig
+ ${CMAKE_CURRENT_BINARY_DIR}/opencvluxconfig
+ ${CMAKE_CURRENT_BINARY_DIR}/opencvdbusconfig
+ ${CMAKE_CURRENT_BINARY_DIR}/qtmainloopconfig
+ ${CMAKE_CURRENT_BINARY_DIR}/websocketsink2
+ ${CMAKE_CURRENT_BINARY_DIR}/websocketsource2
+ ${CMAKE_CURRENT_BINARY_DIR}/testsourceconfig
+ ${CMAKE_CURRENT_BINARY_DIR}/bluemonkey/bluemonkeyconfig)
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/configwheel.in ${CMAKE_CURRENT_SOURCE_DIR}/configwheel @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)
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/gpsnmea.in ${CMAKE_CURRENT_SOURCE_DIR}/gpsnmea @ONLY)
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/obdsourceconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/obdsourceconfig @ONLY)
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/opencvluxconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/opencvluxconfig @ONLY)
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/opencvdbusconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/opencvdbusconfig @ONLY)
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/qtmainloopconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/qtmainloopconfig @ONLY)
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/websocketsink2.in ${CMAKE_CURRENT_SOURCE_DIR}/websocketsink2 @ONLY)
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/websocketsource2.in ${CMAKE_CURRENT_SOURCE_DIR}/websocketsource2 @ONLY)
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/testsourceconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/testsourceconfig @ONLY)
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cangenconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/cangenconfig @ONLY)
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/bluemonkey/bluemonkeyconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/bluemonkey/bluemonkeyconfig @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/configwheel.in.json ${CMAKE_CURRENT_BINARY_DIR}/configwheel @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/databasesource.in.json ${CMAKE_CURRENT_BINARY_DIR}/databasesource @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/databaselogging.in.json ${CMAKE_CURRENT_BINARY_DIR}/databaselogging @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/dbusconfig.in.json ${CMAKE_CURRENT_BINARY_DIR}/dbusconfig @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/exampleconfig.in.json ${CMAKE_CURRENT_BINARY_DIR}/exampleconfig @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/gpsnmea.in.json ${CMAKE_CURRENT_BINARY_DIR}/gpsnmea @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/obdsourceconfig.in.json ${CMAKE_CURRENT_BINARY_DIR}/obdsourceconfig @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/opencvluxconfig.in.json ${CMAKE_CURRENT_BINARY_DIR}/opencvluxconfig @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/opencvdbusconfig.in.json ${CMAKE_CURRENT_BINARY_DIR}/opencvdbusconfig @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/qtmainloopconfig.in.json ${CMAKE_CURRENT_BINARY_DIR}/qtmainloopconfig @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/websocketsink2.in.json ${CMAKE_CURRENT_BINARY_DIR}/websocketsink2 @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/websocketsource2.in.json ${CMAKE_CURRENT_BINARY_DIR}/websocketsource2 @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/databasewebsocketsink.in.json ${CMAKE_CURRENT_BINARY_DIR}/databasewebsocketsink @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/testsourceconfig.in.json ${CMAKE_CURRENT_BINARY_DIR}/testsourceconfig @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cangenconfig.in.json ${CMAKE_CURRENT_BINARY_DIR}/cangenconfig @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/bluemonkey/bluemonkeyconfig.in.json ${CMAKE_CURRENT_BINARY_DIR}/bluemonkey/bluemonkeyconfig @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/testplugins.d.in.json ${CMAKE_CURRENT_SOURCE_DIR}/testplugins.d.json @ONLY)
install (FILES ${amb_examples} DESTINATION /etc/ambd/examples)
diff --git a/examples/bluemonkey/bluemonkeyconfig.in b/examples/bluemonkey/bluemonkeyconfig.in
deleted file mode 100644
index 0ba2c813..00000000
--- a/examples/bluemonkey/bluemonkeyconfig.in
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "mainloop" : "@PLUGIN_INSTALL_PATH@/qtmainloopplugin.so",
-
- "sources" : [
- {
- "path" : "@PLUGIN_INSTALL_PATH@/bluemonkeyplugin.so",
- "config" : "/etc/ambd/bluemonkey/config.js"
- }
- ],
-
- "sinks" : [
-
- {
- "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
- },
- {
- "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so"
- }
- ]
-}
-
diff --git a/examples/bluemonkey/bluemonkeyconfig.in.json b/examples/bluemonkey/bluemonkeyconfig.in.json
new file mode 100644
index 00000000..ea92a3dc
--- /dev/null
+++ b/examples/bluemonkey/bluemonkeyconfig.in.json
@@ -0,0 +1,18 @@
+{
+ "mainloop" : "@PLUGIN_INSTALL_PATH@/qtmainloopplugin.so",
+ "sources" : [
+ {
+ "path" : "@PLUGIN_INSTALL_PATH@/bluemonkeyplugin.so",
+ "config" : "/etc/ambd/bluemonkey/config.js"
+ }
+ ],
+ "sinks" : [
+ {
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
+ },
+ {
+ "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so"
+ }
+ ]
+}
+
diff --git a/examples/cangenconfig.in b/examples/cangenconfig.in.json
index 81add2cb..9886c7a9 100644
--- a/examples/cangenconfig.in
+++ b/examples/cangenconfig.in.json
@@ -1,11 +1,11 @@
{
- "sources" : [
+ "sources" : [
{
"name" : "CANSimPlugin",
"path":"@PLUGIN_INSTALL_PATH@/cansimplugin.so",
"interfaces" : ["vcan0", "vcan1"]
- },
- {
+ },
+ {
"name" : "CANGenPlugin",
"path":"@PLUGIN_INSTALL_PATH@/cangenplugin.so"
}
diff --git a/examples/configwheel.in b/examples/configwheel.in
deleted file mode 100644
index ebd9335e..00000000
--- a/examples/configwheel.in
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "sources" : [
- {
- "name" : "WheelSource",
- "path" : "@PLUGIN_INSTALL_PATH@/wheelsourceplugin.so",
- "device" : "/dev/input/js0"
- }
- ],
- "sinks": [
- {
- "name" : "DBusSink",
- "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so"
- }
- ]
-}
-
diff --git a/examples/configwheel.in.json b/examples/configwheel.in.json
new file mode 100644
index 00000000..2bef1ed2
--- /dev/null
+++ b/examples/configwheel.in.json
@@ -0,0 +1,16 @@
+{
+ "sources" : [
+ {
+ "name" : "WheelSource",
+ "path" : "@PLUGIN_INSTALL_PATH@/wheelsourceplugin.so",
+ "device" : "/dev/input/js0"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "DBusSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so"
+ }
+ ]
+}
+
diff --git a/examples/databaselogging.in.json b/examples/databaselogging.in.json
new file mode 100644
index 00000000..1f76e0f5
--- /dev/null
+++ b/examples/databaselogging.in.json
@@ -0,0 +1,28 @@
+{
+ "sources" : [
+ {
+ "name" : "ExampleSouce",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so",
+ "delay" : "1000"
+ },
+ {
+ "name" : "Database Source",
+ "path" : "@PLUGIN_INSTALL_PATH@/databasesinkplugin.so",
+ "properties" : "{ 'properties' : ['VehicleSpeed','EngineSpeed'] }",
+ "startOnLoad" : "true",
+ "databaseFile" : "/tmp/storage",
+ "frequency" : "1",
+ "bufferLength" : "1"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "ExampleSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
+ },
+ {
+ "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so"
+ }
+ ]
+}
+
diff --git a/examples/databasesource.in b/examples/databasesource.in
deleted file mode 100644
index 69ab8cb9..00000000
--- a/examples/databasesource.in
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "sources" : [
- {
- "name" : "Database Source",
- "path" : "@PLUGIN_INSTALL_PATH@/databasesinkplugin.so",
- "playbackOnLoad" : "true",
- "databaseFile" : "/tmp/storage"
- }
- ],
- "sinks": [
- {
- "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so"
- }
- ]
-}
-
diff --git a/examples/databasesource.in.json b/examples/databasesource.in.json
new file mode 100644
index 00000000..cc21c85e
--- /dev/null
+++ b/examples/databasesource.in.json
@@ -0,0 +1,16 @@
+{
+ "sources" : [
+ {
+ "name" : "Database Source",
+ "path" : "@PLUGIN_INSTALL_PATH@/databasesinkplugin.so",
+ "playbackOnLoad" : "true",
+ "databaseFile" : "/tmp/storage"
+ }
+ ],
+ "sinks": [
+ {
+ "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so"
+ }
+ ]
+}
+
diff --git a/examples/databasewebsocketsink.in.json b/examples/databasewebsocketsink.in.json
new file mode 100644
index 00000000..54b8bf76
--- /dev/null
+++ b/examples/databasewebsocketsink.in.json
@@ -0,0 +1,29 @@
+{
+ "sources" : [
+ {
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so"
+ },
+ {
+ "name" : "Database",
+ "path" : "@PLUGIN_INSTALL_PATH@/databasesinkplugin.so",
+ "databaseFile" : "../tests/generated.db",
+ "bufferLength" : "1",
+ "properties" : "{ 'properties' : ['VehicleSpeed','EngineSpeed'] }",
+ "startOnLoad" : "true",
+ "playbackOnLoad" : "false",
+ "playbackMultiplier" : "1",
+ "frequency" : "1"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "WebSocketSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/websocketsink.so",
+ "interface" : "lo",
+ "ssl" : "false",
+ "port" : "23000",
+ "binaryProtocol" : "false",
+ "useExtensions" : "true"
+ }
+ ]
+}
diff --git a/examples/dbusconfig.in b/examples/dbusconfig.in
deleted file mode 100644
index 22ebc564..00000000
--- a/examples/dbusconfig.in
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "sources" : [
- {
- "name" : "ExampleSouce",
- "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so",
- "delay" : "6"
- }
- ],
- "sinks": [
- {
- "name" : "DBusSink",
- "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so",
- "frequency" : "30"
- }
-
- ]
-}
-
diff --git a/examples/dbusconfig.in.json b/examples/dbusconfig.in.json
new file mode 100644
index 00000000..d554f4f5
--- /dev/null
+++ b/examples/dbusconfig.in.json
@@ -0,0 +1,18 @@
+{
+ "sources" : [
+ {
+ "name" : "ExampleSouce",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so",
+ "delay" : "6"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "DBusSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so",
+ "frequency" : "30"
+ }
+
+ ]
+}
+
diff --git a/examples/exampleconfig.in b/examples/exampleconfig.in
deleted file mode 100644
index f6c3520a..00000000
--- a/examples/exampleconfig.in
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "sources" : [
- {
- "name" : "ExampleSouce",
- "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so",
- "delay" : "1"
- }
- ],
- "sinks": [
- {
- "name" : "ExampleSink",
- "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
- }
- ]
-}
-
diff --git a/examples/exampleconfig.in.json b/examples/exampleconfig.in.json
new file mode 100644
index 00000000..fef96698
--- /dev/null
+++ b/examples/exampleconfig.in.json
@@ -0,0 +1,16 @@
+{
+ "sources" : [
+ {
+ "name" : "ExampleSouce",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so",
+ "delay" : "1"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "ExampleSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
+ }
+ ]
+}
+
diff --git a/examples/gpsnmea.in b/examples/gpsnmea.in
deleted file mode 100644
index 95f5602a..00000000
--- a/examples/gpsnmea.in
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "sources" : [
- {
- "name" : "gps nmea plugin",
- "path" : "@PLUGIN_INSTALL_PATH@/gpsnmea.so",
- "test" : "true",
- "device" : "/dev/ttyACM0"
- }
- ],
- "sinks": [
- {
- "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so"
- }
- ]
-}
-
diff --git a/examples/gpsnmea.in.json b/examples/gpsnmea.in.json
new file mode 100644
index 00000000..de4a93ab
--- /dev/null
+++ b/examples/gpsnmea.in.json
@@ -0,0 +1,16 @@
+{
+ "sources" : [
+ {
+ "name" : "gps nmea plugin",
+ "path" : "@PLUGIN_INSTALL_PATH@/gpsnmea.so",
+ "test" : "true",
+ "device" : "/dev/ttyACM0"
+ }
+ ],
+ "sinks": [
+ {
+ "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so"
+ }
+ ]
+}
+
diff --git a/examples/obdsourceconfig.in b/examples/obdsourceconfig.in
deleted file mode 100644
index 57f4aa2a..00000000
--- a/examples/obdsourceconfig.in
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "sources" : [
- {
- "name" : "OBD2Source",
- "path" : "@PLUGIN_INSTALL_PATH@/obd2sourceplugin.so",
- "device" : "/dev/pts/5",
- "baud" : "115200",
- "bluetoothAdapter" : ""
- }
- ],
- "sinks": [
- {
- "name" : "ExampleSink",
- "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
- }
- ]
-}
-
diff --git a/examples/obdsourceconfig.in.json b/examples/obdsourceconfig.in.json
new file mode 100644
index 00000000..1c28ebfe
--- /dev/null
+++ b/examples/obdsourceconfig.in.json
@@ -0,0 +1,18 @@
+{
+ "sources" : [
+ {
+ "name" : "OBD2Source",
+ "path" : "@PLUGIN_INSTALL_PATH@/obd2sourceplugin.so",
+ "device" : "/dev/pts/5",
+ "baud" : "115200",
+ "bluetoothAdapter" : ""
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "ExampleSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
+ }
+ ]
+}
+
diff --git a/examples/opencvdbusconfig.in b/examples/opencvdbusconfig.in
deleted file mode 100644
index 7634c755..00000000
--- a/examples/opencvdbusconfig.in
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "mainloop" : "@PLUGIN_INSTALL_PATH@/qtmainloopplugin.so",
- "sources" : [
- {
- "name" : "OpenCV LUX",
- "path" : "@PLUGIN_INSTALL_PATH@/opencvluxplugin.so",
- "threaded" : "true",
- "opencl" : "true",
- "fps" : "30",
- "pixelLowerBound" : "18",
- "pixelUpperBound" : "255",
- "device" : "0",
- "codec" : "h264",
- "logging" : "false",
- "logfile" : "/tmp/video.avi",
- "ddd" : "true",
- "faceCascade" : "/usr/share/OpenCV/lbpcascades/lbpcascade_frontalface.xml",
- "eyeCascade" : "/usr/share/OpenCV/haarcascades/haarcascade_eye_tree_eyeglasses.xml"
- },
- {
- "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so"
- }
- ],
- "sinks": [
- {
- "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so",
- },
- ]
-}
-
diff --git a/examples/opencvdbusconfig.in.json b/examples/opencvdbusconfig.in.json
new file mode 100644
index 00000000..c1e4642c
--- /dev/null
+++ b/examples/opencvdbusconfig.in.json
@@ -0,0 +1,30 @@
+{
+ "mainloop" : "@PLUGIN_INSTALL_PATH@/qtmainloopplugin.so",
+ "sources" : [
+ {
+ "name" : "OpenCV LUX",
+ "path" : "@PLUGIN_INSTALL_PATH@/opencvluxplugin.so",
+ "threaded" : "true",
+ "opencl" : "true",
+ "fps" : "30",
+ "pixelLowerBound" : "18",
+ "pixelUpperBound" : "255",
+ "device" : "0",
+ "codec" : "h264",
+ "logging" : "false",
+ "logfile" : "/tmp/video.avi",
+ "ddd" : "true",
+ "faceCascade" : "/usr/share/OpenCV/lbpcascades/lbpcascade_frontalface.xml",
+ "eyeCascade" : "/usr/share/OpenCV/haarcascades/haarcascade_eye_tree_eyeglasses.xml"
+ },
+ {
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so"
+ }
+ ],
+ "sinks": [
+ {
+ "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so",
+ },
+ ]
+}
+
diff --git a/examples/opencvluxconfig.in b/examples/opencvluxconfig.in
deleted file mode 100644
index b6860614..00000000
--- a/examples/opencvluxconfig.in
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "mainloop" : "@PLUGIN_INSTALL_PATH@/qtmainloopplugin.so",
- "sources" : [
- {
- "name" : "OpenCV Lux plugin",
- "path" : "@PLUGIN_INSTALL_PATH@/opencvluxplugin.so",
- "threaded" : "true",
- "kinect" : "false",
- "opencl" : "false",
- "cuda" : "true",
- "pixelLowerBound" : "0",
- "pixelUpperBound" : "255",
- "fps" : "30",
- "device" : "0"
- }
- ],
- "sinks": [
- {
- "name" : "Example sink",
- "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
- }
- ]
-}
-
diff --git a/examples/opencvluxconfig.in.json b/examples/opencvluxconfig.in.json
new file mode 100644
index 00000000..7ca298a0
--- /dev/null
+++ b/examples/opencvluxconfig.in.json
@@ -0,0 +1,24 @@
+{
+ "mainloop" : "@PLUGIN_INSTALL_PATH@/qtmainloopplugin.so",
+ "sources" : [
+ {
+ "name" : "OpenCV Lux plugin",
+ "path" : "@PLUGIN_INSTALL_PATH@/opencvluxplugin.so",
+ "threaded" : "true",
+ "kinect" : "false",
+ "opencl" : "false",
+ "cuda" : "true",
+ "pixelLowerBound" : "0",
+ "pixelUpperBound" : "255",
+ "fps" : "30",
+ "device" : "0"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "Example sink",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
+ }
+ ]
+}
+
diff --git a/examples/qtmainloopconfig.in b/examples/qtmainloopconfig.in
deleted file mode 100644
index 99a01542..00000000
--- a/examples/qtmainloopconfig.in
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "mainloop" : "@PLUGIN_INSTALL_PATH@/qtmainloopplugin.so",
- "sources" : [
- {
- "name" : "ExampleSouce",
- "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so"
- }
- ],
- "sinks": [
- {
- "name" : "Example sink",
- "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so",
- "interface" : "lo",
- "port" : "23000"
- }
- ]
-}
-
diff --git a/examples/qtmainloopconfig.in.json b/examples/qtmainloopconfig.in.json
new file mode 100644
index 00000000..fb959265
--- /dev/null
+++ b/examples/qtmainloopconfig.in.json
@@ -0,0 +1,18 @@
+{
+ "mainloop" : "@PLUGIN_INSTALL_PATH@/qtmainloopplugin.so",
+ "sources" : [
+ {
+ "name" : "ExampleSouce",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "Example sink",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so",
+ "interface" : "lo",
+ "port" : "23000"
+ }
+ ]
+}
+
diff --git a/examples/testplugins.d.in.json b/examples/testplugins.d.in.json
new file mode 100644
index 00000000..8fb41c76
--- /dev/null
+++ b/examples/testplugins.d.in.json
@@ -0,0 +1,4 @@
+{
+ "plugins" : "/home/kev/src/automotive-message-broker/examples/plugins.d"
+}
+
diff --git a/examples/testsourceconfig.in b/examples/testsourceconfig.in
deleted file mode 100644
index 01029c0d..00000000
--- a/examples/testsourceconfig.in
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "sources" : [
- {
- "name" : "TestPlugin",
- "path" : "@PLUGIN_INSTALL_PATH@/testplugin.so"
- }
- ],
- "sinks": [
- {
- "name" : "ExampleSink",
- "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
- }
- ]
-}
-
diff --git a/examples/testsourceconfig.in.json b/examples/testsourceconfig.in.json
new file mode 100644
index 00000000..6af6118e
--- /dev/null
+++ b/examples/testsourceconfig.in.json
@@ -0,0 +1,15 @@
+{
+ "sources" : [
+ {
+ "name" : "TestPlugin",
+ "path" : "@PLUGIN_INSTALL_PATH@/testplugin.so"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "ExampleSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
+ }
+ ]
+}
+
diff --git a/examples/websocketsink2.in b/examples/websocketsink2.in
deleted file mode 100644
index b326dbba..00000000
--- a/examples/websocketsink2.in
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "sources" : [
- {
- "name" : "ExampleSouce",
- "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so",
- "delay" : "10000"
- }
- ],
- "sinks": [
- {
- "name" : "WebSocketSink",
- "path" : "@PLUGIN_INSTALL_PATH@/websocketsink.so",
- "interface" : "eth1",
- "ssl" : "false",
- "port" : "23000",
- "binaryProtocol" : "false",
- "useExtensions" : "true"
- }
- ]
-}
-
diff --git a/examples/websocketsink2.in.json b/examples/websocketsink2.in.json
new file mode 100644
index 00000000..f74ab5d7
--- /dev/null
+++ b/examples/websocketsink2.in.json
@@ -0,0 +1,21 @@
+{
+ "sources" : [
+ {
+ "name" : "ExampleSouce",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so",
+ "delay" : "10000"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "WebSocketSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/websocketsink.so",
+ "interface" : "eth1",
+ "ssl" : "false",
+ "port" : "23000",
+ "binaryProtocol" : "false",
+ "useExtensions" : "true"
+ }
+ ]
+}
+
diff --git a/examples/websocketsource2.in b/examples/websocketsource2.in
deleted file mode 100644
index 053b1ab8..00000000
--- a/examples/websocketsource2.in
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "sources" : [
- {
- "name" : "WebsocketSource",
- "path" : "@PLUGIN_INSTALL_PATH@/websocketsource.so",
- "port" : "23000",
- "ssl" : "false",
- "ip" : "127.0.0.1",
- "binaryProtocol" : "false",
- "useExtensions" : "true"
- }
- ],
- "sinks": [
- {
- "name" : "DBusSink",
- "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so"
- },
- {
- "name" : "ExampleSink",
- "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
- }
- ]
-}
-
diff --git a/examples/websocketsource2.in.json b/examples/websocketsource2.in.json
new file mode 100644
index 00000000..e072f58d
--- /dev/null
+++ b/examples/websocketsource2.in.json
@@ -0,0 +1,24 @@
+{
+ "sources" : [
+ {
+ "name" : "WebsocketSource",
+ "path" : "@PLUGIN_INSTALL_PATH@/websocketsource.so",
+ "port" : "23000",
+ "ssl" : "false",
+ "ip" : "127.0.0.1",
+ "binaryProtocol" : "false",
+ "useExtensions" : "true"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "DBusSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so"
+ },
+ {
+ "name" : "ExampleSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
+ }
+ ]
+}
+
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 0b41a490..b479aaf4 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -1,5 +1,5 @@
-set(amb_sources abstractpropertytype.cpp abstractroutingengine.cpp listplusplus.cpp abstractsink.cpp vehicleproperty.cpp abstractsource.cpp debugout.cpp timestamp.cpp uuidhelper.cpp mappropertytype.hpp propertyinfo.hpp superptr.hpp asyncqueue.hpp ambpluginimpl.cpp ambplugin.h)
-set(amb_headers_install abstractpropertytype.h nullptr.h abstractroutingengine.h listplusplus.h abstractsink.h vehicleproperty.h debugout.h abstractsource.h timestamp.h uuidhelper.h mappropertytype.hpp propertyinfo.hpp superptr.hpp asyncqueue.hpp ambplugin.h ambpluginimpl.h)
+set(amb_sources abstractpropertytype.cpp abstractroutingengine.cpp listplusplus.cpp abstractsink.cpp vehicleproperty.cpp abstractsource.cpp debugout.cpp timestamp.cpp uuidhelper.cpp mappropertytype.hpp propertyinfo.hpp superptr.hpp asyncqueue.hpp ambpluginimpl.cpp ambplugin.h picojson.h)
+set(amb_headers_install abstractpropertytype.h nullptr.h abstractroutingengine.h listplusplus.h abstractsink.h vehicleproperty.h debugout.h abstractsource.h timestamp.h uuidhelper.h mappropertytype.hpp propertyinfo.hpp superptr.hpp asyncqueue.hpp ambplugin.h ambpluginimpl.h picojson.h)
add_library(amb SHARED ${amb_sources})
diff --git a/lib/abstractpropertytype.h b/lib/abstractpropertytype.h
index 6efbee13..a097c142 100644
--- a/lib/abstractpropertytype.h
+++ b/lib/abstractpropertytype.h
@@ -714,6 +714,9 @@ public:
}
};
+/*!
+ * \brief ListPropertyType is a AbstractPropertyType for arrays of AbstractPropertyTypes
+ */
template <class T = AbstractPropertyType>
class ListPropertyType: public AbstractPropertyType
{
diff --git a/lib/abstractroutingengine.h b/lib/abstractroutingengine.h
index 3c4bc8d0..cce0140e 100644
--- a/lib/abstractroutingengine.h
+++ b/lib/abstractroutingengine.h
@@ -112,8 +112,8 @@ public:
};
/*!
- * \brief The AsyncPropertyReply class is used by sources to reply to Get and Set operations. The source should
- * set success to true if the call is successful or 'false' if the request was not successful and set 'error'
+ * \brief The AsyncPropertyReply class is used by sources to reply to Get and Set operations.
+ * The source should set success to true if the call is successful or 'false' if the request was not successful and set 'error'
* to the appropriate error.
* \see AbstractRoutingEngine::getPropertyAsync
* \see AsyncPropertyReply
@@ -142,6 +142,9 @@ public:
ZoneNotSupported
};
+ /*!
+ * \brief errorToStr returns string representing the Error
+ */
static std::string errorToStr(Error err)
{
if(err == NoError)
@@ -154,6 +157,29 @@ public:
return "PermissionDenied";
else if(err == ZoneNotSupported)
return "ZoneNotSupported";
+
+ DebugOut(DebugOut::Warning) << "Could not translate error: " << err << endl;
+ return "";
+ }
+
+ /*!
+ * \brief strToError returns Error representing the string
+ */
+ static Error strToError(std::string err)
+ {
+ if(err == "NoError")
+ return NoError;
+ else if(err == "Timeout")
+ return Timeout;
+ else if(err == "InvalidOperation")
+ return InvalidOperation;
+ else if(err == "PermissionDenied")
+ return PermissionDenied;
+ else if(err == "ZoneNotSupported")
+ return ZoneNotSupported;
+
+ DebugOut(DebugOut::Warning) << "Could not translate error string: " << err << endl;
+ return NoError;
}
/*!
@@ -259,19 +285,22 @@ public:
Zone::Type zone;
/*!
- * \brief completed callback that is called when the ranged request is complete. The reply from this request is passed
+ * \brief completed callback
+ * 'completed' is called when the ranged request is complete. The reply from this request is passed
* into the completed call. The completed callback must free the reply before it returns or there will be a leak.
*/
GetRangedPropertyCompletedSignal completed;
/*!
- * \brief timeBegin set this to request values for the specified property beggining at this time. Time is seconds\
+ * \brief timeBegin
+ * Set this to request values for the specified property beggining at this time. Time is seconds\
* since the unix epoc. Set this to '0' if you do not want values within a time range.
*/
double timeBegin;
/*!
- * \brief timeEnd set this to request values for the specified property beggining at this time. Time is seconds\
+ * \brief timeEnd
+ * Set this to request values for the specified property beggining at this time. Time is seconds\
* since the unix epoc. Set this to '0' if you do not want values within a time range.
*/
double timeEnd;
@@ -296,7 +325,7 @@ public:
/*!
* \brief The AsyncRangePropertyReply class is used by a source to reply to an AsyncRangePropertyRequest.
- * the source should set success to 'true' and populate the 'values' member if the request was successful.
+ * The source should set success to 'true' and populate the 'values' member if the request was successful.
* If the request is not successful, 'success' should be set to 'false' and the 'error' member should be set.
*/
class AsyncRangePropertyReply: public AsyncRangePropertyRequest
@@ -373,7 +402,7 @@ public:
* /see AsyncPropertyReply.
* /param request requested property.
* /return AsyncPropertyReply. The returned AsyncPropertyReply is owned by the caller of getPropertyAsync.
- * /example AsyncPropertyRequest request;
+ * /code AsyncPropertyRequest request;
* request.property = VehicleProperty::VehicleSpeed
* request.completed = [](AsyncPropertyReply* reply)
* {
@@ -381,14 +410,15 @@ public:
* delete reply;
* };
* routingEngine->getPropertyAsync(request);
+ * /endcode
*/
virtual AsyncPropertyReply * getPropertyAsync(AsyncPropertyRequest request) = 0;
/*!
* \brief getRangePropertyAsync is used for getting a range of properties that are within the specified time or sequence parameters.
- * \param request the request containing the property and other information required by the query
+ * \arg request the request containing the property and other information required by the query
* \return a pointer to the reply.
- * \example AsyncRangePropertyRequest vehicleSpeedFromLastWeek;
+ * \code AsyncRangePropertyRequest vehicleSpeedFromLastWeek;
*
* vehicleSpeedFromLastWeek.timeBegin = amb::currentTime() - 10;
* vehicleSpeedFromLastWeek.timeEnd = amb::currentTime();
@@ -411,16 +441,15 @@ public:
* };
*
* routingEngine->getRangePropertyAsync(vehicleSpeedFromLastWeek);
- *
+ * \endcode
*/
-
virtual void getRangePropertyAsync(AsyncRangePropertyRequest request) = 0;
/*!
* \brief setProperty sets a property to a value.
* \see AsyncSetPropertyRequest
* \see AsyncPropertyReply
- * \param request the request containing the property and the value to set
+ * \arg request the request containing the property and the value to set
* \return a pointer to the reply which is owned by the caller of this method
* \example
*/
@@ -428,24 +457,24 @@ public:
/*!
* \brief subscribeToProperty subscribes to propertyName. Value changes will be passed to callback.
- * \param propertyName
- * \param callback
- * \param pid process id of the requesting application
+ * \arg propertyName
+ * \arg callback
+ * \arg pid process id of the requesting application
* \return subscription handle
*/
virtual uint subscribeToProperty(const VehicleProperty::Property & propertyName, PropertyChangedType callback, std::string pid="") = 0;
/*!
* \brief unsubscribeToProperty
- * \param handle
+ * \arg handle
*/
virtual void unsubscribeToProperty(uint handle) = 0;
/*!
* \brief subscribeToProperty subscribe to changes made to a property value.
- * \param propertyName name of the property to request a subscription for.
- * \param self pointer to the sink who is subscribing.
- * \example
+ * \arg propertyName name of the property to request a subscription for.
+ * \arg self pointer to the sink who is subscribing.
+ * \code
* //somewhere in the sink:
* routingEngine->subscribeToProperty(VehicleProperty::EngineSpeed, this);
*
@@ -457,23 +486,24 @@ public:
* ...
* }
* }
+ * \endcode
*/
virtual bool subscribeToProperty(const VehicleProperty::Property & propertyName, AbstractSink* self) = 0;
/*!
* \brief subscribeToProperty subscribe to changes made to a property value.
- * \param propertyName name of the property to request a subscription for.
- * \param sourceUuidFilter source UUID to filter. Only property updates from this source will be sent to the sink.
- * \param self pointer to the sink who is subscribing.
+ * \arg propertyName name of the property to request a subscription for.
+ * \arg sourceUuidFilter source UUID to filter. Only property updates from this source will be sent to the sink.
+ * \arg self pointer to the sink who is subscribing.
*/
virtual bool subscribeToProperty(const VehicleProperty::Property & propertyName, const std::string & sourceUuidFilter, AbstractSink *self) = 0;
/*!
* \brief subscribeToProperty subscribe to changes made to a property value.
- * \param propertyName name of the property to request a subscription for.
- * \param sourceUuidFilter source UUID to filter. Only property updates from this source will be sent to the sink.
- * \param zoneFilter zone to filter. Only updates from this zone will be passed to the sink.
- * \param self pointer to the sink who is subscribing.
+ * \arg propertyName name of the property to request a subscription for.
+ * \arg sourceUuidFilter source UUID to filter. Only property updates from this source will be sent to the sink.
+ * \arg zoneFilter zone to filter. Only updates from this zone will be passed to the sink.
+ * \arg self pointer to the sink who is subscribing.
*/
virtual bool subscribeToProperty(const VehicleProperty::Property & propertyName, const std::string & sourceUuidFilter, Zone::Type zoneFilter, AbstractSink *self) = 0;
diff --git a/lib/asyncqueue.hpp b/lib/asyncqueue.hpp
index ed0c69b4..ada42ac7 100644
--- a/lib/asyncqueue.hpp
+++ b/lib/asyncqueue.hpp
@@ -24,6 +24,7 @@
#include <mutex>
#include <condition_variable>
#include <unordered_set>
+#include <vector>
namespace amb
{
@@ -32,8 +33,8 @@ template <typename T, class Pred = std::equal_to<T> >
class Queue
{
public:
- Queue(bool blocking = false)
- :mBlocking(blocking)
+ Queue(bool unique = false, bool blocking = false)
+ :mUnique(unique), mBlocking(blocking)
{
}
@@ -56,7 +57,7 @@ public:
if(mBlocking)
{
- while(!mQueue.size())
+ if(!mQueue.size())
{
cond.wait(lock);
}
@@ -79,12 +80,16 @@ public:
{
std::lock_guard<std::mutex> lock(mutex);
- mQueue.insert(item);
+ if(contains(mQueue, item))
+ {
+ mQueue.erase(std::find(mQueue.begin(), mQueue.end(), item));
+ }
+ mQueue.push_back(item);
}
if(mBlocking)
{
- cond.notify_one();
+ cond.notify_all();
}
}
@@ -94,11 +99,12 @@ public:
removeOne(&mQueue, item);
}
-protected:
+private:
bool mBlocking;
+ bool mUnique;
std::mutex mutex;
std::condition_variable cond;
- std::unordered_set<T, std::hash<T>, Pred> mQueue;
+ std::vector<T> mQueue;
};
template <typename T, class Pred = std::equal_to<T> >
diff --git a/lib/debugout.h b/lib/debugout.h
index b8030ee9..d6a49e2e 100644
--- a/lib/debugout.h
+++ b/lib/debugout.h
@@ -30,6 +30,30 @@ using namespace std;
void debugOut(const string &message);
+/*!
+ * \brief The DebugOut class represents a class used for outputing debug information
+ * The specified debug level will only be outputed if the debug level is => the debug threshhold
+ * Here's a simple example:
+ * \code
+ * DebugOut::setDebugThreshhold(3);
+ * DebugOut(DebugOut::Warning) << "This is a warning" << std::endl;
+ * DebugOut(3) << "This will only show if the threshhold is 3 or lower." << std::endl;
+ *
+ * /// Start logging to a file:
+ * ofstream logfile;
+ * logfile.open("amb.log", ios::out | ios::trunc);
+ * DebugOut::setOutput(logfile)
+ *
+ * /// Throw exception on warning or error:
+ * DebugOut::setThrowErr(true);
+ * DebugOut::setThrowWarn(true);
+ * DebugOut(DebugOut::Error) << "This will throw an exception." << std::endl;
+ *
+ * /// Log to stderr:
+ * DebugOut::setOutput(std::cerr);
+ * DebugOut() << "This will log to stderr." << std::endl;
+ * \endcode
+ */
class DebugOut
{
public:
diff --git a/xwalk/common/picojson.h b/lib/picojson.h
index 93171e3f..93171e3f 100644
--- a/xwalk/common/picojson.h
+++ b/lib/picojson.h
diff --git a/lib/superptr.hpp b/lib/superptr.hpp
index 671ef3b8..b2c2f530 100644
--- a/lib/superptr.hpp
+++ b/lib/superptr.hpp
@@ -71,7 +71,10 @@ struct traits<GDBusConnection> {
};
template<typename T> using super_ptr =
- ::std::unique_ptr<T, typename traits<T>::delete_functor>;
+ ::std::unique_ptr<T, typename traits<T>::delete_functor>;
+
+template<typename T> using gobject_ptr =
+ ::std::unique_ptr<T , std::function<void(T*)> >;
template<typename T> super_ptr<T> make_super(T* t)
{
@@ -83,5 +86,10 @@ template<typename T> ::std::unique_ptr<T> make_unique(T* t)
return ::std::unique_ptr<T>(t);
}
+template<typename T> gobject_ptr<T> make_gobject(T* t)
+{
+ return gobject_ptr<T>(t, [](auto ptr) { if(ptr) g_object_unref(ptr);});
+}
+
}
#endif
diff --git a/lib/vehicleproperty.cpp b/lib/vehicleproperty.cpp
index 35b58cc6..b0365907 100644
--- a/lib/vehicleproperty.cpp
+++ b/lib/vehicleproperty.cpp
@@ -538,20 +538,24 @@ AbstractPropertyType* VehicleProperty::getPropertyTypeForPropertyNameValue(Vehic
if(registeredPropertyFactoryMap.count(name) > 0)
{
VehicleProperty::PropertyTypeFactoryCallback cb = registeredPropertyFactoryMap[name];
- if ( cb != NULL )
+ if ( cb != nullptr )
{
AbstractPropertyType* type = cb();
- if(type == NULL)
+ if(type == nullptr)
+ {
throw std::runtime_error("Cannot return NULL in a PropertyTypeFactory");
+ }
if(value != "" )
+ {
type->fromString(value);
+ }
return type;
}
}
- DebugOut(DebugOut::Error)<<"Property not found"<<endl;
+ DebugOut(DebugOut::Warning) << "Property not found: " << name << endl;
return nullptr;
}
diff --git a/packaging.in/amb.manifest b/packaging.in/amb.manifest
index 171a6041..bcb207a0 100644
--- a/packaging.in/amb.manifest
+++ b/packaging.in/amb.manifest
@@ -24,7 +24,7 @@
</define>
<assign>
<dbus name="org.automotive.message.broker" own="AMB" bus="system">
- <node name="*/0/MachineGunTurretStatus" >
+ <!--<node name="*/0/MachineGunTurretStatus" >
<interface name="org.freedesktop.DBus.Properties">
<method name="Set" >
<annotation name="com.tizen.smack" value="AMB::machinegun" />
@@ -38,6 +38,7 @@
</method>
</interface>
</node>
+ -->
<!--<node name="*" >
<interface name="org.freedesktop.DBus.Properties">
<method name="Get" >
diff --git a/packaging.in/automotive-message-broker.spec.in b/packaging.in/automotive-message-broker.spec.in
index 1ad1cf76..f0023a3d 100644
--- a/packaging.in/automotive-message-broker.spec.in
+++ b/packaging.in/automotive-message-broker.spec.in
@@ -28,6 +28,7 @@ BuildRequires: pkgconfig(opencv)
BuildRequires: murphy
BuildRequires: pkgconfig(murphy-glib)
BuildRequires: pkgconfig(dbus-1)
+BuildRequires: doxygen
%if %{with qt5}
BuildRequires: qt5-qtcore-devel
BuildRequires: qt5-qtconcurrent-devel
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index 45802660..32a41be6 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -21,7 +21,12 @@ install(TARGETS examplesourceplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/exampleplugins.README.txt ${CMAKE_CURRENT_BINARY_DIR}/exampleplugins.README @ONLY)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/examplesource.in.json ${CMAKE_CURRENT_BINARY_DIR}/examplesource @ONLY)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/examplesink.in.json ${CMAKE_CURRENT_BINARY_DIR}/examplesink @ONLY)
+
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/exampleplugins.README DESTINATION ${DOC_INSTALL_DIR}/plugins)
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/examplesource DESTINATION ${PLUGIN_SEGMENT_INSTALL_PATH})
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/examplesink DESTINATION ${PLUGIN_SEGMENT_INSTALL_PATH})
add_subdirectory(common)
diff --git a/plugins/bluemonkey/bluemonkey.in.idl b/plugins/bluemonkey/bluemonkey.in.idl
index b729492d..bddfde54 100644
--- a/plugins/bluemonkey/bluemonkey.in.idl
+++ b/plugins/bluemonkey/bluemonkey.in.idl
@@ -1,6 +1,8 @@
/*!
* \mainpage Automotive Message Broker Library Documentation - Bluemonkey Plugin
* \version @PROJECT_VERSION@
+ *
+ * <a href="../../../html/index.html">Back to AMB Documentation Main</a>
* \section intro Introduction
* Bluemonkey is a javascript rendering engine that allows the scripting of source plugin behavior in javascript.
* It allows developers a quick way to prototype plugin code as well as a way to create custom properties.
@@ -112,12 +114,14 @@ interface Bluemonkey {
void createCustomProperty(DOMString name, any value, optional unsigned short zone);
/*!
- * \brief exportInterface
+ * \brief exportInterface export a custom DBus interface as org.automotive.[interfaceName] with properties
*/
void exportInterface(DOMString interfaceName, ExportMap[] properties);
};
-
+/*!
+ * \brief PropertyInterface represents an interface to an AMB Property
+ */
interface PropertyInterface {
/*!
* \brief AMB property name of this property
@@ -149,6 +153,10 @@ interface PropertyInterface {
*/
readonly attribute Signal changed;
+ /*!
+ * \brief get logged data between \arg begin and \arg end.
+ * callback is called with the results of this method.
+ */
void getHistory(Date begin, Date end, HistoryCallback callback);
};
@@ -163,6 +171,12 @@ interface Signal {
void connect(ChangedCallback callback)
};
+/*!
+ * \brief ExportMap is a dictionary from AmbPropertyName to DBusPropertyName
+ * AmbPropertyName should represent an internally defined or custom AMB property type.
+ * The DBusPropertyName should represent what you want the property to be represented in
+ * the DBus interface.
+ */
interface ExportMap {
/*!
* \brief internal AMB property name
diff --git a/plugins/bluemonkey/config.js b/plugins/bluemonkey/config.js
index e69e6765..cb7549e2 100644
--- a/plugins/bluemonkey/config.js
+++ b/plugins/bluemonkey/config.js
@@ -20,17 +20,13 @@ bluemonkey.createCustomProperty("AnswerToTheUniverse", 42);
dbusConnected = bluemonkey.subscribeTo("DBusConnected");
dbusConnected.changed.connect(function () {
- bluemonkey.log("WEEEEEEEEEEEEEEEEEEEEEEEEEEEEE!" + dbusConnected.value);
+ if(dbusConnected.value !== true)
+ return;
- if(dbusConnected.value !== true)
- return;
-
- bluemonkey.exportInterface("Bluemonkey",[{'BluemonkeySuperProperty' : 'SuperProperty'},
- {'AnswerToTheUniverse' : 'AnswerToTheUniverse'}]);
+ bluemonkey.exportInterface("Bluemonkey",[{'BluemonkeySuperProperty' : 'SuperProperty'},
+ {'AnswerToTheUniverse' : 'AnswerToTheUniverse'}]);
});
-
-
bluemonkey.createCustomProperty("VehicleSpeed", 10);
bluemonkey.createCustomProperty("EngineSpeed", 5000);
bluemonkey.createCustomProperty("PowertrainTorque", 324);
diff --git a/plugins/common/abstractdbusinterface.cpp b/plugins/common/abstractdbusinterface.cpp
index c3ece473..2f2053ab 100644
--- a/plugins/common/abstractdbusinterface.cpp
+++ b/plugins/common/abstractdbusinterface.cpp
@@ -64,9 +64,7 @@ const uint getPid(const char *owner)
return thePid;
}
-
-
-static void handleMyMethodCall(GDBusConnection *connection,
+void AbstractDBusInterface::handleMyMethodCall(GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
@@ -87,7 +85,80 @@ static void handleMyMethodCall(GDBusConnection *connection,
g_assert(iface);
- if(method == "GetHistory")
+ if(std::string(interface_name) == "org.freedesktop.DBus.Properties")
+ {
+ if(method == "Get")
+ {
+ gchar* propertyName = nullptr;
+ gchar* ifaceName = nullptr;
+ g_variant_get(parameters, "(ss)", &ifaceName, &propertyName);
+
+ DebugOut(6) << "Parameter signature: " << g_variant_get_type_string(parameters) << endl;
+// DebugOut(6) << "Get property " << propertyName << " for interface " << ifaceName << endl;
+
+ GError* error = nullptr;
+ auto value = amb::make_super(AbstractDBusInterface::getProperty(connection, sender, object_path, ifaceName, propertyName, &error, iface));
+ amb::make_super(error);
+
+ if(!value)
+ {
+ g_dbus_method_invocation_return_dbus_error(invocation, std::string(std::string(ifaceName)+".PropertyNotFound").c_str(), "Property not found in interface");
+ }
+
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(v)", value.get()));
+ return;
+ }
+ else if(method == "GetAll")
+ {
+ gchar* ifaceName = nullptr;
+ g_variant_get(parameters, "(s)", &ifaceName);
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
+
+ auto propertyMap = iface->getProperties();
+
+ for(auto itr : propertyMap)
+ {
+ auto prop = itr.second;
+ GError* error = nullptr;
+ auto value = AbstractDBusInterface::getProperty(connection, sender, object_path, ifaceName, prop->name().c_str(), &error, iface);
+ amb::make_super(error);
+ g_variant_builder_add(&builder, "{sv}", prop->name().c_str(), g_variant_new("v", value));
+ //sequence
+ auto sequence = AbstractDBusInterface::getProperty(connection, sender, object_path, ifaceName, std::string(prop->name()+"Sequence").c_str(), &error, iface);
+ g_variant_builder_add(&builder, "{sv}", std::string(prop->name()+"Sequence").c_str(), g_variant_new("v", sequence));
+ }
+
+ auto time = AbstractDBusInterface::getProperty(connection, sender, object_path, ifaceName, "Time", nullptr, iface);
+ auto zone = AbstractDBusInterface::getProperty(connection, sender, object_path, ifaceName, "Zone", nullptr, iface);
+ g_variant_builder_add(&builder, "{sv}", "Time", g_variant_new("v", time));
+ g_variant_builder_add(&builder, "{sv}", "Zone", g_variant_new("v", zone));
+
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(a{sv})", &builder));
+ return;
+ }
+ else if(method == "Set")
+ {
+ gchar* ifaceName = nullptr;
+ gchar* propName = nullptr;
+ GVariant* value;
+ g_variant_get(parameters, "(ssv)", &ifaceName, &propName, &value);
+
+ AbstractDBusInterface::setProperty(connection, sender, object_path, ifaceName, propName, value, nullptr, iface,
+ [&invocation, &ifaceName](bool success, AsyncPropertyReply::Error error) {
+ if(success)
+ {
+ g_dbus_method_invocation_return_value(invocation, nullptr);
+ }
+ else
+ {
+ g_dbus_method_invocation_return_dbus_error(invocation, ifaceName, AsyncPropertyReply::errorToStr(error).c_str());
+ }
+ });
+ }
+ }
+ else if(method == "GetHistory")
{
double beginTime = 0;
double endTime = 0;
@@ -136,17 +207,17 @@ static void handleMyMethodCall(GDBusConnection *connection,
}
GVariantBuilder builder;
- g_variant_builder_init(&builder, G_VARIANT_TYPE("a(svd)"));
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("a{svd}"));
for(auto itr = reply->values.begin(); itr != reply->values.end(); itr++)
{
AbstractPropertyType* value = *itr;
- g_variant_builder_add(&builder, "(svd)", value->name.c_str(), g_variant_ref(value->toVariant()),value->timestamp);
+ g_variant_builder_add(&builder, "{svd}", value->name.c_str(), g_variant_ref(value->toVariant()),value->timestamp);
}
- g_dbus_method_invocation_return_value(invocation,g_variant_new("(a(svd))",&builder));
+ g_dbus_method_invocation_return_value(invocation,g_variant_new("(a{svd})",&builder));
};
iface->re->getRangePropertyAsync(request);
@@ -154,6 +225,7 @@ static void handleMyMethodCall(GDBusConnection *connection,
return;
}
+ ///TODO: Deprecated in 0.15
else if(boost::algorithm::starts_with(method, "Get"))
{
std::string propertyName = method.substr(3);
@@ -219,7 +291,6 @@ AbstractDBusInterface::~AbstractDBusInterface()
}
objectMap.erase(mObjectPath);
-
}
void AbstractDBusInterface::addProperty(VariantType * property)
@@ -242,16 +313,14 @@ void AbstractDBusInterface::addProperty(VariantType * property)
///see which properties are supported:
introspectionXml +=
"<property type='"+ string(property->signature()) + "' name='"+ pn +"' access='"+access+"' />"
+ "<!-- 'GetFoo' is deprecated as of 0.14 -->"
+ /// TODO: remove GetFoo in 0.15
"<method name='Get" + pn + "'>"
" <arg type='v' direction='out' name='value' />"
" <arg type='d' direction='out' name='timestamp' />"
" <arg type='i' direction='out' name='sequence' />"
" <arg type='i' direction='out' name='updateFrequency' />"
"</method>"
- "<signal name='" + pn + "Changed' >"
- " <arg type='v' name='" + nameToLower + "' direction='out' />"
- " <arg type='d' name='imestamp' direction='out' />"
- "</signal>"
"<property type='i' name='" + pn + "Sequence' access='read' />";
properties[pn] = property;
@@ -302,7 +371,7 @@ void AbstractDBusInterface::registerObject()
GDBusInterfaceInfo* mInterfaceInfo = g_dbus_node_info_lookup_interface(introspection, mInterfaceName.c_str());
- const GDBusInterfaceVTable vtable = { handleMyMethodCall, AbstractDBusInterface::getProperty, AbstractDBusInterface::setProperty };
+ const GDBusInterfaceVTable vtable = { handleMyMethodCall, nullptr, nullptr };
GError* error2=NULL;
@@ -399,6 +468,23 @@ void AbstractDBusInterface::startRegistration()
//unregisterObject();
introspectionXml ="<node>" ;
introspectionXml +=
+ "<interface name='org.freedesktop.DBus.Properties'>"
+ "<method name='Get'>"
+ " <arg type='s' direction='in' name='interface' />"
+ " <arg type='s' direction='in' name='property' />"
+ " <arg type='v' direction='out' name='value' />"
+ "</method>"
+ "<method name='Set'>"
+ " <arg type='s' direction='in' name='interface' />"
+ " <arg type='s' direction='in' name='property' />"
+ " <arg type='v' direction='in' name='value' />"
+ "</method>"
+ "<method name='GetAll'>"
+ " <arg type='s' direction='in' name='interface' />"
+ " <arg type='a{sv}' direction='out' name='interface' />"
+ "</method>"
+ "</interface>";
+ introspectionXml +=
"<interface name='"+ mInterfaceName + "' >"
"<property type='i' name='Zone' access='read' />"
"<property type='d' name='Time' access='read' />"
@@ -409,7 +495,8 @@ void AbstractDBusInterface::startRegistration()
"</method>";
}
-GVariant* AbstractDBusInterface::getProperty(GDBusConnection* connection, const gchar* sender, const gchar* objectPath, const gchar* interfaceName, const gchar* propertyName, GError** error, gpointer userData)
+GVariant* AbstractDBusInterface::getProperty(GDBusConnection* connection, const gchar* sender, const gchar* objectPath, const gchar* interfaceName,
+ const gchar* propertyName, GError** error, gpointer userData)
{
if(DebugOut::getDebugThreshhold() >= 6)
{
@@ -478,7 +565,9 @@ GVariant* AbstractDBusInterface::getProperty(GDBusConnection* connection, const
return nullptr;
}
-gboolean AbstractDBusInterface::setProperty(GDBusConnection* connection, const gchar* sender, const gchar* objectPath, const gchar* interfaceName, const gchar* propertyName, GVariant* value, GError** error, gpointer userData)
+gboolean AbstractDBusInterface::setProperty(GDBusConnection* connection, const gchar* sender, const gchar* objectPath, const gchar* interfaceName,
+ const gchar* propertyName, GVariant* value, GError** error, gpointer userData,
+ std::function<void (bool, AsyncPropertyReply::Error)> callback)
{
if(DebugOut::getDebugThreshhold() >= 6)
{
@@ -488,22 +577,22 @@ gboolean AbstractDBusInterface::setProperty(GDBusConnection* connection, const g
if(objectMap.count(objectPath))
{
- objectMap[objectPath]->setProperty(propertyName, value);
+ objectMap[objectPath]->setProperty(propertyName, value, callback);
return true;
}
return false;
}
-void AbstractDBusInterface::setProperty(string propertyName, GVariant *value)
+void AbstractDBusInterface::setProperty(string propertyName, GVariant *value, std::function<void (bool, AsyncPropertyReply::Error)> callback)
{
if(properties.count(propertyName))
{
- properties[propertyName]->fromVariant(value);
+ properties[propertyName]->fromVariant(value, callback);
}
- else
+ else if(callback)
{
- throw -1;
+ callback(false, AsyncPropertyReply::InvalidOperation);
}
}
@@ -511,8 +600,8 @@ GVariant *AbstractDBusInterface::getProperty(string propertyName)
{
if(properties.count(propertyName))
return properties[propertyName]->toVariant();
- else
- throw -1;
+
+ return nullptr;
}
void AbstractDBusInterface::setTimeout(int timeout)
diff --git a/plugins/common/abstractdbusinterface.h b/plugins/common/abstractdbusinterface.h
index a0ba866e..9bff3da9 100644
--- a/plugins/common/abstractdbusinterface.h
+++ b/plugins/common/abstractdbusinterface.h
@@ -131,9 +131,13 @@ protected:
gpointer userData);
static gboolean setProperty(GDBusConnection * connection, const gchar * sender, const gchar *objectPath,
const gchar *interfaceName, const gchar * propertyName, GVariant *value,
- GError** error, gpointer userData);
+ GError** error, gpointer userData, std::function<void (bool, AsyncPropertyReply::Error)> callback);
- virtual void setProperty(std::string propertyName, GVariant * value);
+ static void handleMyMethodCall(GDBusConnection *connection, const gchar *sender, const gchar *object_path,
+ const gchar *interface_name, const gchar *method_name, GVariant *parameters,
+ GDBusMethodInvocation *invocation, gpointer user_data);
+
+ virtual void setProperty(std::string propertyName, GVariant * value, std::function<void (bool, AsyncPropertyReply::Error)> callback);
virtual GVariant * getProperty(std::string propertyName);
void setTimeout(int timeout);
diff --git a/plugins/common/varianttype.cpp b/plugins/common/varianttype.cpp
index 46e5ec80..3cd1254f 100644
--- a/plugins/common/varianttype.cpp
+++ b/plugins/common/varianttype.cpp
@@ -77,7 +77,7 @@ GVariant *VariantType::toVariant()
return v->toVariant();
}
-void VariantType::fromVariant(GVariant *val)
+void VariantType::fromVariant(GVariant *val, std::function<void (bool, AsyncPropertyReply::Error)> callback)
{
AbstractPropertyType *v = VehicleProperty::getPropertyTypeForPropertyNameValue(name());
v->fromVariant(val);
@@ -89,11 +89,9 @@ void VariantType::fromVariant(GVariant *val)
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;
- }
+
+ if(callback)
+ callback(reply->success, reply->error);
};
routingEngine->setProperty(request);
diff --git a/plugins/common/varianttype.h b/plugins/common/varianttype.h
index 1c83d9cc..1904ab64 100644
--- a/plugins/common/varianttype.h
+++ b/plugins/common/varianttype.h
@@ -31,10 +31,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
class AbstractDBusInterface;
-using namespace std;
-
-typedef function<void (boost::any)> SetterFunc;
-
class VariantType
{
@@ -57,11 +53,6 @@ public:
&& other.zoneFilter() == zoneFilter());
}
- virtual void setSetterFunction(SetterFunc setterFunc)
- {
- mSetterFunc = setterFunc;
- }
-
virtual const string signature()
{
GVariant* var = toVariant();
@@ -100,7 +91,7 @@ public:
Zone::Type zoneFilter() { return mZoneFilter; }
virtual GVariant* toVariant();
- virtual void fromVariant(GVariant *value);
+ virtual void fromVariant(GVariant *value, std::function<void (bool, AsyncPropertyReply::Error)> callback);
double timestamp()
{
@@ -166,7 +157,6 @@ protected:
AbstractRoutingEngine* routingEngine;
string mPropertyName;
VehicleProperty::Property mAmbPropertyName;
- SetterFunc mSetterFunc;
Access mAccess;
AbstractPropertyType* mValue;
AbstractDBusInterface* mInterface;
diff --git a/plugins/database/databasesink.cpp b/plugins/database/databasesink.cpp
index 4a9c8b37..8881ae53 100644
--- a/plugins/database/databasesink.cpp
+++ b/plugins/database/databasesink.cpp
@@ -47,7 +47,7 @@ static void * cbFunc(Shared* shared)
NameValuePair<string> zone("zone", boost::lexical_cast<string>(obj.zone));
NameValuePair<string> four("time", boost::lexical_cast<string>(obj.time));
NameValuePair<string> five("sequence", boost::lexical_cast<string>(obj.sequence));
- NameValuePair<string> six("tripId", boost::lexical_cast<string>(shared->tripId));
+ NameValuePair<string> six("tripId", shared->tripId);
dict.push_back(one);
dict.push_back(two);
@@ -76,9 +76,8 @@ static void * cbFunc(Shared* shared)
/// final flush of whatever is still in the queue:
shared->db->exec("BEGIN IMMEDIATE TRANSACTION");
- for(int i=0; i< insertList.size(); i++)
+ for(auto d : insertList)
{
- DictionaryList<string> d = insertList[i];
shared->db->insert(d);
}
shared->db->exec("END TRANSACTION");
@@ -380,6 +379,8 @@ void DatabaseSink::propertyChanged(AbstractPropertyType *value)
{
VehicleProperty::Property property = value->name;
+ DebugOut() << "Received property change for " << property << endl;
+
if(!shared)
return;
diff --git a/plugins/database/databasesink.h b/plugins/database/databasesink.h
index 8976f416..459ec928 100644
--- a/plugins/database/databasesink.h
+++ b/plugins/database/databasesink.h
@@ -52,7 +52,7 @@ public:
bool quit;
- bool operator ==(const DBObject & other) const
+ bool operator == (const DBObject & other) const
{
return (key == other.key && source == other.source && zone == other.zone &&
value == other.value && sequence == other.sequence && time == other.time);
@@ -88,7 +88,7 @@ namespace std {
{
size_t operator()(const DBObject & x) const
{
- return x.key.length();
+ return x.key.length() * x.value.length() + x.time;
}
};
}
diff --git a/plugins/dbus/CMakeLists.txt b/plugins/dbus/CMakeLists.txt
index 67d6ba65..c4e6fef1 100644
--- a/plugins/dbus/CMakeLists.txt
+++ b/plugins/dbus/CMakeLists.txt
@@ -25,8 +25,10 @@ set(dbus_mapping_headers ${dbus_mapping_headers} ${CMAKE_CURRENT_SOURCE_DIR}/par
set(dbus_mapping_headers ${dbus_mapping_headers} ${CMAKE_CURRENT_SOURCE_DIR}/drivingsafety.h CACHE INTERNAL "dbus mapping headers")
set(dbus_mapping_headers ${dbus_mapping_headers} ${CMAKE_CURRENT_SOURCE_DIR}/personalization.h CACHE INTERNAL "dbus mapping headers")
-
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_BINARY_DIR}/dbus.README @ONLY)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/dbus.README DESTINATION ${DOC_INSTALL_DIR}/plugins)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dbus.in.json ${CMAKE_CURRENT_BINARY_DIR}/dbus @ONLY)
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/dbus DESTINATION ${PLUGIN_SEGMENT_INSTALL_PATH})
+
add_subdirectory(amb-qt)
diff --git a/plugins/dbus/automotivemanager.cpp b/plugins/dbus/automotivemanager.cpp
index a6b1ca25..64919e05 100644
--- a/plugins/dbus/automotivemanager.cpp
+++ b/plugins/dbus/automotivemanager.cpp
@@ -340,11 +340,11 @@ static void handleMethodCall(GDBusConnection *connection,
}
}
DebugOut(6) << "member " << propertyToFindStrPtr.get() << " of " << objectNamePtr.get() << " was not found." << endl;
- g_dbus_method_invocation_return_value(invocation,g_variant_new("(b)", false));
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", false));
}
else
{
- g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR,G_DBUS_ERROR_UNKNOWN_METHOD, "Unknown method.");
+ g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Unknown method.");
}
}
@@ -438,14 +438,16 @@ AutomotiveManager::AutomotiveManager(GDBusConnection *connection)
regId = g_dbus_connection_register_object(mConnection, "/", mInterfaceInfo, &interfaceVTable, this, NULL, &error);
g_dbus_node_info_unref(introspection);
- if(error){
- g_error_free(error);
+ auto errorPtr = amb::make_super(error);
+
+ if(errorPtr){
+ DebugOut(DebugOut::Error) << "registering dbus object: " << "'org.automotive.Manager' " << errorPtr->message << endl;
throw -1;
}
g_assert(regId > 0);
- g_dbus_connection_signal_subscribe(g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL,NULL), "org.freedesktop.DBus", "org.freedesktop.DBus",
+ g_dbus_connection_signal_subscribe(mConnection, "org.freedesktop.DBus", "org.freedesktop.DBus",
"NameOwnerChanged", "/org/freedesktop/DBus", NULL, G_DBUS_SIGNAL_FLAGS_NONE,
signalCallback, this, NULL);
}
diff --git a/plugins/dbus/dbus.in.json b/plugins/dbus/dbus.in.json
new file mode 100644
index 00000000..c924d6c9
--- /dev/null
+++ b/plugins/dbus/dbus.in.json
@@ -0,0 +1,6 @@
+{
+ "name" : "DBusSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so",
+ "frequency" : "30",
+ "enabled" : true
+}
diff --git a/plugins/exampleplugin.cpp b/plugins/exampleplugin.cpp
index 32901731..4b643c67 100644
--- a/plugins/exampleplugin.cpp
+++ b/plugins/exampleplugin.cpp
@@ -365,8 +365,10 @@ void ExampleSourcePlugin::randomizeProperties()
DebugOut()<<"setting enginespeed to: "<<engineSpeed<<endl;
vel.setValue(velocity);
+ vel.sequence++;
vel.priority = AbstractPropertyType::High;
es.setValue(engineSpeed);
+ es.sequence++;
es.priority = AbstractPropertyType::Low;
ac.setValue(accelerationX);
swa.setValue(steeringWheelAngle);
diff --git a/plugins/examplesink.cpp b/plugins/examplesink.cpp
index 85f3d39f..bd0afef4 100644
--- a/plugins/examplesink.cpp
+++ b/plugins/examplesink.cpp
@@ -183,7 +183,8 @@ void ExampleSink::supportedChanged(const PropertyList & supportedProperties)
for(auto itr = values.begin(); itr != values.end(); itr++)
{
auto val = *itr;
- DebugOut(1)<<"Value from past: ("<<val->name<<"): "<<val->toString()<<" time: "<<val->timestamp<<endl;
+ DebugOut(1) <<"Value from past: (" << val->name << "): " << val->toString()
+ <<" time: " << val->timestamp << " sequence: " << val->sequence << endl;
}
delete reply;
diff --git a/plugins/examplesink.in.json b/plugins/examplesink.in.json
new file mode 100644
index 00000000..254ce541
--- /dev/null
+++ b/plugins/examplesink.in.json
@@ -0,0 +1,6 @@
+{
+ "name" : "ExampleSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so",
+ "frequency" : "30",
+ "enabled" : true
+}
diff --git a/plugins/examplesource.in.json b/plugins/examplesource.in.json
new file mode 100644
index 00000000..b221fbab
--- /dev/null
+++ b/plugins/examplesource.in.json
@@ -0,0 +1,6 @@
+{
+ "name" : "ExampleSource",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so",
+ "delay" : "6",
+ "enabled" : true
+}
diff --git a/plugins/opencvlux/CMakeLists.txt b/plugins/opencvlux/CMakeLists.txt
index de3645c3..da0b8eb2 100644
--- a/plugins/opencvlux/CMakeLists.txt
+++ b/plugins/opencvlux/CMakeLists.txt
@@ -32,14 +32,11 @@ endif(cuda)
find_package(Qt5Core REQUIRED)
if(Qt5Core_FOUND)
- message(STATUS "using Qt5")
-
set(QT_INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS} )
set(QT_LIBRARIES ${Qt5Core_LIBRARIES} )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
add_definitions(${Qt5Core_DEFINITIONS})
add_definitions(-DQT_NO_KEYWORDS)
-
endif(Qt5Core_FOUND)
set(CMAKE_AUTOMOC ON)
diff --git a/plugins/testplugin/testplugin.cpp b/plugins/testplugin/testplugin.cpp
index 5fa32c56..35679a93 100644
--- a/plugins/testplugin/testplugin.cpp
+++ b/plugins/testplugin/testplugin.cpp
@@ -45,7 +45,7 @@ void testBooleanToStringFromString()
boolean.fromString(boolean.toString());
std::string isTrue2 = boolean.toString();
- g_assert(isTrue == isTrue2);
+ TEST(isTrue == isTrue2);
}
bool beginsWith(std::string a, std::string b)
diff --git a/plugins/websocket/CMakeLists.txt b/plugins/websocket/CMakeLists.txt
index 12ebe299..4da95b28 100644
--- a/plugins/websocket/CMakeLists.txt
+++ b/plugins/websocket/CMakeLists.txt
@@ -8,8 +8,6 @@ include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs})
find_package(Qt5Core REQUIRED)
if(Qt5Core_FOUND)
- message(STATUS "using Qt5")
-
set(QT_INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS} )
set(QT_LIBRARIES ${Qt5Core_LIBRARIES} )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
@@ -40,11 +38,26 @@ target_link_libraries(websocketsource amb ${websockets_LIBRARIES} -L${CMAKE_CURR
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)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test/index.html ${CMAKE_CURRENT_SOURCE_DIR}/test/index.html)
install(TARGETS websocketsource LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_BINARY_DIR}/websocket.README @ONLY)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/protocol.idl ${CMAKE_CURRENT_BINARY_DIR}/docs/protocol.idl @ONLY)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/websocket.README DESTINATION ${DOC_INSTALL_DIR}/plugins)
+if(enable_docs)
+ find_package(Doxygen)
+ if(DOXYGEN_FOUND)
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
+ add_custom_target(websocket_docs ALL ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Generating Websocket protocol documentation with Doxygen" VERBATIM)
+
+ install (DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION ${DOC_INSTALL_DIR}/plugins/websocket COMPONENT Docs)
+ install (DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test DESTINATION ${DOC_INSTALL_DIR}/plugins/websocket COMPONENT Docs)
+ endif(DOXYGEN_FOUND)
+
+endif(enable_docs)
+
endif(websocket_plugin)
diff --git a/plugins/websocket/Doxyfile.in b/plugins/websocket/Doxyfile.in
new file mode 100644
index 00000000..ee0e2735
--- /dev/null
+++ b/plugins/websocket/Doxyfile.in
@@ -0,0 +1,4 @@
+PROJECT_NAME = @PROJECT_NAME@
+PROJECT_NUMBER = @PROJECT_VERSION@
+GENERATE_LATEX = NO
+INPUT = @CMAKE_CURRENT_BINARY_DIR@/docs/
diff --git a/plugins/websocket/protocol b/plugins/websocket/protocol
deleted file mode 100644
index 2d723a0f..00000000
--- a/plugins/websocket/protocol
+++ /dev/null
@@ -1,37 +0,0 @@
-Example protocol messages
-
-Property changed event:
-{"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"}
-
-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":"getSupported","transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"}
-
-Get supported reply:
-{"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","property":"EngineSpeed","transactionid":"d293f670-f0b3-11e1-aff1-0800200c9a66"}
-
-Subscribe to data reply:
-{"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"}
-
-Set property request:
-{ "type" : "method", "name" : "set", "data" : { "property" : "MachineGunTurretStatus", "value" : "true", "zone" : 0 }, "transactionid" : "4123123123" }
-
-Set property reply:
-{ "type" : "methodReply", "name" : "set", "data" : { "property" : "MachineGunTurretStatus", "value" : "true", "zone" : 0, "success" : true }, "transactionid" : "4123123123" }
diff --git a/plugins/websocket/protocol.idl b/plugins/websocket/protocol.idl
new file mode 100644
index 00000000..cb24cf1e
--- /dev/null
+++ b/plugins/websocket/protocol.idl
@@ -0,0 +1,440 @@
+/*!
+ * \mainpage Websocket Plugin Protocol Documentation
+ * \version @PROJECT_VERSION@
+ *
+ * <a href="../../../html/index.html">Back to AMB Documentation Main</a>
+ * \section intro Introduction
+ * This document describes the AMB Websocket protocol. The messages are passed either as JSON or in binary format. The binary format is
+ * defined by the <a href="http://doc.qt.io/qt-5/qjsondocument.html#toBinaryData">Qt project</a>. The JSON format is described in protocol.idl.
+ *
+ * For information about the using the plugin with AMB, see <a href="../../websocket.README">the plugin documentation</a>
+ *
+ * \section example Example javascript
+ * The following is an example of using the websocket protocol in html5. For a more complete example, see the <a href="../test/index.html">html test</a>.
+ * \code
+ * socket = new WebSocket('ws://localhost:23000/');
+ * socket.onmessage = function (msg)
+ * {
+ * // we got a reply!
+ * console.log(msg);
+ * };
+ *
+ * socket.onopen = function() {
+ * var obj = {
+ * "type" : "method",
+ * "name" : "getSupported",
+ * "transactionid" : 'ReallyUniqueId1',
+ * }
+ * socket.send(JSON.stringify(obj));
+ * };
+ * \endcode
+ */
+
+/*!
+ * \file protocol.idl
+ * \brief this document describes the websocket protocol
+ *
+ */
+
+enum MessageType {
+ "method",
+ "methodReply",
+ "valuechanged"
+}
+
+
+interface BaseMessage {
+
+ /*!
+ * \brief transactionid, id for this transaction. For messages with responses, the transaction id is used to match the request with the response.
+ */
+ attribute DOMString transactionid;
+}
+
+enum PropertyType {
+ "UInt16",
+ "UInt32",
+ "Int16",
+ "Int32",
+ "String",
+ "Double",
+ "Boolean"
+}
+
+/*!
+ * \brief Property represents an AMB property
+ */
+interface Property {
+
+ /*!
+ * \brief property - AMB Property name
+ */
+ attribute DOMString? property;
+
+ /*!
+ * \brief value, value of the property
+ */
+ attribute DOMString? value;
+
+ /*!
+ * \brief zone, zone which this property is in
+ */
+ attribute unsigned short zone;
+
+ /*!
+ * \brief type - type of value
+ */
+ attribute PropertyType? type;
+
+ /*!
+ * \brief timestamp
+ */
+ attribute unsigned double? timestamp;
+
+ /*!
+ * \brief sequence
+ */
+ attribute unsigned long? sequence;
+}
+
+/*!
+ * \brief ValueChanged is a message which is generated when a subscribed Property changes.
+ * Subscribe will cause this message to be generated. Unsubscribe stops this message.
+ * \see Subscribe
+ * \see Unsubscribe
+ * The following is an example message for this interface:
+ * \code
+ * {"type" : "valuechanged", "name" : "VehicleSpeed", "data" : {"value" : "217", "zone" : 0, 'type' : 'UInt16', "timestamp" : "1354521964.60253", "sequence" : "0"}, "transactionid" : "d293f670-f0b3-11e1-aff1-0800200c9a66" }
+ * \endcode
+ */
+interface ValueChanged : BaseMessage {
+
+ /*!
+ * \brief message type
+ */
+ const MessageType type = "valuechanged";
+
+ /*!
+ * \brief name of this message.
+ * This represents the property name which changed in this message
+ */
+ attribute DOMString name;
+
+ /*!
+ * \brief data represents the value for the property indicated by 'name'
+ */
+ attribute Property data;
+}
+
+/*!
+ * \brief GetPropertyRequest - request the value of a property
+ * The following is an example of this message:
+ * \code
+ * {"type" : "method", "name" : "get", "data" : { "property" : "VehicleSpeed", "zone" : 0 }, "transactionid" : "d293f670-f0b3-11e1-aff1-0800200c9a66"}
+ * \endcode
+ */
+interface GetPropertyRequest : BaseMessage {
+
+ /*!
+ * \brief message type
+ */
+ const MessageType type = "method";
+
+ /*!
+ * \brief name of this message.
+ * This represents the property name which changed in this message
+ */
+ const DOMString name = "get";
+
+ /*!
+ * \brief data represents property to get
+ * Property attributes type, timestamp, value, and sequence are ignored.
+ */
+ attribute Property data;
+}
+
+/*!
+ * \brief GetPropertyReply - response to GetPropertyRequest
+ * The following is an example of this message:
+ * \code
+ * {"type" : "methodReply", "name" : "get", "data" : {"property" : "VehicleSpeed", "value" : "17", "timestamp" : "1354521964.24962", "sequence" : "0" }, "transactionid" : "d293f670-f0b3-11e1-aff1-0800200c9a66"}
+ * \endcode
+ */
+interface GetPropertyReply : BaseMessage {
+
+ /*!
+ * \brief message type
+ */
+ const MessageType type = "methodReply";
+
+ /*!
+ * \brief name of this methodReply.
+ */
+ const DOMString name = "get";
+
+ /*!
+ * \brief data represents the requested property value
+ */
+ attribute Property data;
+}
+
+/*!
+ * \brief GetSupportedRequest - request supported properties
+ * The following is an example of this message:
+ * \code
+ * {"type" : "method", "name" : "getSupported", "transactionid" : "d293f670-f0b3-11e1-aff1-0800200c9a66"}
+ * \endcode
+ */
+interface GetSupportedRequest : BaseMessage {
+ /*!
+ * \brief message type
+ */
+ const MessageType type = "method";
+
+ /*!
+ * \brief name of this method.
+ */
+ const DOMString name = "getSupported";
+}
+
+/*!
+ * \brief GetSupportedReply- reply for supported properties
+ * The following is an example of this message:
+ * \code
+ * {"type" : "methodReply", "name" : "getSupported", "data" : [{'property' :'EngineSpeed', 'zone' : 0, 'type' : 'UInt16'}, "{'property' :'VehicleSpeed', 'zone' : 0, 'type' : 'UInt16'}], "transactionid" : "d293f670-f0b3-11e1-aff1-0800200c9a66"}
+ * \endcode
+ */
+interface GetSupportedReply : BaseMessage {
+ /*!
+ * \brief message type
+ */
+ const MessageType type = "methodReply";
+
+ /*!
+ * \brief name of this methodReply.
+ */
+ const DOMString name = "getSupported";
+
+ /*!
+ * \brief data - array of properties supported by the system
+ */
+ attribute Property[] data;
+}
+
+/*!
+ * \brief SupportedChanged - message occures when the system's supported properties changes
+ * NOTE: this message is not being generated in 0.13
+ * The following is an example of this message:
+ * \code
+ * {"type" : "methodReply", "name" : "supportedChanged", "data" : [{'property' :'EngineSpeed', 'zone' : 0, 'type' : 'UInt16'}, "{'property' :'VehicleSpeed', 'zone' : 0, 'type' : 'UInt16'}], "transactionid" : "d293f670-f0b3-11e1-aff1-0800200c9a66"}
+ * \endcode
+ */
+interface SupportedChanged : BaseMessage {
+ /*!
+ * \brief message type
+ */
+ const MessageType type = "methodReply";
+
+ /*!
+ * \brief name of this methodReply.
+ */
+ const DOMString name = "getSupported";
+
+ /*!
+ * \brief data - array of properties supported by the system
+ */
+ attribute Property[] data;
+}
+
+/*!
+ * \brief Subscribe - subscribe request
+ * The following is an example of this message:
+ * \code
+ * {"type" : "method", "name" : "subscribe", "property" : "EngineSpeed", "transactionid" : "d293f670-f0b3-11e1-aff1-0800200c9a66"}
+ * \endcode
+ */
+interface Subscribe : BaseMessage {
+
+ /*!
+ * \brief message type
+ */
+ const MessageType type = "method";
+
+ /*!
+ * \brief name of the method.
+ */
+ const DOMString name = "subscribe";
+
+ /*!
+ * \brief property to subscribe to
+ */
+ attribute DOMString property;
+}
+
+/*!
+ * \brief Unsubscribe - unsubscribe request
+ * The following is an example of this message:
+ * \code
+ * {"type" : "method", "name" : "unsubscribe", "property" : "EngineSpeed", "transactionid" : "d293f670-f0b3-11e1-aff1-0800200c9a66"}
+ * \endcode
+ */
+interface Unsubscribe : BaseMessage {
+
+ /*!
+ * \brief message type
+ */
+ const MessageType type = "method";
+
+ /*!
+ * \brief name of the method.
+ */
+ const DOMString name = "subscribe";
+
+ /*!
+ * \brief property to subscribe to
+ */
+ attribute DOMString property;
+}
+
+/*!
+ * \brief GetRangedRequest - request a range of logged properties
+ * The following is an example of this message:
+ * \code
+ * {"type" : "method", "name" : "getRange", "data" : ["VehicleSpeed", "EngineSpeed"], "timeBegin" : "1368825008.35948",
+ * "timeEnd" : "1368825018.35948", "sequenceBegin" : "-1", "sequenceEnd" : "-1", "transactionid" : "b07589ba-417c-4604-80c6-01c0dcbd524d"}
+ * \endcode
+ */
+interface GetRangedRequest : BaseMessage {
+
+ /*!
+ * \brief message type
+ */
+ const MessageType type = "method";
+
+ /*!
+ * \brief name of the method.
+ */
+ const DOMString name = "getRange";
+
+ /*!
+ * \brief data - properties to request
+ */
+ attribute DOMString[] data;
+
+ /*!
+ * \brief zone, zone which this property is in
+ */
+ attribute unsigned short? zone;
+
+ /*!
+ * \brief timeBegin in seconds since Unix Epoc
+ */
+ attribute unsigned double? timeBegin;
+
+ /*!
+ * \brief timeEnd in seconds since Unix Epoc
+ */
+ attribute unsigned double? timeEnd;
+
+ /*!
+ * \brief sequenceBegin
+ */
+ attribute unsigned long? sequenceBegin;
+
+ /*!
+ * \brief sequenceEnd
+ */
+ attribute unsigned long? sequenceEnd;
+}
+
+/*!
+ * \brief GetRangedReply - reply for GetRangedRequest
+ * The following is an example of this message:
+ * \code
+ * {"type" : "methodReply", "name" : "getRanged", "data" : [{'property' :'EngineSpeed', 'zone' : 0, 'type' : 'UInt16'}, "{'property' :'VehicleSpeed', 'zone' : 0, 'type' : 'UInt16'}], "transactionid" : "d293f670-f0b3-11e1-aff1-0800200c9a66"}
+ * \endcode
+ */
+interface GetRangedReply : BaseMessage {
+ /*!
+ * \brief message type
+ */
+ const MessageType type = "methodReply";
+
+ /*!
+ * \brief name of this methodReply.
+ */
+ const DOMString name = "getRanged";
+
+ /*!
+ * \brief data - array of properties supported by the system
+ */
+ attribute Property[] data;
+}
+
+/*!
+ * \brief SetPropertyRequest - request to set a property
+ * The following is an example of this message:
+ * \code
+ * { "type" : "method", "name" : "set", "data" : { "property" : "MachineGunTurretStatus", "value" : "true", "zone" : 0 }, "transactionid" : "4123123123" }
+ * \endcode
+ */
+interface SetPropertyRequest : BaseMessage {
+
+ /*!
+ * \brief message type
+ */
+ const MessageType type = "method";
+
+ /*!
+ * \brief name of this methodReply.
+ */
+ const DOMString name = "set";
+
+ /*!
+ * \brief data represents the new property value
+ */
+ attribute Property data;
+}
+
+enum Error {
+ "NoError",
+ "Timeout",
+ "InvalidOperation",
+ "PermissionDenied",
+ "ZoneNotSupported"
+}
+
+/*!
+ * \brief SetPropertyReply - reply for SetPropertyRequest
+ * The following is an example of this message:
+ * \code
+ * { "type" : "methodReply", "name" : "set", "data" : { "property" : "MachineGunTurretStatus", "value" : "true", "zone" : 0}, "success" : true, "error" : "NoError", "transactionid" : "4123123123" }
+ * \endcode
+ */
+interface SetPropertyReply : BaseMessage {
+
+ /*!
+ * \brief message type
+ */
+ const MessageType type = "methodReply";
+
+ /*!
+ * \brief name of this methodReply.
+ */
+ const DOMString name = "set";
+
+ /*!
+ * \brief data represents the new property value
+ */
+ attribute Property data;
+
+ /*!
+ * \brief success - true if the set operation was successful
+ */
+ attribute boolean success;
+
+ /*!
+ * \brief error - error code
+ */
+ attribute Error error;
+}
diff --git a/plugins/websocket/test/servertest/client.html b/plugins/websocket/test/servertest/client.html
deleted file mode 100644
index 9ef2ee3b..00000000
--- a/plugins/websocket/test/servertest/client.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!doctype html>
-<html lang="en">
-<head>
- <title>IVI API Tester</title>
- <meta charset="utf-8">
- <link rel="stylesheet" href="../style.css"/>
- <script src="../api.js"></script>
-</head>
-<body onload='init("ws://localhost:23023/vehicle?client", "")'>
- <div id="result">
- </div>
- <div id="tester">
- </div>
- <script src="../events.js"></script>
- <script src="../test.js"></script>
-</body>
-</html>
diff --git a/plugins/websocket/test/servertest/server.html b/plugins/websocket/test/servertest/server.html
deleted file mode 100644
index 43dc72ab..00000000
--- a/plugins/websocket/test/servertest/server.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!doctype html>
-<html lang="en">
-<head>
- <title>IVI API Server Test</title>
- <meta charset="utf-8">
- <style>
-#result {
- position: absolute;
- height: 99%;
- width: 99%;
- overflow-y: auto;
- word-wrap: break-word;
-}
- </style>
- <script src="../events.js"></script>
- <script src="server.js"></script>
-</head>
-<body>
- <div id="result">
- </div>
-</body>
-</html>
diff --git a/plugins/websocket/test/servertest/server.js b/plugins/websocket/test/servertest/server.js
deleted file mode 100644
index 3fcda404..00000000
--- a/plugins/websocket/test/servertest/server.js
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright (c) 2012, Intel Corporation.
- *
- * This program is licensed under the terms and conditions of the
- * Apache License, version 2.0. The full text of the Apache License is at
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- */
-
-/* --------------------------- utility code ------------------------------- */
-
-var PRINT = {
- logElement : null,
- init : function(log_id) {
- this.logElement = document.getElementById(log_id);
- },
-
- scrollToBottom : function() {
- this.logElement.scrollTop = this.logElement.scrollHeight;
- },
-
- incoming : function(msg) {
- this.logElement.innerHTML += "<div style='color: blue'> REQUEST: " + msg + "</div>";
- this.scrollToBottom();
- },
-
- outgoing : function(msg) {
- this.logElement.innerHTML += "<div style='color: purple'> RESPONSE: " + msg + "</div>";
- this.scrollToBottom();
- },
-
- pass : function(msg) {
- this.logElement.innerHTML += "<div style='color: green'> SUCCESS: " + msg + "</div>";
- this.scrollToBottom();
- },
-
- fail : function(msg) {
- this.logElement.innerHTML += "<div style='color: red'> FAIL: " + msg + "</div>";
- this.scrollToBottom();
- },
-
- log : function(msg) {
- this.logElement.innerHTML += "<div class='LogClass'> " + msg + "</div>";
- this.scrollToBottom();
- },
-}
-
-/* ----------------------------- test code --------------------------------- */
-
-function VehicleServer(socketUrl)
-{
- var self = this;
- this.vehicleEventType = new VehicleEventType();
- this.subscriptions = [];
-
- this.Signal = function(name)
- {
- var me = this;
- this.users = 0;
- this.name = name;
- this.start = function() {
- if(me.users <= 0)
- {
- var interval = Math.floor(Math.random()*5000) + 1000;
- me.timer = setInterval(function() {
- var value = parseInt(self.vehicleEventType.getValue(me.name)) + 1;
- self.vehicleEventType.setValue(me.name, value);
- var obj = {
- "type" : "valuechanged",
- "name": me.name,
- "data" : value
- };
- self.socket.send(JSON.stringify(obj));
- }, interval);
- }
- me.users = 1;
- }
- this.stop = function() {
- me.users--;
- if((me.users <= 0)&&(me.timer != undefined))
- {
- clearInterval(me.timer);
- }
- }
- }
-
- function init() {
- if ("WebSocket" in window)
- {
- var list = self.vehicleEventType.getValueEventList();
- for(var i = 0; i < list.length; i++)
- {
- self.subscriptions[i] = new self.Signal(list[i]);
- }
-
- self.socket = new WebSocket(socketUrl);
- self.socket.onopen = function()
- {
- PRINT.pass("Server READY");
- };
- self.socket.onclose = function()
- {
- PRINT.fail("Server CLOSED");
- };
- self.socket.onerror = function(e)
- {
- PRINT.fail("Server ERROR: "+e.data);
- };
- self.socket.onmessage = function (e)
- {
- self.receive(e.data);
- };
- }
- else
- {
- PRINT.fail("This browser doesn't appear to support websockets!");
- }
- }
- init();
-}
-
-VehicleServer.prototype.subscribe = function(list)
-{
- for(var i = 0; i < this.subscriptions.length; i++)
- {
- if(list.indexOf(this.subscriptions[i].name) >= 0)
- {
- this.subscriptions[i].start();
- }
- }
-}
-
-VehicleServer.prototype.unsubscribe = function(list)
-{
- for(var i = 0; i < this.subscriptions.length; i++)
- {
- if(list.indexOf(this.subscriptions[i].name) >= 0)
- {
- this.subscriptions[i].stop();
- }
- }
-}
-
-VehicleServer.prototype.receive = function(msg)
-{
- var event = JSON.parse(msg);
- /* accept only methods with transaction ids */
- if((event == undefined)||(event.transactionid == undefined)||
- (event.type != "method"))
- {
- return;
- }
-
- var obj;
- PRINT.incoming(msg);
- if(event.name === "getSupportedEventTypes")
- {
- var data;
- if(event.writeable)
- {
- data = this.vehicleEventType.getValueEventList(event.data);
- }
- else
- {
- data = this.vehicleEventType.getSupportedEventList(event.data);
- }
- obj = {
- "type" : "methodReply",
- "name": event.name,
- "transactionid" : event.transactionid,
- "data" : data
- };
- }
- else if(event.name === "get")
- {
- var names = this.vehicleEventType.getValuesEventList(event.data);
- if(names.length > 0)
- {
- obj = {
- "type" : "methodReply",
- "name": event.name,
- "transactionid" : event.transactionid,
- "data" : []
- };
- for(i in names)
- {
- var value = this.vehicleEventType.getValue(names[i]);
- obj.data.push({"name" : names[i], "value" : value});
- }
- }
- else
- {
- obj = {
- "type" : "methodReply",
- "name": event.name,
- "transactionid" : event.transactionid,
- "error" : event.data + " is not a valid event"
- };
- }
- }
- else if(event.name === "set")
- {
- var bad = [];
- var good = [];
- for(var i = 0; i < event.data.length; i++)
- {
- if((event.data[i].value != undefined) &&
- this.vehicleEventType.isValueEvent(event.data[i].property))
- {
- this.vehicleEventType.setValue(event.data[i].property, parseInt(event.data[i].value));
- good[good.length] = event.data[i].property;
- }
- else
- {
- bad[bad.length] = event.data[i].property;
- }
- }
-
- obj = {
- "type" : "methodReply",
- "name": event.name,
- "transactionid" : event.transactionid
- };
-
- if(bad.length > 0)
- {
- obj.error = "Failed to set:";
- for(var i = 0; i < bad.length; i++)
- {
- obj.error += " "+bad[i];
- }
- }
-
- if(good.length > 0)
- {
- obj.data = "Successfully set:";
- for(var i = 0; i < good.length; i++)
- {
- obj.data += " "+good[i];
- }
- }
- }
- else if(event.name === "subscribe")
- {
- var names = this.vehicleEventType.getValuesEventList(event.data);
- if(names.length > 0)
- {
- obj = {
- "type" : "methodReply",
- "name": event.name,
- "transactionid" : event.transactionid,
- "data" : names
- };
- for(i in names)
- {
- this.subscribe(names[i]);
- }
- }
- else
- {
- obj = {
- "type" : "methodReply",
- "name": event.name,
- "transactionid" : event.transactionid,
- "error" : "no valid events provided"
- };
- }
- }
- else if(event.name === "unsubscribe")
- {
- var names = this.vehicleEventType.getValuesEventList(event.data);
- if(names.length > 0)
- {
- obj = {
- "type" : "methodReply",
- "name": event.name,
- "transactionid" : event.transactionid,
- "data" : names
- };
- for(i in names)
- {
- this.unsubscribe(names[i]);
- }
- }
- else
- {
- obj = {
- "type" : "methodReply",
- "name": event.name,
- "transactionid" : event.transactionid,
- "error" : "no valid events provided"
- };
- }
- }
- else
- {
- obj = {
- "type" : "methodReply",
- "name": event.name,
- "transactionid" : event.transactionid,
- "error" : event.name + " is not a valid method"
- };
- }
- PRINT.outgoing(JSON.stringify(obj));
- this.socket.send(JSON.stringify(obj));
-}
-
-window.addEventListener('load', function () {
- "use strict";
- PRINT.init("result");
- var server = new VehicleServer("ws://localhost:23023/vehicle?server");
-});
diff --git a/plugins/websocket/websocketsinkmanager.cpp b/plugins/websocket/websocketsinkmanager.cpp
index b75db03a..5975c65f 100644
--- a/plugins/websocket/websocketsinkmanager.cpp
+++ b/plugins/websocket/websocketsinkmanager.cpp
@@ -191,19 +191,23 @@ void WebSocketSinkManager::addSingleShotRangedSink(libwebsocket* socket, Propert
rangedRequest.timeEnd = end;
rangedRequest.sequenceBegin = seqstart;
rangedRequest.sequenceEnd = seqend;
+ rangedRequest.properties = properties;
- rangedRequest.completed = [socket,id](AsyncRangePropertyReply* reply)
+ rangedRequest.completed = [socket, id](AsyncRangePropertyReply* reply)
{
QVariantMap replyvar;
QVariantList list;
std::list<AbstractPropertyType*> values = reply->values;
- for(auto itr = values.begin(); itr != values.end(); itr++)
+ for(auto value : values)
{
QVariantMap obj;
- obj["value"]= (*itr)->toString().c_str();
- obj["timestamp"] = (*itr)->timestamp;
- obj["sequence"] = (*itr)->sequence;
+ obj["name"] = value->name.c_str();
+ obj["property"] = value->name.c_str();
+ obj["value"] = value->toString().c_str();
+ obj["timestamp"] = value->timestamp;
+ obj["zone"] = value->zone;
+ obj["sequence"] = value->sequence;
list.append(obj);
}
@@ -242,27 +246,33 @@ void WebSocketSinkManager::removeSink(libwebsocket* socket,VehicleProperty::Prop
lwsWriteVariant(socket, reply);
}
}
-void WebSocketSinkManager::setValue(libwebsocket* socket,VehicleProperty::Property property,string value,Zone::Type zone,string uuid)
+void WebSocketSinkManager::setValue(libwebsocket* socket, VehicleProperty::Property property, string value,Zone::Type zone, string uuid)
{
- AbstractPropertyType* type = VehicleProperty::getPropertyTypeForPropertyNameValue(property,value);
+ AbstractPropertyType* type = VehicleProperty::getPropertyTypeForPropertyNameValue(property, value);
AsyncSetPropertyRequest request;
request.property = property;
+
request.value = type;
request.zoneFilter = zone;
request.completed = [&](AsyncPropertyReply* reply)
{
QVariantMap data;
- data["property"] = property.c_str();
- data["zone"] = zone;
- data["source"] = reply->value->sourceUuid.c_str();
- data["success"] = reply->success;
+ if(reply->value)
+ {
+ data["property"] = property.c_str();
+ data["zone"] = zone;
+ data["source"] = reply->value->sourceUuid.c_str();
+ data["value"] = reply->value->toString().c_str();
+ }
QVariantMap replyvar;
replyvar["type"]="methodReply";
replyvar["name"]="set";
replyvar["data"]= data;
replyvar["transactionid"]=uuid.c_str();
+ replyvar["success"] = reply->success;
+ replyvar["error"] = AsyncPropertyReply::errorToStr(reply->error).c_str();
lwsWriteVariant(socket, replyvar);
@@ -452,16 +462,21 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
{
if(name == "getRanged")
{
- QVariantMap data = call["data"].toMap();
+ QVariant dataVariant = call["data"];
+
+ QVariantList data = dataVariant.toList();
PropertyList propertyList;
- propertyList.push_back(data["property"].toString().toStdString());
+ Q_FOREACH(QVariant v, data)
+ {
+ propertyList.push_back(v.toString().toStdString());
+ }
- double timeBegin = data["timeBegin"].toDouble();
- double timeEnd = data["timeEnd"].toDouble();
- double sequenceBegin = data["sequenceBegin"].toInt();
- double sequenceEnd = data["sequenceEnd"].toInt();
+ double timeBegin = call["timeBegin"].toDouble();
+ double timeEnd = call["timeEnd"].toDouble();
+ int sequenceBegin = call["sequenceBegin"].toInt();
+ int sequenceEnd = call["sequenceEnd"].toInt();
if ((timeBegin < 0 && timeEnd > 0) || (timeBegin > 0 && timeEnd < 0))
{
@@ -473,7 +488,7 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
}
else
{
- sinkManager->addSingleShotRangedSink(wsi,propertyList,timeBegin,timeEnd,sequenceBegin,sequenceEnd,id);
+ sinkManager->addSingleShotRangedSink(wsi, propertyList, timeBegin, timeEnd, sequenceBegin, sequenceEnd, id);
}
}
else if (name == "get")
@@ -495,7 +510,7 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
{
zone = data["zone"].toInt();
}
- sinkManager->setValue(wsi,data["property"].toString().toStdString(), data["value"].toString().toStdString(), zone, id);
+ sinkManager->setValue(wsi, data["property"].toString().toStdString(), data["value"].toString().toStdString(), zone, id);
}
else if (name == "subscribe")
{
@@ -530,6 +545,7 @@ static int websocket_callback(struct libwebsocket_context *context,struct libweb
QVariantMap map;
map["zone"] = zone;
map["name"] = i.c_str();
+ map["property"] = i.c_str();
map["type"] = basicType.c_str();
map["source"] = source.c_str();
diff --git a/plugins/websocket/websocketsinkmanager.h b/plugins/websocket/websocketsinkmanager.h
index 1d1594e8..1b2fba64 100644
--- a/plugins/websocket/websocketsinkmanager.h
+++ b/plugins/websocket/websocketsinkmanager.h
@@ -45,7 +45,7 @@ public:
void init();
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);
+ void setValue(libwebsocket* socket,VehicleProperty::Property property, string value, Zone::Type zone, string uuid);
PropertyList getSupportedProperties();
AbstractRoutingEngine * router() { return routingEngine; }
diff --git a/plugins/websocket/websocketsource.cpp b/plugins/websocket/websocketsource.cpp
index eb0211a5..f4b2ff9e 100644
--- a/plugins/websocket/websocketsource.cpp
+++ b/plugins/websocket/websocketsource.cpp
@@ -391,8 +391,6 @@ static int callback_http_only(libwebsocket_context *context, struct libwebsocket
string name = call["name"].toString().toStdString();
string id = call["transactionid"].toString().toStdString();
- list<pair<string,string> > pairdata;
-
if(type == "multiframe")
{
manager->expectedMessageFrames = call["frames"].toInt();
@@ -464,7 +462,7 @@ static int callback_http_only(libwebsocket_context *context, struct libwebsocket
{
QVariantMap d = p.toMap();
Zone::Type zone = d["zone"].toInt();
- std::string name = d["name"].toString().toStdString();
+ std::string name = d["property"].toString().toStdString();
std::string proptype = d["type"].toString().toStdString();
std::string source = d["source"].toString().toStdString();
@@ -484,12 +482,17 @@ static int callback_http_only(libwebsocket_context *context, struct libwebsocket
{
QVariantMap obj = d.toMap();
- std::string name = obj["name"].toString().toStdString();
+ std::string name = obj["property"].toString().toStdString();
std::string value = obj["value"].toString().toStdString();
double timestamp = obj["timestamp"].toDouble();
int sequence = obj["sequence"].toInt();
AbstractPropertyType* type = VehicleProperty::getPropertyTypeForPropertyNameValue(name, value);
+ if(!type)
+ {
+ DebugOut() << "TODO: support custom types here: " << endl;
+ continue;
+ }
type->timestamp = timestamp;
type->sequence = sequence;
@@ -511,7 +514,7 @@ static int callback_http_only(libwebsocket_context *context, struct libwebsocket
else if (name == "get")
{
- DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "Got \"GET\" event:" << pairdata.size()<<endl;
+ DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "Got \"GET\" reply" << endl;
if (source->uuidReplyMap.find(id) != source->uuidReplyMap.end())
{
QVariantMap obj = call["data"].toMap();
@@ -522,14 +525,15 @@ static int callback_http_only(libwebsocket_context *context, struct libwebsocket
int sequence = obj["sequence"].toInt();
Zone::Type zone = obj["zone"].toInt();
- AbstractPropertyType* v = VehicleProperty::getPropertyTypeForPropertyNameValue(property, value);
+ auto v = amb::make_unique(VehicleProperty::getPropertyTypeForPropertyNameValue(property, value));
+
v->timestamp = timestamp;
v->sequence = sequence;
v->zone = zone;
if (source->uuidReplyMap.find(id) != source->uuidReplyMap.end() && source->uuidReplyMap[id]->error != AsyncPropertyReply::Timeout)
{
- source->uuidReplyMap[id]->value = v;
+ source->uuidReplyMap[id]->value = v.get();
source->uuidReplyMap[id]->success = true;
source->uuidReplyMap[id]->completed(source->uuidReplyMap[id]);
source->uuidReplyMap.erase(id);
@@ -539,15 +543,56 @@ static int callback_http_only(libwebsocket_context *context, struct libwebsocket
{
DebugOut() << "get methodReply has been recieved, without a request being in!. This is likely due to a request coming in after the timeout has elapsed.\n";
}
-
- delete v;
}
else
{
DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "GET Method Reply INVALID! Multiple properties detected, only single are supported!!!" << "\n";
}
- //data will contain a property/value map.
+
+ }
+ else if (name == "set")
+ {
+ DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "Got \"SET\" event" << endl;
+ std::string id = call["transactionid"].toString().toStdString();
+
+ if(source->setReplyMap.find(id) != source->setReplyMap.end() && source->setReplyMap[id]->error != AsyncPropertyReply::Timeout)
+ {
+ AsyncPropertyReply* reply = source->setReplyMap[id];
+
+ reply->success = call["success"].toBool();
+ reply->error = AsyncPropertyReply::strToError(call["error"].toString().toStdString());
+
+ QVariantMap obj = call["data"].toMap();
+
+ std::string property = obj["property"].toString().toStdString();
+ std::string value = obj["value"].toString().toStdString();
+
+ double timestamp = obj["timestamp"].toDouble();
+ int sequence = obj["sequence"].toInt();
+ Zone::Type zone = obj["zone"].toInt();
+
+ auto v = amb::make_unique(VehicleProperty::getPropertyTypeForPropertyNameValue(property, value));
+
+ if(v)
+ {
+ v->timestamp = timestamp;
+ v->sequence = sequence;
+ v->zone = zone;
+ }
+ else
+ {
+ throw std::runtime_error("property may not be registered.");
+ }
+
+ reply->value = v.get();
+ reply->completed(reply);
+ source->setReplyMap.erase(id);
+ }
+ }
+ else
+ {
+ DebugOut(DebugOut::Warning) << "Unhandled methodReply: " << name << endl;
}
}
@@ -698,7 +743,6 @@ void WebSocketSource::getRangePropertyAsync(AsyncRangePropertyReply *reply)
replyvar["sequenceBegin"] = reply->sequenceBegin;
replyvar["sequenceEnd"] = reply->sequenceEnd;
-
QStringList properties;
for (auto itr = reply->properties.begin(); itr != reply->properties.end(); itr++)
@@ -716,23 +760,23 @@ AsyncPropertyReply * WebSocketSource::setProperty( AsyncSetPropertyRequest reque
{
AsyncPropertyReply* reply = new AsyncPropertyReply(request);
+ std::string uuid = amb::createUuid();
+
QVariantMap data;
data["property"] = request.property.c_str();
data["value"] = request.value->toString().c_str();
data["zone"] = request.zoneFilter;
-
QVariantMap replyvar;
replyvar["type"] = "method";
replyvar["name"] = "set";
replyvar["data"] = data;
- replyvar["transactionid"] = amb::createUuid().c_str();
+ replyvar["transactionid"] = uuid.c_str();
lwsWriteVariant(clientsocket, replyvar);
- ///TODO: we should actually wait for a response before we simply complete the call
- reply->success = true;
- reply->completed(reply);
+ setReplyMap[uuid] = reply;
+
return reply;
}
diff --git a/plugins/websocket/websocketsource.h b/plugins/websocket/websocketsource.h
index c19a6e86..4af23ba2 100644
--- a/plugins/websocket/websocketsource.h
+++ b/plugins/websocket/websocketsource.h
@@ -52,9 +52,10 @@ public:
void supportedChanged(const PropertyList &) {}
void setConfiguration(std::map<std::string, std::string> config);
- std::map<std::string,AsyncPropertyReply*> uuidReplyMap;
+ std::map<std::string, AsyncPropertyReply*> uuidReplyMap;
std::map<std::string,double> uuidTimeoutMap;
std::map<std::string, AsyncRangePropertyReply*> uuidRangedReplyMap;
+ std::map<std::string, AsyncPropertyReply*> setReplyMap;
int partialMessageIndex;
QByteArray incompleteMessage;
diff --git a/tools/ambctl.py b/tools/ambctl.py
index 3d79a7fe..0a84d26c 100644
--- a/tools/ambctl.py
+++ b/tools/ambctl.py
@@ -22,34 +22,121 @@ class bcolors:
WHITE = '\x1b[37m'
BLUE = '\x1b[34m'
+class Autocomplete:
+ class Cmd:
+ name = ""
+ description = ""
+ def __init__(self, n, d):
+ self.name = n
+ self.description = d
+
+ commands = []
+ properties = []
+
+ def __init__(self):
+ self.commands = []
+ self.commands.append(Autocomplete.Cmd('help', 'Prints help data (also see COMMAND help)'))
+ self.commands.append(Autocomplete.Cmd('list', 'List supported ObjectNames'))
+ self.commands.append(Autocomplete.Cmd('get', 'Get properties from an ObjectName'))
+ self.commands.append(Autocomplete.Cmd('listen', 'Listen for changes on an ObjectName'))
+ self.commands.append(Autocomplete.Cmd('set', 'Set a property for an ObjectName'))
+ self.commands.append(Autocomplete.Cmd('getHistory', 'Get logged data within a time range'))
+ self.commands.append(Autocomplete.Cmd('plugin', 'enable, disable and get info on a plugin'))
+ self.commands.append(Autocomplete.Cmd('quit', 'Exit ambctl'))
+
+ bus = dbus.SystemBus()
+ try:
+ managerObject = bus.get_object("org.automotive.message.broker", "/");
+ managerInterface = dbus.Interface(managerObject, "org.automotive.Manager")
+ self.properties = managerInterface.List()
+ except dbus.exceptions.DBusException, error:
+ print error
+
+ def complete(self, partialString):
+ results = []
+
+ sameString = ""
+
+ for cmd in self.commands:
+ if not (len(partialString)) or cmd.name.startswith(partialString):
+ results.append(cmd.name)
+
+ for property in self.properties:
+ if not(len(partialString)) or property.startswith(partialString):
+ results.append(str(property))
+
+ if len(results) > 1 and len(results[0]) > 0:
+ for i in range(len(results[0])):
+ for j in range(len(results[0])-i+1):
+ if j > len(sameString) and all(results[0][i:i+j] in x for x in results):
+ sameString = results[0][i:i+j]
+ elif len(results) == 1:
+ sameString = results[0]
+
+ return results, sameString
+
+
def help():
- help = ("Available commands:\n"
- +bcolors.HEADER+ "help" +bcolors.WHITE+ " Prints help data\n"
- +bcolors.HEADER+ "list" +bcolors.WHITE+ " List supported ObjectNames\n"
- +bcolors.HEADER+ "get" +bcolors.WHITE+ " Get properties from an ObjectName\n"
- +bcolors.HEADER+ "listen" +bcolors.WHITE+ " Listen for changes on an ObjectName\n"
- +bcolors.HEADER+ "set" +bcolors.WHITE+ " Set a property for an ObjectName\n"
- +bcolors.HEADER+ "getHistory" +bcolors.WHITE+ " Get logged data within a time range\n"
- +bcolors.HEADER+ "quit" +bcolors.WHITE+ " Exit ambctl\n")
+ help = ("Available commands:\n")
+ autocomplete = Autocomplete()
+ for cmd in autocomplete.commands:
+ help += bcolors.HEADER + cmd.name + bcolors.WHITE
+ for i in range(1, 15 - len(cmd.name)):
+ help += " "
+ help += cmd.description + "\n"
+
return help
def changed(interface, properties, invalidated):
print json.dumps(properties, indent=2)
+def listPlugins():
+ list = []
+ for root, dirs, files in os.walk('@PLUGIN_SEGMENT_INSTALL_PATH@'):
+ for file in files:
+ fullpath = root + "/" + file;
+ pluginFile = open(fullpath)
+ data = json.load(pluginFile)
+ data['segmentPath'] = fullpath
+ pluginFile.close()
+ list.append(data)
+ return list
+
+def enablePlugin(pluginName, enabled):
+ list = listPlugins()
+
+ for plugin in list:
+ if plugin["name"] == pluginName:
+ try :
+ plugin["enabled"] = enabled
+ file = open(plugin["segmentPath"], 'rw+')
+ plugin.pop('segmentPath', None)
+ fixedData = json.dumps(plugin, separators=(', ', ' : '), indent=4)
+ file.truncate()
+ file.write(fixedData)
+ file.close()
+ return True
+ except IOError, error:
+ print error
+ return False
+ return False
+
+
+
def processCommand(command, commandArgs, noMain=True):
if command == 'help':
- print help()
- return 1
+ print help()
+ return 1
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
try:
- managerObject = bus.get_object("org.automotive.message.broker", "/");
- managerInterface = dbus.Interface(managerObject, "org.automotive.Manager")
+ managerObject = bus.get_object("org.automotive.message.broker", "/");
+ managerInterface = dbus.Interface(managerObject, "org.automotive.Manager")
except:
- print "Error connecting to AMB. is AMB running?"
- return 1
+ print "Error connecting to AMB. is AMB running?"
+ return 1
if command == "list" :
supportedList = managerInterface.List()
@@ -112,7 +199,7 @@ def processCommand(command, commandArgs, noMain=True):
if property == realValue:
print propertyName + " = ", property
else:
- print "Error setting property"
+ print "Error setting property. Expected value: ", realValue, " Received: ", property
return 1
elif command == "getHistory":
if len(commandArgs) == 0:
@@ -136,13 +223,52 @@ def processCommand(command, commandArgs, noMain=True):
object = managerInterface.FindObjectForZone(objectName, zone);
propertiesInterface = dbus.Interface(bus.get_object("org.automotive.message.broker", object),"org.automotive."+objectName)
print json.dumps(propertiesInterface.GetHistory(start, end), indent=2)
+ elif command == "plugin":
+ if len(commandArgs) == 0:
+ commandArgs = ['help']
+ if commandArgs[0] == 'help':
+ print "[list] [pluginName] [on/off]"
+ return 1
+ elif commandArgs[0] == 'list':
+ for plugin in listPlugins():
+ print plugin['name']
+ return 1
+ elif len(commandArgs) == 1:
+ for plugin in listPlugins():
+ if plugin['name'] == commandArgs[0]:
+ print json.dumps(plugin, indent=4)
+ return 1
+ else:
+ print "name: " + plugin['name'] + "==?" + commandArgs[0]
+ print "plugin not found: ", commandArgs[0]
+ return 0
+ else:
+ if len(commandArgs) < 2:
+ return 1
+ enArg = commandArgs[1]
+ if not enArg == "on" and not enArg == "off":
+ print "please use 'on' or 'off' to enable/disable the plugin"
+ return 1
+ plugin = commandArgs[0]
+ enabled = enArg == "on"
+ enStr = "disabled"
+ if enablePlugin(plugin, enabled):
+ if enabled:
+ enStr = "enabled"
+ else:
+ print "Error could not enable", plugin
+
+ print plugin, enStr
+
+ return 1
+
else:
print "Invalid command"
return 1
-parser = argparse.ArgumentParser(prog="ambctl", description='Process DBus mappings.', add_help=False)
+parser = argparse.ArgumentParser(prog="ambctl", description='Automotive Message Broker DBus client tool', add_help=False)
parser.add_argument('command', metavar='COMMAND [help]', nargs='?', default='stdin', help='amb dbus command')
parser.add_argument('commandArgs', metavar='ARG', nargs='*',
help='amb dbus command arguments')
@@ -166,6 +292,7 @@ if args.command == "stdin":
fullprompt = promptAmbctl + promptEnd
curpos = 0
historypos = -1
+ autocomplete = Autocomplete()
def full_line_len(self):
return len(self.fullprompt) + len(self.line)
def insert(self, str):
@@ -262,65 +389,105 @@ if args.command == "stdin":
#print "char: ", ord(str)
if len(str) > 1:
- if ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 68: #left arrow
- if data.arrow_back():
- cursor_left()
- sys.stdout.flush()
- elif ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 67: #right arrow
- if data.arrow_forward():
- cursor_right()
- sys.stdout.flush()
- elif ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 70: #end
- while data.arrow_forward():
- cursor_right()
- sys.stdout.flush()
- elif ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 72: #home
- while data.arrow_back():
- cursor_left()
- sys.stdout.flush()
- elif len(str) == 4 and ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 51 and ord(str[3]) == 126: #del
- data.delete()
- redraw(data)
- elif ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 65:
- #up arrow
- data.save_temp()
- data.history_up()
- while data.arrow_forward():
- cursor_right()
- redraw(data)
- elif ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 66:
- #down arrow
- data.history_down()
- while data.arrow_forward():
- cursor_right()
- redraw(data)
- elif ord(str) == 10: #enter
- if data.line == "":
- return True
- print ""
- words = data.line.split(' ')
- if words[0] == "quit":
- termios.tcsetattr(fd, termios.TCSAFLUSH, old)
- fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
- sys.exit()
- try:
- if len(words) > 1:
- processCommand(words[0], words[1:])
- else:
- processCommand(words[0], [])
- except dbus.exceptions.DBusException, error:
- print error
- except:
- print "Error running command ", sys.exc_info()[0]
- data.push();
- data.clear()
+ if ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 68:
+ #left arrow
+ if data.arrow_back():
+ cursor_left()
+ sys.stdout.flush()
+ elif ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 67:
+ #right arrow
+ if data.arrow_forward():
+ cursor_right()
+ sys.stdout.flush()
+ elif ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 70:
+ #end
+ while data.arrow_forward():
+ cursor_right()
+ sys.stdout.flush()
+ elif ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 72: #home
+ while data.arrow_back():
+ cursor_left()
+ sys.stdout.flush()
+ elif len(str) == 4 and ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 51 and ord(str[3]) == 126:
+ #del
+ data.delete()
redraw(data)
- elif ord(str) == 127: #backspace
- data.back_space()
+ elif ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 65:
+ #up arrow
+ data.save_temp()
+ data.history_up()
+ while data.arrow_forward():
+ cursor_right()
redraw(data)
- elif curses.ascii.isalnum(ord(str)) or ord(str) == curses.ascii.SP: #regular text
- data.insert(str)
+ elif ord(str[0]) == 27 and ord(str[1]) == 91 and ord(str[2]) == 66:
+ #down arrow
+ data.history_down()
+ while data.arrow_forward():
+ cursor_right()
redraw(data)
+ elif ord(str) == 10:
+ #enter
+ if data.line == "":
+ return True
+ print ""
+ words = data.line.split(' ')
+ if words[0] == "quit":
+ termios.tcsetattr(fd, termios.TCSAFLUSH, old)
+ fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
+ sys.exit()
+ try:
+ if len(words) > 1:
+ processCommand(words[0], words[1:])
+ else:
+ processCommand(words[0], [])
+ except dbus.exceptions.DBusException, error:
+ print error
+ except:
+ print "Error running command ", sys.exc_info()[0]
+ data.push();
+ data.clear()
+ redraw(data)
+ elif ord(str) == 127: #backspace
+ data.back_space()
+ redraw(data)
+ elif ord(str) == 9:
+ #tab
+ #get last string:
+ wordsList = data.line.split(' ')
+ toComplete = wordsList[-1]
+ results, samestring = data.autocomplete.complete(toComplete)
+ if len(samestring) and len(samestring) > len(toComplete) and not (samestring == toComplete):
+ if len(wordsList) > 1:
+ data.line = ' '.join(wordsList[0:-1]) + ' ' + samestring
+ else:
+ data.line = samestring
+ while data.arrow_forward():
+ cursor_right()
+
+ elif len(results) and not results[0] == toComplete:
+ print ""
+ if len(results) < 3:
+ print ' '.join(results)
+ else:
+ longestLen = 0
+ for r in results:
+ if len(r) > longestLen:
+ longestLen = len(r)
+ for i in range(0, len(results) / 3):
+ row = ""
+ endRow = -1
+ if len(results) >= i+3:
+ endRow = 2
+ for col in results[i : endRow]:
+ row += col
+ for i in range((longestLen + 5) - len(col)):
+ row += ' '
+ print row
+
+ redraw(data)
+ elif curses.ascii.isalnum(ord(str)) or ord(str) == curses.ascii.SP: #regular text
+ data.insert(str)
+ redraw(data)
return True
print "@PROJECT_PRETTY_NAME@ @PROJECT_VERSION@"
@@ -349,6 +516,7 @@ if args.command == "stdin":
finally:
termios.tcsetattr(fd, termios.TCSAFLUSH, old)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
+ print ""
sys.exit()
else:
diff --git a/tools/genmapping.py b/tools/genmapping.py
index 143a67fc..136f9db7 100755
--- a/tools/genmapping.py
+++ b/tools/genmapping.py
@@ -17,13 +17,22 @@ interfaces = []
class Member:
ambName = ""
memberName = ""
-
+ interfaceName = ""
+ def __init__(self, ifaceName):
+ self.interfaceName = ifaceName
def __repr__(self):
return "Member"
def toString(self):
return "{" + self.ambName + " => " + self.memberName + "}"
def toIdl(self):
- return ' const DOMString ' + self.ambName + ' = "' + self.memberName + '";\n'
+ idl = []
+ idl.append('')
+ idl.append('\t/*!')
+ idl.append('\t * \\brief corresponds with DBus property ' + self.memberName + ' for interface org.automotive.' + self.interfaceName)
+ idl.append('\t * AMB fulfills this member with VehicleProperty::' + self.ambName)
+ idl.append('\t */')
+ idl.append('\tconst DOMString ' + self.ambName + ' = "' + self.memberName + '";\n')
+ return '\n'.join(idl)
class Interface:
def __init__(self):
@@ -37,7 +46,7 @@ class Interface:
output += member.toString() + ","
return output
def toIdl(self):
- output = "interface " + self.name + " {\n"
+ output = "/*! \n * \\brief Corresponds with DBus Interface org.automotive." + self.name + "\n */\ninterface " + self.name + " {\n"
for member in self.members:
output += member.toIdl()
output += "\n};\n"
@@ -59,7 +68,7 @@ for input in args.mappingFiles:
wantPropertyVariant = 'wantPropertyVariant('
i = line.find(wantPropertyVariant)
if i!= -1:
- member = Member()
+ member = Member(interfaces[-1].name)
ambNameEnd = line.find(', "')-2
member.ambName = line[i+len(wantPropertyVariant) : i + ambNameEnd].replace("VehicleProperty::", "")
memberNameBeg = line.find(', "')+3
@@ -78,7 +87,9 @@ with outputFile:
" * \\brief This describes the AMB internal property names to AMB DBus interface property names\n"
" * AMB internal property names are designed to be flat variable names (ie, 'ConvertableRoofStatus'). The DBus\n"
" * properties however follow the naming scheme defined in the W3C automotive business group vehicle <a href='http://w3c.github.io/automotive-bg/data_spec.html'>data specification</a>\n"
- " * The pattern each interface is 'const DOMString AMBProperty = DBusProperty' where 'AMBProperty' is the internal name and 'DBusProperty' is the DBus property name")
+ " * The pattern each interface is 'const DOMString AMBProperty = DBusProperty' where 'AMBProperty' is the internal name and 'DBusProperty' is the DBus property name.\n"
+ " *\n"
+ " * For documentation on the interface and members, please see amb.fidl or the AMB DBus documentation.\n")
header += " */\n\n"
outputFile.write(header)
for iface in interfaces:
diff --git a/xwalk/CMakeLists.txt b/xwalk/CMakeLists.txt
index fb96843f..c2ae60f4 100644
--- a/xwalk/CMakeLists.txt
+++ b/xwalk/CMakeLists.txt
@@ -2,14 +2,14 @@ if(xwalk_vehicle_extension)
pkg_check_modules(gio REQUIRED gio-2.0)
-set(vehicle_api_headers vehicle.h vehicle_instance.h vehicle_extension.h common/extension.h common/picojson.h common/utils.h common/virtual_fs.h
- common/XW_Extension_EntryPoints.h common/XW_Extension.h common/XW_Permissions.h common/XW_Extension_Runtime.h common/XW_Extension_SyncMessage.h)
-set(vehicle_api_sources vehicle.cc vehicle_extension.cc vehicle_instance.cc common/extension.cc common/picojson.h)
+set(vehicle_api_headers vehicle.h vehicle_instance.h vehicle_extension.h common/extension.h common/utils.h common/virtual_fs.h
+ common/XW_Extension_EntryPoints.h common/XW_Extension.h common/XW_Permissions.h common/XW_Extension_Runtime.h common/XW_Extension_SyncMessage.h)
+set(vehicle_api_sources vehicle.cc vehicle_extension.cc vehicle_instance.cc common/extension.cc)
include_directories(${include_dirs} ${CMAKE_CURRENT_SOURCE_DIR}/)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vehicle_api.cc
- COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/generate_api.py ${CMAKE_CURRENT_SOURCE_DIR}/vehicle_api.js kSource_vehicle_api ${CMAKE_CURRENT_BINARY_DIR}/vehicle_api.cc )
+ COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/generate_api.py ${CMAKE_CURRENT_SOURCE_DIR}/vehicle_api.js kSource_vehicle_api ${CMAKE_CURRENT_BINARY_DIR}/vehicle_api.cc )
add_library(vehicle_extension MODULE ${vehicle_api_sources} ${CMAKE_CURRENT_BINARY_DIR}/vehicle_api.cc)
target_link_libraries(vehicle_extension ${link_libraries} amb ${gio_LIBRARIES} -L${CMAKE_CURRENT_BINARY_DIR}/lib)
diff --git a/xwalk/vehicle.cc b/xwalk/vehicle.cc
index cea84802..13275f0f 100644
--- a/xwalk/vehicle.cc
+++ b/xwalk/vehicle.cc
@@ -9,6 +9,7 @@
#include <gio/gio.h>
#include <glib.h>
#include <listplusplus.h>
+#include <picojson.h>
#include <superptr.hpp>
#include <algorithm>
@@ -16,7 +17,6 @@
#include <memory>
#include "common/extension.h"
-#include "common/picojson.h"
common::Instance* Vehicle::CallbackInfo::instance = nullptr;
@@ -320,6 +320,45 @@ Vehicle::Vehicle(common::Instance* instance)
DebugOut(DebugOut::Error) << "calling GetAutomotiveManager: "
<< error_ptr->message << endl;
}
+
+
+ GError* list_error = nullptr;
+ auto supported_list_variant = amb::make_super(
+ g_dbus_proxy_call_sync(manager_proxy_.get(),
+ "List",
+ nullptr,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &list_error));
+
+ auto list_error_ptr = amb::make_super(list_error);
+
+ if (list_error_ptr) {
+ DebugOut(DebugOut::Error) << "error calling List: "
+ << error_ptr->message << endl;
+ return;
+ }
+
+ GVariantIter iter;
+ g_variant_iter_init(&iter, supported_list_variant.get());
+ picojson::array list;
+
+ gchar* propertyName = nullptr;
+
+ while(g_variant_iter_next(&iter,"s", &propertyName))
+ {
+ auto propertyNamePtr = amb::make_super(propertyName);
+
+ std::string p = propertyNamePtr.get();
+
+ std::transform(p.begin(), p.begin()+1, p.begin(), ::tolower);
+ list.push_back(picojson::value(p));
+ }
+
+ picojson::object obj;
+ obj["method"] = picojson::value("vehicleSupportedAttributes");
+ obj["value"] = picojson::value(list);
+
+ instance->PostMessage(picojson::value(obj).serialize().c_str());
}
Vehicle::~Vehicle() {
diff --git a/xwalk/vehicle.h b/xwalk/vehicle.h
index 9308b105..877f031f 100644
--- a/xwalk/vehicle.h
+++ b/xwalk/vehicle.h
@@ -8,13 +8,13 @@
#include <abstractpropertytype.h>
#include <gio/gio.h>
#include <glib.h>
+#include <picojson.h>
#include <superptr.hpp>
#include <string>
#include <thread> // NOLINT
#include <vector>
-#include "common/picojson.h"
namespace common {
diff --git a/xwalk/vehicle_api.js b/xwalk/vehicle_api.js
index 9880558f..23b22b9f 100644
--- a/xwalk/vehicle_api.js
+++ b/xwalk/vehicle_api.js
@@ -8,68 +8,68 @@ var async_calls = {};
var subscriptions = [];
function makeCall(call, msg) {
- async_calls[next_async_call_id] = call;
- msg.asyncCallId = next_async_call_id;
- ++next_async_call_id;
+ async_calls[next_async_call_id] = call;
+ msg.asyncCallId = next_async_call_id;
+ ++next_async_call_id;
- extension.postMessage(JSON.stringify(msg));
+ extension.postMessage(JSON.stringify(msg));
}
function vehicleInterfaceCommonContructor(obj, attname) {
- obj.attributeName = attname;
+ obj.attributeName = attname;
- var msg = {};
- msg['method'] = 'zones';
- msg['name'] = obj.attributeName;
+ var msg = {};
+ msg['method'] = 'zones';
+ msg['name'] = obj.attributeName;
- obj._zones = new Zone;
- obj._supported = false;
+ obj._zones = new Zone;
+ obj._supported = false;
- var call = new AsyncCall(function(data) {
- obj._zones = data;
- });
+ var call = new AsyncCall(function(data) {
+ obj._zones = data;
+ });
- makeCall(call, msg);
+ makeCall(call, msg);
- var supportedMessage = {};
- supportedMessage['method'] = 'supported';
- supportedMessage['name'] = obj.attributeName;
+ var supportedMessage = {};
+ supportedMessage['method'] = 'supported';
+ supportedMessage['name'] = obj.attributeName;
- var supportedCall = new AsyncCall(function(data) {
+ var supportedCall = new AsyncCall(function(data) {
obj._supported = data;
- });
+ });
- makeCall(supportedCall, supportedMessage);
+ makeCall(supportedCall, supportedMessage);
- Object.defineProperty(obj, 'zones', { get: function() { return obj._zones } });
- Object.defineProperty(obj, 'supported', { get: function() { return obj._supported; } });
+ Object.defineProperty(obj, 'zones', { get: function() { return obj._zones } });
+ Object.defineProperty(obj, 'supported', { get: function() { return obj._supported; } });
}
function VehicleInterface(attname) {
- vehicleInterfaceCommonContructor(this, attname);
+ vehicleInterfaceCommonContructor(this, attname);
}
VehicleInterface.prototype.get = function(zone) {
- var msg = {};
- msg['method'] = 'get';
- msg['name'] = this.attributeName;
- msg['zone'] = zone;
+ var msg = {};
+ msg['method'] = 'get';
+ msg['name'] = this.attributeName;
+ msg['zone'] = zone;
- return createPromise(msg);
+ return createPromise(msg);
};
VehicleInterface.prototype.availableForRetrieval = function(attName) {
- return isAvailable(this, attName);
+ return isAvailable(this, attName);
}
VehicleInterface.prototype.availabilityChangedListener = function(callback) {
- if(this.changedListenerCount) {
- this.changedListenerCount++;
- }
- else {
- this.changedListenerCount = 0;
- }
- return this.changedListenerCount;
+ if(this.changedListenerCount) {
+ this.changedListenerCount++;
+ }
+ else {
+ this.changedListenerCount = 0;
+ }
+ return this.changedListenerCount;
}
VehicleInterface.prototype.removeAvailabilityChangedListener = function(handle) {
@@ -77,229 +77,242 @@ VehicleInterface.prototype.removeAvailabilityChangedListener = function(handle)
}
function VehicleSignalInterface(attname) {
- vehicleInterfaceCommonContructor(this, attname);
+ vehicleInterfaceCommonContructor(this, attname);
}
VehicleSignalInterface.prototype = VehicleInterface.prototype;
VehicleSignalInterface.prototype.subscribe = function(callback, zone) {
- if (!zone) zone = new Zone();
+ if (!zone) zone = new Zone();
- var msg = {};
- msg['method'] = 'subscribe';
- msg['name'] = this.attributeName;
- msg['zone'] = zone;
+ var msg = {};
+ msg['method'] = 'subscribe';
+ msg['name'] = this.attributeName;
+ msg['zone'] = zone;
- extension.postMessage(JSON.stringify(msg));
+ extension.postMessage(JSON.stringify(msg));
- msg['callback'] = callback;
+ msg['callback'] = callback;
- subscriptions.push(msg);
+ subscriptions.push(msg);
- return subscriptions.length - 1;
+ return subscriptions.length - 1;
};
VehicleSignalInterface.prototype.unsubscribe = function(handle) {
- var obj = subscriptions[handle];
- subscriptions.splice(handle, 1);
+ var obj = subscriptions[handle];
+ subscriptions.splice(handle, 1);
- var unsubscribe = true;
+ var unsubscribe = true;
- for (var i = 0; i < subscriptions.length; i++) {
- var testObj = subscriptions[i];
+ for (var i = 0; i < subscriptions.length; i++) {
+ var testObj = subscriptions[i];
- if (testObj.name === obj.name && testObj.zone.equals(obj.zone)) {
- unsubscribe = false;
- break;
+ if (testObj.name === obj.name && testObj.zone.equals(obj.zone)) {
+ unsubscribe = false;
+ break;
+ }
}
- }
- if (unsubscribe) {
- var msg = {};
- msg['method'] = 'unsubscribe';
- msg['name'] = this.attributeName;
- msg['zone'] = obj.zone;
+ if (unsubscribe) {
+ var msg = {};
+ msg['method'] = 'unsubscribe';
+ msg['name'] = this.attributeName;
+ msg['zone'] = obj.zone;
- extension.postMessage(JSON.stringify(msg));
- }
+ extension.postMessage(JSON.stringify(msg));
+ }
};
VehicleSignalInterface.prototype.set = function (value, zone) {
- var msg = {};
- msg['method'] = 'set';
- msg['name'] = this.attributeName;
- msg['zone'] = zone;
- msg['value'] = value;
+ var msg = {};
+ msg['method'] = 'set';
+ msg['name'] = this.attributeName;
+ msg['zone'] = zone;
+ msg['value'] = value;
- return createPromise(msg);
+ return createPromise(msg);
}
VehicleSignalInterface.prototype.availableForSubscription = function(attName) {
- return isAvailable(this, attName);
+ return isAvailable(this, attName);
}
VehicleSignalInterface.prototype.availableForSetting = function(attName) {
- return isAvailable(this, attName);
+ return isAvailable(this, attName);
}
function isAvailable(obj, attName)
{
- var msg = {};
- msg["method"] = 'availableForRetrieval';
- msg["name"] = obj.attributeName;
- msg["attName"] = attName;
-
- var reply = extension.internal.sendSyncMessage(JSON.stringify(msg));
-
- if (reply === "true") {
- return "available";
- } else {
- return "not_supported";
- }
+ var msg = {};
+ msg["method"] = 'availableForRetrieval';
+ msg["name"] = obj.attributeName;
+ msg["attName"] = attName;
+
+ var reply = extension.internal.sendSyncMessage(JSON.stringify(msg));
+
+ if (reply === "true") {
+ return "available";
+ } else {
+ return "not_supported";
+ }
}
function AsyncCall(resolve, reject) {
- this.resolve = resolve;
- this.reject = reject;
+ this.resolve = resolve;
+ this.reject = reject;
}
function createPromise(msg) {
- var promise = new Promise(function(resolve, reject) {
- async_calls[next_async_call_id] = new AsyncCall(resolve, reject);
- });
+ var promise = new Promise(function(resolve, reject) {
+ async_calls[next_async_call_id] = new AsyncCall(resolve, reject);
+ });
- msg.asyncCallId = next_async_call_id;
- extension.postMessage(JSON.stringify(msg));
- ++next_async_call_id;
+ msg.asyncCallId = next_async_call_id;
+ extension.postMessage(JSON.stringify(msg));
+ ++next_async_call_id;
- return promise;
+ return promise;
}
window.Zone = function(zone) {
- this.value = zone ? zone : [];
+ this.value = zone ? zone : [];
- Object.defineProperty(this, 'driver',
- { enumerable: false, get: function() {
- return new Zone(['Front', 'Left']);
- } });
+ Object.defineProperty(this, 'driver',
+ { enumerable: false, get: function() {
+ return new Zone(['Front', 'Left']);
+ } });
};
window.Zone.prototype.equals = function(zone) {
- var is_equal = true;
+ var is_equal = true;
- for (var i = 0; i < zone.value.length; i++) {
- is_equal &= this.value.indexOf(zone.value[i]) !== -1;
- }
+ for (var i = 0; i < zone.value.length; i++) {
+ is_equal &= this.value.indexOf(zone.value[i]) !== -1;
+ }
- for (var i = 0; i < this.value.length; i++) {
- is_equal &= zone.value.indexOf(this.value[i]) !== -1;
- }
+ for (var i = 0; i < this.value.length; i++) {
+ is_equal &= zone.value.indexOf(this.value[i]) !== -1;
+ }
- return is_equal;
+ return is_equal;
};
function _defineVehicleProperty(obj, prop) {
- Object.defineProperty(obj, prop, { enumerable: true, value: new VehicleInterface(prop) });
+ Object.defineProperty(obj, prop, { enumerable: true, value: new VehicleInterface(prop) });
}
function _defineVehicleSignalProperty(obj, prop) {
- Object.defineProperty(obj, prop, { enumerable: true, value: new VehicleSignalInterface(prop) });
+ Object.defineProperty(obj, prop, { enumerable: true, value: new VehicleSignalInterface(prop) });
}
extension.setMessageListener(function(json) {
- try {
- var msg = JSON.parse(json);
-
- switch (msg.method) {
- case 'get':
- handlePromiseReply(msg);
- break;
- case 'zones':
- handleZonesReply(msg);
- break;
- case 'subscribe':
- handleSubscribeReply(msg);
- break;
- case 'set':
- handlePromiseReply(msg);
- break;
- case 'supported':
- handleSupportedReply(msg)
- break;
- default:
- break;
+ try {
+ var msg = JSON.parse(json);
+
+ switch (msg.method) {
+ case 'get':
+ handlePromiseReply(msg);
+ break;
+ case 'zones':
+ handleZonesReply(msg);
+ break;
+ case 'subscribe':
+ handleSubscribeReply(msg);
+ break;
+ case 'set':
+ handlePromiseReply(msg);
+ break;
+ case 'supported':
+ handleSupportedReply(msg)
+ break;
+ case 'vehicleSupportedAttributes':
+ handleVehicleSupported(msg);
+ break;
+ default:
+ break;
+ }
+ } catch (error) {
+ console.log('Error in message listener: ' + error);
+ console.log("msg: " + JSON.stringify(msg))
}
- } catch (error) {
- console.log('Error in message listener: ' + error);
- console.log("msg: " + JSON.stringify(msg))
- }
});
function handlePromiseReply(msg) {
- var cbobj = async_calls[msg.asyncCallId];
-
- if (msg.error) {
- var error = {};
- error.error = msg.value;
- switch (msg.value) {
- case 'permission_denied':
- error.message = 'Permission denied';
- break;
- case 'invalid_operation':
- error.message = 'Invalid operation';
- break;
- case 'timeout':
- error.message = 'Operation timed out';
- break;
- case 'invalid_zone':
- error.message = 'Zone invalid or not found';
- break;
- case 'unknown':
- error.message = 'An unknown error occured';
- break;
- default:
- error.message = 'Unknown';
- break;
- }
-
- cbobj.reject(error);
- } else {
- if (msg.value && msg.value.zone) {
- msg.value.zone = new Zone(msg.value.zone);
+ var cbobj = async_calls[msg.asyncCallId];
+
+ if (msg.error) {
+ var error = {};
+ error.error = msg.value;
+ switch (msg.value) {
+ case 'permission_denied':
+ error.message = 'Permission denied';
+ break;
+ case 'invalid_operation':
+ error.message = 'Invalid operation';
+ break;
+ case 'timeout':
+ error.message = 'Operation timed out';
+ break;
+ case 'invalid_zone':
+ error.message = 'Zone invalid or not found';
+ break;
+ case 'unknown':
+ error.message = 'An unknown error occured';
+ break;
+ default:
+ error.message = 'Unknown';
+ break;
+ }
+
+ cbobj.reject(error);
+ } else {
+ if (msg.value && msg.value.zone) {
+ msg.value.zone = new Zone(msg.value.zone);
+ }
+ cbobj.resolve(msg.value);
}
- cbobj.resolve(msg.value);
- }
- delete async_calls[msg.asyncCallId];
+ delete async_calls[msg.asyncCallId];
}
function handleZonesReply(msg) {
- var cbobj = async_calls[msg.asyncCallId];
+ var cbobj = async_calls[msg.asyncCallId];
- if (cbobj)
- cbobj.resolve(new Zone(msg.value));
+ if (cbobj)
+ cbobj.resolve(new Zone(msg.value));
}
function handleSupportedReply(msg) {
- var cbobj = async_calls[msg.asyncCallId];
+ var cbobj = async_calls[msg.asyncCallId];
- if (cbobj)
- cbobj.resolve(msg.value);
+ if (cbobj)
+ cbobj.resolve(msg.value);
}
function handleSubscribeReply(msg) {
- delete async_calls[msg.asyncCallId];
- var value = msg.value;
- value.zone = new Zone(value.zone);
-
- for (var i = 0; i < subscriptions.length; i++) {
- var itr = subscriptions[i];
- var ifaceIs = (value.interfaceName.toLowerCase() === itr.name.toLowerCase());
- if (ifaceIs === true && value.zone.equals(itr.zone)) {
- itr.callback(value);
+ delete async_calls[msg.asyncCallId];
+ var value = msg.value;
+ value.zone = new Zone(value.zone);
+
+ for (var i = 0; i < subscriptions.length; i++) {
+ var itr = subscriptions[i];
+ var ifaceIs = (value.interfaceName.toLowerCase() === itr.name.toLowerCase());
+ if (ifaceIs === true && value.zone.equals(itr.zone)) {
+ itr.callback(value);
+ }
}
- }
}
+
+function handleVehicleSupported(msg) {
+ var value = msg.value;
+ for(i in value) {
+ if(exports[i] !== undefined) {
+ _defineVehicleSignalProperty(exports, i);
+ }
+ }
+}
+
/// Runningstatus attributes:
_defineVehicleSignalProperty(exports, 'vehicleSpeed');
_defineVehicleSignalProperty(exports, 'engineSpeed');
diff --git a/xwalk/vehicle_instance.h b/xwalk/vehicle_instance.h
index 33dc8ba8..48093b63 100644
--- a/xwalk/vehicle_instance.h
+++ b/xwalk/vehicle_instance.h
@@ -7,8 +7,9 @@
#include <string>
+#include <picojson.h>
+
#include "common/extension.h"
-#include "common/picojson.h"
#include "vehicle.h"
class VehicleInstance : public common::Instance {