summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevron Rees <tripzero.kev@gmail.com>2016-04-19 10:52:50 -0700
committerKevron Rees <tripzero.kev@gmail.com>2016-04-19 10:52:50 -0700
commit5b29630e57cc1e422b3b656572a02466c28bf8e1 (patch)
tree6e1eb0ec71277a87587ee1b782e92257767b6a0a
parenteae423172640cf239757ff489a46fba95814a00a (diff)
parent1944003b76d590c3db6c606b42de5656f69960d0 (diff)
downloadautomotive-message-broker-5b29630e57cc1e422b3b656572a02466c28bf8e1.tar.gz
Merge branch '0.14' into gh-pages
-rw-r--r--CMakeLists.txt116
-rw-r--r--COPYING18
-rw-r--r--README.md76
-rw-r--r--RELEASE.in.md24
-rw-r--r--RELEASE.md24
-rw-r--r--TODO7
-rw-r--r--ambd/CMakeLists.txt42
-rw-r--r--ambd/config.in.json6
-rw-r--r--ambd/core.cpp589
-rw-r--r--ambd/core.h110
-rw-r--r--ambd/glibmainloop.cpp23
-rw-r--r--ambd/glibmainloop.h21
-rw-r--r--ambd/imainloop.h25
-rw-r--r--ambd/main.cpp226
-rw-r--r--ambd/pluginloader.cpp289
-rw-r--r--ambd/pluginloader.h148
-rw-r--r--ambd/qtmainloop.cpp22
-rw-r--r--ambd/qtmainloop.h19
-rw-r--r--automotive-message-broker.odpbin0 -> 170477 bytes
-rw-r--r--automotive-message-broker.pdfbin0 -> 134466 bytes
-rw-r--r--cmake_uninstall.cmake21
-rw-r--r--docs/CMakeLists.txt27
-rw-r--r--docs/Doxyfile.idl.in6
-rw-r--r--docs/Doxyfile.in11
-rw-r--r--docs/Doxyfile.mainpage.in4
-rw-r--r--docs/README9
-rw-r--r--docs/amb.in.fidl1864
-rw-r--r--docs/amb/README1
-rw-r--r--docs/ambd-configuration.in.idl84
-rw-r--r--docs/ambd.in.md76
-rw-r--r--docs/dbus/README1
-rw-r--r--docs/images/AMBArchitecture.pngbin0 -> 71850 bytes
-rw-r--r--docs/libamb.in.h54
-rw-r--r--docs/mainpage.in.idl34
-rw-r--r--docs/plugins/bluemonkey/bluemonkey.idl156
-rw-r--r--examples/CMakeLists.txt38
-rw-r--r--examples/bluemonkey/bluemonkeyconfig.in.json18
-rw-r--r--examples/bluetooth.in.json17
-rw-r--r--examples/cangenconfig.in.json22
-rw-r--r--examples/chrony.in.json16
-rw-r--r--examples/configwebsocketsink19
-rw-r--r--examples/configwebsocketsource18
-rw-r--r--examples/configwheel.in.json16
-rw-r--r--examples/databaselogging.in.json28
-rw-r--r--examples/databasesource.in.json16
-rw-r--r--examples/databasewebsocketsink.in.json29
-rw-r--r--examples/dbusconfig.in.json18
-rw-r--r--examples/democonfig24
-rw-r--r--examples/exampleconfig.in.json16
-rw-r--r--examples/gpsdconfig15
-rw-r--r--examples/gpsnmea.in.json16
-rw-r--r--examples/obdsourceconfig.in.json18
-rw-r--r--examples/opencvdbusconfig.in.json30
-rw-r--r--examples/opencvluxconfig.in.json24
-rw-r--r--examples/openxcconfig17
-rw-r--r--examples/qtmainloopconfig.in.json18
-rwxr-xr-xexamples/rundemo40
-rwxr-xr-xexamples/testmultiisource20
-rw-r--r--examples/testplugins.d.in.json4
-rw-r--r--examples/testsourceconfig.in.json15
-rw-r--r--examples/websinkssl20
-rw-r--r--examples/websocketsink2.in.json21
-rw-r--r--examples/websocketsource2.in.json24
-rw-r--r--lib/CMakeLists.txt28
-rw-r--r--lib/abstractpropertytype.cpp8
-rw-r--r--lib/abstractpropertytype.h899
-rw-r--r--lib/abstractroutingengine.cpp78
-rw-r--r--lib/abstractroutingengine.h518
-rw-r--r--lib/abstractsink.cpp37
-rw-r--r--lib/abstractsink.h75
-rw-r--r--lib/abstractsource.cpp35
-rw-r--r--lib/abstractsource.h128
-rw-r--r--lib/ambplugin.h274
-rw-r--r--lib/ambpluginimpl.cpp186
-rw-r--r--lib/ambpluginimpl.h209
-rw-r--r--lib/asyncqueue.hpp200
-rw-r--r--lib/automotive-message-broker.pc.in11
-rw-r--r--lib/debugout.cpp45
-rw-r--r--lib/debugout.h199
-rw-r--r--lib/listplusplus.cpp21
-rw-r--r--lib/listplusplus.h56
-rw-r--r--lib/mappropertytype.hpp153
-rw-r--r--lib/nullptr.h7
-rw-r--r--lib/picojson.h1029
-rw-r--r--lib/propertyinfo.hpp72
-rw-r--r--lib/superptr.hpp95
-rw-r--r--lib/timestamp.cpp54
-rw-r--r--lib/timestamp.h31
-rw-r--r--lib/uuidhelper.cpp12
-rw-r--r--lib/uuidhelper.h17
-rw-r--r--lib/vehicleproperty.cpp593
-rw-r--r--lib/vehicleproperty.h1151
-rw-r--r--packaging.in/CMakeLists.txt25
-rw-r--r--packaging.in/amb.manifest.in.xml63
-rw-r--r--packaging.in/amb.manifest.plugins5
-rwxr-xr-xpackaging.in/ambd.conf.upstart25
-rw-r--r--packaging.in/ambd.service.systemd17
-rw-r--r--packaging.in/ambd.service.systemd.tizen18
-rw-r--r--packaging.in/automotive-message-broker.changes.in874
-rw-r--r--packaging.in/automotive-message-broker.spec.in410
-rw-r--r--packaging.in/config.tizen.in18
-rw-r--r--packaging.in/debian/automotive-message-broker-plugins-bluemonkey.debian.install5
-rw-r--r--packaging.in/debian/automotive-message-broker-plugins-bluetooth.debian.install3
-rw-r--r--packaging.in/debian/automotive-message-broker-plugins-qtmainloop.debian.install3
-rw-r--r--packaging.in/debian/automotive-message-broker-plugins.debian.install5
-rw-r--r--packaging.in/debian/automotive-message-broker.debian.install3
-rw-r--r--packaging.in/debian/changelog5
-rw-r--r--packaging.in/debian/control.debian.in66
-rw-r--r--packaging.in/debian/libamb-dev.debian.install3
-rw-r--r--packaging.in/debian/libamb.debian.install1
-rwxr-xr-xpackaging.in/debian/rules21
-rw-r--r--plugins/CMakeLists.txt53
-rw-r--r--plugins/bluemonkey/CMakeLists.txt81
-rw-r--r--plugins/bluemonkey/Doxyfile.in4
-rw-r--r--plugins/bluemonkey/README31
-rw-r--r--plugins/bluemonkey/agent.cpp41
-rw-r--r--plugins/bluemonkey/agent.h24
-rw-r--r--plugins/bluemonkey/authSettings.js1
-rw-r--r--plugins/bluemonkey/authenticate.cpp54
-rw-r--r--plugins/bluemonkey/authenticate.h28
-rw-r--r--plugins/bluemonkey/bluemonkey.cpp600
-rw-r--r--plugins/bluemonkey/bluemonkey.h168
-rw-r--r--plugins/bluemonkey/bluemonkey.in.idl198
-rw-r--r--plugins/bluemonkey/bluemonkey.in.json6
-rw-r--r--plugins/bluemonkey/bmdbus.cpp56
-rw-r--r--plugins/bluemonkey/bmdbus.h50
-rw-r--r--plugins/bluemonkey/config.js279
-rw-r--r--plugins/bluemonkey/customPrograms.js2
-rw-r--r--plugins/bluemonkey/db.cpp108
-rw-r--r--plugins/bluemonkey/db.h87
-rw-r--r--plugins/bluemonkey/ircSettings.js26
-rw-r--r--plugins/bluemonkey/irccoms.cpp217
-rw-r--r--plugins/bluemonkey/irccoms.h70
-rw-r--r--plugins/bluetooth/CMakeLists.txt39
-rw-r--r--plugins/bluetooth/ambbt.conf15
-rw-r--r--plugins/bluetooth/bluetooth.in.json5
-rw-r--r--plugins/bluetooth/bluetoothplugin.cpp207
-rw-r--r--plugins/bluetooth/bluetoothplugin.h106
-rw-r--r--plugins/bluetooth/testAmbBt.cpp48
-rw-r--r--plugins/cangenplugin/CMakeLists.txt20
-rw-r--r--plugins/cangenplugin/cangenplugin.cpp466
-rw-r--r--plugins/cangenplugin/cangenplugin.h314
-rw-r--r--plugins/cangenplugin/test/CMakeLists.txt48
-rw-r--r--plugins/cangenplugin/test/main.cpp73
-rw-r--r--plugins/cangenplugin/test/ut_cangenplugin.cpp345
-rw-r--r--plugins/cangenplugin/websockets.cpp251
-rw-r--r--plugins/cangenplugin/websockets.h194
-rw-r--r--plugins/cansimplugin/CMakeLists.txt20
-rw-r--r--plugins/cansimplugin/cansimplugin.cpp389
-rw-r--r--plugins/cansimplugin/cansimplugin.h174
-rw-r--r--plugins/cansimplugin/test/CMakeLists.txt20
-rw-r--r--plugins/cansimplugin/test/main.cpp67
-rw-r--r--plugins/cansimplugin/test/ut_cansimplugin.cpp475
-rw-r--r--plugins/chrony/CMakeLists.txt19
-rw-r--r--plugins/chrony/README24
-rw-r--r--plugins/chrony/chrony.cpp81
-rw-r--r--plugins/chrony/chrony.h50
-rw-r--r--plugins/chrony/chrony.in.json5
-rw-r--r--plugins/common/CMakeLists.txt24
-rw-r--r--plugins/common/abstractdbusinterface.cpp616
-rw-r--r--plugins/common/abstractdbusinterface.h168
-rw-r--r--plugins/common/abstractio.hpp19
-rw-r--r--plugins/common/amb-plugins-common.pc.in11
-rw-r--r--plugins/common/bluetooth.hpp191
-rw-r--r--plugins/common/bluetooth5.cpp368
-rw-r--r--plugins/common/bluetooth5.h32
-rw-r--r--plugins/common/bluetoothadapterproxy.c3801
-rw-r--r--plugins/common/bluetoothadapterproxy.h578
-rw-r--r--plugins/common/bluetoothmanagerproxy.c1941
-rw-r--r--plugins/common/bluetoothmanagerproxy.h292
-rw-r--r--plugins/common/bluetoothserialproxy.c1397
-rw-r--r--plugins/common/bluetoothserialproxy.h230
-rw-r--r--plugins/common/canadapter.cpp42
-rw-r--r--plugins/common/canadapter.h90
-rw-r--r--plugins/common/canbus.h89
-rw-r--r--plugins/common/canbusimpl.cpp140
-rw-r--r--plugins/common/canbusimpl.h98
-rw-r--r--plugins/common/canobserver.h91
-rw-r--r--plugins/common/cansocket.cpp158
-rw-r--r--plugins/common/cansocket.h116
-rw-r--r--plugins/common/cansocketadapter.cpp98
-rw-r--r--plugins/common/cansocketadapter.h98
-rw-r--r--plugins/common/cansocketreader.cpp95
-rw-r--r--plugins/common/cansocketreader.h86
-rw-r--r--plugins/common/dbusexport.cpp9
-rw-r--r--plugins/common/dbusexport.h136
-rw-r--r--plugins/common/dbusplugin.cpp99
-rw-r--r--plugins/common/dbusplugin.h74
-rw-r--r--plugins/common/dbussignaller.cpp3
-rw-r--r--plugins/common/dbussignaller.h163
-rw-r--r--plugins/common/logger.cpp226
-rw-r--r--plugins/common/logger.h296
-rw-r--r--plugins/common/mutex.cpp58
-rw-r--r--plugins/common/mutex.h78
-rw-r--r--plugins/common/serialport.hpp169
-rw-r--r--plugins/common/thread.cpp167
-rw-r--r--plugins/common/thread.h154
-rw-r--r--plugins/common/varianttype.cpp105
-rw-r--r--plugins/common/varianttype.h168
-rw-r--r--plugins/database/CMakeLists.txt28
-rw-r--r--plugins/database/README119
-rw-r--r--plugins/database/basedb.hpp346
-rw-r--r--plugins/database/baseobject.h37
-rw-r--r--plugins/database/database.in.json12
-rw-r--r--plugins/database/databasesink.cpp559
-rw-r--r--plugins/database/databasesink.h182
-rw-r--r--plugins/database/sqlitedatabase.cpp88
-rw-r--r--plugins/database/sqlitedatabase.h61
-rw-r--r--plugins/database/sqlitequery.cpp402
-rw-r--r--plugins/database/sqlitequery.h86
-rw-r--r--plugins/database/utils.cpp52
-rw-r--r--plugins/database/utils.h35
-rw-r--r--plugins/dbus/CMakeLists.txt34
-rw-r--r--plugins/dbus/README28
-rw-r--r--plugins/dbus/amb-qt/CMakeLists.txt39
-rw-r--r--plugins/dbus/amb-qt/amb-qt_global.h12
-rw-r--r--plugins/dbus/amb-qt/ambqt.cpp92
-rw-r--r--plugins/dbus/amb-qt/ambqt.h75
-rw-r--r--plugins/dbus/amb-qt/ambqtquick.cpp14
-rw-r--r--plugins/dbus/amb-qt/ambqtquick.h14
-rw-r--r--plugins/dbus/amb-qt/qmldir1
-rw-r--r--plugins/dbus/amb-qt/test.cpp35
-rw-r--r--plugins/dbus/amb.conf21
-rw-r--r--plugins/dbus/automotivemanager.cpp458
-rw-r--r--plugins/dbus/automotivemanager.h27
-rw-r--r--plugins/dbus/custompropertyinterface.cpp30
-rw-r--r--plugins/dbus/custompropertyinterface.h13
-rw-r--r--plugins/dbus/dbus.in.json6
-rw-r--r--plugins/dbus/dbusinterfacemanager.cpp230
-rw-r--r--plugins/dbus/dbusinterfacemanager.h53
-rw-r--r--plugins/dbus/drivingsafety.cpp1
-rw-r--r--plugins/dbus/drivingsafety.h160
-rw-r--r--plugins/dbus/environmentproperties.cpp1
-rw-r--r--plugins/dbus/environmentproperties.h139
-rw-r--r--plugins/dbus/fakeidlheader.h76
-rw-r--r--plugins/dbus/maintenance.cpp1
-rw-r--r--plugins/dbus/maintenance.h146
-rw-r--r--plugins/dbus/parking.cpp0
-rw-r--r--plugins/dbus/parking.h51
-rw-r--r--plugins/dbus/personalization.cpp2
-rw-r--r--plugins/dbus/personalization.h69
-rw-r--r--plugins/dbus/runningstatus.cpp0
-rw-r--r--plugins/dbus/runningstatus.h323
-rw-r--r--plugins/dbus/uncategorizedproperty.cpp25
-rw-r--r--plugins/dbus/uncategorizedproperty.h13
-rw-r--r--plugins/dbus/vehicleinfo.cpp1
-rw-r--r--plugins/dbus/vehicleinfo.h101
-rw-r--r--plugins/demosink/CMakeLists.txt16
-rw-r--r--plugins/demosink/demosinkplugin.cpp123
-rw-r--r--plugins/demosink/demosinkplugin.h47
-rw-r--r--plugins/exampleplugin.cpp426
-rw-r--r--plugins/exampleplugin.h79
-rw-r--r--plugins/exampleplugins.README.txt36
-rw-r--r--plugins/examplesink.cpp210
-rw-r--r--plugins/examplesink.h37
-rw-r--r--plugins/examplesink.in.json6
-rw-r--r--plugins/examplesource.in.json6
-rw-r--r--plugins/gpsnmea/CMakeLists.txt18
-rw-r--r--plugins/gpsnmea/README99
-rw-r--r--plugins/gpsnmea/gpsnmea.cpp756
-rw-r--r--plugins/gpsnmea/gpsnmea.h76
-rw-r--r--plugins/murphyplugin/CMakeLists.txt34
-rw-r--r--plugins/murphyplugin/murphysource.cpp462
-rw-r--r--plugins/murphyplugin/murphysource.h90
-rw-r--r--plugins/obd2plugin/CMakeLists.txt25
-rw-r--r--plugins/obd2plugin/README56
-rw-r--r--plugins/obd2plugin/asyncqueuewatcher.cpp89
-rw-r--r--plugins/obd2plugin/asyncqueuewatcher.h42
-rw-r--r--plugins/obd2plugin/obd2.in.json7
-rw-r--r--plugins/obd2plugin/obd2source.conf1
-rw-r--r--plugins/obd2plugin/obd2source.cpp836
-rw-r--r--plugins/obd2plugin/obd2source.h202
-rw-r--r--plugins/obd2plugin/obdlib.cpp606
-rw-r--r--plugins/obd2plugin/obdlib.h141
-rw-r--r--plugins/obd2plugin/obdpid.cpp4
-rw-r--r--plugins/obd2plugin/obdpid.h447
-rw-r--r--plugins/opencvlux/CMakeLists.txt61
-rw-r--r--plugins/opencvlux/README61
-rw-r--r--plugins/opencvlux/opencvlux.in.json17
-rw-r--r--plugins/opencvlux/opencvluxplugin.cpp588
-rw-r--r--plugins/opencvlux/opencvluxplugin.h127
-rw-r--r--plugins/openxc/CMakeLists.txt19
-rw-r--r--plugins/openxc/README40
-rw-r--r--plugins/openxc/openxcplugin.cpp498
-rw-r--r--plugins/openxc/openxcplugin.h61
-rw-r--r--plugins/plugins.in.idl21
-rw-r--r--plugins/testplugin/CMakeLists.txt16
-rw-r--r--plugins/testplugin/README18
-rw-r--r--plugins/testplugin/testplugin.cpp446
-rw-r--r--plugins/testplugin/testplugin.h78
-rw-r--r--plugins/websocket/CMakeLists.txt52
-rw-r--r--plugins/websocket/README75
-rw-r--r--plugins/websocket/common.cpp136
-rw-r--r--plugins/websocket/common.h44
-rw-r--r--plugins/websocket/common.hpp0
-rw-r--r--plugins/websocket/protocol.idl446
-rw-r--r--plugins/websocket/test/events.js129
-rw-r--r--plugins/websocket/test/index.html17
-rw-r--r--plugins/websocket/test/style.css182
-rw-r--r--plugins/websocket/test/test.js267
-rw-r--r--plugins/websocket/test/vehicle.js367
-rw-r--r--plugins/websocket/websocketsink.cpp84
-rw-r--r--plugins/websocket/websocketsink.h49
-rw-r--r--plugins/websocket/websocketsinkmanager.cpp641
-rw-r--r--plugins/websocket/websocketsinkmanager.h68
-rw-r--r--plugins/websocket/websocketsource.cpp817
-rw-r--r--plugins/websocket/websocketsource.h73
-rw-r--r--plugins/wheel/CMakeLists.txt20
-rw-r--r--plugins/wheel/README31
-rw-r--r--plugins/wheel/wheelplugin.cpp629
-rw-r--r--plugins/wheel/wheelplugin.h60
-rw-r--r--tests/CMakeLists.txt13
-rwxr-xr-xtests/amb-get-history.py30
-rwxr-xr-xtests/amb-get.py24
-rwxr-xr-xtests/amb-listen.py35
-rwxr-xr-xtests/amb-set.py47
-rwxr-xr-xtests/gen-set.py27
-rwxr-xr-xtests/gendb.sh28
-rw-r--r--tests/testing94
-rw-r--r--tools/AmbSignalMapper/.gitignore18
-rw-r--r--tools/AmbSignalMapper/Changes5
-rw-r--r--tools/AmbSignalMapper/MANIFEST23
-rw-r--r--tools/AmbSignalMapper/Makefile.PL72
-rw-r--r--tools/AmbSignalMapper/README77
-rwxr-xr-xtools/AmbSignalMapper/bin/dbc2json204
-rwxr-xr-xtools/AmbSignalMapper/bin/json2amb164
-rw-r--r--tools/AmbSignalMapper/dbc2json.html144
-rw-r--r--tools/AmbSignalMapper/json2amb.html139
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/AmbCommon.pm212
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/AmbPluginGenerator.pm718
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/DbcGrammar218
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/DbcGrammar.pod90
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/templates/CMakeLists.txt68
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.cpp188
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.h231
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignals.h30
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.cpp289
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.h196
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.idl18
-rw-r--r--tools/AmbSignalMapper/t/00-load.t13
-rw-r--r--tools/AmbSignalMapper/t/ambsignalmapper.t18
-rw-r--r--tools/AmbSignalMapper/t/boilerplate.t57
-rw-r--r--tools/AmbSignalMapper/t/manifest.t15
-rw-r--r--tools/AmbSignalMapper/t/pod-coverage.t20
-rw-r--r--tools/AmbSignalMapper/t/pod.t12
-rw-r--r--tools/CMakeLists.txt4
-rw-r--r--tools/ambctl.py574
-rwxr-xr-xtools/genmapping.py101
-rw-r--r--xwalk/CMakeLists.txt30
-rw-r--r--xwalk/LICENSE27
-rw-r--r--xwalk/common/XW_Extension.h185
-rw-r--r--xwalk/common/XW_Extension_EntryPoints.h49
-rw-r--r--xwalk/common/XW_Extension_Permissions.h41
-rw-r--r--xwalk/common/XW_Extension_Runtime.h44
-rw-r--r--xwalk/common/XW_Extension_SyncMessage.h48
-rw-r--r--xwalk/common/extension.cc212
-rw-r--r--xwalk/common/extension.h96
-rw-r--r--xwalk/common/utils.h22
-rw-r--r--xwalk/common/virtual_fs.cc317
-rw-r--r--xwalk/common/virtual_fs.h130
-rwxr-xr-xxwalk/generate_api.py19
-rw-r--r--xwalk/js/js-test-post.js28
-rw-r--r--xwalk/js/js-test-pre.js604
-rw-r--r--xwalk/vehicle.cc816
-rw-r--r--xwalk/vehicle.h90
-rw-r--r--xwalk/vehicle.html102
-rw-r--r--xwalk/vehicle_api.js382
-rw-r--r--xwalk/vehicle_extension.cc29
-rw-r--r--xwalk/vehicle_extension.h20
-rw-r--r--xwalk/vehicle_instance.cc169
-rw-r--r--xwalk/vehicle_instance.h33
371 files changed, 54136 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 00000000..867717ca
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,116 @@
+project(automotive-message-broker)
+cmake_minimum_required(VERSION 2.8)
+
+set(CMAKE_BUILD_TYPE, Debug)
+
+include(FindPkgConfig)
+include(CMakeDependentOption)
+include(GNUInstallDirs)
+
+set(PROJECT_NAME "automotive-message-broker")
+set(PROJECT_PRETTY_NAME "Automotive Message Broker")
+set(PROJECT_SERIES "0.14")
+set(PROJECT_MAJOR_VERSION "0.14")
+set(PROJECT_MINOR_VERSION "0")
+set(PROJECT_VERSION "${PROJECT_MAJOR_VERSION}.${PROJECT_MINOR_VERSION}")
+set(PROJECT_CODENAME "74A")
+set(PROJECT_QUALITY "final")
+
+add_definitions(-DPROJECT_VERSION="${PROJECT_VERSION}")
+add_definitions(-DPROJECT_NAME="${PROJECT_PRETTY_NAME}")
+add_definitions(-DPROJECT_CODENAME="${PROJECT_CODENAME}")
+add_definitions(-DPROJECT_QUALITY="${PROJECT_QUALITY}")
+add_definitions(-DPROJECT_SERIES="${PROJECT_SERIES}")
+
+set (LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
+set (LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" )
+set (PLUGIN_INSTALL_PATH "${LIB_INSTALL_DIR}/${PROJECT_NAME}")
+set (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}")
+set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DOCDIR}/${PROJECT_SERIES}")
+set (PLUGIN_SEGMENT_INSTALL_PATH "/${CMAKE_INSTALL_SYSCONFDIR}/ambd/plugins.d")
+
+option(qtmainloop "Use QCoreApplication mainloop " OFF)
+option(websocket_plugin "websocket source and sink plugins" OFF)
+option(obd2_plugin "OBD-II plugin" OFF)
+option(database_plugin "Database plugins" OFF)
+option(qt_bindings "AMB Qt DBus bindings" OFF)
+option(opencvlux_plugin "OpenCV Lux plugin" OFF)
+option(murphy_plugin "murphy policy framework plugin" OFF)
+option(test_plugin "Test Plugin" ON)
+option(bluemonkey_plugin "bluemonkey plugin" OFF)
+option(gpsnmea_plugin "gps NMEA location plugin" OFF)
+option(chrony_plugin "chrony plugin" OFF)
+option(openxc_plugin "OpenXC plugin" OFF)
+option(bluetooth_plugin "bluetooth plugin" OFF)
+option(cansim_plugin "Can simulator plugin" OFF)
+option(cangen_plugin "Can generator plugin" OFF)
+option(enable_icecc "Enable icecc checking, for distributed compilation" ON)
+option(enable_docs "enable Doxygen doc generation" OFF)
+option(usebluez5 "use bluez 5 API" OFF)
+option(xwalk_vehicle_extension "Crosswalk vehicle extension" OFF)
+set(XWALK_EXTENSION_PATH "/automotive-message-broker/xwalk" CACHE PATH "directory the xwalk extension will be installed to")
+
+#turn on -fpic/-fpie:
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpie -pie -std=c++11")
+
+if (enable_icecc)
+ include (CMakeForceCompiler)
+ find_program(ICECC /usr/lib/icecc/bin/g++)
+ if (ICECC)
+ message(STATUS "icecc will be used for distributed compiling")
+ cmake_force_cxx_compiler(${ICECC} icecc)
+ else(ICECC)
+ message(STATUS "Not using icecc")
+ endif(ICECC)
+endif(enable_icecc)
+
+find_package(Boost REQUIRED)
+
+
+pkg_check_modules(glib REQUIRED glib-2.0 gobject-2.0)
+
+add_definitions(-DDBusServiceName="org.automotive.message.broker")
+
+set(include_dirs ${libtool_INCLUDE_DIR} ${glib_INCLUDE_DIRS} ${gio_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${json_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/lib)
+set(link_libraries -lamb ${glib_LIBRARIES} ${json_LIBRARIES} -L${CMAKE_CURRENT_BINARY_DIR}/lib)
+
+if(usebluez5)
+ add_definitions(-DUSE_BLUEZ5)
+
+endif(usebluez5)
+
+set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${PROJECT_VERSION})
+add_custom_target(dist COMMAND git archive --prefix=${ARCHIVE_NAME}/ HEAD | bzip2 > ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
+
+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" @ONLY)
+
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/TODO" "${CMAKE_CURRENT_SOURCE_DIR}/TODO.md" @ONLY)
+
+# packaging stuff:
+# Common things to every type of package
+SET(CPACK_PACKAGE_DESCRIPTION "daemon that provides access vehicle data")
+SET(CPACK_PACKAGE_NAME "automotive-message-broker")
+SET(CPACK_PACKAGE_EXECUTABLES "ambd")
+SET(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
+SET(CPACK_STRIP_FILES true)
+SET(CPACK_PACKAGE_CONTACT "tripzero.kev@gmail.com")
+SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
+
+# Always build .tar.gz and .sh files
+SET(CPACK_GENERATOR "STGZ;TGZ;TBZ2")
+
+add_subdirectory(lib)
+add_subdirectory(plugins)
+add_subdirectory(ambd)
+add_subdirectory(docs)
+add_subdirectory(tests)
+add_subdirectory(tools)
+add_subdirectory(examples)
+add_subdirectory(xwalk)
+add_subdirectory(packaging.in)
+
+
diff --git a/COPYING b/COPYING
new file mode 100644
index 00000000..b3bdacba
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,18 @@
+Automotive Message Broker
+
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..77e241fd
--- /dev/null
+++ b/README.md
@@ -0,0 +1,76 @@
+# Automotive Message Broker Daemon {#ambd}
+
+Version 0.14.0
+
+## 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/x86_64-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.in.md b/RELEASE.in.md
new file mode 100644
index 00000000..e40d5f46
--- /dev/null
+++ b/RELEASE.in.md
@@ -0,0 +1,24 @@
+# AMB Release Notes {#release_notes}
+Version: @PROJECT_SERIES@
+
+## New features:
+- [DBus] some classes for exporting custom interfaces moved to plugins-common
+- [Bluemonkey plugin] support for creating custom dbus interfaces: bluemonkey.exportInterface()
+- [Bluemonkey plugin] dbus module supports creating dbus interfaces to system or session services and
+ creating/exporting dbus objects
+- [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:
+- [XWalk] Fixed misspelled 'diagnostics' interface
+- [DBus] Fixed misspelled 'Diagnostics' interface
diff --git a/RELEASE.md b/RELEASE.md
new file mode 100644
index 00000000..91fc0f30
--- /dev/null
+++ b/RELEASE.md
@@ -0,0 +1,24 @@
+# AMB Release Notes {#release_notes}
+Version: 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()
+- [Bluemonkey plugin] dbus module supports creating dbus interfaces to system or session services and
+ creating/exporting dbus objects
+- [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:
+- [XWalk] Fixed misspelled 'diagnostics' interface
+- [DBus] Fixed misspelled 'Diagnostics' interface
diff --git a/TODO b/TODO
new file mode 100644
index 00000000..31fb46be
--- /dev/null
+++ b/TODO
@@ -0,0 +1,7 @@
+- Make updateFrequency a normal property
+- Core auto-calculate updateFrequency
+- Create API export class that creates the standardized API regardless of IPC mechanism. That way, the same API can be used over websockets too.
+- Refactor obd2 plugin with AsyncQueue. Use thread-safe updateProperty.
+- source export from database plugin does not reflect the source in the database
+- grep all the TODOs in the code and do them
+
diff --git a/ambd/CMakeLists.txt b/ambd/CMakeLists.txt
new file mode 100644
index 00000000..4c66e05e
--- /dev/null
+++ b/ambd/CMakeLists.txt
@@ -0,0 +1,42 @@
+set(ambd_headers core.h imainloop.h pluginloader.h glibmainloop.h)
+set(ambd_sources core.cpp main.cpp pluginloader.cpp glibmainloop.cpp imainloop.h)
+
+pkg_check_modules(gio REQUIRED gio-2.0)
+
+if(qtmainloop)
+
+ message(STATUS "using Qt mainloop")
+
+ find_package(Qt5Core)
+ if(Qt5Core_FOUND)
+ 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})
+
+ set(include_dirs ${include_dirs} ${QT_INCLUDE_DIRS})
+ set(link_libraries ${link_libraries} ${QT_LIBRARIES})
+
+ add_definitions(-DQT_NO_KEYWORDS)
+ add_definitions(-DUSE_QT_CORE)
+
+ set(qtmainloopplugin_headers qtmainloop.h)
+ set(qtmainloopplugin_sources qtmainloop.cpp)
+
+ add_library(qtmainloopplugin MODULE ${qtmainloopplugin_sources})
+ set_target_properties(qtmainloopplugin PROPERTIES PREFIX "")
+ target_link_libraries(qtmainloopplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries})
+
+ install(TARGETS qtmainloopplugin LIBRARY DESTINATION ${LIB_INSTALL_DIR}/automotive-message-broker)
+ endif(Qt5Core_FOUND)
+endif(qtmainloop)
+
+add_executable(ambd ${ambd_sources})
+
+include_directories(${include_dirs} )
+target_link_libraries(ambd ${link_libraries} dl amb ${gio_LIBRARIES})
+
+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.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/core.cpp b/ambd/core.cpp
new file mode 100644
index 00000000..02e4a08e
--- /dev/null
+++ b/ambd/core.cpp
@@ -0,0 +1,589 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "core.h"
+#include <functional>
+#include <glib.h>
+#include "listplusplus.h"
+#include "debugout.h"
+
+using namespace std::placeholders;
+
+int lastpps=0;
+int lastfpps=0;
+
+static int PPSUpdate(void* data)
+{
+ Core::Performance *performance = (Core::Performance*)data;
+
+ if(performance->propertiesPerSecond > 0 && performance->propertiesPerSecond != lastpps)
+ {
+ lastpps = performance->propertiesPerSecond;
+ DebugOut(1)<<"Property updates per second: "<<performance->propertiesPerSecond<<endl;
+ }
+
+ performance->propertiesPerSecond = 0;
+
+ if(performance->firedPropertiesPerSecond > 0 && performance->firedPropertiesPerSecond != lastfpps)
+ {
+ lastfpps = performance->firedPropertiesPerSecond;
+ DebugOut(1)<<"Fired property updates per second: "<<performance->firedPropertiesPerSecond<<endl;
+ }
+
+ performance->firedPropertiesPerSecond = 0;
+
+ return 1;
+}
+
+Core::Core(std::map<string, string> config): AbstractRoutingEngine(config), handleCount(0)
+{
+ g_timeout_add(1000,PPSUpdate,&performance);
+
+ auto simpleCb = [this](amb::Queue<AbstractPropertyType*, amb::PropertyCompare>* q)
+ {
+ while(q->count())
+ {
+ AbstractPropertyType* value = q->pop();
+ updateProperty(value);
+ }
+ };
+
+ int hpqs = 0;
+ int lpqs = 0;
+ int npqs = 0;
+
+ if(config.find("highPriorityQueueSize") != config.end())
+ {
+ hpqs = boost::lexical_cast<int, std::string>(config["highPriorityQueueSize"]);
+ }
+
+ if(config.find("normalPriorityQueueSize") != config.end())
+ {
+ npqs = boost::lexical_cast<int, std::string>(config["normalPriorityQueueSize"]);
+ }
+
+ if(config.find("lowPriorityQueueSize") != config.end())
+ {
+ lpqs = boost::lexical_cast<int, std::string>(config["lowPriorityQueueSize"]);
+ }
+
+ watcherPtr = new amb::AsyncQueueWatcher<AbstractPropertyType*, amb::PropertyCompare>(&updatePropertyQueue, simpleCb, npqs);
+ watcherPtrLow = new amb::AsyncQueueWatcher<AbstractPropertyType*, amb::PropertyCompare>(&updatePropertyQueueLow,
+ simpleCb, lpqs,
+ AbstractPropertyType::Low);
+ watcherPtrHigh = new amb::AsyncQueueWatcher<AbstractPropertyType*, amb::PropertyCompare>(&updatePropertyQueueHigh,
+ simpleCb, hpqs,
+ AbstractPropertyType::High);
+
+}
+
+Core::~Core()
+{
+ delete watcherPtr;
+
+ for(auto itr = mSinks.begin(); itr != mSinks.end(); ++itr)
+ {
+ delete *itr;
+ itr = mSinks.begin();
+ }
+ mSinks.clear();
+}
+
+void Core::registerSource(AbstractSource *source)
+{
+ mSources.insert(source);
+}
+
+void Core::updateSupported(PropertyList added, PropertyList removed, AbstractSource* source)
+{
+ if(!source || mSources.find(source) == mSources.end())
+ return;
+
+ /// add the newly supported to master list
+
+ if(added.size())
+ handleAddSupported(added, source);
+
+ /// removed no longer supported properties from master list.
+ if(removed.size())
+ handleRemoveSupported(removed, source);
+
+ /// tell all sinks about the newly supported properties.
+
+ PropertyList s = supported();
+
+ if(!s.size()) return;
+
+ for(auto sink : mSinks)
+ {
+ sink->supportedChanged(s);
+ }
+}
+
+PropertyList Core::supported()
+{
+ PropertyList supportedProperties;
+
+ std::transform(mMasterPropertyList.begin(), mMasterPropertyList.end(), std::back_inserter(supportedProperties),
+ [](const std::multimap<AbstractSource*, VehicleProperty::Property>::value_type& itr)
+ {
+ return itr.second;
+ });
+
+ // remove duplicates:
+ std::sort(supportedProperties.begin(), supportedProperties.end());
+ auto itr = std::unique(supportedProperties.begin(), supportedProperties.end());
+
+ supportedProperties.erase(itr,supportedProperties.end());
+
+ return supportedProperties;
+}
+
+void Core::updateProperty(AbstractPropertyType *value, const string & uuid)
+{
+ if(value->sourceUuid != uuid)
+ {
+ value->sourceUuid = uuid;
+ }
+
+ if(value->priority == AbstractPropertyType::Instant)
+ updateProperty(value);
+ else if(value->priority == AbstractPropertyType::High)
+ {
+ value->destroyed.push_back([this](AbstractPropertyType* v)
+ {
+ updatePropertyQueueHigh.remove(v);
+ });
+ updatePropertyQueueHigh.append(value);
+ }
+ else if(value->priority == AbstractPropertyType::Normal)
+ {
+ value->destroyed.push_back([this](AbstractPropertyType* v)
+ {
+ updatePropertyQueue.remove(v);
+ });
+ updatePropertyQueue.append(value);
+ }
+ else if(value->priority == AbstractPropertyType::Low)
+ {
+ value->destroyed.push_back([this](AbstractPropertyType* v)
+ {
+ updatePropertyQueueLow.remove(v);
+ });
+ updatePropertyQueueLow.append(value);
+ }
+}
+
+void Core::updateProperty(AbstractPropertyType * value)
+{
+ VehicleProperty::Property & property = value->name;
+ const string & uuid = value->sourceUuid;
+
+ performance.propertiesPerSecond++;
+
+ auto filteredSourceSinkMapIt = propertySinkMap.find(property);
+ auto cbMapItr = propertyCbMap.find(property);
+
+ if(filteredSourceSinkMapIt != propertySinkMap.end())
+ {
+ const FilteredSourceSinkMap & filteredSourceSinks = filteredSourceSinkMapIt->second;
+
+ DebugOut()<<__FUNCTION__<<"() there are "<<filteredSourceSinks.size()<<" sinks connected to property: "<<property<<endl;
+
+ performance.firedPropertiesPerSecond++;
+
+ for(auto itr = filteredSourceSinks.begin(); itr != filteredSourceSinks.end(); ++itr)
+ {
+ AbstractSink* sink = itr->first;
+ const std::string & sourceUuid = itr->second;
+
+ bool isFiltered = !sourceUuid.empty();
+
+ if(isFiltered)
+ {
+ DebugOut()<<"Property ("<<property<<") for sink is filtered for source: "<<sourceUuid<<endl;
+ }
+
+ if( !isFiltered || sourceUuid == uuid)
+ {
+ sink->propertyChanged(value);
+ }
+ }
+ }
+ else
+ {
+ DebugOut()<<__FUNCTION__<<"() there are no sinks connected to property: "<<property<<endl;
+ }
+
+ if(cbMapItr != propertyCbMap.end())
+ {
+ FilteredSourceCbMap cbs = (*cbMapItr).second;
+
+ for(auto itr : cbs)
+ {
+ uint handle = itr.first;
+ const std::string& sourceUuid = itr.second;
+
+ bool isFiltered = !sourceUuid.empty();
+
+ if(isFiltered)
+ {
+ DebugOut()<<"Property ("<<property<<") for cb is filtered for source: "<<sourceUuid<<endl;
+ }
+
+ if( !isFiltered || sourceUuid == uuid)
+ {
+ if(handleCbMap.count(handle))
+ {
+ auto cb = handleCbMap[handle];
+ try
+ {
+ cb(value);
+ }
+ catch(...)
+ {
+ DebugOut(DebugOut::Warning)<<"Failed to call callback subscribed to property: "<<property<<endl;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ DebugOut()<<__FUNCTION__<<"() there are no cb connected to property: "<<property<<endl;
+ return;
+ }
+}
+
+void Core::registerSink(AbstractSink *self)
+{
+ mSinks.insert(self);
+}
+
+void Core::unregisterSink(AbstractSink *self)
+{
+ mSinks.erase(self);
+}
+
+AsyncPropertyReply *Core::getPropertyAsync(AsyncPropertyRequest request)
+{
+ AbstractSource* source = sourceForProperty(request.property, request.sourceUuidFilter);
+
+ AsyncPropertyReply* reply = new AsyncPropertyReply(request);
+
+ if(!source || ((source->supportedOperations() & AbstractSource::Get) != AbstractSource::Get)) { // not found or doesn't support AbstractSource::Get
+ // Don't wait until timer expire, complete with error here.
+ reply->error = AsyncPropertyReply::InvalidOperation;
+ if(request.completed)
+ request.completed(reply);
+ }
+ else{
+ source->getPropertyAsync(reply);
+
+ }
+
+ /** right now the owner of the reply becomes the requestor that called this method.
+ * reply will become invalid after the first reply. */
+ return reply;
+}
+
+void Core::getRangePropertyAsync(AsyncRangePropertyRequest request)
+{
+ AsyncRangePropertyReply * reply = new AsyncRangePropertyReply(request);
+
+ bool anySupport = false;
+ for(auto src : mSources)
+ {
+ if(((src->supportedOperations() & AbstractSource::GetRanged) == AbstractSource::GetRanged))
+ {
+ anySupport = true;
+ src->getRangePropertyAsync(reply);
+ }
+ }
+
+ if(!anySupport)
+ {
+ reply->success = false;
+ reply->error = AsyncPropertyReply::InvalidOperation;
+ reply->completed(reply);
+ }
+}
+
+AsyncPropertyReply * Core::setProperty(AsyncSetPropertyRequest request)
+{
+ AbstractSource* src = sourceForProperty(request.property, request.sourceUuidFilter);
+
+ if(src && ((src->supportedOperations() & AbstractSource::Set) == AbstractSource::Set))
+ return src->setProperty(request);
+
+ DebugOut(DebugOut::Warning)<<"Error: setProperty opration failed. Property may not be supported: "<<request.property<<endl;
+ return NULL;
+}
+
+bool Core::subscribeToProperty(const VehicleProperty::Property &property, AbstractSink* sink)
+{
+ auto sinksIt = propertySinkMap.find(property);
+ if(sinksIt != propertySinkMap.end() && sinksIt->second.find(sink) != sinksIt->second.end())
+ {
+ DebugOut(1)<<__FUNCTION__<<" property " << property << " has already been subscribed." << endl;
+ return false;
+ }
+
+ DebugOut(1)<<"Subscribing to: "<<property<<endl;
+
+ bool subscribed(false);
+ auto itr = mMasterPropertyList.begin();
+ while(itr != mMasterPropertyList.end())
+ {
+ VehicleProperty::Property prop = itr->second;
+ if(prop == property) {
+ AbstractSource* src = itr->first;
+ src->subscribeToPropertyChanges(property);
+ // Move to next source. It will skip all the remaining properties in this source.
+ itr = mMasterPropertyList.upper_bound(src);
+ subscribed = true;
+ }
+ else{
+ ++itr;
+ }
+ }
+
+ //if(subscribed)
+ propertySinkMap[property].emplace(sink, std::string(""));
+
+ return subscribed;
+}
+
+bool Core::subscribeToProperty(const VehicleProperty::Property &property, const string &sourceUuidFilter, AbstractSink *sink)
+{
+ auto sinksIt = propertySinkMap.find(property);
+ if(sinksIt != propertySinkMap.end() && sinksIt->second.find(sink) != sinksIt->second.end())
+ {
+ DebugOut(1)<<__FUNCTION__<<" property " << property << " has already been subscribed." << endl;
+ return false;
+ }
+
+ DebugOut(1)<<"Subscribing to: "<<property<<endl;
+
+ AbstractSource* src = sourceForProperty(property, sourceUuidFilter);
+ if(!src)
+ return false;
+
+ propertySinkMap[property].emplace(sink, sourceUuidFilter);
+
+ src->subscribeToPropertyChanges(property);
+
+ return true;
+}
+
+bool Core::subscribeToProperty(const VehicleProperty::Property &, const string & sourceUuidFilter, Zone::Type zoneFilter, AbstractSink *sink)
+{
+ /// TODO: implement
+ throw std::runtime_error("Not implemented");
+}
+
+uint Core::subscribeToProperty(const VehicleProperty::Property &property, AbstractRoutingEngine::PropertyChangedType cb, std::string pid)
+{
+ DebugOut(1)<<"Subscribing to: "<<property<<endl;
+
+ auto itr = mMasterPropertyList.begin();
+ while(itr != mMasterPropertyList.end())
+ {
+ VehicleProperty::Property prop = itr->second;
+ if(prop == property) {
+ AbstractSource* src = itr->first;
+ src->subscribeToPropertyChanges(property);
+ // Move to next source. It will skip all the remaining properties in this source.
+ itr = mMasterPropertyList.upper_bound(src);
+ }
+ else{
+ ++itr;
+ }
+ }
+
+ handleCbMap[++handleCount] = cb;
+ propertyCbMap[property].emplace(handleCount, std::string(""));
+ return handleCount;
+}
+
+bool Core::unsubscribeToProperty(const VehicleProperty::Property & property, AbstractSink* sink)
+{
+ auto sinksIt = propertySinkMap.find(property);
+ if(sinksIt == propertySinkMap.end())
+ {
+ DebugOut(1)<<__FUNCTION__<<" property not subscribed to: "<<property<<endl;
+ return false;
+ }
+
+ sinksIt->second.erase(sink);
+
+ /// Now we check to see if this is the last subscriber
+ if(sinksIt->second.empty())
+ {
+ propertySinkMap.erase(sinksIt);
+ auto itr = mMasterPropertyList.begin();
+ while(itr != mMasterPropertyList.end())
+ {
+ if(itr->second == property) {
+ AbstractSource* src = itr->first;
+ src->unsubscribeToPropertyChanges(property);
+ // Move to next source. It will skip all the remaining properties in this source.
+ itr = mMasterPropertyList.upper_bound(src);
+ }
+ else{
+ ++itr;
+ }
+ }
+ }
+
+ return true;
+}
+
+void Core::unsubscribeToProperty(uint handle)
+{
+ handleCbMap.erase(handle);
+ /// TODO: unsubscribe from source
+}
+
+PropertyInfo Core::getPropertyInfo(const VehicleProperty::Property &property, const string &sourceUuid)
+{
+ if(sourceUuid == "")
+ return PropertyInfo::invalid();
+
+ auto srcs = sourcesForProperty(property);
+
+ if(!contains(srcs, sourceUuid))
+ return PropertyInfo::invalid();
+
+ auto theSource = find_if(mSources.begin(), mSources.end(),[&sourceUuid](const std::set<AbstractSource*>::value_type & itr)
+ {
+ return (itr)->uuid() == sourceUuid;
+ });
+
+ return (*theSource)->getPropertyInfo(property);
+}
+
+std::vector<string> Core::sourcesForProperty(const VehicleProperty::Property & property)
+{
+ std::vector<std::string> list;
+
+ for(auto src : mSources)
+ {
+ if(contains(src->supported(), property))
+ list.push_back(src->uuid());
+ }
+
+ return list;
+}
+
+void Core::inspectSupported()
+{
+ for(AbstractSource* src : mSources)
+ {
+ updateSupported(src->supported(), PropertyList(), src);
+ }
+}
+
+void Core::handleAddSupported(const PropertyList& added, AbstractSource* source)
+{
+ if(!source)
+ throw std::runtime_error("Core::handleAddSupported passed a null source");
+
+ if(!contains(mSources, source))
+ {
+ mSources.insert(source);
+ }
+
+ for(auto property : added)
+ {
+ if(!sourceForProperty(property, source->uuid()))
+ mMasterPropertyList.emplace(source, property);
+
+ // Subscribe to property in a new source if such property was subscribed. This catches newly supported properties in the process.
+ if( propertySinkMap.find(property) != propertySinkMap.end()){
+ source->subscribeToPropertyChanges(property);
+ }
+ }
+}
+
+void Core::handleRemoveSupported(const PropertyList& removed, AbstractSource* source)
+{
+ if(!source)
+ return;
+
+ auto range = mMasterPropertyList.equal_range(source);
+ for(auto itr = removed.begin(); itr != removed.end(); ++itr)
+ {
+ //
+ // TODO: We do not have info about all subscribed sources in
+ // std::unordered_map<VehicleProperty::Property, std::map<AbstractSink*, std::string> > propertySinkMap
+ // so we do not know if we can/should remove property from propertySinkMap,
+ // but I suppose this should be handled by each AbstractSink implementation in a callback AbstractSink::supportedChanged().
+
+ const VehicleProperty::Property property(*itr);
+
+ auto it = find_if(
+ range.first, // the first property in source
+ range.second, // one item right after the last property in source
+ [&property](const std::multimap<AbstractSource*, VehicleProperty::Property>::value_type& it) { return it.second == property; }
+ );
+
+ if (it != range.second)// property was found
+ {
+ mMasterPropertyList.erase(it);// References and iterators to the erased elements are invalidated. Other iterators and references are not invalidated.
+
+ // TODO: Do we need to unsubscribe here ???
+ }
+ }
+}
+
+AbstractSource* Core::sourceForProperty(const VehicleProperty::Property& property, const std::string& sourceUuidFilter) const
+{
+ auto it = mMasterPropertyList.end();
+ if(sourceUuidFilter.empty()){
+ it = std::find_if(mMasterPropertyList.begin(), mMasterPropertyList.end(),
+ [&property](const std::multimap<AbstractSource*, VehicleProperty::Property>::value_type& it) { return it.second == property; }
+ );
+ }
+ else{
+ auto itSource = find_if(mSources.begin(),mSources.end(),[&sourceUuidFilter](const std::set<AbstractSource*>::value_type & it)
+ {
+ return (it)->uuid() == sourceUuidFilter;
+ });
+ if(itSource != mSources.end()){
+ auto range = mMasterPropertyList.equal_range(*itSource);
+ auto temp = find_if(
+ range.first, // the first property in source
+ range.second, // one item right after the last property in source
+ [&property](const std::multimap<AbstractSource*, VehicleProperty::Property>::value_type& it)
+ {
+ return it.second == property; }
+ );
+
+ if (temp != range.second)// property was found
+ it = temp;
+ }
+ }
+
+ if(it == mMasterPropertyList.end())
+ return nullptr;
+ else
+ return it->first;
+}
+
diff --git a/ambd/core.h b/ambd/core.h
new file mode 100644
index 00000000..9a1f23a1
--- /dev/null
+++ b/ambd/core.h
@@ -0,0 +1,110 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef CORE_H
+#define CORE_H
+
+#include "abstractsink.h"
+#include "abstractsource.h"
+#include "abstractroutingengine.h"
+#include "asyncqueue.hpp"
+
+#include <unordered_map>
+#include <unordered_set>
+#include <map>
+
+class Core: public AbstractRoutingEngine
+{
+
+public:
+ Core(std::map<std::string, std::string> config);
+ ~Core();
+ /// sources:
+
+ void registerSource(AbstractSource *src);
+ void updateSupported(PropertyList added, PropertyList removed, AbstractSource* source);
+ void updateProperty(AbstractPropertyType* value, const std::string &uuid);
+
+ /// sinks:
+
+ void registerSink(AbstractSink *self);
+ void unregisterSink(AbstractSink *self);
+ AsyncPropertyReply* getPropertyAsync(AsyncPropertyRequest request);
+ void getRangePropertyAsync(AsyncRangePropertyRequest request);
+ AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request);
+ uint subscribeToProperty(const VehicleProperty::Property &, AbstractRoutingEngine::PropertyChangedType, std::string pid="");
+ bool subscribeToProperty(const VehicleProperty::Property &, AbstractSink* self);
+ bool subscribeToProperty(const VehicleProperty::Property &, const std::string & sourceUuidFilter, AbstractSink *self);
+ bool subscribeToProperty(const VehicleProperty::Property &, const std::string & sourceUuidFilter, Zone::Type zoneFilter, AbstractSink *self);
+ bool unsubscribeToProperty(const VehicleProperty::Property &, AbstractSink* self);
+ void unsubscribeToProperty(uint handle);
+ PropertyList supported();
+
+ PropertyInfo getPropertyInfo(const VehicleProperty::Property &,const std::string &sourceUuid);
+ std::vector<std::string> sourcesForProperty(const VehicleProperty::Property & property);
+
+ struct Performance {
+ Performance(): propertiesPerSecond(0), firedPropertiesPerSecond(0) {}
+ int propertiesPerSecond;
+ int firedPropertiesPerSecond;
+ };
+
+ void inspectSupported();
+
+private:
+
+ void handleAddSupported(const PropertyList& added, AbstractSource* source);
+ void handleRemoveSupported(const PropertyList& removed, AbstractSource* source);
+ AbstractSource* sourceForProperty(const VehicleProperty::Property& property, const std::string& sourceUuidFilter = "") const;
+ void updateProperty(AbstractPropertyType* value);
+
+private:
+
+ //typedef std::map< Zone::Type, AbstractPropertyType> ZonePropertyType;
+
+ // to support zone filtering replace VehicleProperty::Property with ZonePropertyType
+ std::multimap<AbstractSource*, VehicleProperty::Property> mMasterPropertyList;
+
+ std::unordered_set<AbstractSource*> mSources;
+ std::unordered_set<AbstractSink*> mSinks;
+
+ Performance performance;
+
+ // std::string here is AbstractSource::uuid()
+ typedef std::map<AbstractSink*, std::string> FilteredSourceSinkMap;
+
+ ///uint cbHandle, std::string uuid
+ typedef std::unordered_map<uint, std::string> FilteredSourceCbMap;
+
+ // to support zone filtering replace VehicleProperty::Property with ZonePropertyType
+ std::unordered_map<VehicleProperty::Property, FilteredSourceSinkMap > propertySinkMap;
+ std::unordered_map<VehicleProperty::Property, FilteredSourceCbMap> propertyCbMap;
+ std::unordered_map<uint, AbstractRoutingEngine::PropertyChangedType> handleCbMap;
+
+ amb::Queue<AbstractPropertyType*, amb::PropertyCompare> updatePropertyQueue;
+ amb::Queue<AbstractPropertyType*, amb::PropertyCompare> updatePropertyQueueHigh;
+ amb::Queue<AbstractPropertyType*, amb::PropertyCompare> updatePropertyQueueLow;
+ amb::AsyncQueueWatcher<AbstractPropertyType*, amb::PropertyCompare>* watcherPtr;
+ amb::AsyncQueueWatcher<AbstractPropertyType*, amb::PropertyCompare>* watcherPtrHigh;
+ amb::AsyncQueueWatcher<AbstractPropertyType*, amb::PropertyCompare>* watcherPtrLow;
+
+ uint handleCount;
+};
+
+#endif // CORE_H
diff --git a/ambd/glibmainloop.cpp b/ambd/glibmainloop.cpp
new file mode 100644
index 00000000..f2f80ca8
--- /dev/null
+++ b/ambd/glibmainloop.cpp
@@ -0,0 +1,23 @@
+#include "glibmainloop.h"
+#include <glib.h>
+#include <stdlib.h>
+
+GlibMainLoop::GlibMainLoop(int argc, char **argv)
+ :IMainLoop(argc,argv)
+{
+ mainLoop = g_main_loop_new(NULL, false);
+}
+
+GlibMainLoop::~GlibMainLoop()
+{
+ g_main_loop_quit(mainLoop);
+ g_main_loop_unref(mainLoop);
+ //exit(0);
+}
+
+int GlibMainLoop::exec()
+{
+ g_main_loop_run(mainLoop);
+ return 1;
+}
+
diff --git a/ambd/glibmainloop.h b/ambd/glibmainloop.h
new file mode 100644
index 00000000..547e4327
--- /dev/null
+++ b/ambd/glibmainloop.h
@@ -0,0 +1,21 @@
+#ifndef _GLIBMAINLOOP_H_
+#define _GLIBMAINLOOP_H_
+
+#include "imainloop.h"
+#include <glib.h>
+
+class GlibMainLoop: public IMainLoop
+{
+public:
+
+ GlibMainLoop(int argc, char** argv);
+ ~GlibMainLoop();
+
+ int exec();
+
+private:
+ GMainLoop* mainLoop;
+};
+
+
+#endif
diff --git a/ambd/imainloop.h b/ambd/imainloop.h
new file mode 100644
index 00000000..9bcdc1be
--- /dev/null
+++ b/ambd/imainloop.h
@@ -0,0 +1,25 @@
+#ifndef IMAINLOOP_H_
+#define IMAINLOOP_H_
+
+
+
+class IMainLoop {
+public:
+
+ IMainLoop(int argc, char **argv)
+ :mArgc(argc),mArgv(argv)
+ {
+
+ }
+
+ virtual ~IMainLoop() { }
+
+ virtual int exec() = 0;
+
+private:
+ int mArgc;
+ char** mArgv;
+};
+
+
+#endif
diff --git a/ambd/main.cpp b/ambd/main.cpp
new file mode 100644
index 00000000..d39c2d68
--- /dev/null
+++ b/ambd/main.cpp
@@ -0,0 +1,226 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <iostream>
+#include <string>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <stdexcept>
+#include <glib-object.h>
+
+#ifdef USE_QT_CORE
+
+#include <QCoreApplication>
+
+#else
+
+#include <glib.h>
+
+#endif
+
+#include "pluginloader.h"
+#include <debugout.h>
+
+using namespace std;
+
+IMainLoop* mainloop = nullptr;
+
+void interrupt(int sign)
+{
+ signal(sign, SIG_IGN);
+ cout<<"Signal caught. Exiting gracefully.\n"<<endl;
+
+ /// this will cause the application to terminate and clean up:
+ delete mainloop;
+}
+
+void daemonize();
+
+void printhelp(const char *argv0);
+
+static const char shortopts[] = "hvDc:d:l:we";
+
+static const struct option longopts[] = {
+ { "help", no_argument, NULL, 'h' }, ///< Print the help text
+ { "version", no_argument, NULL, 'v' }, ///< Print the version text
+ { "daemonise", no_argument, NULL, 'D' }, ///< Daemonise
+ { "config", required_argument, NULL, 'c' },
+ { "debug", required_argument, NULL, 'd' },
+ { "log", required_argument, NULL, 'l' },
+ { "warn", no_argument, NULL, 'w' },
+ { "err", no_argument, NULL, 'e' },
+ { NULL, 0, NULL, 0 } ///< End
+};
+
+void printVersion()
+{
+ DebugOut(0) << PROJECT_NAME << endl;
+ DebugOut(0)<<"Version: " << PROJECT_VERSION<<" Series: " << PROJECT_SERIES <<" (" << PROJECT_CODENAME<<" " << PROJECT_QUALITY << ")" << endl;
+}
+
+static void glibLogHandler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
+{
+ if(log_level == G_LOG_LEVEL_CRITICAL)
+ DebugOut(DebugOut::Error) << message << endl;
+ else if(log_level == G_LOG_LEVEL_WARNING)
+ DebugOut(DebugOut::Warning) << message << endl;
+ else
+ DebugOut() << message << endl;
+}
+
+int main(int argc, char **argv)
+{
+
+ bool isdeamonize=false;
+ int optc;
+ int th = 0;
+ string config="/etc/ambd/config";
+ ofstream logfile;
+ string logfn;
+
+ g_log_set_handler(G_LOG_DOMAIN, GLogLevelFlags(G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL), glibLogHandler, nullptr);
+
+ while ((optc = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)
+ {
+ switch (optc)
+ {
+ case 'D':
+ isdeamonize = true;
+ break;
+
+ case 'v':
+ printVersion();
+ return (0);
+ break;
+ case 'c':
+ DebugOut(0)<<"Config: "<<optarg<<endl;
+ config=optarg;
+ break;
+ case 'd':
+ th = atoi(optarg);
+ DebugOut::setDebugThreshhold(th);
+ break;
+ case 'l':
+ logfn = optarg;
+ break;
+ case 'w':
+ DebugOut::setThrowWarn(true);
+ break;
+ case 'e':
+ DebugOut::setThrowErr(true);
+ break;
+ default:
+ DebugOut(0)<<"Unknown option "<<optc<<endl;
+ printhelp(argv[0]);
+ return (0);
+ break;
+ }
+ }
+
+ if(isdeamonize)
+ daemonize();
+
+ if(!logfn.empty())
+ {
+ logfile.open(logfn, ios::out | ios::trunc);
+ DebugOut::setOutput(logfile);
+ }
+
+ printVersion();
+
+ if(getuid() == 0)
+ {
+ DebugOut(DebugOut::Warning)<<"Running as root. This is dangerous."<<endl;
+ }
+
+#ifndef GLIB_VERSION_2_36
+ g_type_init();
+#endif
+
+ VehicleProperty::factory();
+
+ PluginLoader loader(config, argc, argv);
+
+ mainloop = loader.mainloop();
+
+ /* Register signal handler */
+ signal(SIGINT, interrupt);
+ signal(SIGTERM, interrupt);
+
+ mainloop->exec();
+
+ if(logfile.is_open())
+ logfile.close();
+
+ return 0;
+}
+
+void daemonize()
+{
+ int i=0;
+ if(getppid() == 1)
+ {
+ return; // already a daemon
+ }
+ if((i = fork()) < 0)
+ {
+ fprintf(stderr, "%s:%s(%d) - fork error: %s", __FILE__, __FUNCTION__, __LINE__, strerror(errno));
+ exit(1);
+ }
+ if(i > 0)
+ {
+ exit(0); // parent exits
+ } // child (daemon) continues
+ setsid(); // obtain a new process group
+ for(i = getdtablesize(); i >= 0; --i)
+ {
+ close(i); // close all descriptors
+ }
+ { // handle standard I/O
+ i = open("/dev/null", O_RDWR);
+ dup(i);
+ dup(i);
+ }
+ // first instance continues
+}
+
+void printhelp(const char *argv0)
+{
+ printf("Usage: %s [args]\n"
+ " [-D|--daemonise] run ambd in daemon mode\n"
+ " [-v|--version] spit out the version then exit\n"
+ " [-c|--config </path/to/config> ] specify which config to use\n"
+ " [-d|--debug <level (0-5)> ] set the debug level\n"
+ " [-l]--log </path/to/logfile> ] specify an debug output log file\n"
+ " [-w]--warn] throw on warnings\n"
+ " [-e]--err] throw on errors\n"
+ " [-h|--help] print this menu and exit\n"
+ , argv0);
+}
+
+
diff --git a/ambd/pluginloader.cpp b/ambd/pluginloader.cpp
new file mode 100644
index 00000000..dd1d2ed1
--- /dev/null
+++ b/ambd/pluginloader.cpp
@@ -0,0 +1,289 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "pluginloader.h"
+#include "glibmainloop.h"
+#include "core.h"
+
+#include <gio/gio.h>
+#include <picojson.h>
+
+#include <iostream>
+#include <fstream>
+#include <stdexcept>
+#include <boost/concept_check.hpp>
+
+std::string get_file_contents(const char *filename)
+{
+ std::ifstream in(filename, std::ios::in);
+ if(in.fail())
+ {
+ DebugOut(DebugOut::Error) << "Failed to open file '" << filename << "':' " << strerror(errno) << endl;
+ return "";
+ }
+
+ std::string output;
+ std::string line;
+ while(in.good())
+ {
+ getline(in,line);
+ output.append(line);
+ }
+ return output;
+}
+
+PluginLoader::PluginLoader(string configFile, int argc, char** argv): f_create(NULL), routingEngine(nullptr), mMainLoop(nullptr)
+{
+ DebugOut()<<"Loading config file: "<<configFile<<endl;
+ std::string configBuffer = get_file_contents(configFile.c_str());
+
+ std::string picojsonerr = "";
+ picojson::value v;
+ picojson::parse(v, configBuffer.begin(), configBuffer.end(), &picojsonerr);
+
+ if(!picojsonerr.empty())
+ {
+ DebugOut(DebugOut::Error) << "Failed to parse main config! " << picojsonerr << endl;
+ throw std::runtime_error("Error parsing config");
+ }
+
+ if(v.contains("routingEngine"))
+ {
+ string restr = v.get("routingEngine").to_str();
+
+ routingEngine = loadRoutingEngine(restr);
+
+ if(!routingEngine)
+ {
+ DebugOut(DebugOut::Warning)<<"Failed to load routing engine plugin: "<<restr<<endl;
+ }
+ }
+
+ if(!routingEngine)
+ {
+ /// there is no mainloop entry, use default glib
+ DebugOut()<<"No routing engine specified in config. Using built-in 'core' routing engine by default."<<endl;
+
+ /// core wants some specific configuration settings:
+ std::map<std::string,std::string> settings;
+
+
+ for (auto q : {"lowPriorityQueueSize", "normalPriorityQueueSize", "highPriorityQueueSize"})
+ {
+ 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);
+ }
+
+ if(v.contains("mainloop"))
+ {
+ /// there is a mainloop entry. Load the plugin:
+
+ string mainloopstr = v.get("mainloop").to_str();
+
+ mMainLoop = loadMainLoop(mainloopstr, argc, argv);
+
+ if(!mMainLoop)
+ {
+ DebugOut(DebugOut::Warning)<<"Failed to load main loop plugin."<<endl;
+ }
+ }
+ else if(!mMainLoop)
+ {
+ /// there is no mainloop entry, use default glib
+ DebugOut()<<"No mainloop specified in config. Using glib by default."<<endl;
+ mMainLoop = new GlibMainLoop(argc, argv);
+ }
+
+
+ for (auto q : {"sources", "sinks"})
+ {
+ if(v.contains("sources"))
+ {
+ picojson::array list = v.get(q).get<picojson::array>();
+ if (!list.size())
+ {
+ DebugOut() << "Error getting list for " << q << endl;
+ }
+
+ 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;
+
+ configurationMap[key] = valstr;
+ }
+
+ 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();
+ }
+}
+
+PluginLoader::~PluginLoader()
+{
+ for(auto handle : openHandles)
+ dlclose(handle);
+}
+
+IMainLoop *PluginLoader::mainloop()
+{
+ return mMainLoop;
+}
+
+std::string PluginLoader::errorString()
+{
+ return mErrorString;
+}
+
+void PluginLoader::scanPluginDir(const std::string & dir)
+{
+ DebugOut() << "Scanning plugin directory: " << dir << endl;
+
+ auto pluginsDirectory = amb::make_gobject(g_file_new_for_path(dir.c_str()));
+
+ GError* enumerateError = nullptr;
+
+ auto enumerator = amb::make_gobject(g_file_enumerate_children(pluginsDirectory.get(),
+ G_FILE_ATTRIBUTE_ID_FILE "," G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NONE, nullptr,
+ &enumerateError));
+ auto enumerateErrorPtr = amb::make_super(enumerateError);
+
+ if(enumerateErrorPtr)
+ {
+ DebugOut(DebugOut::Error) << "Scanning plugin directory: " << enumerateErrorPtr->message << endl;
+ return;
+ }
+
+ GError* errorGetFile = nullptr;
+ while(auto pluginConfig = amb::make_gobject(g_file_enumerator_next_file(enumerator.get(), nullptr, &errorGetFile)))
+ {
+ 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());
+
+ if(!readPluginConfig(data))
+ {
+ DebugOut(DebugOut::Error) << "Reading contentds of file: " << name << endl;
+ }
+ }
+
+ auto errorGetFilePtr = amb::make_super(errorGetFile);
+
+ if(errorGetFilePtr)
+ {
+ DebugOut(DebugOut::Error) << "enumerating file: " << errorGetFilePtr->message << endl;
+ return;
+ }
+}
+
+bool PluginLoader::readPluginConfig(const string &configData)
+{
+ picojson::value v;
+ std::string err;
+
+ picojson::parse(v, configData.begin(), configData.end(), &err);
+
+ if (!err.empty())
+ {
+ DebugOut(DebugOut::Error) << err << endl;
+ return false;
+ }
+
+ std::string pluginName;
+ if(v.contains("name"))
+ {
+ pluginName = v.get("name").to_str();
+ }
+
+ std::string pluginPath;
+ if(v.contains("path"))
+ {
+ pluginPath = v.get("path").to_str();
+ }
+ else
+ {
+ DebugOut(DebugOut::Error) << "config missing 'path'." << endl;
+ return false;
+ }
+
+ bool enabled = false;
+ if(v.contains("enabled"))
+ {
+ enabled = v.get("enabled").get<bool>();
+ }
+ else
+ {
+ DebugOut(DebugOut::Error) << "config missing 'enabled'." << endl;
+ return false;
+ }
+
+ DebugOut() << "Plugin: " << pluginName << endl;
+ DebugOut() << "Path: " << pluginPath << endl;
+ DebugOut() << "Enabled: " << enabled << endl;
+
+ if(enabled)
+ {
+ std::map<std::string, std::string> otherConfig;
+
+ picojson::object obj = v.get<picojson::object>();
+ for(auto itr : obj)
+ {
+ if(!itr.second.is<std::string>())
+ otherConfig[itr.first] = itr.second.serialize();
+ else
+ otherConfig[itr.first] = itr.second.to_str();
+ }
+
+ loadPlugin(pluginPath, otherConfig);
+ }
+
+ return true;
+}
+
diff --git a/ambd/pluginloader.h b/ambd/pluginloader.h
new file mode 100644
index 00000000..7700feed
--- /dev/null
+++ b/ambd/pluginloader.h
@@ -0,0 +1,148 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef PLUGINLOADER_H
+#define PLUGINLOADER_H
+
+#include <string>
+#include <functional>
+#include <dlfcn.h>
+#include <iostream>
+
+#include "abstractsource.h"
+#include "abstractsink.h"
+#include "abstractroutingengine.h"
+#include "debugout.h"
+#include "imainloop.h"
+
+typedef void create_t(AbstractRoutingEngine*, map<string, string> );
+typedef void* create_mainloop_t(int argc, char** argv);
+typedef void* createRoutingEngine(void);
+
+class PluginLoader
+{
+
+public:
+ 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, std::map<std::string, std::string> config)
+ {
+ DebugOut()<<"Loading plugin: "<<pluginName<<endl;
+
+ void* handle = dlopen(pluginName.c_str(), RTLD_LAZY);
+
+ if(!handle)
+ {
+ mErrorString = dlerror();
+ DebugOut(DebugOut::Error)<<"error opening plugin: "<<pluginName<<" in "<<__FILE__<<" - "<<__FUNCTION__<<":"<<__LINE__<<" "<<mErrorString<<endl;
+ return false;
+ }
+
+ openHandles.push_back(handle);
+
+ f_create = (create_t *)dlsym(handle, "create");
+
+ if(f_create)
+ {
+ f_create(routingEngine, config);
+ return true;
+ }
+
+ return false;
+ }
+
+ IMainLoop* loadMainLoop(string pluginName, int argc, char** argv)
+ {
+ DebugOut()<<"Loading plugin: "<<pluginName<<endl;
+
+ void* handle = dlopen(pluginName.c_str(), RTLD_LAZY);
+
+ if(!handle)
+ {
+ mErrorString = dlerror();
+ DebugOut(DebugOut::Error)<<"error opening plugin: "<<pluginName<<" in "<<__FILE__<<" - "<<__FUNCTION__<<":"<<__LINE__<<" "<<mErrorString<<endl;
+ return nullptr;
+ }
+
+ openHandles.push_back(handle);
+
+ m_create = (create_mainloop_t *)dlsym(handle, "create");
+
+ if(m_create)
+ {
+ void* obj = m_create(argc, argv);
+ return static_cast<IMainLoop*>( obj );
+ }
+
+ return nullptr;
+ }
+ AbstractRoutingEngine* loadRoutingEngine(string pluginName)
+ {
+ DebugOut()<<"Loading plugin: "<<pluginName<<endl;
+
+ void* handle = dlopen(pluginName.c_str(), RTLD_LAZY);
+
+ if(!handle)
+ {
+ mErrorString = dlerror();
+ cerr<<"error opening plugin: "<<pluginName<<" in "<<__FILE__<<" - "<<__FUNCTION__<<":"<<__LINE__<<" "<<mErrorString<<endl;
+ return nullptr;
+ }
+
+ openHandles.push_back(handle);
+
+ r_create = (createRoutingEngine *)dlsym(handle, "create");
+
+ if(r_create)
+ {
+ void* obj = r_create();
+ return static_cast<AbstractRoutingEngine*>( obj );
+ }
+
+ return nullptr;
+ }
+
+private:
+
+ std::string mPluginPath;
+ std::string mErrorString;
+
+ AbstractRoutingEngine* routingEngine;
+
+ create_t * f_create;
+ create_mainloop_t * m_create;
+ createRoutingEngine * r_create;
+
+ IMainLoop* mMainLoop;
+
+ std::vector<void*> openHandles;
+};
+
+#endif // PLUGINLOADER_H
diff --git a/ambd/qtmainloop.cpp b/ambd/qtmainloop.cpp
new file mode 100644
index 00000000..32bee662
--- /dev/null
+++ b/ambd/qtmainloop.cpp
@@ -0,0 +1,22 @@
+#include "qtmainloop.h"
+
+extern "C" IMainLoop * create(int argc, char** argv)
+{
+ return new QtMainLoop(argc, argv);
+}
+
+QtMainLoop::QtMainLoop(int argc, char** argv)
+ :IMainLoop(argc,argv)
+{
+ app = new QCoreApplication(argc,argv);
+}
+
+QtMainLoop::~QtMainLoop()
+{
+ app->exit(0);
+}
+
+int QtMainLoop::exec()
+{
+ return app->exec();
+}
diff --git a/ambd/qtmainloop.h b/ambd/qtmainloop.h
new file mode 100644
index 00000000..a3d7affb
--- /dev/null
+++ b/ambd/qtmainloop.h
@@ -0,0 +1,19 @@
+#ifndef _QTMAINLOOP_H_
+#define _QTMAINLOOP_H_
+
+#include <QCoreApplication>
+#include "imainloop.h"
+
+class QtMainLoop: public IMainLoop
+{
+public:
+
+ QtMainLoop(int argc, char **argv);
+ ~QtMainLoop();
+
+ int exec();
+private:
+ QCoreApplication* app;
+};
+
+#endif
diff --git a/automotive-message-broker.odp b/automotive-message-broker.odp
new file mode 100644
index 00000000..c404e59f
--- /dev/null
+++ b/automotive-message-broker.odp
Binary files differ
diff --git a/automotive-message-broker.pdf b/automotive-message-broker.pdf
new file mode 100644
index 00000000..bd132653
--- /dev/null
+++ b/automotive-message-broker.pdf
Binary files differ
diff --git a/cmake_uninstall.cmake b/cmake_uninstall.cmake
new file mode 100644
index 00000000..df95fb9d
--- /dev/null
+++ b/cmake_uninstall.cmake
@@ -0,0 +1,21 @@
+IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+ MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
+ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+
+FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+STRING(REGEX REPLACE "\n" ";" files "${files}")
+FOREACH(file ${files})
+ MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
+ IF(EXISTS "$ENV{DESTDIR}${file}")
+ EXEC_PROGRAM(
+ "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+ OUTPUT_VARIABLE rm_out
+ RETURN_VALUE rm_retval
+ )
+ IF(NOT "${rm_retval}" STREQUAL 0)
+ MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+ ENDIF(NOT "${rm_retval}" STREQUAL 0)
+ ELSE(EXISTS "$ENV{DESTDIR}${file}")
+ MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
+ ENDIF(EXISTS "$ENV{DESTDIR}${file}")
+ENDFOREACH(file)
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
new file mode 100644
index 00000000..ead8bf2d
--- /dev/null
+++ b/docs/CMakeLists.txt
@@ -0,0 +1,27 @@
+if(enable_docs)
+
+
+# add a target to generate API documentation with Doxygen
+message(STATUS "doxygen doc generation enabled")
+find_package(Doxygen)
+if(DOXYGEN_FOUND)
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
+ add_custom_target(docs ALL ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM)
+
+ #generate mappings documentation
+ add_custom_target(genmappings_libamb
+ python ${CMAKE_BINARY_DIR}/tools/genmapping --output ${CMAKE_CURRENT_BINARY_DIR}/ambdbusmappings.idl ${dbus_mapping_headers}
+ COMMENT "running genmapping")
+ add_dependencies(docs genmappings_libamb)
+
+ install (DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DESTINATION ${DOC_INSTALL_DIR} COMPONENT Docs)
+endif(DOXYGEN_FOUND)
+
+
+endif(enable_docs)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/libamb.in.h ${CMAKE_CURRENT_BINARY_DIR}/libamb.h @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/amb.in.fidl ${CMAKE_CURRENT_BINARY_DIR}/amb.fidl @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/mainpage.in.idl ${CMAKE_CURRENT_BINARY_DIR}/mainpage.idl @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/ambd-configuration.in.idl ${CMAKE_CURRENT_BINARY_DIR}/ambd-configuration.idl @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/ambd.in.md ${CMAKE_CURRENT_BINARY_DIR}/ambd.md @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/ambd.in.md ${CMAKE_SOURCE_DIR}/README.md @ONLY)
diff --git a/docs/Doxyfile.idl.in b/docs/Doxyfile.idl.in
new file mode 100644
index 00000000..55235849
--- /dev/null
+++ b/docs/Doxyfile.idl.in
@@ -0,0 +1,6 @@
+PROJECT_NAME = @PROJECT_NAME@
+PROJECT_NUMBER = @PROJECT_VERSION@
+FILE_PATTERNS = *.fidl
+EXTENSION_MAPPING = fidl=IDL
+INPUT = @CMAKE_CURRENT_SOURCE_DIR@/amb.fidl @CMAKE_CURRENT_BINARY_DIR@/ambdbusmappings.idl
+
diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in
new file mode 100644
index 00000000..2c51d1aa
--- /dev/null
+++ b/docs/Doxyfile.in
@@ -0,0 +1,11 @@
+PROJECT_NAME = @PROJECT_NAME@
+PROJECT_NUMBER = @PROJECT_VERSION@
+PROJECT_NAME = @PROJECT_NAME@
+PROJECT_NUMBER = @PROJECT_VERSION@
+GENERATE_LATEX = NO
+EXTENSION_MAPPING = fidl=IDL
+FILE_PATTERNS = *.md *.idl *.fidl *.h
+RECURSIVE = YES
+IMAGE_PATH = @CMAKE_SOURCE_DIR@/docs/images
+INPUT = @CMAKE_SOURCE_DIR@/RELEASE.md @CMAKE_SOURCE_DIR@/lib/ @CMAKE_BINARY_DIR@/plugins @CMAKE_BINARY_DIR@/docs
+HTML_OUTPUT=@CMAKE_BINARY_DIR@/docs
diff --git a/docs/Doxyfile.mainpage.in b/docs/Doxyfile.mainpage.in
new file mode 100644
index 00000000..10fc0604
--- /dev/null
+++ b/docs/Doxyfile.mainpage.in
@@ -0,0 +1,4 @@
+PROJECT_NAME = @PROJECT_NAME@
+PROJECT_NUMBER = @PROJECT_VERSION@
+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/README b/docs/README
new file mode 100644
index 00000000..e60609fe
--- /dev/null
+++ b/docs/README
@@ -0,0 +1,9 @@
+The Documentation for AMB is generated using Doxygen from amb.fidl.
+To enable doxygen generation of documents, pass -Denable_docs=ON to cmake:
+
+cmake -Denable_docs=ON ..
+
+The internal AMB class and interface documentation is generated in the docs/amb folder.
+DBus API documentation is generated in the docs/dbus folder.
+
+Specific plugin documentation can be found in the plugins/${plugin}/README (ie plugins/dbus/README).
diff --git a/docs/amb.in.fidl b/docs/amb.in.fidl
new file mode 100644
index 00000000..6d36c5a6
--- /dev/null
+++ b/docs/amb.in.fidl
@@ -0,0 +1,1864 @@
+/**
+ * \addtogroup dbus_api_module
+ * @{
+ */
+
+/*!
+* \file amb.fidl
+* \section dbus_api Automotive Message Broker DBus API Documentation
+* \version @PROJECT_VERSION@
+*
+* \section dbus_api_intro Introduction
+* This document describes the DBus interfaces and data types for the
+* Automotive Message Broker API. The data types are intended to as-close-as-
+* possible be compatible with the W3C vehicle <a href="https://rawgit.com/w3c/automotive-bg/master/data_spec.html">data spec</a>.
+*
+* AMB organizes the API into two general interface categories. First the Manager interface (see manager.txt)
+* which includes tools for using the other interfaces. Second is a number of interfaces that
+* represent vehicle data. The latter follows the schema of "org.automotive.DataType" and are
+* contained in verious DBus paths. The DBus paths are generally organized by
+* /{source}/{zone}/DataType. "source" refers to the AMB source that produces the data. "zone"
+* refers to the zone in which the data type is located in the vehicle or "0" for no zone.
+*
+* The interfaces and data types are documented in <a href="amb.fidl">amb.fidl</a>. Franca IDL
+* tools can be used to generate DBus introspection xml which can be used to generate bindings
+* for your language of choice. These interfaces types map to internal AMB properties. To understand the mappings,
+* see the <a href="ambdbusmappings_8idl.html">mapping documentation</a>
+*
+* \section dbus_api_basic_usage Basic Recommended Usage
+*
+* It is recommended that the Manager interface be used to find the DBus Object that contains the
+* data type you need. This is done through the FindObject() call. It is expected that DBus
+* Object Paths may change and so it is not appropriate to hard code DBus Object Paths.
+*
+* Here is a pseudo-code example of how the api is to be used:
+*
+* \code
+* var manager = dbus.interface("org.automotive.Manager", "/");
+*
+* var speedObjectPaths = manager.FindObject("VehicleSpeed");
+*
+* var speedObject = dbus.interface("org.automotive.VehicleSpeed", speedObjectPaths[0]);
+*
+* console.log("Vehicle Speed: " + speedObject.Speed);
+* \endcode
+* \section dbus_api_automotive_manager Automotive Manager
+* Manager is a helper interface for discovering and finding available objects. Manager also helps users look up objects by zone and get additional information about a data type (ieorg.automotive.Manager.ZonesForObjectName).
+* \section dbus_api_zones Zones
+*
+* 'Zone' describes the position in the vehicle where the object is located. The Zone type is a bitfield of values that can be combined to describe a specific location. For example
+*
+* \code
+* Zone.Front | Zone.Left
+* \endcode
+*
+* (which is '9') may represent the driver position.
+*
+* \code
+* enumeration Zone {
+* None = 0,
+* Front = 1,
+* Middle = 1 << 1,
+* Right = 1 << 2,
+* Left = 1 << 3,
+* Rear = 1 << 4,
+* Center = 1 << 5
+* }
+* \endcode
+*
+* \section dbus_api_vehicle_property_type Vehicle Property Type
+* Vehicle Property Type is the common interface which all Data types are derived. This interface is as follows:
+*
+* \code
+* interface VehiclePropertyType {
+* attribute Double Time readonly
+* attribute Zone Zone readonly
+* method GetHistory(Double beginTime, Double endTime) {
+* out{ Dictionary result}
+* }
+* }
+* \endcode
+*
+* \section dbus_api_data_types Data types
+*
+* The data types try to conform to the [http://w3c.github.io/automotive-bg/data_spec.html W3C Automotive Business Group Vehicle Data Specification] as much as possible. There are differences in the Zone type, and this vehicle API contains some additional data types that the W3C Business Group has not yet defined. 'Time' also represents relative time in seconds rather than time in ms since epoch (DOMTimeStamp). The names of the attributes are also different because of Web vs. DBus conventions. In this Vehicle API, DBus properties use CamelCase (ie Speed vs speed) vs lowerCamelCase. Units and types are the same where possible.
+*
+* Also note that many types have been marked "deprecated" and replaced with the W3C version of the type. Deprecated types should not be used in new projects.
+*
+*/
+
+/** @} */
+
+/*!
+* Variant
+*/
+union Variant {
+ UInt8 uint8
+ Int8 int8
+ UInt16 uint16
+ Int16 int16
+ UInt32 uint32
+ Int32 int32
+ UInt32 uin32
+ Int64 int64
+ UInt64 uint64
+ Boolean boolean
+ Float float
+ Double double
+ String string
+ ByteBuffer bytebuffer
+}
+
+/*!
+* Dictionary
+*/
+map Dictionary {
+ String to Variant
+}
+
+/*!
+ * \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.
+*/
+interface VehiclePropertyType {
+
+ /*!
+ * \brief time in seconds since system start when a property in the interface updated.
+ */
+ attribute Double Time readonly
+
+ /*!
+ * \brief Zone in which the interface is situated.
+ */
+ attribute Zone Zone readonly
+
+ /*!
+ * \brief return dictionary of objectName and values for data between
+ * 'beginTime' and 'endTime'
+ * \arg beginTime time stamp in Seconds since Unix Epoc
+ * \arg endTime time stamp in Seconds since Unix Epoc
+ */
+ method GetHistory(Double beginTime, Double endTime) {
+ out{ array of HistoryObject result }
+ }
+}
+
+enumeration Zone {
+ None = 0,
+ Front = 1,
+ Middle = 1 << 1,
+ Right = 1 << 2,
+ Left = 1 << 3,
+ Rear = 1 << 4,
+ Center = 1 << 5
+}
+
+/*! org.automotive.Manager
+ * \brief Manager is a helper interface for discovering and finding available objects.
+ * Objects represent interfaces to data types.
+ */
+interface org.automotive.Manager {
+
+ /*! List
+ * \brief return supported properties
+ */
+ method List {
+ out {array of String objectNames}
+ }
+
+ /*!
+ * FindObject
+ * \brief find the DBus object path matching the given "objectName" (ie "VehicleSpeed" is the object name for
+ * the DBus object at path: "/path/to/VehicleSpeed") or org.automotive.Manager.ObjectNotFound if the object
+ * name is not supported.
+ *
+ * If the object path does not exist, it will be created. The object path will be removed
+ * when the last proccess that calls Find* disconnects from DBus.
+ *
+ * \arg String objectName to find
+ * \return list of object paths that provide the given object Name.
+ */
+ method FindObject {
+ in {
+ String objectName
+ }
+ out {
+ array of String objectPaths
+ }
+ }
+
+ /*!
+ * FindObjectForZone
+ * \brief find the DBus object path which matches "objectName" and "zone". This has the same behavior as FindObject
+ * except that it takes an addition zone argument and only return the path for that zone.
+ * \arg String property is the requested property to be retrieved.
+ * \arg Zone zone is the zone which the object
+ * \return string representing the DBus Object path.
+ * Possible errors:
+ * "org.automotive.Manager.InvalidZone"
+ * "org.automotive.Manager.ObjectNotFound"
+ */
+ method FindObjectForZone {
+ in {
+ String objectName
+ Zone zone
+ }
+ out {
+ String objectPath
+ }
+ }
+
+ /*!
+ * ZonesForObjectName
+ * \brief get a list of zones for a given objectName.
+ * \arg String objectName object name.
+ * \return list of zones for the given objectName (@see Zone)
+ */
+ method ZonesForObjectName {
+ in {
+ String objectName
+ }
+ out {
+ array of UInt32 zones
+ }
+ }
+
+ /*!
+ * SupportsProperty
+ * \brief check whether a Property exists.
+ * \arg propertyName name of property of Object
+ * \return true if Property exists
+ */
+ method SupportsProperty {
+ in {
+ String propertyName
+ }
+ out {
+ Boolean supported
+ }
+ }
+
+}
+
+/*! org.automotive.VehicleSpeed
+ \brief contains information about VehicleSpeed
+ DBus Path: variable
+*/
+interface org.automotive.VehicleSpeed extends VehiclePropertyType {
+
+ /*! Speed
+ * \brief MUST return Vehicle Speed in kilometers per hour.
+ */
+ attribute UInt16 Speed readonly
+}
+
+/*! org.automotive.EngineSpeed
+ \brief contains information about EngineSpeed
+ DBus Path: variable
+*/
+interface org.automotive.EngineSpeed extends VehiclePropertyType {
+
+ /*! EngineSpeed
+ * \brief MUST return Engine Speed in rotations per minute.
+ */
+ attribute UInt16 Speed readonly
+}
+
+enumeration PowerMode {
+ Off = 0
+ Accessory1 = 1
+ Accessory2 = 2
+ Run = 3
+}
+
+interface org.automotive.VehiclePowerMode extends VehiclePropertyType {
+
+ /*! VehiclePowerMode
+ * \brief MUST return vehicle power mode
+ */
+ attribute PowerMode VehiclePowerMode readonly
+}
+
+/*! org.automotive.TripMeter
+ \brief contains information about TripMeter
+ DBus Path: variable
+*/
+interface org.automotive.TripMeter extends VehiclePropertyType {
+
+ /*! TripMeters
+ * \brief MUST return trip meters. Changing any items in the array will reset the item's value to '0'.
+ */
+ attribute array TripMeters of UInt16
+}
+
+/*! org.automotive.Acceleration
+ \brief contains information about Acceleration
+ DBus Path: variable
+*/
+interface org.automotive.Acceleration extends VehiclePropertyType {
+
+ /*! X
+ * \brief return acceleration on the "X" axis (Unit: centimeters per second squared)
+ */
+ attribute Int16 X readonly
+
+ /*! Y
+ * \brief return acceleration on the "Y" axis (Unit: centimeters per second squared)
+ */
+ attribute Int16 Y readonly
+
+ /*! Z
+ * \brief return acceleration on the "Z" axis (Unit: centimeters per second squared)
+ */
+ attribute Int16 Z readonly
+}
+
+enumeration TransmissionMode {
+ park = "park",
+ reverse = "reverse",
+ neutral = "neutral",
+ low = "low",
+ drive = "drive",
+ overdrive = "overdrive"
+}
+
+/*! TransmissionPosition
+ * \brief Describes Transmission Pistion. Deprecated. Will disappear in 0.14
+ */
+enumeration TransmissionPosition {
+ Neutral = 0,
+ First = 1,
+ Second = 2,
+ Third = 3,
+ Fourth = 4,
+ Fifth = 5,
+ Sixth = 6,
+ Seventh = 7,
+ Eighth = 8,
+ Ninth = 9,
+ Tenth = 10,
+ Cvt = 64,
+ Reverse = 128,
+ Park = 255
+}
+
+/*! TransmissionGearType
+ * \brief Describes the transmission gearbox type
+*/
+enumeration TransmissionGearType
+{
+ Auto = 0,
+ Manual = 1,
+ CVT = 2
+}
+
+interface org.automotive.Transmission extends VehiclePropertyType {
+ /*! GearPosition
+ * \brief MUST return transmission gear position (see TRANSMISSIONPOSITION) Deprecated. Replaced with Gear
+ */
+ attribute TransmissionPosition GearPosition readonly
+
+ /*! TransmissionGearType
+ * \brief MUST return transmission gear type of either Automatic, Manual or Constant Variable (CV).
+ * See TRANSMISSIONGEARTYPE
+ */
+ attribute TransmissionGearType Type
+
+ /*! Gear
+ * \brief MUST return transmission gear position 1-10
+ */
+ attribute UInt8 Gear readonly
+
+ /*! Mode
+ * \brief MUST return transmission Mode
+ */
+ attribute TransmissionMode Mode readonly
+}
+
+
+interface org.automotive.CruiseControlStatus extends VehiclePropertyType {
+
+ /*! Activated
+ * \brief MUST return whether or not the Cruise Control system is active (true) or inactive (false). Depricated. Remove in 0.14. Use "Status"
+ */
+ attribute Boolean Activated readonly
+
+ /*! Speed
+ * \brief MUST return target Cruise Control speed in kilometers per hour (kph).
+ */
+ attribute UInt16 Speed readonly
+
+ /*! Status
+ * \brief MUST return whether or not the Cruise Control system is active (true) or inactive (false).
+ */
+ attribute Boolean Status readonly
+}
+
+/*!
+ * Deprecated. Use BrakeOperation. Remove in 0.14
+ */
+interface org.automotive.WheelBrake extends VehiclePropertyType {
+
+ /*! Engaged
+ * \brief MUST return Wheel Brake status: Engaged = true, disengaged = false
+ */
+ attribute Boolean Engaged readonly
+}
+
+interface org.automotive.BrakeOperation extends VehiclePropertyType {
+
+ /*! BrakePedalDepressed
+ * \brief MUST return whether brake pedal is depressed or not. true: brake pedal is depressed, false: brake pedal is not depressed
+ */
+ attribute Boolean BrakePedalDepressed readonly
+}
+
+interface org.automotive.LightStatus extends VehiclePropertyType {
+
+ /*! Head
+ * \brief MUST return headlight status: on = true, off = false.
+ */
+ attribute Boolean Head
+
+ /*! RightTurn
+ * \brief MUST return right turn signal status: on = true, off = false.
+ */
+ attribute Boolean RightTurn
+
+ /*! LeftTurn
+ * \brief MUST return left turn signal status: on = true, off = false.
+ */
+ attribute Boolean LeftTurn
+
+ /*! Brake
+ * \brief MUST return brake signal light status: on = true, off = false.
+ */
+ attribute Boolean Brake
+
+ /*! Fog
+ * \brief MUST return fog light status: on = true, off = false.
+ */
+ attribute Boolean Fog
+
+ /*! Hazard
+ * \brief MUST return hazard light status: on = true, off = false.
+ */
+ attribute Boolean Hazard
+
+ /*! Parking
+ * \brief MUST return parking light status: on = true, off = false.
+ */
+ attribute Boolean Parking
+
+ /*! HighBeam
+ * \brief MUST return high beam status: on = true, off = false.
+ */
+ attribute Boolean HighBeam
+
+ /*! AutomaticHeadlights
+ * \brief MUST return automatic headlight status: on = true, off = false.
+ */
+ attribute Boolean AutomaticHeadlights
+
+ /*! DynamicHighBeam
+ * \brief MUST return dynamic high beam status: on = true, off = false.
+ */
+ attribute Boolean DynamicHighBeam
+}
+
+
+interface org.automotive.InteriorLightStatus extends VehiclePropertyType {
+
+ /*! Passenger
+ * \brief MUST return passenger interior light status: on = true, off = false. Deprecated. Remove in 0.14. Use status and zone.
+ */
+ attribute Boolean Passenger readonly
+
+ /*! Driver
+ * \brief MUST return driver interior light status: on = true, off = false. Deprecated. Remove in 0.14. Use status and zone.
+ */
+ attribute Boolean Driver readonly
+
+ /*! Center
+ * \brief MUST return center interior light status: on = true, off = false. Deprecated. Remove in 0.14. Use status and zone.
+ */
+ attribute Boolean Center readonly
+
+ /*! Status
+ * \brief MUST return interior light status for the zone. on = true, off = false
+ */
+ attribute Boolean Status
+}
+
+
+interface org.automotive.Horn extends VehiclePropertyType {
+
+ /*! On
+ * \brief MUST return horn status: on = true, off = false
+ */
+ attribute Boolean On readonly
+}
+
+
+interface org.automotive.Fuel extends VehiclePropertyType {
+
+ /*! Level
+ * \brief MUST return fuel level as a percentage of fullness.
+ */
+ attribute UInt16 Level readonly
+
+ /*! Range
+ * \brief MUST return estimated fuel range in meters.
+ */
+ attribute UInt32 Range readonly
+
+ /*! InstantConsumption
+ * \brief MUST return instant fuel consumption in per distance travelled (Unit: milliliters per 100 kilometers).
+ */
+ attribute UInt32 InstantConsumption readonly
+
+ /*! InstantEconomy
+ * \brief MUST return instant fuel 'economy' in kilometers per liter of fuel.
+ */
+ attribute UInt16 InstantEconomy readonly
+
+ /*! AverageEconomy
+ * \brief MUST return average fuel 'economy' in kilometers per liter of fuel since last reset. Setting this to any value should reset the counter to '0'
+ */
+ attribute UInt16 AverageEconomy
+
+ /*! AverageConsumption
+ * \brief MUST return average fuel consumption in per distance travelled (Unit: milliliters per 100 kilometers). Setting this to any value should reset the counter to '0'
+ */
+ attribute UInt32 AverageConsumption
+
+ /*! FuelConsumedSinceRestart
+ * \brief MUST return fuel consumed since engine start (Unit: milliliters per 100 kilometers) resets to 0 each restart
+ */
+ attribute UInt32 FuelConsumedSinceRestart readonly
+
+ /*! TimeSinceRestart
+ * \brief MUST return time elapsed since vehicle restart (Unit: seconds)
+ */
+ attribute UInt32 TimeSinceRestart readonly
+}
+
+
+interface org.automotive.EngineOil extends VehiclePropertyType {
+
+ /*! Remaining
+ * \brief MUST return remaining engine oil as percentage of fullness. Deprecated. Remove in 0.14. Use "Level"
+ */
+ attribute UInt16 Remaining readonly
+
+ /*! Temperature
+ * \brief MUST return Engine Oil Temperature in Celcius.
+ */
+ attribute long Temperature readonly
+
+ /*! Pressure
+ * \brief MUST return Engine Oil Pressure in kPa.
+ */
+ attribute UInt16 Pressure readonly
+
+ /*! Level
+ * \brief MUST return engine oil level (Unit: percentage, 0%: empty, 100%: full
+ */
+ attribute UInt16 Level readonly
+
+ /*! Change
+ * \brief MUST return engine oil change indicator status: change oil (true) or no change (false)
+ */
+ attribute boolean Change readonly
+
+ /*! LifeRemaining
+ * \brief MUST return engine oil change indicator status: change oil (true) or no change (false)
+ */
+ attribute boolean LifeRemaining readonly
+
+}
+
+
+interface org.automotive.Location extends VehiclePropertyType {
+
+ /*! Latitude
+ * \brief MUST return latitude in Deg.Min (-180, +180)
+ */
+ attribute Double Latitude readonly
+
+ /*! Longitude
+ * \brief MUST return longitude in Deg.Min (-90, +90)
+ */
+ attribute Double Longitude readonly
+
+ /*! Altitude
+ * \brief MUST return altitude in meters above sea-level (0).
+ */
+ attribute Double Altitude readonly
+
+ /*! Direction
+ * \brief MUST return direction in Degrees (0-360)
+ */
+ attribute UInt16 Direction readonly
+}
+
+
+interface org.automotive.ExteriorBrightness extends VehiclePropertyType {
+
+ /*! ExteriorBrightness
+ * \brief MUST return the brightness outside the vehicle in lux.
+ */
+ attribute UInt16 ExteriorBrightness readonly
+}
+
+
+interface org.automotive.Temperature extends VehiclePropertyType {
+
+ /*! Interior
+ * \brief MUST return the temperature of the interior of the vehicle in celcius.
+ */
+ /// Deprecated. Use InteriorTemperature. Remove in 0.14
+ attribute signed short Interior readonly
+
+ /*! Exterior
+ * \brief MUST return the temperature of the exterior of the vehicle in celcius.
+ */
+ /// Deprecated. Use ExteriorTemperature. Remove in 0.14
+ attribute signed short Exterior readonly
+
+ /*! Interior
+ * \brief MUST return the temperature of the interior of the vehicle in celcius.
+ */
+ attribute signed short InteriorTemperature readonly
+
+ /*! Exterior
+ * \brief MUST return the temperature of the exterior of the vehicle in celcius.
+ */
+ attribute signed short ExteriorTemperature readonly
+}
+
+
+interface org.automotive.RainSensor extends VehiclePropertyType {
+
+ /*! RainSensor
+ * \brief MUST return level of rain intensity 0: No Rain - 10: Heaviest Rain.
+ * Deprecated in 0.14. Use rainIntensity
+ */
+ attribute UInt16 RainSensor readonly
+
+ /*! RainIntensity
+ * \brief MUST return level of rain intensity 0: No Rain - 10: Heaviest Rain.
+ */
+ attribute UInt16 RainIntensity readonly
+}
+
+
+/// TODO: Depricated in 0.14 Use WiperStatus
+interface org.automotive.WindshieldWiper extends VehiclePropertyType {
+
+ /*! WindshieldWiper
+ * \brief MUST return Level of windshield whiper speed (0-10)
+ */
+ attribute UInt16 WindshieldWiper readonly
+
+}
+
+enumeration WiperControl {
+ off = "off",
+ once = "once",
+ slowest = "slowest",
+ slow = "slow",
+ middle = "middle",
+ fast = "fast",
+ fastest = "fastest",
+ auto = "auto"
+}
+
+interface org.automotive.WiperStatus extends VehiclePropertyType {
+
+ /*! WiperSpeed
+ * \brief MUST return current speed interval of wiping windshield
+ */
+ attribute WiperControl WiperSpeed readonly
+
+ /*! WiperSetting
+ * \brief MUST return current setting of the front wiper controller. It can be used to send user's request for changing setting.
+ */
+ attribute WiperControl WiperSetting
+}
+
+/*! Deprecated. Use ClimateControl interface. Remove in 0.14
+*/
+interface org.automotive.HVAC extends VehiclePropertyType {
+ const UInt16 AIRFLOWDIRECTION_FRONTPANEL = 0
+ const UInt16 AIRFLOWDIRECTION_FLOORDUCT= 1
+ const UInt16 AIRFLOWDIRECTION_FRONT = 0x02
+ const UInt16 AIRFLOWDIRECTION_DEFROSTER = 0x04
+
+ /*! AirflowDirection
+ * \brief MUST return airflow direction. See
+ */
+ attribute UInt16 AirflowDirection
+
+ /*! FanSpeed
+ * \brief MUST return speed of the fan (0-7)
+ */
+ attribute UInt16 FanSpeed
+
+ /*! TargetTemperature
+ * \brief MUST return target desired temperature in celcius.
+ */
+ attribute UInt16 TargetTemperature
+
+ /*! AirConditioning
+ * \brief MUST return air conditioning on (true) / off (false).
+ */
+ attribute Boolean AirConditioning
+
+ /*! AirRecirculation
+ * \brief MUST return air recirculation on (true) / off (false).
+ */
+ attribute Boolean AirRecirculation
+
+ /*! Heater
+ * \brief MUST return heater on (true) / off (false).
+ */
+ attribute Boolean Heater
+
+ /*! SteeringWheelHeater
+ * \brief MUST return air recirculation on (true) / off (false).
+ */
+ attribute Boolean SteeringWheelHeater
+
+ /*! SeatHeater
+ * \brief MUST return seat heater status: 0-100%.
+ */
+ attribute UInt16 SeatHeater
+
+ /*! SeatCooler
+ * \brief MUST return seat heater status: on (true) / off (false).
+ */
+ attribute Boolean SeatCooler
+}
+
+enumeration AirflowDirectionType
+{
+ frontpanel = "frontpanel",
+ floorduct = "floorduct",
+ bilevel = "bilevel",
+ defrostfloor = "defrostfloor"
+}
+
+interface org.automotive.ClimateControl extends VehiclePropertyType {
+ /*! AirflowDirection
+ * \brief MUST return current status of the direction of the air flow through the ventilation system
+ */
+ attribute AirflowDirectionType AirflowDirection
+
+ /*! FanSpeedLevel
+ * \brief MUST return seat heater status: on (true) / off (false).
+ */
+ attribute UInt8 FanSpeedLevel
+
+ /*! TargetTemperature
+ * \brief MUST return current setting of the desired temperature (Unit: celsius)
+ */
+ attribute Int8 TargetTemperature
+
+ /*! AirConditioning
+ * \brief MUST return current status of the air conditioning system: on (true) or off (false)
+ */
+ attribute Boolean AirConditioning
+
+ /*! Heater
+ * \brief MUST return current status of the heating system: on (true) or off (false)
+ */
+ attribute Boolean Heater
+
+ /*! SeatHeater
+ * \brief MUST return current status of the seat warmer ( 0: off, 1: least warm, 10: warmest )
+ */
+ attribute UInt8 SeatHeater
+
+ /*! SeatCooler
+ * \brief MUST return current status of the seat ventilation ( 0: off, 1: least warm, 10: warmest )
+ */
+ attribute UInt8 SeatCooler
+
+ /*! AirRecirculation
+ * \brief MUST return current setting of air recirculation: on (true) or pulling in outside air (false).
+ */
+ attribute Boolean AirRecirculation
+
+ /*! SteeringWheelHeater
+ * \brief MUST return current status of steering wheel heater ( 0: off, 1: least warm, 10: warmest ).
+ */
+ attribute UInt8 SteeringWheelHeater
+}
+
+/// Deprecated in 0.14. Use SideWindow
+interface org.automotive.WindowStatus extends VehiclePropertyType {
+
+ /*! Openness
+ * \brief MUST return window openness percentage (100% fully open, 0% fully closed)
+ * for the window location see "zone" attribute
+ */
+ attribute UInt16 Openness
+
+ /*! Defrost
+ * \brief MUST return the defroster status of the window. On = true, Off = false.
+ * Deprecated. Use Defrost interface. Remove in 0.14.
+ */
+ attribute Boolean Defrost
+}
+
+interface org.automotive.SideWindow extends VehiclePropertyType {
+
+ /*! Openness
+ * \brief MUST return window openness percentage (100% fully open, 0% fully closed)
+ */
+ attribute UInt16 Openness
+
+ /*! Lock
+ * \brief MUST return whether or not the window is locked (true) or unlocked (false)
+ */
+ attribute Boolean Lock
+}
+
+interface org.automotive.Defrost extends VehiclePropertyType {
+
+ /*! DefrostWindow
+ * \brief MUST return current status of the defrost switch for mirrors. It can be
+ * used to send user's request for changing setting.
+ */
+ attribute Boolean DefrostWindow
+
+ /*! DefrostMirrors
+ * \brief MUST return current status of the defrost switch for window. It can be
+ * used to send user's request for changing setting.
+ */
+ attribute Boolean DefrostMirrors
+}
+
+interface org.automotive.Sunroof extends VehiclePropertyType {
+
+ /*! Openness
+ * \brief MUST return window status for sunroof openness percentage.
+ */
+ attribute UInt16 Openness
+
+ /*! Tilt
+ * \brief MUST return tilt status for sunroof percentage.
+ */
+ attribute UInt16 Tilt
+}
+
+
+enumeration ConvertibleRoofStatus {
+ closed = "closed",
+ closing = "closing",
+ opening = "opening",
+ opened = "opened"
+}
+
+interface org.automotive.ConvertibleRoof extends VehiclePropertyType {
+ /*! Status
+ * \brief MUST return current status of Convertible Roof.
+ *
+ */
+ attribute ConvertibleRoofStatus Status readonly
+
+ /*! Setting
+ * \brief MUST return current setting of Convertible Roof. This is used to open (true) and close (false).
+ *
+ */
+ attribute Boolean Setting
+}
+
+
+interface org.automotive.VehicleId extends VehiclePropertyType {
+
+ /*! WMI
+ * \brief MUST return World Manufacturer Identifier (WMI)
+ * WMI is defined by SAE ISO 3780:2009. 3 characters.
+ */
+ attribute String WMI readonly
+
+ /*! VIN
+ * \brief MUST return Vehicle Identification Number (VIN) as defined by ISO 3779. 17 characters.
+ */
+ attribute String VIN readonly
+}
+
+
+interface org.automotive.Size extends VehiclePropertyType {
+
+ /*! Width
+ * \brief MUST return width of vehicle in mm
+ */
+ attribute UInt16 Width readonly
+
+ /*! Height
+ * \brief MUST return height of vehicle in mm
+ */
+ attribute UInt16 Height readonly
+
+ /*! Length
+ * \brief MUST return length of vehicle in mm
+ */
+ attribute UInt16 Length readonly
+}
+
+
+interface org.automotive.FuelInfo extends VehiclePropertyType {
+ const UInt16 FUELTYPE_GASOLINE = 0
+ const UInt16 FUELTYPE_HIGH_OCTANE= 1
+ const UInt16 FUELTYPE_DIESEL = 2
+ const UInt16 FUELTYPE_ELECTRIC = 3
+ const UInt16 FUELTYPE_HYDROGEN = 4
+ const UInt16 REFUELPOSITION_LEFT = 0
+ const UInt16 REFUELPOSITION_RIGHT= 1
+ const UInt16 REFUELPOSITION_FRONT = 2
+ const UInt16 REFUELPOSITION_REAR = 3
+
+ /*! Type
+ * \brief MUST return type of fuel. integer 0-4 (see
+ */
+ attribute UInt16 Type readonly
+
+ /*! RefuelPosition
+ * \brief MUST return position of refuling (see
+ */
+ attribute UInt16 RefuelPosition readonly
+}
+
+
+interface org.automotive.VehicleType extends VehiclePropertyType {
+ const UInt16 VEHICLETYPE_SEDAN = 0
+ const UInt16 VEHICLETYPE_COUPE= 1
+ const UInt16 VEHICLETYPE_CABRIOLE = 2
+ const UInt16 VEHICLETYPE_ROADSTER = 3
+ const UInt16 VEHICLETYPE_SUV = 4
+ const UInt16 VEHICLETYPE_TRUCK = 5
+
+ /*! Type
+ * \brief MUST return type of Vehicle. Integer 0-5 (see
+ */
+ attribute UInt16 Type readonly
+}
+
+
+interface org.automotive.Doors extends VehiclePropertyType {
+
+ /*! DoorsPerRow
+ * \brief MUST return Number of doors in each row. The index represents the row. Position '0'
+ * represents the first row, '1' the second row etc.
+ * Example a common mini-van may have Doors[0] = 2 doors,
+ * Doors[1] = 1 (side door), Doors[2] = 1 (trunk).
+ */
+ attribute array DoorsPerRow of UInt16 readonly
+}
+
+
+interface org.automotive.WheelInformation extends VehiclePropertyType {
+
+ /*! FrontWheelRadius
+ * \brief MUST return Radius of Front Wheel(s) in mm.
+ */
+ attribute UInt16 FrontWheelRadius readonly
+
+ /*! RearWheelRadius
+ * \brief MUST return Radius of Rear Wheel(s) in mm.
+ */
+ attribute UInt16 RearWheelRadius readonly
+
+ /*! WheelTrack
+ * \brief MUST return Wheel Track in mm.
+ */
+ attribute UInt16 WheelTrack readonly
+
+ /*! ABS
+ * \brief MUST return Antilock Brake System status: on = true, off = false.
+ */
+ attribute Boolean ABS readonly
+}
+
+
+interface org.automotive.Odometer extends VehiclePropertyType {
+
+ /*! Odometer
+ * \brief MUST return Distance traveled in km
+ */
+ /// Deprecated. Use DistanceTotal. Remove in 0.14
+ attribute UInt32 Odometer readonly
+
+ /*! DistnaceTotal
+ * \brief MUST return Distance traveled in m
+ */
+ attribute UInt32 DistanceTotal readonly
+
+ /*! DistanceSinceStart
+ * \brief MUST return Distance traveled since start in m
+ */
+ attribute UInt32 DistanceSinceStart readonly
+
+}
+
+interface org.automotive.Fluid extends VehiclePropertyType {
+
+ /*! Transmission
+ * \brief MUST return Transmission fluid level percentage. 0-100.
+ */
+ attribute UInt16 Transmission readonly
+
+ /*! Brake
+ * \brief MUST return Brake fluid level percentage. 0-100.
+ * TODO: Deprecated. use BrakeMaintenance::FluidLevel Remove in 0.14
+ */
+ attribute UInt16 Brake readonly
+
+ /*! Washer
+ * \brief MUST return Washer fluid level percentage. 0-100.
+ * TODO: Deprecated. use WasherFluid::Level. Remove in 0.14
+ */
+ attribute UInt16 Washer readonly
+}
+
+///TODO: Deprecated. Use BatteryStatus. Remove in 0.14
+interface org.automotive.Battery extends VehiclePropertyType {
+
+ /*! Voltage
+ * \brief MUST return battery voltage.
+ */
+ attribute Double Voltage readonly
+
+ /*! Current
+ * \brief MUST return battery current in Amperes
+ */
+ attribute Double Current readonly
+}
+
+interface org.automotive.BatteryStatus extends VehiclePropertyType {
+
+ /*! Voltage
+ * \brief MUST return battery voltage.
+ */
+ attribute UInt8 Voltage readonly
+
+ /*! Current
+ * \brief MUST return battery current in Amperes
+ */
+ attribute UInt8 Current readonly
+
+ /*! ChargeLevel
+ * \brief MUST return battery charge level (Unit: percentage, 0%: empty, 100%: full).
+ */
+ attribute UInt8 ChargeLevel readonly
+}
+
+
+interface org.automotive.Tire extends VehiclePropertyType {
+
+ /*! Pressure
+ * \brief MUST return tire pressure in kPa.
+ */
+ attribute UInt16 Pressure readonly
+
+ /*! Temperature
+ * \brief MUST return left front tire temperature in Celcius.
+ */
+ attribute Int16 Temperature readonly
+
+ /*! Temperature
+ * \brief MUST return true if any tire pressure is low: pressure low (true), pressure not low (false).
+ */
+ attribute Boolean PressureLow readonly
+}
+
+
+interface org.automotive.SecurityAlert extends VehiclePropertyType {
+
+ /*! SecurityAlert
+ * \brief MUST return
+ */
+ attribute Boolean SecurityAlert readonly
+}
+
+interface org.automotive.ParkingBrake extends VehiclePropertyType {
+
+ /*! ParkingBrake
+ * MUST return status of parking brake: Engaged = true, Disengaged = false.
+ TODO: Deprecated in 0.14. Use Status
+ */
+ attribute Boolean ParkingBrake readonly
+
+ /*!
+ * \brief MUST return the current status of parking brake.
+ */
+ attribute ParkingBrakeStatus Status
+}
+
+/// Deprecated. Use LightStatus. remove in 0.14
+interface org.automotive.ParkingLight extends VehiclePropertyType {
+
+ /*! ParkingLight
+ * MUST return status of parking light: Engaged = true, Disengaged = false.
+ */
+ attribute Boolean ParkingLight readonly
+}
+
+/// Deprecated. Use LightStatus. remove in 0.14
+interface org.automotive.HazardLight extends VehiclePropertyType {
+
+ /*! HazardLight
+ * MUST return status of hazard light: Engaged = true, Disengaged = false.
+ */
+ attribute Boolean HazardLight readonly
+}
+
+
+interface org.automotive.AntilockBrakingSystem extends VehiclePropertyType {
+
+ /*! AntilockBrakingSystem
+ * \brief MUST return whether Antilock Braking System is Idle (false) or Engaged (true)
+ * TODO: Deprecated. Use Engaged. Remove in 0.14
+ */
+ attribute Boolean AntilockBrakingSystem readonly
+
+ /*!
+ * \brief MUST return whether or not the ABS Setting is enabled: enabled (true) or disabled (false)
+ */
+ attribute Boolean Enabled readonly
+
+ /*!
+ * \brief MUST return whether or not the ABS is engaged: engaged (true) or idle (false)
+ */
+ attribute Boolean Engaged readonly
+}
+
+
+interface org.automotive.TractionControlSystem extends VehiclePropertyType {
+
+ /*! TractionControlSystem
+ * \brief MUST return whether Traction Control System is Off (false) or On (true)
+ * TODO: Deprecated. Use Engaged. Remove in 0.14
+ */
+ attribute Boolean TractionControlSystem readonly
+
+ /*!
+ * \brief MUST return whether or not the TCS Setting is enabled: enabled (true) or disabled (false)
+ */
+ attribute Boolean Enabled readonly
+
+ /*!
+ * \brief MUST return whether or not the TCS is engaged: engaged (true) or idle (false)
+ */
+ attribute Boolean Engaged readonly
+}
+
+
+interface org.automotive.VehicleTopSpeedLimit extends VehiclePropertyType {
+
+ /*! VehicleTopSpeedLimit
+ * \brief MUST return top rated speed in km/h. 0 = no limit
+ */
+ attribute UInt16 VehicleTopSpeedLimit readonly
+}
+
+
+interface org.automotive.AirbagStatus extends VehiclePropertyType {
+
+ /*! AirbagStatus
+ * \brief MUST return Airbag status (byte) (see AIRBAGSTATUS_*)
+ * TODO: deprecated. Remove in 0.14
+ */
+ attribute UInt16 AirbagStatus readonly
+
+ /*!
+ * \brief MUST return whether or not the airbag is activaged: activated (true) or deactivated (false)
+ */
+ attribute Boolean Activated readonly
+
+ /*!
+ * \brief MUST return whether the airbag is deployed: deployed (true) or not (false)
+ */
+ attribute Boolean Deployed readonly
+}
+
+/// TODO: deprecated. Remove in 0.14
+enumeration AirbagStatus {
+ inactive = 0,
+ active = 1,
+ deployed = 2
+}
+
+/*!
+ * Deprecated. Use "Door". Remove in 0.14
+ */
+interface org.automotive.DoorStatus extends VehiclePropertyType {
+
+ /*! DoorStatus
+ * \brief MUST return Door status (byte).
+ * CLOSED = 0
+ * OPEN = 1
+ * AJAR = 2
+ */
+ attribute UInt16 DoorStatus readonly
+
+ /*! DoorLockStatus
+ * \brief MUST return Door status (bool locked = true, unlocked = false).
+ */
+ attribute Boolean DoorLockStatus
+
+ /*! ChildLockStatus
+ * \brief MUST return Child lock status of rear doors. active = true, inactive = false.
+ * Setting this to 'true' will prevent the rear doors from being opened
+ * from the inside.
+ */
+ ///TODO: Deprecated in 0.14. Use org.automotive.ChildLockStatus
+ attribute Boolean ChildLockStatus
+}
+
+enumeration DoorStatus {
+ open = "open",
+ ajar = "ajar",
+ closed = "closed"
+}
+
+interface org.automotive.Door extends VehiclePropertyType {
+
+ /*! Status
+ * \brief MUST return Door status (byte). See DOORSTATUS_*
+ */
+ attribute DoorStatus Status readonly
+
+ /*! Lock
+ * \brief MUST return Door status (bool locked = true, unlocked = false).
+ */
+ attribute Boolean Lock
+
+ /*! ChildLock
+ * \brief MUST return Child lock status of rear doors. active = true, inactive = false.
+ * Setting this to 'true' will prevent the rear doors from being opened
+ * from the inside.
+ */
+ attribute Boolean ChildLock
+}
+
+///TODO: Deprecated in 0.14. Use org.automotive.Seat
+interface org.automotive.SeatBelt extends VehiclePropertyType {
+
+ /*! Status
+ * \brief MUST return Seat Belt Status (bool: Fasten = true, Unfastened = false)
+ */
+ attribute Boolean Status readonly
+}
+
+///TODO: Deprecated in 0.14. Use org.automotive.Seat
+interface org.automotive.OccupantStatus extends VehiclePropertyType {
+
+ /*! OccupantStatus
+ * \brief MUST return status of Occupant (byte, see
+ */
+ attribute UInt16 OccupantStatus readonly
+}
+
+
+interface org.automotive.ObstacleDistance extends VehiclePropertyType {
+
+ /*! ObstacleDistance
+ * \brief MUST return Distance Sensor distance (Double) in m.
+ */
+ attribute Double ObstacleDistance readonly
+}
+
+
+interface org.automotive.NightMode extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return whether or not the system is in NightMode or not. True = Night time, False = Day time
+ * Deprecated. Will be removed in 0.14. Use "Mode"
+ */
+ attribute Boolean NightMode readonly
+
+ /*!
+ * \brief MUST return whether or not the system is in NightMode or not. True = Night time, False = Day time
+ */
+ attribute Boolean Mode readonly
+}
+
+
+interface org.automotive.DrivingMode extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return whether or not the system is in DrivingMode or not. 1 = Driving, 0 = Not Driving
+ */
+ attribute UInt16 DrivingMode readonly
+
+ /*!
+ * \brief MUST return true if vehicle is in driving mode
+ */
+ attribute Boolean Mode readonly
+}
+
+
+interface org.automotive.KeyId extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return
+ */
+ attribute String KeyId readonly
+}
+
+interface org.automotive.Language extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return
+ */
+ attribute String Language readonly
+}
+
+
+interface org.automotive.MeasurementSystem extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return 0 = Metric, 1 = ImperialUS, 2 = ImperialUK
+ */
+ attribute UInt16 MeasurementSystem readonly
+}
+
+
+///TODO Deprecated. Use org.automotive.Mirror. Remove in 0.14
+interface org.automotive.MirrorSetting extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return
+ */
+ attribute UInt8 Pan readonly
+ attribute UInt8 Tilt readonly
+}
+
+
+///TODO Deprecated. Use org.automotive.SeadAdjustment. Remove in 0.14
+interface org.automotive.SeatPosition extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return
+ */
+ attribute UInt16 Recline readonly
+
+ /*!
+ * \brief MUST return
+ */
+ attribute UInt16 Slide readonly
+
+ /*!
+ * \brief MUST return
+ */
+ attribute UInt16 CushionHeight readonly
+
+ /*!
+ * \brief MUST return
+ */
+ attribute UInt16 Headrest readonly
+
+ /*!
+ * \brief MUST return
+ */
+ attribute UInt16 BackCushion readonly
+
+ /*!
+ * \brief MUST return
+ */
+ attribute UInt16 SideCushion readonly
+}
+
+
+interface org.automotive.SteeringWheelPosition extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return
+ */
+ attribute UInt16 Tilt readonly
+
+ /*!
+ * \brief MUST return
+ */
+ attribute UInt16 Slide readonly
+}
+
+
+interface org.automotive.DashboardIllumination extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return
+ */
+ attribute UInt16 DashboardIllumination readonly
+}
+
+///TODO Deprecated. Use org.automotive.VehicleSound. Remove in 0.14
+interface org.automotive.GeneratedVehicleSoundMode extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return Sound Mode: 0 = Normal, 1 = Quiet, 2 = Sportive
+ */
+ attribute UInt16 GeneratedVehicleSoundMode readonly
+}
+
+
+/*! SteeringWheelAngle
+ *\brief
+ * Deprecated. Use SteeringWheel
+ */
+interface org.automotive.SteeringWheelAngle extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return angle of the steering wheel. 0-359 degrees.
+ */
+ attribute UInt16 SteeringWheelAngle readonly
+}
+
+interface org.automotive.SteeringWheel extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return angle of steering wheel off centerline (Unit: degrees -:degrees to the left, +:degrees to the right)
+ */
+ attribute Int16 Angle readonly
+}
+
+interface org.automotive.DriverId extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return driver ID. Driver Id is an abstract and can be determined
+ * from multiple sources including bluetooth, key, key fob, etc.
+ */
+ attribute String DriverId readonly
+}
+
+interface org.automotive.ThrottlePosition extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return throttle position as a percentage (Unit: percentage, 0%: closed, 100%: fully open)
+ */
+ attribute Uint8 Value readonly
+}
+
+interface org.automotive.EngineCoolant extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return engine coolant level (Unit: percentage 0%: empty, 100%: full)
+ */
+ attribute Uint16 Level readonly
+
+ /*!
+ * \brief MUST return engine coolant temperature (Unit: celcius)
+ */
+ attribute Int16 Temperature readonly
+}
+
+interface org.automotive.PowertrainTorque extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return powertrain torque (Unit: newton meters)
+ */
+ attribute UInt16 Value readonly
+}
+
+interface org.automotive.AcceleratorPedalPosition extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return accelerator pedal position as a percentage (Unit: percentage, 0%: released pedal, 100%: fully depressed)
+ */
+ attribute UInt8 Value readonly
+}
+
+interface org.automotive.WheelTick extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return number of ticks per second (Unit: ticks per second)
+ */
+ attribute UInt8 Value readonly
+}
+
+interface IgnitionTime : VehicleCommonDataType {
+ /*!
+ * \brief MUST return time at ignition on
+ */
+ attribute UInt64 ignitionOnTime readonly
+
+ /*!
+ * \brief MUST return time at ignition off
+ */
+ attribute UInt64 ignitionOffTime readonly
+}
+
+interface org.automotive.YawRate extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return yaw rate of vehicle. (Unit: degrees per second)
+ */
+ attribute Int16 Value readonly
+}
+
+interface org.automotive.BrakeOperation extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return whether brake pedal is depressed or not. true: brake pedal is depressed, false: brake pedal is not depressed
+ */
+ attribute Boolean BrakePedalDepressed readonly
+}
+
+enumeration Button {
+ home = "home",
+ back = "back",
+ search = "search",
+ call = "call",
+ end_call = "end_call",
+ media_play = "media_play",
+ media_next = "media_next",
+ media_previous = "media_previous",
+ media_pause = "media_pause",
+ voice_recognize = "voice_recognize",
+ enter = "enter",
+ left = "left",
+ right = "right",
+ up = "up",
+ down = "down"
+}
+
+enumeration ButtonEventType {
+ press = "press",
+ long_press = "long_press",
+ release = "release"
+}
+
+interface VehicleButton {
+ /*!
+ * \brief MUST return the button corresponding to the event.
+ */
+ attribute Button button readonly
+
+ /*!
+ * \brief MUST return the type of event
+ */
+ attribute ButtonEventType state readonly
+}
+
+interface org.automotive.ButtonEvent extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return the button events that occured. This supports multiple simultanious button events.
+ */
+ attribute array Button of VehicleButton readonly
+}
+
+interface org.automotive.TransmissionOil extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return current temperature of the transmission oil(Unit: celsius).
+ */
+ attribute Int8 Temperature readonly
+
+ /*!
+ * \brief MUST return transmission oil wear (Unit: percentage, 0: no wear, 100: completely worn).
+ */
+ attribute UInt8 Wear readonly
+}
+
+interface org.automotive.TransmissionClutch extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return transmission clutch wear (Unit: percentage, 0: no wear, 100: completely worn).
+ */
+ attribute UInt8 Wear readonly
+}
+
+interface org.automotive.BrakeMaintenance extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return brake pad wear (Unit: percentage, 0%: no wear, 100%: completely worn).
+ */
+ attribute UInt8 PadWear readonly
+
+ /*!
+ * \brief MUST return brake fluid level (Unit: percentage, 0%: empty, 100%: full).
+ */
+ attribute UInt8 FluidLevel readonly
+
+ /*!
+ * \brief MUST return true if brake fluid level: low (true), not low (false)
+ */
+ attribute Boolean FluidLevelLow readonly
+
+ /*!
+ * \brief MUST return true if brakes are worn: worn (true), not worn (false)
+ */
+ attribute Boolean BrakesWorn readonly
+}
+
+interface org.automotive.WasherFluid extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return washer fluid level (Unit: percentage, 0%: empty, 100%: full).
+ */
+ attribute UInt8 Level readonly
+
+ /*!
+ * \brief MUST return true if washer fluid level is low: low (true), not low: (false)
+ */
+ attribute Boolean LevelLow readonly
+}
+
+interface org.automotive.MalfunctionIndicator extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return true if washer fluid level is low: low (true), not low: (false)
+ */
+ attribute Boolean On readonly
+}
+
+interface org.automotive.Diagnostic extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return engine runtime (Unit: seconds)
+ */
+ attribute UInt32 AccumulatedEngineRuntime readonly
+
+ /*!
+ * \brief MUST return distance travelled since the codes were last cleared (Unit: meters)
+ */
+ attribute UInt32 DistanceSinceCodeCleared readonly
+
+ /*!
+ * \brief MUST return distance travelled with the malfunction indicator light on (Unit: meters)
+ */
+ attribute UInt32 DistanceWithMILOn readonly
+
+ /*!
+ * \brief MUST return time elapsed with the malfunction indicator light on (Unit: seconds)
+ */
+ attribute UInt32 TimeRunMILOn readonly
+
+ /*!
+ * \brief MUST return time elapsed since the trouble codes were last cleared (Unit: seconds)
+ */
+ attribute UInt32 TimeTroubleCodeClear readonly
+}
+
+interface org.automotive.Mirror extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return mirror pan position in percentage distance travelled, from left to right position (Unit: percentage, %0: center position, -100%: fully left, 100%: fully right)
+ */
+ attribute UInt8 MirrorPan
+
+ /*!
+ * \brief MUST return mirror tilt position in percentage distance travelled, from downward-facing to upward-facing position (Unit: percentage, 0%:center position, -100%:fully downward, 100%:full upward)
+ */
+ attribute UInt8 MirrorTilt
+}
+
+interface org.automotive.SeatAdjustment extends VehiclePropertyType {
+
+ /*!
+ * \brief MUST return seat back recline position as percent to completely reclined (Unit: percentage, 0%: fully forward, 100%: fully reclined)
+ */
+ attribute UInt8 ReclineSeatBack
+
+ /*!
+ * \brief MUST return seat slide position as percentage of distance travelled away from forwardmost position (Unit: percentage, 0%: farthest forward, 100%: farthest back)
+ */
+ attribute UInt8 SeatSlide
+
+ /*!
+ * \brief MUST return seat cushion height position as a percentage of upward distance travelled (Unit: percentage, 0%:lowest. 100%:highest)
+ */
+ attribute UInt8 SeatCushionHeight
+
+ /*!
+ * \brief MUST return headrest position as a percentage of upward distance travelled (Unit: percentage, 0%: lowest, 100%: highest)
+ */
+ attribute UInt8 SeatHeadrest
+
+ /*!
+ * \brief MUST return back cushion position as a percentage of lumbar curvature (Unit: percentage, 0%: flat, 100%: maximum curvature)
+ */
+ attribute UInt8 SeatBackCushion
+
+ /*!
+ * \brief MUST return sides of back cushion position as a percentage of curvature (Unit: percentage, 0%: flat, 100%: maximum curvature)
+ */
+ attribute UInt8 SeatSideCushion
+}
+
+enumeration DriveModeType {
+ comfort = "comfort",
+ auto = "auto",
+ sport = "sport",
+ eco = "eco",
+ manual = "manual",
+ winter = "winter"
+}
+
+interface org.automotive.DriveMode extends VehiclePropertyType {
+ /*!
+ * \brief MUST return vehicle drive mode. See http://w3c.github.io/automotive-bg/data_spec.html#idl-def-DriveModeEnum
+ */
+ attribute DriveModeType DriveMode
+}
+
+interface org.automotive.DashboardIllumination extends VehiclePropertyType {
+ /*!
+ * \brief MUST return illumination of dashboard as a percentage (Unit: percentage, 0%: none, 100%: maximum illumination)
+ */
+ attribute UInt8 DashboardIllumination
+}
+
+interface org.automotive.VehicleSound extends VehiclePropertyType {
+ /*!
+ * \brief MUST return active noise control status: not-activated (false), activated (true)
+ */
+ attribute Boolean ActiveNoiseControlMode
+
+ /*!
+ * \brief MUST return active noise control status: not-activated (false), activated (true)
+ */
+ attribute Boolean EngineSoundEnhancementMode
+
+ /*!
+ * \brief MUST return array of available sounds. See EngineSoundEnhancementMode
+ */
+ attribute array EngineSoundEnhancementMode of String readonly
+}
+
+interface org.automotive.ElectronicStabilityControl extends VehiclePropertyType {
+ /*!
+ * \brief MUST return whether or not the ESC Setting is enabled: enabled (true) or disabled (false)
+ */
+ attribute Boolean Enabled readonly
+
+ /*!
+ * \brief MUST return whether or not the ESC is engaged: engaged (true) or idle (false)
+ */
+ attribute Boolean Engaged readonly
+}
+
+interface org.automotive.TopSpeedLimit extends VehiclePropertyType {
+ /*!
+ * \brief MUST return whether or not the ESC Setting is enabled: enabled (true) or disabled (false)
+ */
+ attribute UInt16 Speed readonly
+}
+
+interface org.automotive.ChildSafetyLock extends VehiclePropertyType {
+ /*!
+ * \brief MUST return whether or not the Child Safety Lock is locked: locked (true) or unlocked (false)
+ */
+ attribute Boolean Lock
+}
+
+enumeration OccupantStatus {
+ adult = "adult",
+ child = "child",
+ vacant = "vacant"
+}
+
+enumeration IdentificationTypeEnum {
+ pin = "pin",
+ keyfob = "keyfob",
+ Bluetooth = "Bluetooth",
+ NFC = "NFC",
+ fingerprint = "fingerprint",
+ camera = "camera",
+ voice = "voice"
+}
+
+interface org.automotive.Seat extends VehiclePropertyType {
+ /*!
+ * \brief MUST return the status of seat occupant
+ */
+ attribute OccupantStatus Occupant
+
+ /*!
+ * \brief MUST return whether or not the seat belt is fastened: fastened (true) or unfastened (false)
+ */
+ attribute Boolean SeatBelt
+
+ /*!
+ * \brief MUST return occupant identifier
+ */
+ attribute String OccupantName
+
+ /*!
+ * \brief MUST return identification type
+ */
+ attribute IdentificationTypeEnum IdentificationType
+}
+
+interface org.automotive.AtmosphericPressure extends VehiclePropertyType {
+ /*!
+ * \brief MUST return the current atmospheric pressure outside of the vehicle (Unit: hectopascal)
+ */
+ attribute UInt16 Pressure
+}
+
+enumeration LaneDepartureStatus {
+ off = "off",
+ pause = "pause",
+ running = "running"
+}
+
+interface org.automotive.LaneDepartureDetection extends VehiclePropertyType {
+ /*!
+ * \brief MUST return current status of Lane departure warning function.
+ */
+ attribute LaneDepartureStatus Status readonly
+}
+
+enumeration AlarmStatus {
+ disarmed = "disarmed",
+ prearmed = "prearmed",
+ armed = "armed",
+ alarmed = "alarmed"
+}
+
+interface org.automotive.Alarm extends VehiclePropertyType {
+ /*!
+ * \brief MUST return the current status of vehicle Alarm System.
+ */
+ attribute AlarmStatus Status
+}
+
+enumeration ParkingBrakeStatus {
+ inactive = "inactive",
+ active = "active",
+ error = "error"
+}
+
+interface org.automotive.ParkingBrake extends VehiclePropertyType {
+ /*!
+ * \brief MUST return the current status of vehicle Alarm System.
+ */
+ attribute ParkingBrakeStatus Status readonly
+}
diff --git a/docs/amb/README b/docs/amb/README
new file mode 100644
index 00000000..52661229
--- /dev/null
+++ b/docs/amb/README
@@ -0,0 +1 @@
+amb internal structure API directory
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..020454c5
--- /dev/null
+++ b/docs/ambd.in.md
@@ -0,0 +1,76 @@
+# Automotive Message Broker Daemon {#ambd}
+
+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/dbus/README b/docs/dbus/README
new file mode 100644
index 00000000..1f950244
--- /dev/null
+++ b/docs/dbus/README
@@ -0,0 +1 @@
+AMB DBus API documentation
diff --git a/docs/images/AMBArchitecture.png b/docs/images/AMBArchitecture.png
new file mode 100644
index 00000000..69a9a077
--- /dev/null
+++ b/docs/images/AMBArchitecture.png
Binary files differ
diff --git a/docs/libamb.in.h b/docs/libamb.in.h
new file mode 100644
index 00000000..581afad8
--- /dev/null
+++ b/docs/libamb.in.h
@@ -0,0 +1,54 @@
+/*!
+ \file libamb.h
+ \section libamb Automotive Message Broker Library Documentation
+ \version @PROJECT_VERSION@
+
+ \section libamb_intro Introduction
+ Automotive Message Broker (AMB) Library documentation outlines the internal classes and structures for building
+ plugins for AMB.
+
+ \section libamb_architecture General Architecture
+ AMB has 3 main parts. Source plugins which provide data, a routing engine that
+ routes data and sink plugins that consume the data.
+
+ \section libamb_properties Properties
+ AMB defines a number of properties itself. These properties are defined in vehicleproperty.h. The DBus plugin
+ will take many of these properties and combine them in DBus interfaces. The mappings of AMB internal properties
+ to DBus Interface properties can be found in the <a href="ambdbusmappings_8idl.html">mappings documentation</a>. This file will come in handy when you want to
+ implement a particular AMB DBus interface in your source plugin.
+
+ By default, for any property not explicitly
+ included in a DBus interface, the DBus plugin will generate a custom interface. The pattern is as follows:
+
+ CustomProperty = "org.automotive.CustomProperty.CustomProperty"
+
+ "org.automotive.CustomProperty is the DBus interface and CustomProperty is a DBus property in that interface.
+
+ \section libamb_plugins Plugins
+ There are two types of plugins: plugins that provide data, called "sources"
+ (AbstractSource) and plugins that consume data, called "sinks" (AbstractSink).
+ A typical source would get data from the vehicle and then translate the raw data
+ into AMB property types. Sinks then subscribe to the property types and do useful
+ things with the data.
+
+ Example plugins can be found in plugins/exampleplugin.{h,cpp} for an example
+ source plugin and plugins/examplesink.{h,cpp} for an example sink plugin. There
+ are also many different types of plugins useful for testing and development in the
+ plugins/ directory.
+
+ Various plugins have separate documentation found in @DOC_INSTALL_DIR@/plugins/.
+
+ \section libamb_plugin_creation Creating your own plugin
+ AMB allows you to create your own plugins. Plugins inherit from either AbstractSource, AbstractSink, or AmbPluginImpl.
+
+ It is recommended that new plugins be written using AmbPlugin and AmbPluginImpl.
+
+ \section routing_engine Routing Engine Plugins
+ As of 0.12, the routing engine itself can be exchanged for a plugin. This allows
+ users to swap in routing engines with different behaviors, additional security,
+ and custom throttling and filtering features.
+
+ The easiest way to get started creating a routing engine plugin would be to look at
+ AbstractRoutingEngine, the base class for all routing engines and the default
+ routing engine in ambd/core.cpp.
+**/
diff --git a/docs/mainpage.in.idl b/docs/mainpage.in.idl
new file mode 100644
index 00000000..eb0b28bf
--- /dev/null
+++ b/docs/mainpage.in.idl
@@ -0,0 +1,34 @@
+/*!
+* \mainpage Automotive Message Broker Documentation
+* \version @PROJECT_VERSION@
+* \section links AMB Documentation Sections
+* - \ref ambd
+* - \ref dbus_api - Using AMB with your application
+* - \ref libamb - Developing AMB or AMB plugins
+* - \ref plugins - Using Built in AMB plugins
+* - \ref release_notes - 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 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/docs/plugins/bluemonkey/bluemonkey.idl b/docs/plugins/bluemonkey/bluemonkey.idl
new file mode 100644
index 00000000..2029c3c3
--- /dev/null
+++ b/docs/plugins/bluemonkey/bluemonkey.idl
@@ -0,0 +1,156 @@
+/*!
+ * \mainpage Automotive Message Broker Library Documentation - Bluemonkey Plugin
+ * \version 0.12.903
+ * \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.
+ * \section properties Properties
+ * Bluemonkey uses internal property names (not DBus API interface names). These properties are defined in
+ * lib/vehicleproperty.h. There are mappings from AMB internal property names to DBus API properties in the
+ * <a href="ambdbusmappings_8idl">mappings documentation</a>. The mappings comes in handy when you want to implement properties that are
+ * exported as an DBus API interface (ie, org.automotive.VehicleSpeed).
+ * \section example Example bluemonkey script
+ * \code
+ * var speedProperty = bluemonkey.subscribeTo("VehicleSpeed");
+ *
+ * var testTimer = bluemonkey.createTimer();
+ * testTimer.interval = 3000;
+ * testTimer.singleShot = false;
+ * testTimer.timeout.connect(function() {
+ * //VehicleSpeed
+ * speedProperty.value = Math.floor((Math.random() * 100) + 1);
+ * });
+ * testTimer.start();
+ * \endcode
+ * \section Javascript API documentation
+ * Javascript API documentation is found in bluemonkey.idl and is described using WebIDL. Plugin configuration documentation can be found in bluemonkey.README.
+ */
+
+ /*!
+ * \name automotive-message-broker Bluemonkey interface documentation
+ * \version 0.12.903
+ * \brief the bluemonkey script engine is powered by Qt QML's javascript engine. It supports QObject types as well
+ * as ECMA script (javascript). All QObject properties, slots, and signals are available in javascript.
+ * \see Qt's QMetaObject system for additional details
+ */
+
+/*!
+ * \brief Entry point for bluemonkey
+ */
+partial interface Navigator {
+ readonly attribute Bluemonkey bluemonkey;
+};
+
+/*!
+ * \brief Bluemonkey interface
+ * Bluemonkey provides AMB plugin-like interfaces and allows the loading of other modules, timers, and QObject creation.
+ * Typical usage is such:
+ * \code
+ * var speedProperty = bluemonkey.subscribeTo("VehicleSpeed");
+ * bluemonkey.log("Current speed: " + speedProperty.value);
+ * \endcode
+ */
+interface Bluemonkey {
+ /*!
+ * \brief subscribe to a property
+ * \returns PropertyInterface representing the property
+ */
+ PropertyInterface subscribeTo(DOMString propertyName, optional unsigned short zone, optional DOMString source);
+
+ /*!
+ * \brief return the AMB sources that provide propertyName
+ */
+ DOMString[] sourcesForProperty(DOMString propertyName);
+
+ /*!
+ * \brief returns the available zones that contians propertyName
+ */
+ unsigned short[] zonesForProperty(DOMString propertyName);
+
+ /*!
+ * \brief return supported properties
+ */
+ DOMString[] supportedProperties();
+
+ /*!
+ * \brief load another script
+ */
+ void loadConfig(DOMString configFile);
+
+ /*!
+ * \brief load a bluemonkey module
+ */
+ void loadModule(DOMString moduleFile);
+
+ /*!
+ * \brief log text to AMB output
+ */
+ void log(DOMString text);
+
+ /*!
+ * \brief
+ */
+ QTimer createTimer();
+
+ /*!
+ * \brief
+ */
+ QObject createQObject();
+
+ /*!
+ * \brief return logged data between "begin" and "end"
+ */
+ void getHistory(DOMString[] properties, Date begin, Date end, HistoryCallback callback);
+
+ /*!
+ * \brief
+ */
+ void createCustomProperty(DOMString name, any value, optional unsigned short zone);
+
+};
+
+interface PropertyInterface {
+ /*!
+ * \brief
+ */
+ readonly attribute DOMString type;
+
+ /*!
+ * \brief
+ */
+ readonly attribute unsigned short zone;
+
+ /*!
+ * \brief
+ */
+ readonly attribute any value;
+
+ /*!
+ * \brief
+ */
+ readonly attribute DOMString source;
+
+ /*!
+ * \brief
+ */
+ readonly attribute DOMTimestamp timestamp;
+
+ /*!
+ * \brief
+ */
+ readonly attribute Signal changed;
+
+ void getHistory(Date begin, Date end, HistoryCallback callback);
+};
+
+interface Signal {
+ /*!
+ * \brief
+ */
+ void connect(ChangedCallback callback)
+};
+
+callback ChangedCallback = void(any value); ();
+
+callback HistoryCallback = void(PropertyInterface[] data); ();
+
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
new file mode 100644
index 00000000..08672330
--- /dev/null
+++ b/examples/CMakeLists.txt
@@ -0,0 +1,38 @@
+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
+ ${CMAKE_CURRENT_BINARY_DIR}/bluetooth
+ ${CMAKE_CURRENT_BINARY_DIR}/chrony)
+
+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}/bluetooth.in.json ${CMAKE_CURRENT_BINARY_DIR}/bluetooth @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/testplugins.d.in.json ${CMAKE_CURRENT_SOURCE_DIR}/testplugins.d.json @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/chrony.in.json ${CMAKE_CURRENT_BINARY_DIR}/chrony @ONLY)
+
+install (FILES ${amb_examples} DESTINATION /etc/ambd/examples)
+
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/bluetooth.in.json b/examples/bluetooth.in.json
new file mode 100644
index 00000000..30674b95
--- /dev/null
+++ b/examples/bluetooth.in.json
@@ -0,0 +1,17 @@
+{
+ "mainloop" : "@PLUGIN_INSTALL_PATH@/qtmainloopplugin.so",
+ "sources" : [
+ {
+ "name" : "ExampleSouce",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so",
+ "delay" : "10000"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "Bluetooth",
+ "path" : "@PLUGIN_INSTALL_PATH@/bluetoothplugin.so"
+ }
+ ]
+}
+
diff --git a/examples/cangenconfig.in.json b/examples/cangenconfig.in.json
new file mode 100644
index 00000000..9886c7a9
--- /dev/null
+++ b/examples/cangenconfig.in.json
@@ -0,0 +1,22 @@
+{
+ "sources" : [
+ {
+ "name" : "CANSimPlugin",
+ "path":"@PLUGIN_INSTALL_PATH@/cansimplugin.so",
+ "interfaces" : ["vcan0", "vcan1"]
+ },
+ {
+ "name" : "CANGenPlugin",
+ "path":"@PLUGIN_INSTALL_PATH@/cangenplugin.so"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "DBusSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so",
+ "frequency" : "60"
+ }
+
+ ]
+}
+
diff --git a/examples/chrony.in.json b/examples/chrony.in.json
new file mode 100644
index 00000000..360ceecd
--- /dev/null
+++ b/examples/chrony.in.json
@@ -0,0 +1,16 @@
+{
+ "sources" : [
+ {
+ "name" : "gps nmea plugin",
+ "path" : "@PLUGIN_INSTALL_PATH@/gpsnmea.so",
+ "device" : "/dev/ttyUSB0",
+ "baudrate" : "4800"
+ }
+ ],
+ "sinks": [
+ {
+ "path" : "@PLUGIN_INSTALL_PATH@/chrony.so"
+ }
+ ]
+}
+
diff --git a/examples/configwebsocketsink b/examples/configwebsocketsink
new file mode 100644
index 00000000..9f55d203
--- /dev/null
+++ b/examples/configwebsocketsink
@@ -0,0 +1,19 @@
+{
+ "sources" : [
+ {
+ "name" : "ExampleSouce",
+ "path" : "/usr/lib/automotive-message-broker/examplesourceplugin.so",
+ "delay" : "6"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "WebSocketSink",
+ "path" : "/usr/lib/automotive-message-broker/websocketsinkplugin.so",
+ "interface" : "lo",
+ "ssl" : "false",
+ "port" : "23000"
+ }
+ ]
+}
+
diff --git a/examples/configwebsocketsource b/examples/configwebsocketsource
new file mode 100644
index 00000000..5ead5d17
--- /dev/null
+++ b/examples/configwebsocketsource
@@ -0,0 +1,18 @@
+{
+ "sources" : [
+ {
+ "name" : "WebsocketSource",
+ "path" : "/usr/lib/automotive-message-broker/websocketsourceplugin.so",
+ "port" : "23000",
+ "ssl" : "false",
+ "ip" : "127.0.0.1"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "ExampleSink",
+ "path" : "/usr/lib/automotive-message-broker/examplesinkplugin.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.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..5dec82f1
--- /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" : "['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.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/democonfig b/examples/democonfig
new file mode 100644
index 00000000..11fc7a5f
--- /dev/null
+++ b/examples/democonfig
@@ -0,0 +1,24 @@
+{
+ "sources" : [
+ {
+ "name" : "WheelSource",
+ "path" : "/usr/lib/automotive-message-broker/wheelsourceplugin.so",
+ "device" : "/dev/input/js0"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "WebSocketSink",
+ "path" : "/usr/lib/automotive-message-broker/websocketsinkplugin.so",
+ "interface" : "lo"
+ } ,
+ {
+ "path" : "/usr/lib/automotive-message-broker/dbussinkplugin.so"
+ },
+ {
+ "path" : "/usr/lib/automotive-message-broker/demosinkplugin.so",
+ "script" : "./rundemo %1"
+ }
+ ]
+}
+
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/gpsdconfig b/examples/gpsdconfig
new file mode 100644
index 00000000..3d6c09df
--- /dev/null
+++ b/examples/gpsdconfig
@@ -0,0 +1,15 @@
+{
+ "sources" : [
+ {
+ "name" : "gpsd plugin",
+ "path" : "/usr/lib/automotive-message-broker/gpsdplugin.so",
+ "updateVelocity" : "true"
+ }
+ ],
+ "sinks": [
+ {
+ "path" : "/usr/lib/automotive-message-broker/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.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.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.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/openxcconfig b/examples/openxcconfig
new file mode 100644
index 00000000..f507c307
--- /dev/null
+++ b/examples/openxcconfig
@@ -0,0 +1,17 @@
+{
+ "sources" : [
+ {
+ "name" : "openxc plugin",
+ "path" : "/usr/lib/automotive-message-broker/openxcplugin.so",
+ "test" : "true",
+ "device" : "10:C6:FC:27:C3:1C",
+ "bluetoothAdapter" : ""
+ }
+ ],
+ "sinks": [
+ {
+ "path" : "/usr/lib/automotive-message-broker/dbussinkplugin.so"
+ }
+ ]
+}
+
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/rundemo b/examples/rundemo
new file mode 100755
index 00000000..5cc5ba6e
--- /dev/null
+++ b/examples/rundemo
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+BUTTONVALUE=$1
+
+echo "Button pressed: ${BUTTONVALUE}"
+
+if [[ ${BUTTONVALUE} = Right ]]
+then
+ gst-launch v4l2src device=/dev/video1 ! 'video/x-raw-yuv,width=1920,height=1080,framerate=30/1' ! xvimagesink
+else
+ if [[ ${BUTTONVALUE} = Left ]]
+ then
+ gst-launch v4l2src device=/dev/video2 ! 'video/x-raw-yuv,width=1920,height=1080,framerate=30/1' ! xvimagesink
+ fi
+fi
+
+if [[ ${BUTTONVALUE} = Off ]]
+then
+ killall gst-launch-0.10
+fi
+
+if [[ ${BUTTONVALUE} = "Button1" ]]; then
+ #Run script 1 here
+ echo "Button 1 script!"
+fi
+
+if [[ ${BUTTONVALUE} = "Button2" ]]; then
+ #Run script 2 here
+ echo "Button 2 script!"
+fi
+
+if [[ ${BUTTONVALUE} = "Button3" ]]; then
+ #Run script 3 here
+ echo "Button 3 script!"
+fi
+
+if [[ ${BUTTONVALUE} = "Button4" ]]; then
+ #Run script 4 here
+ echo "Button 4 script!"
+fi
diff --git a/examples/testmultiisource b/examples/testmultiisource
new file mode 100755
index 00000000..a02a19c5
--- /dev/null
+++ b/examples/testmultiisource
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+
+numclients=$2
+config=$1
+
+#start initial ambd client:
+
+ambd -D -c $config -d1 -l host.output
+
+sleep 10
+
+for (( i=1; i<=$numclients; i++ ))
+do
+ ambd -D -c configwebsocketsource -d2 -l client.$i.output
+done
+
+sleep 60
+
+killall ambd
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.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/websinkssl b/examples/websinkssl
new file mode 100644
index 00000000..f4eca853
--- /dev/null
+++ b/examples/websinkssl
@@ -0,0 +1,20 @@
+{
+ "sources" : [
+ {
+ "name" : "example",
+ "path" : "/usr/lib/automotive-message-broker/examplesourceplugin.so"
+ }
+ ],
+ "sinks": [
+ {
+ "name" : "WebSocketSink",
+ "path" : "/usr/lib/automotive-message-broker/websocketsinkplugin.so",
+ "cert" : "libwebsockets-test-server.pem",
+ "key" : "libwebsockets-test-server.key.pem",
+ "interface" : "eth0",
+ "port" : "23000",
+ "ssl" : "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.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
new file mode 100644
index 00000000..b479aaf4
--- /dev/null
+++ b/lib/CMakeLists.txt
@@ -0,0 +1,28 @@
+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})
+
+find_library(uuid_LIBRARY uuid DOC "Uuid libraries")
+find_path(uuid_INCLUDE_DIR uuid/uuid.h DOC "Libtool headers")
+
+if(uuid_LIBRARY)
+ message(STATUS "uuid found")
+else(uuid_LIBRARY)
+ message(FATAL_ERROR "uuid missing. please install uuid-dev")
+endif(uuid_LIBRARY)
+
+include_directories( ${include_dirs} ${uuid_INCLUDE_DIR})
+
+target_link_libraries(amb ${libtool_LIBRARY} ${glib_LIBRARIES} ${gio_LIBRARIES} ${uuid_LIBRARY} ${json_LIBRARIES})
+set_target_properties(amb PROPERTIES SOVERSION ${PROJECT_VERSION})
+
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/automotive-message-broker.pc.in ${CMAKE_CURRENT_BINARY_DIR}/automotive-message-broker.pc @ONLY)
+
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/automotive-message-broker.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+
+install (FILES ${amb_headers_install} DESTINATION ${INCLUDE_INSTALL_DIR}/amb COMPONENT Devel)
+
+install (TARGETS amb LIBRARY DESTINATION ${LIB_INSTALL_DIR} RUNTIME DESTINATION bin ARCHIVE DESTINATION ${LIB_INSTALL_DIR})
+
+
diff --git a/lib/abstractpropertytype.cpp b/lib/abstractpropertytype.cpp
new file mode 100644
index 00000000..5ad2588f
--- /dev/null
+++ b/lib/abstractpropertytype.cpp
@@ -0,0 +1,8 @@
+#include "abstractpropertytype.h"
+
+const Zone::Type Zone::FrontRight = Zone::Type(Zone::Front | Zone::Right);
+const Zone::Type Zone::FrontLeft = Zone::Type(Zone::Front | Zone::Left);
+const Zone::Type Zone::MiddleRight = Zone::Type(Zone::Middle | Zone::Right);
+const Zone::Type Zone::MiddleLeft = Zone::Type(Zone::Middle | Zone::Left);
+const Zone::Type Zone::RearRight = Zone::Type(Zone::Rear | Zone::Right);
+const Zone::Type Zone::RearLeft = Zone::Type(Zone::Rear | Zone::Left);
diff --git a/lib/abstractpropertytype.h b/lib/abstractpropertytype.h
new file mode 100644
index 00000000..bfdd45aa
--- /dev/null
+++ b/lib/abstractpropertytype.h
@@ -0,0 +1,899 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _ABSTRACTPROPERTYTYPE_H_
+#define _ABSTRACTPROPERTYTYPE_H_
+
+#include <string>
+#include <sstream>
+#include <stdexcept>
+#include <vector>
+#include <iostream>
+#include <memory>
+#include <boost/any.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/utility.hpp>
+#include <type_traits>
+#include <glib.h>
+#include <list>
+#include "timestamp.h"
+#include <debugout.h>
+#include <boost/algorithm/string.hpp>
+#include <superptr.hpp>
+
+class Zone {
+
+public:
+
+ typedef int Type;
+
+ enum {
+ None = 0,
+ Front = 1,
+ Middle = 1 << 1,
+ Right = 1 << 2,
+ Left = 1 << 3,
+ Rear = 1 << 4,
+ Center = 1 << 5,
+ LeftSide = 1 << 6,
+ RightSide = 1 << 7,
+ FrontSide = 1 << 8,
+ BackSide = 1 << 9
+ };
+
+static const Zone::Type FrontRight;
+static const Zone::Type FrontLeft;
+static const Zone::Type MiddleRight;
+static const Zone::Type MiddleLeft;
+static const Zone::Type RearRight;
+static const Zone::Type RearLeft;
+
+typedef std::vector<Zone::Type> ZoneList;
+
+};
+
+class AbstractPropertyType
+{
+public:
+
+ /*!
+ * \brief The Priority enum describes prority of the property type.
+ */
+ enum Priority
+ {
+ /*!< normal priority. This is default */
+ Normal = 0,
+ /*!< Low priority. */
+ Low,
+ /*!< High priority*/
+ High,
+ /*!< Instant. Using this priority is not thread safe. This is typically used for
+ * Properties that need to be deterministic.
+ */
+ Instant
+ };
+
+ AbstractPropertyType(std::string property)
+ : name(property), timestamp(amb::currentTime()), sequence(-1), zone(Zone::None), priority(Normal)
+ {
+
+ }
+
+ virtual ~AbstractPropertyType()
+ {
+ for(auto i : destroyed)
+ {
+ if(i) i(this);
+ }
+ }
+
+ /**
+ * @brief toString
+ * @return strigified value
+ */
+ virtual std::string toString() const = 0;
+
+ /**
+ * @brief fromString converts from string value
+ */
+ virtual void fromString(std::string)= 0;
+
+ /**
+ * @brief toVariant
+ * @return GVariant representation of value. Caller must unref the returned GVariant
+ */
+ virtual GVariant* toVariant() = 0;
+
+ /**
+ * @brief fromVariant converts GVariant value into compatible native value. Caller owns
+ * GVariant argument.
+ */
+ virtual void fromVariant(GVariant*) = 0;
+
+ /**
+ * @brief copy
+ * @return a copy of the AbstractPropertyType
+ */
+ virtual AbstractPropertyType* copy() = 0;
+
+ /**
+ * @brief quickCopy is intended as a way to quickly copy the often changing bits from one abstract property to another
+ * It assumes that the properties are almost identical in name, source, and zone.
+ * @param other the property to copy from
+ */
+ virtual void quickCopy(AbstractPropertyType* other)
+ {
+ sequence = other->sequence;
+ mValue = other->anyValue();
+ timestamp = other->timestamp;
+ }
+
+ bool operator == (AbstractPropertyType &other)
+ {
+ std::string one = toString();
+ std::string two = other.toString();
+ return one == two
+ && zone == other.zone
+ && sourceUuid == other.sourceUuid
+ && name == other.name;
+ }
+
+ bool operator != (AbstractPropertyType &other)
+ {
+ std::string one = toString();
+ std::string two = other.toString();
+ return one != two;
+ }
+
+ /**
+ * @brief name Property name. @see VehicleProperty for built-in supported property names
+ */
+ std::string name;
+
+ /**
+ * @brief timestamp. Timestamp when the value was last updated by the system. This is updated automatically
+ * any time setValue() is called
+ * @see amb::currentTime()
+ * @see setValue()
+ */
+ double timestamp;
+
+ /**
+ * @brief sequence internal counter. Useful as a unique indentifier. values is -1 if not used (default).
+ */
+ int32_t sequence;
+
+ /**
+ * @brief sourceUuid uuid of the source that produced this property. This is set by the routingengine
+ * if left unmodified.
+ */
+ std::string sourceUuid;
+
+ /**
+ * @brief zone that the property is situated in.
+ */
+ Zone::Type zone;
+
+ /*!
+ * \brief priority is used to tell the routing engine how to prioritize routing the value to plugins.
+ * setting this value to AbstractPropertyType::Instant will tell the routing engine to immedietly
+ * route the value without any reliance on the mainloop. Instant priority is NOT thread safe.
+ * Default priority is AbstractPropertyType::Normal.
+ */
+ Priority priority;
+
+ /**
+ * @brief setValue
+ * @param val boost::any value. NOTE: boost::any does not accept type coercion. Types must match exactly
+ * with native type. (ie, don't use "int" if the native type is "uint")
+ */
+ virtual void setValue(boost::any val)
+ {
+ mValue = val;
+ timestamp = amb::currentTime();
+ }
+
+ /**
+ * \brief value() native value. Does not use type coercion. Will throw if types do not match.
+ */
+ template <typename T>
+ T value() const
+ {
+ return boost::any_cast<T>(mValue);
+ }
+
+ /**
+ * @brief anyValue
+ * @return boost::any value
+ */
+ boost::any anyValue()
+ {
+ return mValue;
+ }
+
+ /*!
+ * \brief signature
+ * \return gvariant signature
+ */
+ virtual const string signature()
+ {
+ auto var = amb::make_super(toVariant());
+ if(!var) return "";
+
+ const string s = g_variant_get_type_string(var.get());
+
+ DebugOut() << "returning signature: " << s << " for "<< name << endl;
+
+ return s;
+ }
+
+ /**
+ * @brief destroyed is called if this property is destroyed.
+ */
+ std::vector<std::function<void(AbstractPropertyType*)>> destroyed;
+
+protected:
+
+ boost::any mValue;
+
+};
+
+namespace amb
+{
+
+struct PropertyCompare
+{
+ bool operator()(AbstractPropertyType* const & lhs, AbstractPropertyType* & rhs) const
+ {
+ if (lhs->name == rhs->name
+ && lhs->sourceUuid == rhs->sourceUuid
+ && lhs->zone == rhs->zone)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+};
+
+}
+
+
+template <typename T>
+class GVS;
+
+template <>
+class GVS<int>
+{
+public:
+ static const char* signature() { return "i"; }
+
+ static int value(GVariant* v)
+ {
+ int val = 0;
+ g_variant_get(v, signature(), &val);
+ return val;
+ }
+
+ static std::string stringize(std::string v)
+ {
+ return v;
+ }
+};
+
+template <>
+class GVS<double>
+{
+public:
+ static const char* signature() { return "d"; }
+
+ static double value(GVariant* v)
+ {
+ return g_variant_get_double(v);
+ }
+ static std::string stringize(std::string v)
+ {
+ return v;
+ }
+};
+
+template <>
+class GVS<uint16_t>
+{
+public:
+ static const char* signature() { return "q"; }
+
+ static uint16_t value(GVariant* v)
+ {
+ return g_variant_get_uint16(v);
+ }
+ static std::string stringize(std::string v)
+ {
+ return v;
+ }
+};
+
+template <>
+class GVS<int16_t>
+{
+public:
+ static const char* signature() { return "n"; }
+
+ static int16_t value(GVariant* v)
+ {
+ return g_variant_get_int16(v);
+ }
+ static std::string stringize(std::string v)
+ {
+ return v;
+ }
+};
+
+template <>
+class GVS<char>
+{
+public:
+ static const char* signature() { return "y"; }
+
+ static char value(GVariant* v)
+ {
+ return g_variant_get_byte(v);
+ }
+ static std::string stringize(std::string v)
+ {
+ return v;
+ }
+};
+
+template <>
+class GVS<uint32_t>
+{
+public:
+ static const char* signature() { return "u"; }
+
+ static uint32_t value(GVariant* v)
+ {
+ return g_variant_get_uint32(v);
+ }
+ static std::string stringize(std::string v)
+ {
+ return v;
+ }
+};
+
+template <>
+class GVS<int64_t>
+{
+public:
+ static const char* signature() { return "x"; }
+
+ static int64_t value(GVariant* v)
+ {
+ return g_variant_get_int64(v);
+ }
+ static std::string stringize(std::string v)
+ {
+ return v;
+ }
+};
+
+template <>
+class GVS<uint64_t>
+{
+public:
+ static const char* signature() { return "t"; }
+
+ static uint64_t value(GVariant* v)
+ {
+ return g_variant_get_uint64(v);
+ }
+ static std::string stringize(std::string v)
+ {
+ return v;
+ }
+};
+
+template <>
+class GVS<bool>
+{
+public:
+ static const char* signature() { return "b"; }
+
+ static bool value(GVariant *v)
+ {
+ return g_variant_get_boolean(v);
+ }
+ static std::string stringize(std::string v)
+ {
+ if(v == "0" || v == "1")
+ return v;
+
+ boost::algorithm::to_lower(v);
+ return v == "true" ? "1":"0";
+ }
+};
+
+/**
+ * \brief BasicPropertyType is a typed property type. Most internal types are derived from this class
+ * \example
+ * std::unique_ptr<BasicPropertyType<int>> boostPSI = new BasicPropertyType<int>("BoostPSI",5);
+ * boostPSI->priority = AbstractPropertyType::Instant; //set instant because we clean up right after.
+ * routingEngine->updateProperty(boostPSI.get(), sourceUuid());
+ */
+template <typename T>
+class BasicPropertyType: public AbstractPropertyType
+{
+public:
+ BasicPropertyType(): AbstractPropertyType("")
+ {
+ mValue = T();
+ }
+
+ BasicPropertyType(BasicPropertyType const & other)
+ :AbstractPropertyType(other.name)
+ {
+ setValue(other.value<T>());
+ timestamp = other.timestamp;
+ sequence = other.sequence;
+ sourceUuid = other.sourceUuid;
+ name = other.name;
+ zone = other.zone;
+
+ }
+
+ BasicPropertyType & operator = (BasicPropertyType const & other)
+ {
+ setValue(other.value<T>());
+ timestamp = other.timestamp;
+ sequence = other.sequence;
+ sourceUuid = other.sourceUuid;
+ name = other.name;
+ zone = other.zone;
+
+ return *this;
+ }
+
+ BasicPropertyType & operator = (T const & other)
+ {
+ setValue(other);
+ return *this;
+ }
+
+ BasicPropertyType & operator ++ ()
+ {
+ setValue(basicValue() + 1);
+ }
+
+ BasicPropertyType & operator -- ()
+ {
+ setValue(basicValue() - 1);
+ }
+
+ bool operator < (const BasicPropertyType<T>& other) const
+ {
+ return value<T>() < other.value<T>();
+ }
+
+ bool operator > (const BasicPropertyType<T>& other) const
+ {
+ return value<T>() > other.value<T>();
+ }
+
+ BasicPropertyType( T val)
+ :AbstractPropertyType("")
+ {
+ setValue(val);
+ }
+
+ BasicPropertyType( std::string propertyName, T val)
+ :AbstractPropertyType(propertyName)
+ {
+ setValue(val);
+ }
+
+ BasicPropertyType( std::string propertyName, std::string val)
+ :AbstractPropertyType(propertyName)
+ {
+ if(!val.empty() && val != "")
+ {
+ serialize<T>(val);
+ }
+ else setValue(T());
+ }
+
+ BasicPropertyType(std::string propertyName)
+ :AbstractPropertyType(propertyName)
+ {
+ mValue = T();
+ }
+
+ AbstractPropertyType* copy()
+ {
+ return new BasicPropertyType<T>(*this);
+ }
+
+ void fromString(std::string val)
+ {
+ if(!val.empty() && val != "")
+ {
+ serialize<T>(val);
+ }
+ }
+
+ std::string toString() const
+ {
+ std::stringstream stream;
+ stream.precision(10);
+ stream<<value<T>();
+
+ return stream.str();
+ }
+
+ GVariant* toVariant()
+ {
+ return serializeVariant<T>(value<T>());
+ }
+
+ void fromVariant(GVariant *v)
+ {
+ setValue(deserializeVariant<T>(v));
+ }
+
+ /**
+ * @brief basicValue
+ * @return Typed version of value. Slightly more useful than @see AbstractPropertyType::value()
+ */
+
+ T basicValue()
+ {
+ return value<T>();
+ }
+
+ void setValue(T val)
+ {
+ AbstractPropertyType::setValue(val);
+ }
+
+ void setValue(boost::any val)
+ {
+ AbstractPropertyType::setValue(val);
+ }
+
+private:
+
+ //GVariant* mVariant;
+
+ template <class N>
+ void serialize(std::string val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
+ {
+ int someTemp;
+
+ std::stringstream stream(val);
+
+ stream>>someTemp;
+ setValue((N)someTemp);
+ }
+
+ template <class N>
+ void serialize(std::string val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
+ {
+ std::stringstream stream(GVS<T>::stringize(val));
+ N someTemp;
+ stream>>someTemp;
+ setValue(someTemp);
+ }
+
+ template <class N>
+ GVariant* serializeVariant(T val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
+ {
+ //mVariant = Glib::VariantBase(Glib::Variant<gint16>::create((int)val).gobj());
+
+ return (g_variant_new("i",(int)val));
+ }
+
+ template <class N>
+ GVariant* serializeVariant(T val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
+ {
+ //mVariant = Glib::Variant<T>::create(val);
+ //mVariant = g_variant_ref(g_variant_new(GVS<T>::signature(),val));
+ return g_variant_new(GVS<T>::signature(),val);
+ }
+
+ template <class N>
+ T deserializeVariant(GVariant* v, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
+ {
+// return (T)((Glib::Variant<int>::cast_dynamic<Glib::Variant<int> >(*v)).get());
+
+ return (T)GVS<int>::value(v);
+ }
+
+ template <class N>
+ T deserializeVariant(GVariant* v, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
+ {
+ // return Glib::VariantBase::cast_dynamic<Glib::Variant<T> >(*v).get();
+ return GVS<T>::value(v);
+ }
+};
+
+class StringPropertyType: public AbstractPropertyType
+{
+public:
+
+
+ StringPropertyType()
+ :AbstractPropertyType("")
+ {
+ setValue(std::string());
+ }
+
+ StringPropertyType(std::string propertyName)
+ :AbstractPropertyType(propertyName)
+ {
+ setValue(std::string());
+ }
+
+ StringPropertyType(std::string propertyName, std::string val)
+ :AbstractPropertyType(propertyName)
+ {
+ setValue(val);
+ }
+
+ StringPropertyType(StringPropertyType const & other)
+ :AbstractPropertyType(other.name)
+ {
+ setValue(other.value<std::string>());
+ timestamp = other.timestamp;
+ sequence = other.sequence;
+ sourceUuid = other.sourceUuid;
+ name = other.name;
+ zone = other.zone;
+ }
+
+ StringPropertyType & operator = (StringPropertyType const & other)
+ {
+ setValue(other.value<std::string>());
+ timestamp = other.timestamp;
+ sequence = other.sequence;
+ sourceUuid = other.sourceUuid;
+ name = other.name;
+ zone = other.zone;
+
+ return *this;
+ }
+
+ StringPropertyType & operator = (std::string const & other)
+ {
+ setValue(std::string(other));
+ return *this;
+ }
+
+ bool operator < (const StringPropertyType& other) const
+ {
+ return value<std::string>() < other.value<std::string>();
+ }
+
+
+ void fromString(std::string val)
+ {
+ setValue(val);
+ }
+
+ AbstractPropertyType* copy()
+ {
+ return new StringPropertyType(*this);
+ }
+
+ std::string toString() const
+ {
+ return value<std::string>();
+ }
+
+ GVariant* toVariant()
+ {
+ //mVariant = Glib::Variant<std::string>::create(toString());
+
+ return g_variant_new_string(toString().c_str());
+
+ }
+
+ void fromVariant(GVariant *v)
+ {
+ setValue(std::string(g_variant_get_string(v,NULL)));
+ }
+};
+
+/*!
+ * \brief ListPropertyType is a AbstractPropertyType for arrays of AbstractPropertyTypes
+ */
+template <class T = AbstractPropertyType>
+class ListPropertyType: public AbstractPropertyType
+{
+public:
+
+ ListPropertyType(std::string propertyName)
+ : AbstractPropertyType(propertyName), initialized(false)
+ {
+
+ }
+
+ ListPropertyType(std::string propertyName, T value)
+ : AbstractPropertyType(propertyName), initialized(false)
+ {
+ appendPriv(value);
+ }
+
+ ListPropertyType(ListPropertyType & other)
+ :AbstractPropertyType(other.name),initialized(false)
+ {
+ std::vector<T> l = other.list();
+ for(auto i : l)
+ {
+ append(i);
+ }
+
+ timestamp = other.timestamp;
+ sequence = other.sequence;
+ sourceUuid = other.sourceUuid;
+ name = other.name;
+ zone = other.zone;
+ }
+
+ ~ListPropertyType()
+ {
+ clear();
+ }
+
+ /** \brief append - appends a property to the list
+ * @arg property - property to be appended.
+ **/
+ void append(T property)
+ {
+ if(!initialized)
+ {
+ mList.clear();
+ initialized = true;
+ }
+
+ appendPriv(property);
+ }
+
+ uint count()
+ {
+ return mList.size();
+ }
+
+ AbstractPropertyType* copy()
+ {
+ return new ListPropertyType(*this);
+ }
+
+ void quickCopy(AbstractPropertyType* other)
+ {
+ AbstractPropertyType::quickCopy(other);
+ ListPropertyType<T>* v = static_cast<ListPropertyType<T>*>(other);
+ if(!v)
+ {
+ DebugOut(DebugOut::Error) << "ListPropertyType Quick Copy failed" << endl;
+ return;
+ }
+ mList = v->list();
+ }
+
+ std::string toString() const
+ {
+ std::string str = "[";
+
+ for(auto itr = mList.begin(); itr != mList.end(); itr++)
+ {
+ if(str != "[")
+ str += ",";
+
+ T t = *itr;
+
+ str += t.toString();
+ }
+
+ str += "]";
+
+ return str;
+ }
+
+
+ void fromString(std::string str )
+ {
+ clear();
+
+ if(!str.length())
+ return;
+
+ if(str[0] == '[' && str[str.length()-1] == ']')
+ {
+ str = str.substr(1,str.length() - 2);
+ }
+
+ std::vector<std::string> elements;
+
+ std::istringstream f(str);
+
+ std::string element;
+ while(std::getline(f,element,','))
+ {
+ T foo("", element);
+ append (foo);
+ }
+ timestamp = amb::currentTime();
+ }
+
+
+ GVariant* toVariant()
+ {
+
+ GVariantBuilder params;
+ g_variant_builder_init(&params, ((const GVariantType *) "av"));
+
+ for(auto itr = mList.begin(); itr != mList.end(); itr++)
+ {
+ T t = *itr;
+ auto var = t.toVariant();
+ GVariant *newvar = g_variant_new("v", var);
+ g_variant_builder_add_value(&params, newvar);
+ }
+
+ GVariant* var = g_variant_builder_end(&params);
+ g_assert(var);
+ return var;
+
+ }
+
+ void fromVariant(GVariant* v)
+ {
+ clear();
+
+ /// TODO: fill this in
+ gsize dictsize = g_variant_n_children(v);
+ for (int i=0;i<dictsize;i++)
+ {
+ GVariant *childvariant = g_variant_get_child_value(v,i);
+ GVariant *innervariant = g_variant_get_variant(childvariant);
+ T t;
+ t.fromVariant(innervariant);
+ appendPriv(t);
+ }
+ }
+
+ std::vector<T> list() { return mList; }
+
+private:
+
+ void clear()
+ {
+ mList.clear();
+ }
+
+ void appendPriv(T i)
+ {
+ mList.push_back(i);
+ }
+
+ bool initialized;
+
+ std::vector<T> mList;
+};
+
+#endif
diff --git a/lib/abstractroutingengine.cpp b/lib/abstractroutingengine.cpp
new file mode 100644
index 00000000..0ebfb473
--- /dev/null
+++ b/lib/abstractroutingengine.cpp
@@ -0,0 +1,78 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "abstractroutingengine.h"
+
+
+
+AbstractRoutingEngine::~AbstractRoutingEngine()
+{
+}
+
+AsyncPropertyReply::AsyncPropertyReply()
+ :AsyncPropertyRequest(), value(nullptr), success(false), timeoutSource(nullptr), timedout(nullptr)
+{
+ setTimeout();
+}
+
+AsyncPropertyReply::AsyncPropertyReply(const AsyncPropertyRequest &request)
+ :AsyncPropertyRequest(request), value(NULL), success(false), timeoutSource(nullptr), timedout(nullptr)
+{
+ setTimeout();
+}
+
+AsyncPropertyReply::AsyncPropertyReply(const AsyncSetPropertyRequest &request)
+ :AsyncPropertyRequest(request), value(request.value), success(false), timeoutSource(nullptr), timedout(nullptr)
+{
+ setTimeout();
+ if(value)
+ value->zone = request.zoneFilter;
+}
+
+AsyncPropertyReply::~AsyncPropertyReply()
+{
+ if(timeoutSource)
+ {
+ g_source_destroy(timeoutSource);
+ g_source_unref(timeoutSource);
+ }
+}
+
+void AsyncPropertyReply::setTimeout()
+{
+ auto timeoutfunc = [](gpointer userData) {
+ AsyncPropertyReply* thisReply = static_cast<AsyncPropertyReply*>(userData);
+ if(thisReply->success == false)
+ {
+ thisReply->error = Timeout;
+ if(thisReply->timedout)
+ thisReply->timedout(thisReply);
+ if(thisReply->completed)
+ thisReply->completed(thisReply);
+ }
+ return 0;
+ };
+
+ if(timeout)
+ {
+ timeoutSource = g_timeout_source_new(timeout);
+ g_source_set_callback(timeoutSource,(GSourceFunc) timeoutfunc, this, nullptr);
+ g_source_attach(timeoutSource, nullptr);
+ }
+}
diff --git a/lib/abstractroutingengine.h b/lib/abstractroutingengine.h
new file mode 100644
index 00000000..cce0140e
--- /dev/null
+++ b/lib/abstractroutingengine.h
@@ -0,0 +1,518 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef ABSTRACTROUTINGENGINE_H
+#define ABSTRACTROUTINGENGINE_H
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <boost/any.hpp>
+#include <functional>
+#include <string>
+#include <time.h>
+
+#include "vehicleproperty.h"
+#include "abstractpropertytype.h"
+#include "propertyinfo.hpp"
+
+class AbstractSink;
+class AbstractSource;
+class AsyncPropertyReply;
+class AsyncRangePropertyReply;
+class AsyncSetPropertyRequest;
+
+
+typedef std::function<void (AsyncPropertyReply*)> GetPropertyCompletedSignal;
+typedef std::function<void (AsyncRangePropertyReply*)> GetRangedPropertyCompletedSignal;
+typedef std::function<void (AsyncPropertyReply*)> TimedOutCallback;
+
+/*!
+ * \brief The AsyncPropertyRequest class is used by sinks to request property values.
+ * \see AbstractRoutingEngine::getPropertyAsync
+ * \see AsyncPropertyReply
+ */
+class AsyncPropertyRequest
+{
+public:
+ AsyncPropertyRequest()
+ :property(VehicleProperty::NoValue),zoneFilter(Zone::None), timeout(10000)
+ {
+
+ }
+
+ AsyncPropertyRequest(const AsyncPropertyRequest &request)
+ {
+ this->property = request.property;
+ this->completed = request.completed;
+ this->sourceUuidFilter = request.sourceUuidFilter;
+ this->zoneFilter = request.zoneFilter;
+ this->timeout = request.timeout;
+ }
+
+ AsyncPropertyRequest & operator = (const AsyncPropertyRequest & other)
+ {
+ this->property = other.property;
+ this->completed = other.completed;
+ this->sourceUuidFilter = other.sourceUuidFilter;
+ this->zoneFilter = other.zoneFilter;
+ this->timeout = other.timeout;
+
+ return *this;
+ }
+
+ virtual ~AsyncPropertyRequest() { }
+
+ /*!
+ * \brief property property to request.
+ */
+ VehicleProperty::Property property;
+
+ /*!
+ * \brief sourceUuidFilter the requesting sink should use this to filter on a specific source or leave blank to use any source
+ */
+ std::string sourceUuidFilter;
+
+ /*!
+ * \brief zoneFilter the requesting sink should use this if he wants to filter on a specific zone
+ */
+ Zone::Type zoneFilter;
+
+ /*!
+ * \brief completed the callback when the request has been completed.
+ */
+ GetPropertyCompletedSignal completed;
+
+ /*!
+ * \brief use to specify a timeout in ms for the request. When a timeout occurs, the 'completed' callback
+ * will be called with an error. @see AsyncPropertyReply
+ * default value is: 10000 ms
+ */
+ uint timeout;
+
+ /*!
+ * \brief pid requesting process id
+ */
+ std::string pid;
+};
+
+/*!
+ * \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
+ * \see AbstractSource::Operations
+ * \see AbstractSource::getPropertyAsync
+ */
+class AsyncPropertyReply: public AsyncPropertyRequest
+{
+public:
+ AsyncPropertyReply();
+
+ AsyncPropertyReply(const AsyncPropertyRequest &request);
+
+ AsyncPropertyReply(const AsyncSetPropertyRequest &request);
+
+ virtual ~AsyncPropertyReply();
+
+ /*!
+ * \brief The Error enum
+ */
+ enum Error {
+ NoError = 0,
+ Timeout,
+ InvalidOperation,
+ PermissionDenied,
+ ZoneNotSupported
+ };
+
+ /*!
+ * \brief errorToStr returns string representing the Error
+ */
+ static std::string errorToStr(Error 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: " << 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;
+ }
+
+ /*!
+ * \brief value of the reply. This may be null if success = false. This is owned by the source.
+ */
+ AbstractPropertyType* value;
+
+ /*!
+ * \brief success indicates if the request was successfull or not. True means success. False means fail and the 'error'
+ * member should be set.
+ */
+ bool success;
+
+ /*!
+ * \brief timed out callback is called when the reply times out. This is so sources can avoid using this reply which
+ * may become invalid after it times out.
+ */
+ TimedOutCallback timedout;
+
+ /*!
+ * \brief error contains the error if the request was not successful.\
+ * \see Error
+ */
+ Error error;
+
+private:
+ void setTimeout();
+ GSource* timeoutSource;
+};
+
+/*!
+ * \brief The AsyncSetPropertyRequest class is used by sinks to set a property to the 'value'. The source will reply
+ * with a AsyncPropertyReply containing the new value or an error.
+ * \see AbstractRoutingEngine::setProperty
+ * \see AsyncPropertyReply
+ */
+class AsyncSetPropertyRequest: public AsyncPropertyRequest
+{
+public:
+ AsyncSetPropertyRequest()
+ :value(NULL)
+ {
+
+ }
+
+ AsyncSetPropertyRequest(const AsyncPropertyRequest &request)
+ :AsyncPropertyRequest(request), value(NULL)
+ {
+
+ }
+
+ virtual ~AsyncSetPropertyRequest()
+ {
+
+ }
+
+ /*!
+ * \brief value the new value to set the property to.
+ */
+ AbstractPropertyType* value;
+};
+
+/*!
+ * \brief The AsyncRangePropertyRequest class is used by sinks to request values within a time or sequence range
+ * \see AbstractRoutingEngine::getRangePropertyAsync
+ */
+class AsyncRangePropertyRequest
+{
+public:
+ AsyncRangePropertyRequest()
+ :zone(Zone::None), timeBegin(0), timeEnd(0), sequenceBegin(-1), sequenceEnd(-1)
+ {
+
+ }
+
+ AsyncRangePropertyRequest(const AsyncRangePropertyRequest &request)
+ {
+ this->properties = request.properties;
+ this->completed = request.completed;
+ this->timeBegin = request.timeBegin;
+ this->timeEnd = request.timeEnd;
+ this->sequenceBegin = request.sequenceBegin;
+ this->sequenceEnd = request.sequenceEnd;
+ this->sourceUuid = request.sourceUuid;
+ this->zone = request.zone;
+ }
+
+ virtual ~AsyncRangePropertyRequest() {}
+
+ /*!
+ * \brief properties list of properties to request
+ */
+ PropertyList properties;
+
+ /*!
+ * \brief sourceUuid if the sink wishes to request a specific source, this should be set to the uuid of the source.
+ */
+ std::string sourceUuid;
+
+ /*!
+ * \brief zone if the sink wishes to request a specific zone, this should be set to the desired zone .
+ */
+ Zone::Type zone;
+
+ /*!
+ * \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\
+ * 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\
+ * since the unix epoc. Set this to '0' if you do not want values within a time range.
+ */
+ double timeEnd;
+
+ /*!
+ * \brief sequenceBegin set this to request values with a sequence >= to the sequenceBegin value. Set to -1 if
+ * you don't want values within a sequence ranges.
+ */
+ int32_t sequenceBegin;
+
+ /*!
+ * \brief sequenceEnd set this to request values with a sequence <= to the sequenceEnd value. Set to -1 if
+ * you don't want values within a sequence ranges.
+ */
+ int32_t sequenceEnd;
+
+ /*!
+ * \brief pid requesting process id
+ */
+ std::string pid;
+};
+
+/*!
+ * \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.
+ * If the request is not successful, 'success' should be set to 'false' and the 'error' member should be set.
+ */
+class AsyncRangePropertyReply: public AsyncRangePropertyRequest
+{
+public:
+ AsyncRangePropertyReply(AsyncRangePropertyRequest request)
+ :AsyncRangePropertyRequest(request), success(false)
+ {
+
+ }
+
+ ~AsyncRangePropertyReply()
+ {
+ for(auto itr = values.begin(); itr != values.end(); itr++)
+ {
+ delete (*itr);
+ }
+
+ values.clear();
+ }
+
+ /*!
+ * \brief error this is set if there was an error in the request. "success" will also be set to false.
+ */
+ AsyncPropertyReply::Error error;
+
+ /*!
+ * \brief values if the request was successful, this will contain a list of values meeting the criteria of the request.
+ */
+ std::list<AbstractPropertyType*> values;
+
+ /*!
+ * \brief success this will be true if the request was successful. If not, this is false and error is set.
+ */
+ bool success;
+};
+
+class AbstractRoutingEngine
+{
+public:
+ typedef std::function<void (AbstractPropertyType* value)> PropertyChangedType;
+
+ AbstractRoutingEngine(std::map<std::string, std::string> configuration):mConfig(configuration) {}
+ virtual ~AbstractRoutingEngine();
+
+ virtual void registerSource(AbstractSource* src) = 0;
+ virtual void updateSupported(PropertyList added, PropertyList removed, AbstractSource* source) = 0;
+
+
+ /// Deprecated:
+ void updateProperty(VehicleProperty::Property property, AbstractPropertyType* value, std::string uuid)
+ {
+ DebugOut(DebugOut::Warning)<<"updateProperty(VehicleProperty::Property,AbstractPropertyType*,std::string) is deprecated. use new updateProperty(AbstractPropertyType*, const std::string &)"<<endl;
+ updateProperty(value,uuid);
+ }
+
+ virtual void updateProperty(AbstractPropertyType* value, const std::string &uuid) = 0;
+ virtual PropertyList supported() = 0;
+
+ /// sinks:
+ virtual void registerSink(AbstractSink* self) = 0;
+ virtual void unregisterSink(AbstractSink* self) = 0;
+
+ /**
+ * /brief sourcesForProperty
+ * /param property
+ * /return vector of source uuid's that support the "property"
+ */
+ virtual std::vector<std::string> sourcesForProperty(const VehicleProperty::Property & property) = 0;
+
+ /**
+ * /brief getPropertyAsync requests a property value from a source. This call has a timeout and the callback specified in the request will always be called.
+ * /see AsyncPropertyRequest
+ * /see AsyncPropertyReply.
+ * /param request requested property.
+ * /return AsyncPropertyReply. The returned AsyncPropertyReply is owned by the caller of getPropertyAsync.
+ * /code AsyncPropertyRequest request;
+ * request.property = VehicleProperty::VehicleSpeed
+ * request.completed = [](AsyncPropertyReply* reply)
+ * {
+ * //you own the reply
+ * 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.
+ * \arg request the request containing the property and other information required by the query
+ * \return a pointer to the reply.
+ * \code AsyncRangePropertyRequest vehicleSpeedFromLastWeek;
+ *
+ * vehicleSpeedFromLastWeek.timeBegin = amb::currentTime() - 10;
+ * vehicleSpeedFromLastWeek.timeEnd = amb::currentTime();
+ *
+ * PropertyList requestList;
+ * requestList.push_back(VehicleProperty::VehicleSpeed);
+ * requestList.push_back(VehicleProperty::EngineSpeed);
+ *
+ * vehicleSpeedFromLastWeek.properties = requestList;
+ * vehicleSpeedFromLastWeek.completed = [](AsyncRangePropertyReply* reply)
+ * {
+ * std::list<AbstractPropertyType*> values = reply->values;
+ * 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;
+ * }
+ *
+ * delete reply;
+ * };
+ *
+ * routingEngine->getRangePropertyAsync(vehicleSpeedFromLastWeek);
+ * \endcode
+ */
+ virtual void getRangePropertyAsync(AsyncRangePropertyRequest request) = 0;
+
+ /*!
+ * \brief setProperty sets a property to a value.
+ * \see AsyncSetPropertyRequest
+ * \see AsyncPropertyReply
+ * \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
+ */
+ virtual AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request) = 0;
+
+ /*!
+ * \brief subscribeToProperty subscribes to propertyName. Value changes will be passed to callback.
+ * \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
+ * \arg handle
+ */
+ virtual void unsubscribeToProperty(uint handle) = 0;
+
+ /*!
+ * \brief subscribeToProperty subscribe to changes made to a property value.
+ * \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);
+ *
+ * //... elsewhere in the sink, this will be called when a property changes:
+ * void MySink::propertyChanged(const AbstractPropertyType* property)
+ * {
+ * if(property->name == VehicleProperty::EngineSpeed)
+ * {
+ * ...
+ * }
+ * }
+ * \endcode
+ */
+ virtual bool subscribeToProperty(const VehicleProperty::Property & propertyName, AbstractSink* self) = 0;
+
+ /*!
+ * \brief subscribeToProperty subscribe to changes made to a property value.
+ * \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.
+ * \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;
+
+ virtual bool unsubscribeToProperty(const VehicleProperty::Property &, AbstractSink* self) = 0;
+
+ virtual PropertyInfo getPropertyInfo(const VehicleProperty::Property &, const std::string & sourceUuid) = 0;
+
+protected:
+ std::map<std::string, std::string> mConfig;
+};
+
+#endif // ABSTRACTROUTINGENGINE_H
diff --git a/lib/abstractsink.cpp b/lib/abstractsink.cpp
new file mode 100644
index 00000000..e87c2f92
--- /dev/null
+++ b/lib/abstractsink.cpp
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "abstractsink.h"
+#include "abstractroutingengine.h"
+
+AbstractSink::AbstractSink(AbstractRoutingEngine* engine, map<string, string> config)
+ :routingEngine(engine), configuration(config)
+{
+ if(routingEngine)
+ routingEngine->registerSink(this);
+}
+
+AbstractSink::~AbstractSink()
+{
+ if(routingEngine)
+ routingEngine->unregisterSink(this);
+}
+
+
+
diff --git a/lib/abstractsink.h b/lib/abstractsink.h
new file mode 100644
index 00000000..a24b3570
--- /dev/null
+++ b/lib/abstractsink.h
@@ -0,0 +1,75 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef ABSTRACTSINK_H
+#define ABSTRACTSINK_H
+
+#include <string>
+#include <list>
+#include <vector>
+#include <map>
+#include <functional>
+#include <boost/any.hpp>
+
+#include "vehicleproperty.h"
+#include "abstractpropertytype.h"
+
+using namespace std;
+
+class AbstractRoutingEngine;
+class AbstractSink;
+
+typedef vector<AbstractSink*> SinkList;
+
+class AbstractSink
+{
+
+public:
+ AbstractSink(AbstractRoutingEngine* engine, map<string, string> config);
+ virtual ~AbstractSink();
+
+ ///Pure virtual methods:
+
+ /*! uuid() is a unique identifier
+ * @return a guid-style unique identifier
+ */
+ virtual const string uuid() = 0;
+
+ /*! \brief propertyChanged is called when a subscribed to property changes.
+ * \see AbstractRoutingEngine::subscribeToPropertyChanges()
+ * \param value value of the property that changed. this is a temporary pointer that will be destroyed.
+ * Do not destroy it. If you need to store the value use value.anyValue(), value.value<T>() or
+ * value->copy() to copy.
+ */
+ virtual void propertyChanged(AbstractPropertyType *value){ (void)value; }
+
+ /*! supportedChanged() is called when the supported properties changes
+ * @arg supportedProperties the new list of supported properties.
+ */
+ virtual void supportedChanged(const PropertyList & supportedProperties) = 0;
+
+protected:
+ /*!
+ * \brief routingEngine is the core of AMB. It is used to pass plugin and property information to other plugins
+ */
+ AbstractRoutingEngine* routingEngine;
+ map<string, string> configuration;
+};
+
+#endif // ABSTRACTSINK_H
diff --git a/lib/abstractsource.cpp b/lib/abstractsource.cpp
new file mode 100644
index 00000000..5e78c363
--- /dev/null
+++ b/lib/abstractsource.cpp
@@ -0,0 +1,35 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "abstractsource.h"
+
+AbstractSource::AbstractSource(AbstractRoutingEngine* engine, map<string, string> config)
+ : AbstractSink(engine,config), routingEngine(engine)
+{
+ if(engine)
+ engine->registerSource(this);
+}
+
+AbstractSource::~AbstractSource()
+{
+
+}
+
+
+
diff --git a/lib/abstractsource.h b/lib/abstractsource.h
new file mode 100644
index 00000000..ebeaebdc
--- /dev/null
+++ b/lib/abstractsource.h
@@ -0,0 +1,128 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef ABSTRACTSOURCE_H
+#define ABSTRACTSOURCE_H
+
+#include <string>
+#include <list>
+#include <boost/any.hpp>
+
+#include "abstractsink.h"
+#include "vehicleproperty.h"
+#include "abstractroutingengine.h"
+#include "abstractpropertytype.h"
+#include "propertyinfo.hpp"
+
+
+
+class AbstractSource;
+
+typedef std::list<AbstractSource*> SourceList;
+
+
+
+class AbstractSource: public AbstractSink
+{
+
+public:
+ /*!
+ * \brief The Operations enum is a bitmask flag used to specify which operations are supported by the source plugin
+ */
+ enum Operations {
+ Get = 0x01,
+ Set = 0x02,
+ GetRanged = 0x04
+ };
+
+ AbstractSource(AbstractRoutingEngine* engine, map<string, string> config);
+ virtual ~AbstractSource();
+
+ ///pure virtual methods:
+
+ /*!
+ * \brief getPropertyAsync is called when a sink requests the value for given property.
+ * This is only called if the source supports the Get operation (@see Operation)
+ * \param reply the reply variable. @see AsyncPropertyReply
+ */
+ virtual void getPropertyAsync(AsyncPropertyReply *reply) = 0;
+
+ /*!
+ * \brief getRangePropertyAsync is called when a sink requests a series of values for a given
+ * property within a specified time or sequencial range. This will only be called if the source
+ * support the Ranged Operation (@see Operations)
+ * \param reply is the reply variable. @see AsyncRangePropertyReply
+ */
+ virtual void getRangePropertyAsync(AsyncRangePropertyReply *reply) = 0;
+
+ /*!
+ * \brief setProperty is called when a sink requests to set a value for a given property.
+ * This is only called if the source supports the Set Operation (@see Operation)
+ * \param request the requested property to set.
+ * \return returns a pointer to the new value for the property. @see AsyncPropertyReply
+ */
+ virtual AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request) = 0;
+
+ /*!
+ * \brief subscribeToPropertyChanges is called when a sink requests a subscription. Source plugins
+ * can keep track of subscriptions and may wish to sleep if there are no subscriptions.
+ * \param property the property that is being subscribed.
+ * @see unsubscribeToPropertyChanges
+ */
+ virtual void subscribeToPropertyChanges(VehicleProperty::Property property) = 0;
+
+ /*!
+ * \brief unsubscribeToPropertyChanges is called when a sink requests to unsubscribe from a given property's changes.
+ * \param property the property to unsubscribe to
+ * @see subscribeToPropertyChanges
+ */
+ virtual void unsubscribeToPropertyChanges(VehicleProperty::Property property) = 0;
+
+ /*!
+ * \brief supportedOperations
+ * \return returns the supported operations. @see Operations
+ */
+ virtual int supportedOperations() = 0;
+
+ /*!
+ * \brief getPropertyInfo used to return specific information about a property @see PropertyInfo
+ * the source should override this otherwise a PropertyInfo::invalid() will be returned for the property
+ * \param property the property to get info for.
+ * \return a PropertyInfo object.
+ */
+ virtual PropertyInfo getPropertyInfo(const VehicleProperty::Property & property) = 0;
+
+ /*!
+ * \brief supported
+ * \return returns the supported properties.
+ */
+ virtual PropertyList supported() = 0;
+
+protected:
+ /*!
+ * \brief routingEngine the core routing engine used to send property updates to sink plugins.
+ * @see AbstractRoutingEngine
+ */
+ AbstractRoutingEngine* routingEngine;
+
+private:
+ AbstractSource():AbstractSink(nullptr, std::map<std::string,std::string>()) { }
+};
+
+#endif // ABSTRACTSOURCE_H
diff --git a/lib/ambplugin.h b/lib/ambplugin.h
new file mode 100644
index 00000000..d73ed8d2
--- /dev/null
+++ b/lib/ambplugin.h
@@ -0,0 +1,274 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _AMBPLUGIN_H_
+#define _AMBPLUGIN_H_
+
+#include <abstractsource.h>
+#include "ambpluginimpl.h"
+#include <string>
+
+/*!
+ * \file ambplugin.h
+ * \brief Contains common code used in plugins for Automotive message broker(AMB).
+ */
+
+/*!
+ * AmbPlugin class contains common code used in plugins for Automotive message broker(AMB).
+ * For the AMB library API please visit \ref libamb</a>.
+ *
+ * \class AmbPlugin
+ *
+ * Example of the minimal code to write a new plugin using AmbPlugin:
+ *
+ * \code
+ * #include "ambpluginimpl.h"
+ *
+ * class MyPlugin: public AmbPluginImpl {
+ *
+ * public:
+ * MyPlugin(AbstractRoutingEngine* re, const std::map<std::string, std::string>& config, AbstractSource& parent);
+ * ~MyPlugin();
+ *
+ * const std::string uuid() const { return "plugin_uuid"; }
+ * };
+ *
+ * // library exported function for plugin loader
+ * extern "C" void create(AbstractRoutingEngine* routingengine, std::map<std::string, std::string> config)
+ * {
+ * new AmbPlugin<MyPlugin>(routingengine, config);
+ * }
+ * \endcode
+ * \addtogroup libamb
+ * @{
+ */
+
+template<class T>
+class AmbPlugin : public AbstractSource {
+
+ /*!
+ * Compile time check
+ * \internal
+ */
+ static_assert(std::is_base_of<AmbPluginImpl, T>::value, "AmbPluginImpl has to be a base of T");
+
+public:
+ /*!
+ * \param re AbstractRoutingEngine
+ * \param config Map of the configuration string values loaded on startup from AMB configuration file
+ */
+ AmbPlugin(AbstractRoutingEngine* re, const std::map<std::string, std::string>& config);
+ virtual ~AmbPlugin() {}
+
+ // from AbstractSource:
+public:
+
+ /*!
+ * \brief getPropertyAsync is called when a sink requests the value for given property.
+ * This is only called if the source supports the Get operation.
+ * \param reply the reply variable. @see AsyncPropertyReply
+ */
+ virtual void getPropertyAsync(AsyncPropertyReply *reply);
+
+ /*!
+ * \brief getRangePropertyAsync is called when a sink requests a series of values for a given
+ * property within a specified time or sequencial range. This will only be called if the source
+ * support the Ranged Operation.
+ * \param reply is the reply variable. @see AsyncRangePropertyReply
+ */
+ virtual void getRangePropertyAsync(AsyncRangePropertyReply *reply);
+
+ /*!
+ * \brief setProperty is called when a sink requests to set a value for a given property.
+ * This is only called if the source supports the Set Operation.
+ * \param request the requested property to set.
+ * \return returns a pointer to the new value for the property.
+ */
+ virtual AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request);
+
+ /*!
+ * \brief subscribeToPropertyChanges is called when a sink requests a subscription. Source plugins
+ * can keep track of subscriptions and may wish to sleep if there are no subscriptions.
+ * \param property the property that is being subscribed.
+ */
+ virtual void subscribeToPropertyChanges(VehicleProperty::Property property);
+
+ /*!
+ * \brief unsubscribeToPropertyChanges is called when a sink requests to unsubscribe from a given property's changes.
+ * \param property the property to unsubscribe to
+ */
+ virtual void unsubscribeToPropertyChanges(VehicleProperty::Property property);
+
+ /*!
+ * \brief supported is called by the routingEngine to understand what properties this source supports
+ * \return returns a list of supported properties. If the the supported properties changed, the source should call AbstractRoutingEngine::setSupported.
+ */
+ virtual PropertyList supported();
+
+ /*!
+ * \brief supportedOperations
+ * \return returns the supported operations.
+ */
+ virtual int supportedOperations();
+
+ /*!
+ * \brief getPropertyInfo used to return specific information about a property.
+ * The source should override this otherwise a PropertyInfo::invalid() will be returned for the property.
+ * \param property the property to get info for.
+ * \return a PropertyInfo object.
+ */
+ virtual PropertyInfo getPropertyInfo(const VehicleProperty::Property & property);
+
+ // from AbstractSink
+public:
+
+ /*! uuid() is a unique identifier
+ * \return A guid-style unique identifier
+ */
+ virtual const string uuid();
+
+ /*! propertyChanged is called when a subscribed to property changes.
+ * \param value value of the property that changed. this is a temporary pointer that will be destroyed.
+ * Do not destroy it. If you need to store the value use value.anyValue(), value.value<T>() or
+ * value->copy() to copy.
+ */
+ virtual void propertyChanged(AbstractPropertyType* value);
+
+ /*! supportedChanged() is called when the supported properties changes
+ * \param supportedProperties the new list of supported properties.
+ */
+ virtual void supportedChanged(const PropertyList & supportedProperties);
+
+
+ // AmbPlugin's own methods
+public:
+
+ /*!
+ * Second phase of the plugin initialization.
+ * \fn init
+ */
+ void init();
+
+private:
+
+ /**
+ * \brief AmbPlugin class private implementation
+ */
+ std::unique_ptr<T> d;
+};
+
+//----------------------------------------------------------------------------
+// Function implementations
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// AmbPlugin
+//----------------------------------------------------------------------------
+
+template<typename T>
+AmbPlugin<T>::AmbPlugin(AbstractRoutingEngine* re, const std::map<std::string, std::string>& config) :
+ AbstractSource(re, config),
+ d(new T(re, config, *this))
+{
+
+}
+
+template<typename T>
+void AmbPlugin<T>::getPropertyAsync(AsyncPropertyReply *reply)
+{
+ if(d)
+ d->getPropertyAsync(reply);
+}
+
+template<typename T>
+void AmbPlugin<T>::getRangePropertyAsync(AsyncRangePropertyReply *reply)
+{
+ if(d)
+ d->getRangePropertyAsync(reply);
+}
+
+template<typename T>
+AsyncPropertyReply* AmbPlugin<T>::setProperty(AsyncSetPropertyRequest request)
+{
+ if(d)
+ return d->setProperty(request);
+ return nullptr;
+}
+
+template<typename T>
+void AmbPlugin<T>::subscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ if(d)
+ d->subscribeToPropertyChanges(property);
+}
+
+template<typename T>
+void AmbPlugin<T>::unsubscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ if(d)
+ return d->unsubscribeToPropertyChanges(property);
+}
+
+template<typename T>
+PropertyList AmbPlugin<T>::supported()
+{
+ return d ? d->supported() : PropertyList();
+}
+
+template<typename T>
+int AmbPlugin<T>::supportedOperations()
+{
+ return d ? d->supportedOperations() : 0;
+}
+
+template<typename T>
+PropertyInfo AmbPlugin<T>::getPropertyInfo(const VehicleProperty::Property &property)
+{
+ return d ? d->getPropertyInfo(property) : PropertyInfo::invalid();
+}
+
+template<typename T>
+const string AmbPlugin<T>::uuid()
+{
+ return d ? d->uuid() : "";
+}
+
+template<typename T>
+void AmbPlugin<T>::propertyChanged(AbstractPropertyType* value)
+{
+ if(d)
+ d->propertyChanged(value);
+}
+
+template<typename T>
+void AmbPlugin<T>::supportedChanged(const PropertyList &supportedProperties)
+{
+ if(d)
+ d->supportedChanged(supportedProperties);
+}
+
+template<typename T>
+void AmbPlugin<T>::init()
+{
+ if(d)
+ d->init();
+}
+
+#endif // _AMBPLUGIN_H_
+
+/** @} */
diff --git a/lib/ambpluginimpl.cpp b/lib/ambpluginimpl.cpp
new file mode 100644
index 00000000..7bf7e712
--- /dev/null
+++ b/lib/ambpluginimpl.cpp
@@ -0,0 +1,186 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <vehicleproperty.h>
+#include <listplusplus.h>
+
+#include "ambpluginimpl.h"
+
+//----------------------------------------------------------------------------
+// AmbPluginImpl
+//----------------------------------------------------------------------------
+
+AmbPluginImpl::AmbPluginImpl(AbstractRoutingEngine* re, const map<string, string>& config, AbstractSource& parent) :
+ source(parent),
+ routingEngine(re),
+ configuration(config)
+{
+}
+
+void AmbPluginImpl::init()
+{
+}
+
+void AmbPluginImpl::getPropertyAsync(AsyncPropertyReply *reply)
+{
+ if(!reply) {
+ DebugOut(DebugOut::Error) << "AmbPluginImpl::getPropertyAsync - reply is null" << std::endl;
+ return;
+ }
+
+ DebugOut() << "AmbPluginImpl::getPropertyAsync called for property: " << reply->property << endl;
+
+ reply->success = false;
+ reply->error = AsyncPropertyReply::InvalidOperation;
+ AbstractPropertyType *value = findPropertyType(reply->property, reply->zoneFilter);
+ if (value) {
+ reply->value = value;
+ reply->success = true;
+ reply->error = AsyncPropertyReply::NoError;
+ }
+
+ if(reply->completed)
+ reply->completed(reply);
+}
+
+void AmbPluginImpl::getRangePropertyAsync(AsyncRangePropertyReply *reply)
+{
+ if(!reply) {
+ DebugOut(DebugOut::Error) << "AmbPluginImpl::getRangePropertyAsync - reply is null" << std::endl;
+ return;
+ }
+
+ DebugOut() << "AmbPluginImpl::getRangePropertyAsync not supported "<< std::endl;
+ reply->success = false;
+ reply->error = AsyncPropertyReply::InvalidOperation;
+ if(reply->completed)
+ reply->completed(reply);
+}
+
+AsyncPropertyReply *AmbPluginImpl::setProperty(const AsyncSetPropertyRequest& request )
+{
+ AsyncPropertyReply* reply = new AsyncPropertyReply(request);
+ reply->success = false;
+ reply->error = AsyncPropertyReply::InvalidOperation;
+
+ AbstractPropertyType *value = findPropertyType(request.property, request.zoneFilter);
+ if (value && request.value) {
+ DebugOut(2) << "updating property "<< request.property << " to: " << request.value->toString() << endl;
+ value->quickCopy(request.value);
+ routingEngine->updateProperty(value, uuid());
+ reply->success = true;
+ reply->error = AsyncPropertyReply::NoError;
+ }
+
+ try {
+ if(reply->completed)
+ reply->completed(reply);
+ }
+ catch (...) { }
+
+ return reply;
+}
+
+void AmbPluginImpl::subscribeToPropertyChanges(const VehicleProperty::Property& property)
+{
+
+}
+
+PropertyList AmbPluginImpl::supported() const
+{
+ PropertyList props;
+ for(auto itPropMap = properties.begin(); itPropMap != properties.end(); ++itPropMap)
+ props.push_back(itPropMap->first);
+ return props;
+}
+
+int AmbPluginImpl::supportedOperations() const
+{
+ return AbstractSource::Get | AbstractSource::Set;
+}
+
+void AmbPluginImpl::unsubscribeToPropertyChanges(const VehicleProperty::Property& property)
+{
+}
+
+// if signal does not exits return nullptr(we do not know its datatype), if zone does not exists, add it
+AbstractPropertyType* AmbPluginImpl::findPropertyType(const VehicleProperty::Property& propertyName, const Zone::Type& zone)
+{
+ auto itPropMap = properties.find(propertyName);
+ if(itPropMap == properties.end())
+ return nullptr;
+
+ for( auto it = itPropMap->second.begin(); it != itPropMap->second.end(); ++it ) {
+ if(it->first == zone)
+ return it->second.get();
+ }
+
+ return nullptr;
+}
+
+std::shared_ptr<AbstractPropertyType> AmbPluginImpl::addPropertySupport(Zone::Type zone, std::function<AbstractPropertyType* (void)> typeFactory, std::string sourceUuid)
+{
+ if(sourceUuid.empty())
+ sourceUuid = uuid();
+ std::shared_ptr<AbstractPropertyType> propertyType(typeFactory());
+ if(!propertyType)
+ return propertyType;
+
+ VehicleProperty::Property name(propertyType->name);
+ PropertyList registeredProperties(VehicleProperty::capabilities());
+ bool registeredType(false);
+ if(!contains(registeredProperties,name))
+ {
+ registeredType = VehicleProperty::registerProperty(name, typeFactory);
+ }
+ if(!registeredType)
+ { // Property type wasn't registered by us. Is it predefined in AMB API or some other source plug-in has already registered it ???
+ std::shared_ptr<AbstractPropertyType> registeredPropertyType(VehicleProperty::getPropertyTypeForPropertyNameValue(name));
+ if(!registeredPropertyType)
+ return nullptr;
+ propertyType.swap(registeredPropertyType);
+ }
+ propertyType->zone = zone;
+ propertyType->sourceUuid = sourceUuid;
+ propertyType->timestamp = amb::currentTime();
+ ZonePropertyType& zonePropType = properties[name];
+ zonePropType.insert(make_pair(zone, propertyType));
+ return propertyType;
+}
+
+PropertyInfo AmbPluginImpl::getPropertyInfo(const VehicleProperty::Property & property)
+{
+ auto it = properties.find(property);
+ if(it != properties.end()) {
+ Zone::ZoneList zones;
+ for(auto itZonePropType = it->second.begin(); itZonePropType != it->second.end(); ++itZonePropType)
+ zones.push_back(itZonePropType->first);
+
+ return PropertyInfo( 0, zones );
+ }
+
+ return PropertyInfo::invalid();
+}
+
+void AmbPluginImpl::propertyChanged(AbstractPropertyType* value)
+{
+}
+
+void AmbPluginImpl::supportedChanged(const PropertyList& supportedProperties)
+{
+}
diff --git a/lib/ambpluginimpl.h b/lib/ambpluginimpl.h
new file mode 100644
index 00000000..9bd3c2d9
--- /dev/null
+++ b/lib/ambpluginimpl.h
@@ -0,0 +1,209 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _AMBPLUGINIMPL_H_
+#define _AMBPLUGINIMPL_H_
+
+#include "abstractsource.h"
+
+/*! \addtogroup libamb
+ * @{
+ */
+
+/*!
+ * \brief AmbPlugin private class implementation - base class for all plugin implementations.
+ *
+ * Contains common code used in plugins for Automotive message broker(AMB).
+ * For the AMB library API please visit \ref libamb.
+ *
+ * \class AmbPluginImpl
+ */
+class AmbPluginImpl
+{
+
+public:
+ /*!
+ * \param re AbstractRoutingEngine
+ * \param config Map of the configuration string values loaded on startup from AMB configuration file
+ * \param parent AmbPlugin instance
+ */
+ AmbPluginImpl(AbstractRoutingEngine* re, const map<string, string>& config, AbstractSource &parent);
+ virtual ~AmbPluginImpl() { } /*LCOV_EXCL_LINE*/
+
+ // aka AbstractSource:
+public:
+
+ /*!
+ * \brief getPropertyAsync is called when a sink requests the value for given property.
+ * This is only called if the source supports the Get operation.
+ * \param reply the reply variable.
+ */
+ virtual void getPropertyAsync(AsyncPropertyReply *reply);
+
+ /*!
+ * \brief getRangePropertyAsync is called when a sink requests a series of values for a given
+ * property within a specified time or sequencial range. This will only be called if the source
+ * support the Ranged Operation.
+ * \param reply is the reply variable.
+ */
+ virtual void getRangePropertyAsync(AsyncRangePropertyReply *reply);
+
+ /*!
+ * \brief setProperty is called when a sink requests to set a value for a given property.
+ * This is only called if the source supports the Set Operation.
+ * \param request the requested property to set.
+ * \return returns a pointer to the new value for the property.
+ */
+ virtual AsyncPropertyReply *setProperty(const AsyncSetPropertyRequest& request );
+
+ /*!
+ * \brief subscribeToPropertyChanges is called when a sink requests a subscription. Source plugins
+ * can keep track of subscriptions and may wish to sleep if there are no subscriptions.
+ * \param property the property that is being subscribed.
+ */
+ virtual void subscribeToPropertyChanges(const VehicleProperty::Property& property);
+
+ /*!
+ * \brief unsubscribeToPropertyChanges is called when a sink requests to unsubscribe from a given property's changes.
+ * \param property the property to unsubscribe to
+ */
+ virtual void unsubscribeToPropertyChanges(const VehicleProperty::Property& property);
+
+ /*!
+ * \brief supported is called by the routingEngine to understand what properties this source supports.
+ * \return returns a list of supported properties. If the the supported properties changed, the source should call AbstractRoutingEngine::setSupported.
+ */
+ virtual PropertyList supported() const;
+
+ /*!
+ * \brief supportedOperations
+ * \return returns the supported operations.
+ */
+ virtual int supportedOperations() const;
+
+ /*!
+ * \brief getPropertyInfo used to return specific information about a property.
+ * The source should override this otherwise a PropertyInfo::invalid() will be returned for the property
+ * \param property the property to get info for.
+ * \return a PropertyInfo object.
+ */
+ virtual PropertyInfo getPropertyInfo(const VehicleProperty::Property & property);
+
+ // aka AbstractSink:
+public:
+
+ /*! uuid() is a unique identifier
+ * @return a guid-style unique identifier
+ */
+ virtual const std::string uuid() const = 0;
+
+ /*! propertyChanged is called when a subscribed to property changes.
+ * @param value value of the property that changed. this is a temporary pointer that will be destroyed.
+ * Do not destroy it. If you need to store the value use value.anyValue(), value.value<T>() or
+ * value->copy() to copy.
+ */
+ virtual void propertyChanged(AbstractPropertyType* value);
+
+ /*! supportedChanged() is called when the supported properties changes
+ * \fn supportedChanged
+ * \param supportedProperties the new list of supported properties.
+ */
+ virtual void supportedChanged(const PropertyList& supportedProperties);
+
+ /*!
+ * Second phase of the plugin initialization.
+ * \fn init
+ */
+ virtual void init();
+
+ /*!
+ * \brief setValue of a property
+ */
+ template <typename T>
+ void setValue(std::shared_ptr<AbstractPropertyType> property, T value)
+ {
+ if(property->value<T>() == value)
+ {
+ return;
+ }
+
+ property->setValue(value);
+ routingEngine->updateProperty(property.get(), source.uuid());
+ }
+
+
+protected:
+
+ /*! Finds property type in #properties
+ * \param propertyName Name of the property to be found.
+ * \param zone Zone of the property to be found.
+ * \return AbstractPropertyType* if signal exits otherwise nullptr(in this case we do not know its datatype)
+ */
+ virtual AbstractPropertyType* findPropertyType(const VehicleProperty::Property& propertyName, const Zone::Type& zone = Zone::None);
+
+ /*! Registers property in AMB
+ * \param zone Zone of the property to be registered.
+ * \param typeFactory Function to be used to create instance of the AbstractPropertyType for registered property
+ * \return AbstractPropertyType* if signal exits otherwise nullptr(in this case we do not know its datatype)
+ */
+ std::shared_ptr<AbstractPropertyType> addPropertySupport(Zone::Type zone, std::function<AbstractPropertyType* (void)> typeFactory, std::string sourceUuid="");
+
+ template <class T>
+ std::shared_ptr<AbstractPropertyType> addPropertySupport(Zone::Type zone)
+ {
+ auto typeFactory = [](){
+ return new T;
+ };
+ return addPropertySupport(zone, typeFactory);
+ }
+
+ //
+ // data:
+ //
+
+ /*! AmbPlugin instance
+ * \property parent
+ */
+ AbstractSource& source;
+
+ /*!
+ * AbstractRoutingEngine instance
+ * \property routingEngine
+ */
+ AbstractRoutingEngine* routingEngine;
+
+ /*! Helper typedef
+ * \internal
+ */
+ typedef std::map< Zone::Type, std::shared_ptr<AbstractPropertyType> > ZonePropertyType;
+
+ /*!
+ * Supported property values map
+ * \property properties
+ */
+ std::map< VehicleProperty::Property, ZonePropertyType > properties;
+
+ /*!
+ * configuration
+ */
+ std::map< std::string, std::string> configuration;
+};
+
+#endif // _AMBPLUGINIMPL_H_
+
+/** @} */
diff --git a/lib/asyncqueue.hpp b/lib/asyncqueue.hpp
new file mode 100644
index 00000000..61ff412e
--- /dev/null
+++ b/lib/asyncqueue.hpp
@@ -0,0 +1,200 @@
+/*
+ Copyright (C) 2014 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <glib.h>
+
+#include <abstractpropertytype.h>
+#include "listplusplus.h"
+
+#include <mutex>
+#include <condition_variable>
+#include <unordered_set>
+#include <vector>
+
+namespace amb
+{
+
+template <typename T, class Pred = std::equal_to<T> >
+class Queue
+{
+public:
+ Queue(bool unique = false, bool blocking = false)
+ :mUnique(unique), mBlocking(blocking)
+ {
+
+ }
+
+ virtual ~Queue()
+ {
+
+ }
+
+ int count()
+ {
+ std::lock_guard<std::mutex> lock(mutex);
+
+ return mQueue.size();
+ }
+
+ T pop()
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+
+ if(mBlocking)
+ {
+ if(!mQueue.size())
+ {
+ cond.wait(lock);
+ }
+ }
+
+ if(!mQueue.size())
+ {
+ throw std::runtime_error("nothing in queue");
+ }
+
+ auto itr = mQueue.begin();
+
+ T item = *itr;
+
+ mQueue.erase(itr);
+
+ return item;
+ }
+
+ virtual void append(T item)
+ {
+ {
+ std::lock_guard<std::mutex> lock(mutex);
+
+ if(contains(mQueue, item))
+ {
+ mQueue.erase(std::find(mQueue.begin(), mQueue.end(), item));
+ }
+ mQueue.push_back(item);
+ }
+
+ if(mBlocking)
+ {
+ cond.notify_all();
+ }
+ }
+
+ void remove(T item)
+ {
+ std::lock_guard<std::mutex> lock(mutex);
+ removeOne(&mQueue, item);
+ }
+
+private:
+ bool mBlocking;
+ bool mUnique;
+ std::mutex mutex;
+ std::condition_variable cond;
+ std::vector<T> mQueue;
+};
+
+template <typename T, class Pred = std::equal_to<T> >
+struct AsyncQueueSource{
+ GSource source;
+ Queue<T, Pred>* queue;
+ int minQueueSize;
+};
+
+template <typename T, class Pred = std::equal_to<T> >
+class AsyncQueueWatcher
+{
+public:
+ typedef function<void (Queue<T, Pred> *)> AsyncQueueWatcherCallback;
+ AsyncQueueWatcher(Queue<T, Pred> * queue, AsyncQueueWatcherCallback cb, int queueSize = 0, AbstractPropertyType::Priority priority = AbstractPropertyType::Normal)
+ : callback(cb), mMaxQueueSize(queueSize)
+ {
+
+ static GSourceFuncs funcs = {prepare, check, dispatch, finalize};
+ GSource* source = (GSource *) g_source_new(&funcs, sizeof(AsyncQueueSource<T, Pred>));
+
+ AsyncQueueSource<T, Pred>* watch = (AsyncQueueSource<T, Pred>*)source;
+ watch->queue = queue;
+ watch->minQueueSize = queueSize;
+
+ gint p = G_PRIORITY_DEFAULT;
+
+ if(priority == AbstractPropertyType::Normal)
+ p = G_PRIORITY_DEFAULT;
+ else if(priority == AbstractPropertyType::High)
+ p = G_PRIORITY_HIGH;
+ else if(priority == AbstractPropertyType::Low)
+ p = G_PRIORITY_LOW;
+
+ g_source_set_priority(source, p);
+ g_source_set_callback(source, nullptr, this, nullptr);
+
+ g_source_attach(source, nullptr);
+ g_source_unref(source);
+ }
+
+ AsyncQueueWatcherCallback callback;
+
+
+protected:
+ AsyncQueueWatcher(){}
+
+ int mMaxQueueSize;
+
+private:
+
+ static gboolean prepare(GSource *source, gint *timeout)
+ {
+ AsyncQueueSource<T, Pred>* s = (AsyncQueueSource<T, Pred>*)source;
+ *timeout = -1;
+
+ if (!s)
+ return false;
+
+ return s->queue->count() > s->minQueueSize;
+ }
+
+ static gboolean check(GSource *source)
+ {
+ AsyncQueueSource<T, Pred>* s = (AsyncQueueSource<T, Pred>*)source;
+
+ if (!s)
+ return false;
+
+ return s->queue->count() > s->minQueueSize;
+ }
+
+ static gboolean dispatch(GSource *source, GSourceFunc callback, gpointer userData)
+ {
+ AsyncQueueSource<T, Pred>* s = (AsyncQueueSource<T, Pred>*)source;
+
+ if (!s)
+ return false;
+
+ AsyncQueueWatcher<T, Pred>* watcher = static_cast<AsyncQueueWatcher<T, Pred>*>(userData);
+
+ watcher->callback(s->queue);
+ return true;
+ }
+
+ static void finalize(GSource* source)
+ {
+
+ }
+};
+} // namespace amb
diff --git a/lib/automotive-message-broker.pc.in b/lib/automotive-message-broker.pc.in
new file mode 100644
index 00000000..2602b31b
--- /dev/null
+++ b/lib/automotive-message-broker.pc.in
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDE_INSTALL_DIR@/amb
+
+Name: automotive-message-broker
+Description: Message Broker for vehicle data
+Version: @PROJECT_VERSION@
+Requires: gio-2.0 glib-2.0 json
+Libs: -L${libdir} -lamb -luuid
+Cflags: -I${includedir}
diff --git a/lib/debugout.cpp b/lib/debugout.cpp
new file mode 100644
index 00000000..f9bac352
--- /dev/null
+++ b/lib/debugout.cpp
@@ -0,0 +1,45 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "debugout.h"
+
+using namespace std;
+
+int DebugOut::debugThreshhold = 0;
+std::streambuf * DebugOut::buf = cout.rdbuf();
+bool DebugOut::throwErr = false;
+bool DebugOut::throwWarn = false;
+
+const int DebugOut::Error = 1 << 16;
+const int DebugOut::Warning = 1 << 24;
+
+void debugOut(const string &message)
+{
+ DebugOut()<<"DEBUG: "<<message.c_str()<<endl;
+}
+
+
+void amb::deprecateMethod(const string & methodName, const string &version)
+{
+ DebugOut(DebugOut::Warning) << methodName << " is deprecated in " << version << endl;
+
+ if(version == PROJECT_SERIES)
+ {
+ throw std::runtime_error("Using deprecated function.");
+ }
+}
diff --git a/lib/debugout.h b/lib/debugout.h
new file mode 100644
index 00000000..a1649082
--- /dev/null
+++ b/lib/debugout.h
@@ -0,0 +1,199 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef DEBUGOUT__H__
+#define DEBUGOUT__H__
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <stdexcept>
+#include "timestamp.h"
+
+using namespace std;
+
+void debugOut(const string &message);
+
+/*! \addtogroup libamb
+ * @{
+ */
+
+/*!
+ * \file debugout.h
+ * \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
+ */
+
+namespace amb
+{
+/*!
+ * \brief deprecateMethod prints warning if method is used. Throws if version >= PROJECT_SERIES
+ * \param methodName name of method being deprecated.
+ * \param version version in which this method will no longer function in.
+ */
+void deprecateMethod(const string &methodName, const std::string & version);
+}
+
+class DebugOut
+{
+public:
+
+ /*!
+ * \brief Error use when essential functionality is blocked
+ */
+ static const int Error;
+
+ /*!
+ * \brief Warning use when non-essential functionality is bocked, or when workarounds exist.
+ */
+ static const int Warning;
+
+ DebugOut(int debugLevel = 4)
+ {
+ mDebugLevel = debugLevel;
+
+ if(mDebugLevel <= debugThreshhold || mDebugLevel == Error || mDebugLevel == Warning)
+ {
+ ostream out(buf);
+ out.precision(15);
+ out<<bufferTime(amb::currentTime())<<" | ";
+
+ if(mDebugLevel == Error)
+ out<<"ERROR ";
+ if(mDebugLevel == Warning)
+ out<<"WARNING ";
+ }
+ }
+ DebugOut const& operator << (const string &message) const
+ {
+ if(mDebugLevel <= debugThreshhold || mDebugLevel == Error || mDebugLevel == Warning)
+ {
+ ostream out(buf);
+ out.precision(15);
+ out<<message;
+ }
+ return *this;
+ }
+
+ DebugOut const& operator << (ostream & (*manip)(std::ostream&)) const
+ {
+
+
+ if(mDebugLevel <= debugThreshhold || mDebugLevel == Error || mDebugLevel == Warning)
+ {
+ ostream out(buf);
+ out.precision(15);
+ out<<endl;
+
+ if((mDebugLevel == Error && throwErr))
+ {
+ throw std::runtime_error("Abort on Error is set");
+ }
+ else if ((mDebugLevel == Warning && throwWarn))
+ {
+ throw std::runtime_error("Abort on Warning is set");
+ }
+ }
+ return *this;
+ }
+
+ DebugOut const & operator << (double val) const
+ {
+ if(mDebugLevel <= debugThreshhold || mDebugLevel == Error || mDebugLevel == Warning)
+ {
+ ostream out(buf);
+ out.precision(15);
+ out<<val<<" ";
+ }
+ return *this;
+ }
+
+ static void setDebugThreshhold(int th)
+ {
+ debugThreshhold = th;
+ }
+
+ static void setOutput(ostream &o)
+ {
+ buf = o.rdbuf();
+ }
+
+ static void setThrowWarn(bool v)
+ {
+ throwWarn = v;
+ }
+
+ static void setThrowErr(bool v)
+ {
+ throwErr = v;
+ }
+
+ static const int getDebugThreshhold()
+ {
+ return debugThreshhold;
+ }
+
+private:
+
+ std::string bufferTime(double time)
+ {
+ ostringstream f;
+
+ f.precision(15);
+
+ f<<time;
+
+ while(f.str().length() <= 15)
+ {
+ f<<" ";
+ }
+
+ return f.str();
+ }
+
+ static int debugThreshhold;
+ static std::streambuf *buf;
+ static bool throwWarn;
+ static bool throwErr;
+ int mDebugLevel;
+};
+
+#endif
+
+/** @} */
diff --git a/lib/listplusplus.cpp b/lib/listplusplus.cpp
new file mode 100644
index 00000000..13514912
--- /dev/null
+++ b/lib/listplusplus.cpp
@@ -0,0 +1,21 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "listplusplus.h"
+
diff --git a/lib/listplusplus.h b/lib/listplusplus.h
new file mode 100644
index 00000000..750f3211
--- /dev/null
+++ b/lib/listplusplus.h
@@ -0,0 +1,56 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef LISTPLUSPLUS_H
+#define LISTPLUSPLUS_H
+
+#include <list>
+#include <algorithm>
+#include <functional>
+
+template <class T, class V>
+bool contains(const T & iteratable, V value)
+{
+ return iteratable.size() > 0 && (std::find(iteratable.begin(), iteratable.end(), value) != iteratable.end());
+}
+
+template <class T, class V>
+bool contains(const T & iteratable, V value, std::function<bool(V,V)> comparator)
+{
+ for(auto i : iteratable)
+ {
+ if(comparator(value, i))
+ return true;
+ }
+
+ return false;
+}
+
+template <class T, class V>
+void removeOne(T * iteratable, V value)
+{
+ typename T::iterator itr = std::find(iteratable->begin(), iteratable->end(), value);
+
+ if (itr != iteratable->end())
+ {
+ iteratable->erase(itr);
+ }
+}
+
+#endif // LISTPLUSPLUS_H
diff --git a/lib/mappropertytype.hpp b/lib/mappropertytype.hpp
new file mode 100644
index 00000000..c9e3d984
--- /dev/null
+++ b/lib/mappropertytype.hpp
@@ -0,0 +1,153 @@
+#ifndef _MAPPROPERTYTYPE_H_
+#define _MAPPROPERTYTYPE_H_
+
+
+#include "abstractpropertytype.h"
+
+#include <map>
+#include <debugout.h>
+#include "picojson.h"
+
+template <class N>
+class MapPropertyType: public AbstractPropertyType
+{
+public:
+ MapPropertyType(std::string propertyName):AbstractPropertyType(propertyName){}
+
+ void append(std::string key, N value)
+ {
+ appendPriv(key, value);
+ }
+
+ AbstractPropertyType* copy()
+ {
+ MapPropertyType<N> *t = new MapPropertyType<N>(name);
+
+ t->setMap(mMap);
+ t->timestamp = timestamp;
+ t->sequence = sequence;
+ t->sourceUuid = sourceUuid;
+ t->name = name;
+ t->zone = zone;
+
+ return t;
+ }
+
+ std::string toString() const
+ {
+ std::stringstream str;
+
+ str<<"{";
+
+ for(auto itr: mMap)
+ {
+ if(str.str() != "{")
+ str << ", ";
+
+
+ str <<"\""<< itr.first <<"\":\""<<itr.second.toString()<<"\"";
+ }
+
+ str << "}";
+
+ return str.str();
+ }
+
+ void fromString(std::string str)
+ {
+ clear();
+
+ DebugOut() << str << endl;
+
+ picojson::value value;
+ picojson::parse(value, str);
+
+ std::string picojsonerr = picojson::get_last_error();
+
+ if(!value.is<picojson::object>() || !picojsonerr.empty())
+ {
+ DebugOut(DebugOut::Warning) << "JSon is invalid for MapPropertyType: " << str << endl;
+ DebugOut(DebugOut::Warning) << picojsonerr << endl;
+ return;
+ }
+
+ const picojson::object& obj = value.get<picojson::object>();
+
+ DebugOut() << "obj size: " << obj.size() << endl;
+
+ for(auto i : obj)
+ {
+ std::string key = i.first;
+ N val("");
+ val.fromString(i.second.to_str());
+ append(key, val);
+ }
+ }
+
+ GVariant* toVariant()
+ {
+ GVariantBuilder params;
+ g_variant_builder_init(&params, G_VARIANT_TYPE_DICTIONARY);
+ for(auto itr = mMap.begin(); itr != mMap.end(); itr++)
+ {
+ auto &foo = (*itr).first;
+ g_variant_builder_add(&params,"{sv}",foo.c_str(), (*itr).second.toVariant());
+ }
+
+ GVariant* var = g_variant_builder_end(&params);
+ g_assert(var);
+ return var;
+ }
+
+ void fromVariant(GVariant* variant)
+ {
+ clear();
+ gsize dictsize = g_variant_n_children(variant);
+ for (int i=0;i<dictsize;i++)
+ {
+ GVariant *childvariant = g_variant_get_child_value(variant,i);
+ gsize dictvalsize = g_variant_n_children(childvariant);
+ if (dictvalsize == 2)
+ {
+ //It is a dictionary entry
+ GVariant *keyvariant = g_variant_get_child_value(childvariant,0);
+ GVariant *valvariant = g_variant_get_child_value(childvariant,1);
+ std::string key = g_variant_get_string(keyvariant, nullptr);
+ N n = N();
+ GVariant *innerValue = nullptr;
+
+ DebugOut() << "variantType: " << g_variant_get_type_string(valvariant) << endl;
+
+ g_variant_get(valvariant, "v", &innerValue);
+
+ DebugOut() << "inner variange: " << g_variant_get_type_string(innerValue) << endl;
+
+ n.fromVariant(innerValue);
+ appendPriv(key,n);
+ }
+ }
+
+ }
+
+ void setMap(std::map<std::string, N> m)
+ {
+ mMap = m;
+ }
+
+private:
+
+ void clear()
+ {
+ mMap.clear();
+ }
+
+ void appendPriv(std::string key, N value)
+ {
+ mMap[key] = value;
+ }
+
+ std::map<std::string, N> mMap;
+};
+
+
+#endif
diff --git a/lib/nullptr.h b/lib/nullptr.h
new file mode 100644
index 00000000..4d05370d
--- /dev/null
+++ b/lib/nullptr.h
@@ -0,0 +1,7 @@
+#define GCC_VERSION (__GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+
+#if GCC_VERSION < 40600
+#define nullptr 0
+#endif
diff --git a/lib/picojson.h b/lib/picojson.h
new file mode 100644
index 00000000..8fa4a928
--- /dev/null
+++ b/lib/picojson.h
@@ -0,0 +1,1029 @@
+/*
+ * Copyright 2009-2010 Cybozu Labs, Inc.
+ * Copyright 2011-2014 Kazuho Oku
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef picojson_h
+#define picojson_h
+
+#include <algorithm>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <iterator>
+#include <limits>
+#include <map>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+// for isnan/isinf
+#if __cplusplus>=201103L
+# include <cmath>
+#else
+extern "C" {
+# ifdef _MSC_VER
+# include <float.h>
+# elif defined(__INTEL_COMPILER)
+# include <mathimf.h>
+# else
+# include <math.h>
+# endif
+}
+#endif
+
+// experimental support for int64_t (see README.mkdn for detail)
+#ifdef PICOJSON_USE_INT64
+# define __STDC_FORMAT_MACROS
+# include <errno.h>
+# include <inttypes.h>
+#endif
+
+// to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0
+#ifndef PICOJSON_USE_LOCALE
+# define PICOJSON_USE_LOCALE 1
+#endif
+#if PICOJSON_USE_LOCALE
+extern "C" {
+# include <locale.h>
+}
+#endif
+
+#ifndef PICOJSON_ASSERT
+# define PICOJSON_ASSERT(e) do { if (! (e)) throw std::runtime_error(#e); } while (0)
+#endif
+
+#ifdef _MSC_VER
+ #define SNPRINTF _snprintf_s
+ #pragma warning(push)
+ #pragma warning(disable : 4244) // conversion from int to char
+ #pragma warning(disable : 4127) // conditional expression is constant
+ #pragma warning(disable : 4702) // unreachable code
+#else
+ #define SNPRINTF snprintf
+#endif
+
+namespace picojson {
+
+ enum {
+ null_type,
+ boolean_type,
+ number_type,
+ string_type,
+ array_type,
+ object_type
+#ifdef PICOJSON_USE_INT64
+ , int64_type
+#endif
+ };
+
+ enum {
+ INDENT_WIDTH = 2
+ };
+
+ struct null {};
+
+ class value {
+ public:
+ typedef std::vector<value> array;
+ typedef std::map<std::string, value> object;
+ union _storage {
+ bool boolean_;
+ double number_;
+#ifdef PICOJSON_USE_INT64
+ int64_t int64_;
+#endif
+ std::string* string_;
+ array* array_;
+ object* object_;
+ };
+ protected:
+ int type_;
+ _storage u_;
+ public:
+ value();
+ value(int type, bool);
+ explicit value(bool b);
+#ifdef PICOJSON_USE_INT64
+ explicit value(int64_t i);
+#endif
+ explicit value(double n);
+ explicit value(const std::string& s);
+ explicit value(const array& a);
+ explicit value(const object& o);
+ explicit value(const char* s);
+ value(const char* s, size_t len);
+ ~value();
+ value(const value& x);
+ value& operator=(const value& x);
+ void swap(value& x);
+ template <typename T> bool is() const;
+ template <typename T> const T& get() const;
+ template <typename T> T& get();
+ bool evaluate_as_boolean() const;
+ const value& get(size_t idx) const;
+ const value& get(const std::string& key) const;
+ value& get(size_t idx);
+ value& get(const std::string& key);
+
+ bool contains(size_t idx) const;
+ bool contains(const std::string& key) const;
+ std::string to_str() const;
+ template <typename Iter> void serialize(Iter os, bool prettify = false) const;
+ std::string serialize(bool prettify = false) const;
+ private:
+ template <typename T> value(const T*); // intentionally defined to block implicit conversion of pointer to bool
+ template <typename Iter> static void _indent(Iter os, int indent);
+ template <typename Iter> void _serialize(Iter os, int indent) const;
+ std::string _serialize(int indent) const;
+ };
+
+ typedef value::array array;
+ typedef value::object object;
+
+ inline value::value() : type_(null_type) {}
+
+ inline value::value(int type, bool) : type_(type) {
+ switch (type) {
+#define INIT(p, v) case p##type: u_.p = v; break
+ INIT(boolean_, false);
+ INIT(number_, 0.0);
+#ifdef PICOJSON_USE_INT64
+ INIT(int64_, 0);
+#endif
+ INIT(string_, new std::string());
+ INIT(array_, new array());
+ INIT(object_, new object());
+#undef INIT
+ default: break;
+ }
+ }
+
+ inline value::value(bool b) : type_(boolean_type) {
+ u_.boolean_ = b;
+ }
+
+#ifdef PICOJSON_USE_INT64
+ inline value::value(int64_t i) : type_(int64_type) {
+ u_.int64_ = i;
+ }
+#endif
+
+ inline value::value(double n) : type_(number_type) {
+ if (
+#ifdef _MSC_VER
+ ! _finite(n)
+#elif __cplusplus>=201103L || !(defined(isnan) && defined(isinf))
+ std::isnan(n) || std::isinf(n)
+#else
+ isnan(n) || isinf(n)
+#endif
+ ) {
+ throw std::overflow_error("");
+ }
+ u_.number_ = n;
+ }
+
+ inline value::value(const std::string& s) : type_(string_type) {
+ u_.string_ = new std::string(s);
+ }
+
+ inline value::value(const array& a) : type_(array_type) {
+ u_.array_ = new array(a);
+ }
+
+ inline value::value(const object& o) : type_(object_type) {
+ u_.object_ = new object(o);
+ }
+
+ inline value::value(const char* s) : type_(string_type) {
+ u_.string_ = new std::string(s);
+ }
+
+ inline value::value(const char* s, size_t len) : type_(string_type) {
+ u_.string_ = new std::string(s, len);
+ }
+
+ inline value::~value() {
+ switch (type_) {
+#define DEINIT(p) case p##type: delete u_.p; break
+ DEINIT(string_);
+ DEINIT(array_);
+ DEINIT(object_);
+#undef DEINIT
+ default: break;
+ }
+ }
+
+ inline value::value(const value& x) : type_(x.type_) {
+ switch (type_) {
+#define INIT(p, v) case p##type: u_.p = v; break
+ INIT(string_, new std::string(*x.u_.string_));
+ INIT(array_, new array(*x.u_.array_));
+ INIT(object_, new object(*x.u_.object_));
+#undef INIT
+ default:
+ u_ = x.u_;
+ break;
+ }
+ }
+
+ inline value& value::operator=(const value& x) {
+ if (this != &x) {
+ this->~value();
+ new (this) value(x);
+ }
+ return *this;
+ }
+
+ inline void value::swap(value& x) {
+ std::swap(type_, x.type_);
+ std::swap(u_, x.u_);
+ }
+
+#define IS(ctype, jtype) \
+ template <> inline bool value::is<ctype>() const { \
+ return type_ == jtype##_type; \
+ }
+ IS(null, null)
+ IS(bool, boolean)
+#ifdef PICOJSON_USE_INT64
+ IS(int64_t, int64)
+#endif
+ IS(std::string, string)
+ IS(array, array)
+ IS(object, object)
+#undef IS
+ template <> inline bool value::is<double>() const {
+ return type_ == number_type
+#ifdef PICOJSON_USE_INT64
+ || type_ == int64_type
+#endif
+ ;
+ }
+
+#define GET(ctype, var) \
+ template <> inline const ctype& value::get<ctype>() const { \
+ PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" \
+ && is<ctype>()); \
+ return var; \
+ } \
+ template <> inline ctype& value::get<ctype>() { \
+ PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" \
+ && is<ctype>()); \
+ return var; \
+ }
+ GET(bool, u_.boolean_)
+ GET(std::string, *u_.string_)
+ GET(array, *u_.array_)
+ GET(object, *u_.object_)
+#ifdef PICOJSON_USE_INT64
+ GET(double, (type_ == int64_type && (const_cast<value*>(this)->type_ = number_type, const_cast<value*>(this)->u_.number_ = u_.int64_), u_.number_))
+ GET(int64_t, u_.int64_)
+#else
+ GET(double, u_.number_)
+#endif
+#undef GET
+
+ inline bool value::evaluate_as_boolean() const {
+ switch (type_) {
+ case null_type:
+ return false;
+ case boolean_type:
+ return u_.boolean_;
+ case number_type:
+ return u_.number_ != 0;
+ case string_type:
+ return ! u_.string_->empty();
+ default:
+ return true;
+ }
+ }
+
+ inline const value& value::get(size_t idx) const {
+ static value s_null;
+ PICOJSON_ASSERT(is<array>());
+ return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
+ }
+
+ inline value& value::get(size_t idx) {
+ static value s_null;
+ PICOJSON_ASSERT(is<array>());
+ return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
+ }
+
+ inline const value& value::get(const std::string& key) const {
+ static value s_null;
+ PICOJSON_ASSERT(is<object>());
+ object::const_iterator i = u_.object_->find(key);
+ return i != u_.object_->end() ? i->second : s_null;
+ }
+
+ inline value& value::get(const std::string& key) {
+ static value s_null;
+ PICOJSON_ASSERT(is<object>());
+ object::iterator i = u_.object_->find(key);
+ return i != u_.object_->end() ? i->second : s_null;
+ }
+
+ inline bool value::contains(size_t idx) const {
+ PICOJSON_ASSERT(is<array>());
+ return idx < u_.array_->size();
+ }
+
+ inline bool value::contains(const std::string& key) const {
+ PICOJSON_ASSERT(is<object>());
+ object::const_iterator i = u_.object_->find(key);
+ return i != u_.object_->end();
+ }
+
+ inline std::string value::to_str() const {
+ switch (type_) {
+ case null_type: return "null";
+ case boolean_type: return u_.boolean_ ? "true" : "false";
+#ifdef PICOJSON_USE_INT64
+ case int64_type: {
+ char buf[sizeof("-9223372036854775808")];
+ SNPRINTF(buf, sizeof(buf), "%" PRId64, u_.int64_);
+ return buf;
+ }
+#endif
+ case number_type: {
+ char buf[256];
+ double tmp;
+ SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.17g", u_.number_);
+#if PICOJSON_USE_LOCALE
+ char *decimal_point = localeconv()->decimal_point;
+ if (strcmp(decimal_point, ".") != 0) {
+ size_t decimal_point_len = strlen(decimal_point);
+ for (char *p = buf; *p != '\0'; ++p) {
+ if (strncmp(p, decimal_point, decimal_point_len) == 0) {
+ return std::string(buf, p) + "." + (p + decimal_point_len);
+ }
+ }
+ }
+#endif
+ return buf;
+ }
+ case string_type: return *u_.string_;
+ case array_type: {
+ std::string output;
+ for(auto i : get<array>()) {
+ if(i.is<std::string>())
+ output += "\"" + i.to_str() +"\",";
+ else
+ output+= i.to_str() + ",";
+ }
+ output = output.substr(0, output.length() - 1);
+ output = "[" + output + "]";
+ return output;
+ }
+ case object_type: {
+ std::string output;
+ for(auto i : get<object>()) {
+ output += "\""+ i.first + "\":" + i.second.to_str() + ",";
+ }
+ output = output.substr(0, output.length() - 1);
+ output = "{" + output + "}";
+ return output;
+ }
+ default: PICOJSON_ASSERT(0);
+#ifdef _MSC_VER
+ __assume(0);
+#endif
+ }
+ return std::string();
+ }
+
+ template <typename Iter> void copy(const std::string& s, Iter oi) {
+ std::copy(s.begin(), s.end(), oi);
+ }
+
+ template <typename Iter> void serialize_str(const std::string& s, Iter oi) {
+ *oi++ = '"';
+ for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
+ switch (*i) {
+#define MAP(val, sym) case val: copy(sym, oi); break
+ MAP('"', "\\\"");
+ MAP('\\', "\\\\");
+ MAP('/', "\\/");
+ MAP('\b', "\\b");
+ MAP('\f', "\\f");
+ MAP('\n', "\\n");
+ MAP('\r', "\\r");
+ MAP('\t', "\\t");
+#undef MAP
+ default:
+ if (static_cast<unsigned char>(*i) < 0x20 || *i == 0x7f) {
+ char buf[7];
+ SNPRINTF(buf, sizeof(buf), "\\u%04x", *i & 0xff);
+ copy(buf, buf + 6, oi);
+ } else {
+ *oi++ = *i;
+ }
+ break;
+ }
+ }
+ *oi++ = '"';
+ }
+
+ template <typename Iter> void value::serialize(Iter oi, bool prettify) const {
+ return _serialize(oi, prettify ? 0 : -1);
+ }
+
+ inline std::string value::serialize(bool prettify) const {
+ return _serialize(prettify ? 0 : -1);
+ }
+
+ template <typename Iter> void value::_indent(Iter oi, int indent) {
+ *oi++ = '\n';
+ for (int i = 0; i < indent * INDENT_WIDTH; ++i) {
+ *oi++ = ' ';
+ }
+ }
+
+ template <typename Iter> void value::_serialize(Iter oi, int indent) const {
+ switch (type_) {
+ case string_type:
+ serialize_str(*u_.string_, oi);
+ break;
+ case array_type: {
+ *oi++ = '[';
+ if (indent != -1) {
+ ++indent;
+ }
+ for (array::const_iterator i = u_.array_->begin();
+ i != u_.array_->end();
+ ++i) {
+ if (i != u_.array_->begin()) {
+ *oi++ = ',';
+ }
+ if (indent != -1) {
+ _indent(oi, indent);
+ }
+ i->_serialize(oi, indent);
+ }
+ if (indent != -1) {
+ --indent;
+ if (! u_.array_->empty()) {
+ _indent(oi, indent);
+ }
+ }
+ *oi++ = ']';
+ break;
+ }
+ case object_type: {
+ *oi++ = '{';
+ if (indent != -1) {
+ ++indent;
+ }
+ for (object::const_iterator i = u_.object_->begin();
+ i != u_.object_->end();
+ ++i) {
+ if (i != u_.object_->begin()) {
+ *oi++ = ',';
+ }
+ if (indent != -1) {
+ _indent(oi, indent);
+ }
+ serialize_str(i->first, oi);
+ *oi++ = ':';
+ if (indent != -1) {
+ *oi++ = ' ';
+ }
+ i->second._serialize(oi, indent);
+ }
+ if (indent != -1) {
+ --indent;
+ if (! u_.object_->empty()) {
+ _indent(oi, indent);
+ }
+ }
+ *oi++ = '}';
+ break;
+ }
+ default:
+ copy(to_str(), oi);
+ break;
+ }
+ if (indent == 0) {
+ *oi++ = '\n';
+ }
+ }
+
+ inline std::string value::_serialize(int indent) const {
+ std::string s;
+ _serialize(std::back_inserter(s), indent);
+ return s;
+ }
+
+ template <typename Iter> class input {
+ protected:
+ Iter cur_, end_;
+ int last_ch_;
+ bool ungot_;
+ int line_;
+ public:
+ input(const Iter& first, const Iter& last) : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {}
+ int getc() {
+ if (ungot_) {
+ ungot_ = false;
+ return last_ch_;
+ }
+ if (cur_ == end_) {
+ last_ch_ = -1;
+ return -1;
+ }
+ if (last_ch_ == '\n') {
+ line_++;
+ }
+ last_ch_ = *cur_ & 0xff;
+ ++cur_;
+ return last_ch_;
+ }
+ void ungetc() {
+ if (last_ch_ != -1) {
+ PICOJSON_ASSERT(! ungot_);
+ ungot_ = true;
+ }
+ }
+ Iter cur() const { return cur_; }
+ int line() const { return line_; }
+ void skip_ws() {
+ while (1) {
+ int ch = getc();
+ if (! (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
+ ungetc();
+ break;
+ }
+ }
+ }
+ bool expect(int expect) {
+ skip_ws();
+ if (getc() != expect) {
+ ungetc();
+ return false;
+ }
+ return true;
+ }
+ bool match(const std::string& pattern) {
+ for (std::string::const_iterator pi(pattern.begin());
+ pi != pattern.end();
+ ++pi) {
+ if (getc() != *pi) {
+ ungetc();
+ return false;
+ }
+ }
+ return true;
+ }
+ };
+
+ template<typename Iter> inline int _parse_quadhex(input<Iter> &in) {
+ int uni_ch = 0, hex;
+ for (int i = 0; i < 4; i++) {
+ if ((hex = in.getc()) == -1) {
+ return -1;
+ }
+ if ('0' <= hex && hex <= '9') {
+ hex -= '0';
+ } else if ('A' <= hex && hex <= 'F') {
+ hex -= 'A' - 0xa;
+ } else if ('a' <= hex && hex <= 'f') {
+ hex -= 'a' - 0xa;
+ } else {
+ in.ungetc();
+ return -1;
+ }
+ uni_ch = uni_ch * 16 + hex;
+ }
+ return uni_ch;
+ }
+
+ template<typename String, typename Iter> inline bool _parse_codepoint(String& out, input<Iter>& in) {
+ int uni_ch;
+ if ((uni_ch = _parse_quadhex(in)) == -1) {
+ return false;
+ }
+ if (0xd800 <= uni_ch && uni_ch <= 0xdfff) {
+ if (0xdc00 <= uni_ch) {
+ // a second 16-bit of a surrogate pair appeared
+ return false;
+ }
+ // first 16-bit of surrogate pair, get the next one
+ if (in.getc() != '\\' || in.getc() != 'u') {
+ in.ungetc();
+ return false;
+ }
+ int second = _parse_quadhex(in);
+ if (! (0xdc00 <= second && second <= 0xdfff)) {
+ return false;
+ }
+ uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff);
+ uni_ch += 0x10000;
+ }
+ if (uni_ch < 0x80) {
+ out.push_back(uni_ch);
+ } else {
+ if (uni_ch < 0x800) {
+ out.push_back(0xc0 | (uni_ch >> 6));
+ } else {
+ if (uni_ch < 0x10000) {
+ out.push_back(0xe0 | (uni_ch >> 12));
+ } else {
+ out.push_back(0xf0 | (uni_ch >> 18));
+ out.push_back(0x80 | ((uni_ch >> 12) & 0x3f));
+ }
+ out.push_back(0x80 | ((uni_ch >> 6) & 0x3f));
+ }
+ out.push_back(0x80 | (uni_ch & 0x3f));
+ }
+ return true;
+ }
+
+ template<typename String, typename Iter> inline bool _parse_string(String& out, input<Iter>& in) {
+ while (1) {
+ int ch = in.getc();
+ if (ch < ' ') {
+ in.ungetc();
+ return false;
+ } else if (ch == '"') {
+ return true;
+ } else if (ch == '\\') {
+ if ((ch = in.getc()) == -1) {
+ return false;
+ }
+ switch (ch) {
+#define MAP(sym, val) case sym: out.push_back(val); break
+ MAP('"', '\"');
+ MAP('\\', '\\');
+ MAP('/', '/');
+ MAP('b', '\b');
+ MAP('f', '\f');
+ MAP('n', '\n');
+ MAP('r', '\r');
+ MAP('t', '\t');
+#undef MAP
+ case 'u':
+ if (! _parse_codepoint(out, in)) {
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ } else {
+ out.push_back(ch);
+ }
+ }
+ return false;
+ }
+
+ template <typename Context, typename Iter> inline bool _parse_array(Context& ctx, input<Iter>& in) {
+ if (! ctx.parse_array_start()) {
+ return false;
+ }
+ size_t idx = 0;
+ if (in.expect(']')) {
+ return ctx.parse_array_stop(idx);
+ }
+ do {
+ if (! ctx.parse_array_item(in, idx)) {
+ return false;
+ }
+ idx++;
+ } while (in.expect(','));
+ return in.expect(']') && ctx.parse_array_stop(idx);
+ }
+
+ template <typename Context, typename Iter> inline bool _parse_object(Context& ctx, input<Iter>& in) {
+ if (! ctx.parse_object_start()) {
+ return false;
+ }
+ if (in.expect('}')) {
+ return true;
+ }
+ do {
+ std::string key;
+ if (! in.expect('"')
+ || ! _parse_string(key, in)
+ || ! in.expect(':')) {
+ return false;
+ }
+ if (! ctx.parse_object_item(in, key)) {
+ return false;
+ }
+ } while (in.expect(','));
+ return in.expect('}');
+ }
+
+ template <typename Iter> inline std::string _parse_number(input<Iter>& in) {
+ std::string num_str;
+ while (1) {
+ int ch = in.getc();
+ if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-'
+ || ch == 'e' || ch == 'E') {
+ num_str.push_back(ch);
+ } else if (ch == '.') {
+#if PICOJSON_USE_LOCALE
+ num_str += localeconv()->decimal_point;
+#else
+ num_str.push_back('.');
+#endif
+ } else {
+ in.ungetc();
+ break;
+ }
+ }
+ return num_str;
+ }
+
+ template <typename Context, typename Iter> inline bool _parse(Context& ctx, input<Iter>& in) {
+ in.skip_ws();
+ int ch = in.getc();
+ switch (ch) {
+#define IS(ch, text, op) case ch: \
+ if (in.match(text) && op) { \
+ return true; \
+ } else { \
+ return false; \
+ }
+ IS('n', "ull", ctx.set_null());
+ IS('f', "alse", ctx.set_bool(false));
+ IS('t', "rue", ctx.set_bool(true));
+#undef IS
+ case '"':
+ return ctx.parse_string(in);
+ case '[':
+ return _parse_array(ctx, in);
+ case '{':
+ return _parse_object(ctx, in);
+ default:
+ if (('0' <= ch && ch <= '9') || ch == '-') {
+ double f;
+ char *endp;
+ in.ungetc();
+ std::string num_str = _parse_number(in);
+ if (num_str.empty()) {
+ return false;
+ }
+#ifdef PICOJSON_USE_INT64
+ {
+ errno = 0;
+ intmax_t ival = strtoimax(num_str.c_str(), &endp, 10);
+ if (errno == 0
+ && std::numeric_limits<int64_t>::min() <= ival
+ && ival <= std::numeric_limits<int64_t>::max()
+ && endp == num_str.c_str() + num_str.size()) {
+ ctx.set_int64(ival);
+ return true;
+ }
+ }
+#endif
+ f = strtod(num_str.c_str(), &endp);
+ if (endp == num_str.c_str() + num_str.size()) {
+ ctx.set_number(f);
+ return true;
+ }
+ return false;
+ }
+ break;
+ }
+ in.ungetc();
+ return false;
+ }
+
+ class deny_parse_context {
+ public:
+ bool set_null() { return false; }
+ bool set_bool(bool) { return false; }
+#ifdef PICOJSON_USE_INT64
+ bool set_int64(int64_t) { return false; }
+#endif
+ bool set_number(double) { return false; }
+ template <typename Iter> bool parse_string(input<Iter>&) { return false; }
+ bool parse_array_start() { return false; }
+ template <typename Iter> bool parse_array_item(input<Iter>&, size_t) {
+ return false;
+ }
+ bool parse_array_stop(size_t) { return false; }
+ bool parse_object_start() { return false; }
+ template <typename Iter> bool parse_object_item(input<Iter>&, const std::string&) {
+ return false;
+ }
+ };
+
+ class default_parse_context {
+ protected:
+ value* out_;
+ public:
+ default_parse_context(value* out) : out_(out) {}
+ bool set_null() {
+ *out_ = value();
+ return true;
+ }
+ bool set_bool(bool b) {
+ *out_ = value(b);
+ return true;
+ }
+#ifdef PICOJSON_USE_INT64
+ bool set_int64(int64_t i) {
+ *out_ = value(i);
+ return true;
+ }
+#endif
+ bool set_number(double f) {
+ *out_ = value(f);
+ return true;
+ }
+ template<typename Iter> bool parse_string(input<Iter>& in) {
+ *out_ = value(string_type, false);
+ return _parse_string(out_->get<std::string>(), in);
+ }
+ bool parse_array_start() {
+ *out_ = value(array_type, false);
+ return true;
+ }
+ template <typename Iter> bool parse_array_item(input<Iter>& in, size_t) {
+ array& a = out_->get<array>();
+ a.push_back(value());
+ default_parse_context ctx(&a.back());
+ return _parse(ctx, in);
+ }
+ bool parse_array_stop(size_t) { return true; }
+ bool parse_object_start() {
+ *out_ = value(object_type, false);
+ return true;
+ }
+ template <typename Iter> bool parse_object_item(input<Iter>& in, const std::string& key) {
+ object& o = out_->get<object>();
+ default_parse_context ctx(&o[key]);
+ return _parse(ctx, in);
+ }
+ private:
+ default_parse_context(const default_parse_context&);
+ default_parse_context& operator=(const default_parse_context&);
+ };
+
+ class null_parse_context {
+ public:
+ struct dummy_str {
+ void push_back(int) {}
+ };
+ public:
+ null_parse_context() {}
+ bool set_null() { return true; }
+ bool set_bool(bool) { return true; }
+#ifdef PICOJSON_USE_INT64
+ bool set_int64(int64_t) { return true; }
+#endif
+ bool set_number(double) { return true; }
+ template <typename Iter> bool parse_string(input<Iter>& in) {
+ dummy_str s;
+ return _parse_string(s, in);
+ }
+ bool parse_array_start() { return true; }
+ template <typename Iter> bool parse_array_item(input<Iter>& in, size_t) {
+ return _parse(*this, in);
+ }
+ bool parse_array_stop(size_t) { return true; }
+ bool parse_object_start() { return true; }
+ template <typename Iter> bool parse_object_item(input<Iter>& in, const std::string&) {
+ return _parse(*this, in);
+ }
+ private:
+ null_parse_context(const null_parse_context&);
+ null_parse_context& operator=(const null_parse_context&);
+ };
+
+ // obsolete, use the version below
+ template <typename Iter> inline std::string parse(value& out, Iter& pos, const Iter& last) {
+ std::string err;
+ pos = parse(out, pos, last, &err);
+ return err;
+ }
+
+ template <typename Context, typename Iter> inline Iter _parse(Context& ctx, const Iter& first, const Iter& last, std::string* err) {
+ input<Iter> in(first, last);
+ if (! _parse(ctx, in) && err != NULL) {
+ char buf[64];
+ SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line());
+ *err = buf;
+ while (1) {
+ int ch = in.getc();
+ if (ch == -1 || ch == '\n') {
+ break;
+ } else if (ch >= ' ') {
+ err->push_back(ch);
+ }
+ }
+ }
+ return in.cur();
+ }
+
+ template <typename Iter> inline Iter parse(value& out, const Iter& first, const Iter& last, std::string* err) {
+ default_parse_context ctx(&out);
+ return _parse(ctx, first, last, err);
+ }
+
+ inline std::string parse(value& out, const std::string& s) {
+ std::string err;
+ parse(out, s.begin(), s.end(), &err);
+ return err;
+ }
+
+ inline std::string parse(value& out, std::istream& is) {
+ std::string err;
+ parse(out, std::istreambuf_iterator<char>(is.rdbuf()),
+ std::istreambuf_iterator<char>(), &err);
+ return err;
+ }
+
+ template <typename T> struct last_error_t {
+ static std::string s;
+ };
+ template <typename T> std::string last_error_t<T>::s;
+
+ inline void set_last_error(const std::string& s) {
+ last_error_t<bool>::s = s;
+ }
+
+ inline const std::string& get_last_error() {
+ return last_error_t<bool>::s;
+ }
+
+ inline bool operator==(const value& x, const value& y) {
+ if (x.is<null>())
+ return y.is<null>();
+#define PICOJSON_CMP(type) \
+ if (x.is<type>()) \
+ return y.is<type>() && x.get<type>() == y.get<type>()
+ PICOJSON_CMP(bool);
+ PICOJSON_CMP(double);
+ PICOJSON_CMP(std::string);
+ PICOJSON_CMP(array);
+ PICOJSON_CMP(object);
+#undef PICOJSON_CMP
+ PICOJSON_ASSERT(0);
+#ifdef _MSC_VER
+ __assume(0);
+#endif
+ return false;
+ }
+
+ inline bool operator!=(const value& x, const value& y) {
+ return ! (x == y);
+ }
+}
+
+namespace std {
+ template<> inline void swap(picojson::value& x, picojson::value& y)
+ {
+ x.swap(y);
+ }
+}
+
+inline std::istream& operator>>(std::istream& is, picojson::value& x)
+{
+ picojson::set_last_error(std::string());
+ std::string err = picojson::parse(x, is);
+ if (! err.empty()) {
+ picojson::set_last_error(err);
+ is.setstate(std::ios::failbit);
+ }
+ return is;
+}
+
+inline std::ostream& operator<<(std::ostream& os, const picojson::value& x)
+{
+ x.serialize(std::ostream_iterator<char>(os));
+ return os;
+}
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif
+
+#endif
diff --git a/lib/propertyinfo.hpp b/lib/propertyinfo.hpp
new file mode 100644
index 00000000..ae229a45
--- /dev/null
+++ b/lib/propertyinfo.hpp
@@ -0,0 +1,72 @@
+#ifndef PROPERTYINFO_H_
+#define PROPERTYINFO_H_
+
+#include "abstractpropertytype.h"
+
+class PropertyInfo
+{
+public:
+
+
+ /** PropertyInfo
+ *
+ **/
+ PropertyInfo(): mUpdateFrequency(0), mIsValid(false) {}
+
+ /** PropertyInfo
+ * @arg updateFrequency
+ * @arg zonesList
+ */
+ PropertyInfo(uint updateFreq, Zone::ZoneList zonesList)
+ :mUpdateFrequency(updateFreq), mZones(zonesList), mIsValid(true)
+ {
+
+ }
+
+
+ /** updateFrequency
+ * Maximum times per second a property is expected to update.
+ *
+ **/
+ uint updateFrequency()
+ {
+ return mUpdateFrequency;
+ }
+
+ /** zones
+ * Number of different zones supported by this property.
+ *
+ */
+ Zone::ZoneList zones()
+ {
+ return mZones;
+ }
+
+ /** isValid
+ * returns whether this PropertyInfo is valid
+ *
+ * default when you construct a PropertyInfo is false
+ **/
+ bool isValid()
+ {
+ return mIsValid;
+ }
+
+
+ /** invalid()
+ * returns instance of PropertyInfo that isn't valid
+ **/
+ static PropertyInfo invalid()
+ {
+ return PropertyInfo();
+ }
+
+private:
+
+ uint mUpdateFrequency;
+ Zone::ZoneList mZones;
+ bool mIsValid;
+};
+
+
+#endif
diff --git a/lib/superptr.hpp b/lib/superptr.hpp
new file mode 100644
index 00000000..2c9356d9
--- /dev/null
+++ b/lib/superptr.hpp
@@ -0,0 +1,95 @@
+#ifndef SUPERPTR_H_
+#define SUPERPTR_H_
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <memory>
+
+namespace amb {
+
+template<typename T> struct traits;
+
+template<>
+struct traits<GVariant> {
+ struct delete_functor {
+ void operator()(GVariant * p) const {
+ if (p != nullptr)
+ g_variant_unref(p);
+ }
+ };
+};
+
+template<>
+struct traits<GError> {
+ struct delete_functor {
+ void operator()(GError * p) const {
+ if (p != nullptr)
+ g_error_free(p);
+ }
+ };
+};
+
+template<>
+struct traits<GDBusProxy> {
+ struct delete_functor {
+ void operator()(GDBusProxy * p) const {
+ if (p != nullptr)
+ g_object_unref(p);
+ }
+ };
+};
+
+template<>
+struct traits<GVariantIter> {
+ struct delete_functor {
+ void operator()(GVariantIter * p) const {
+ if (p != nullptr)
+ g_variant_iter_free(p);
+ }
+ };
+};
+
+template<>
+struct traits<gchar> {
+ struct delete_functor {
+ void operator()(gchar * p) const {
+ if (p != nullptr)
+ g_free(p);
+ }
+ };
+};
+
+template <>
+struct traits<GDBusConnection> {
+ struct delete_functor {
+ void operator()(GDBusConnection* p) const {
+ if (p != nullptr)
+ g_dbus_connection_close_sync(p, nullptr, nullptr);
+ }
+ };
+};
+
+template<typename T> using super_ptr =
+ ::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)
+{
+ return super_ptr<T>(t);
+}
+
+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, [](T* ptr) { if(ptr) g_object_unref(ptr);});
+}
+
+}
+#endif
diff --git a/lib/timestamp.cpp b/lib/timestamp.cpp
new file mode 100644
index 00000000..33e01823
--- /dev/null
+++ b/lib/timestamp.cpp
@@ -0,0 +1,54 @@
+#include "timestamp.h"
+
+#include <time.h>
+#include <iostream>
+#include <chrono>
+
+double amb::currentTime()
+{
+ return Timestamp::instance()->currentTime();
+}
+
+amb::Timestamp* amb::Timestamp::mInstance = nullptr;
+
+amb::Timestamp::Timestamp()
+{
+ auto tm = std::chrono::system_clock::now();
+ auto tm2 = std::chrono::steady_clock::now();
+
+ double eTime = (std::chrono::duration_cast<std::chrono::milliseconds>(tm.time_since_epoch()).count() / 1000.00);
+ double sTime = (std::chrono::duration_cast<std::chrono::milliseconds>(tm2.time_since_epoch()).count() / 1000.00);
+
+ startTimeEpoch = eTime - sTime;
+}
+
+double amb::Timestamp::currentTime()
+{
+ auto tm = std::chrono::steady_clock::now();
+
+ double time = std::chrono::duration_cast<std::chrono::milliseconds>(tm.time_since_epoch()).count() / 1000.00;
+
+ return time;
+}
+
+double amb::Timestamp::epochTime(double time)
+{
+ return startTimeEpoch + time;
+}
+
+double amb::Timestamp::epochTime()
+{
+ auto tm = std::chrono::system_clock::now();
+
+ double time = std::chrono::duration_cast<std::chrono::milliseconds>(tm.time_since_epoch()).count() / 1000.00;
+
+ return time;
+}
+
+amb::Timestamp* amb::Timestamp::instance()
+{
+ if(!mInstance)
+ mInstance = new Timestamp();
+
+ return mInstance;
+}
diff --git a/lib/timestamp.h b/lib/timestamp.h
new file mode 100644
index 00000000..5300488b
--- /dev/null
+++ b/lib/timestamp.h
@@ -0,0 +1,31 @@
+#ifndef _TIMESTAMP_H___
+#define _TIMESTAMP_H___
+
+
+namespace amb {
+
+double currentTime();
+
+class Timestamp {
+protected:
+ Timestamp();
+
+public:
+
+ double currentTime();
+
+ double epochTime(double time);
+
+ double epochTime();
+
+public:
+ static Timestamp *instance();
+
+private:
+ double startTimeEpoch;
+ static Timestamp* mInstance;
+};
+
+}
+
+#endif
diff --git a/lib/uuidhelper.cpp b/lib/uuidhelper.cpp
new file mode 100644
index 00000000..6fbc9cf5
--- /dev/null
+++ b/lib/uuidhelper.cpp
@@ -0,0 +1,12 @@
+#include "uuidhelper.h"
+
+std::string amb::createUuid()
+{
+ uuid_t id;
+ uuid_generate_random(id);
+
+ char out[37];
+ uuid_unparse(id, out);
+
+ return out;
+}
diff --git a/lib/uuidhelper.h b/lib/uuidhelper.h
new file mode 100644
index 00000000..15bc55b9
--- /dev/null
+++ b/lib/uuidhelper.h
@@ -0,0 +1,17 @@
+#ifndef _UUIDHELPER__H_
+#define _UUIDHELPER__H_
+
+
+#include <uuid/uuid.h>
+#include <string>
+
+namespace amb
+{
+
+std::string createUuid();
+
+}
+
+
+#endif
+
diff --git a/lib/vehicleproperty.cpp b/lib/vehicleproperty.cpp
new file mode 100644
index 00000000..a78df284
--- /dev/null
+++ b/lib/vehicleproperty.cpp
@@ -0,0 +1,593 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "vehicleproperty.h"
+#include "listplusplus.h"
+#include "debugout.h"
+#include "mappropertytype.hpp"
+#include "superptr.hpp"
+#include <map>
+
+
+#define REGISTERPROPERTY(property, defaultValue) \
+ registerPropertyPriv(property, []() { return new property ## Type(defaultValue); });
+
+#define REGISTERPROPERTYWITHTYPE(property, type, defaultValue) \
+ registerPropertyPriv(property, []() { return new type(property, defaultValue); });
+
+using namespace std;
+
+std::map<VehicleProperty::Property, VehicleProperty::PropertyTypeFactoryCallback> VehicleProperty::registeredPropertyFactoryMap;
+
+std::unique_ptr<VehicleProperty> VehicleProperty::thereCanOnlyBeOne(nullptr);
+
+const char* ButtonEvents::W3C::Home = "home";
+const char* ButtonEvents::W3C::Back = "back";
+const char* ButtonEvents::W3C::Search = "search";
+const char* ButtonEvents::W3C::Call = "call";
+const char* ButtonEvents::W3C::EndCall = "end_call";
+const char* ButtonEvents::W3C::MediaPlay = "media_play";
+const char* ButtonEvents::W3C::MediaPause = "media_pause";
+const char* ButtonEvents::W3C::MediaPrevious = "media_previous";
+const char* ButtonEvents::W3C::MediaNext = "media_next";
+const char* ButtonEvents::W3C::VoiceRecognize = "voice_regocnize";
+const char* ButtonEvents::W3C::Enter = "enter";
+const char* ButtonEvents::W3C::Left = "left";
+const char* ButtonEvents::W3C::Right = "right";
+const char* ButtonEvents::W3C::Up = "up";
+const char* ButtonEvents::W3C::Down = "down";
+
+const char* Transmission::W3C::Park = "park";
+const char* Transmission::W3C::Reverse = "reverse";
+const char* Transmission::W3C::Neutral = "neutral";
+const char* Transmission::W3C::Low = "low";
+const char* Transmission::W3C::Drive = "drive";
+const char* Transmission::W3C::Overdrive = "overdrive";
+
+const char* Door::W3C::Closed = "closed";
+const char* Door::W3C::Open = "open";
+const char* Door::W3C::Ajar = "ajar";
+
+const char* Seat::W3C::Vacant = "vacant";
+const char* Seat::W3C::Child = "child";
+const char* Seat::W3C::Adult = "adult";
+
+const char* Seat::W3C::Pin = "pin";
+const char* Seat::W3C::Keyfob = "keyfob";
+const char* Seat::W3C::Bluetooth = "Bluetooth";
+const char* Seat::W3C::NFC = "NFC";
+const char* Seat::W3C::Fingerprint = "fingerprint";
+const char* Seat::W3C::Camera = "camera";
+const char* Seat::W3C::Voice = "voice";
+
+const char* HVAC::W3C::FloorPanel = "floorpanel";
+const char* HVAC::W3C::FloorDuct = "floorduct";
+const char* HVAC::W3C::Bilevel = "bilevel";
+const char* HVAC::W3C::DefrostFloor = "defrostfloor";
+
+const char* Drive::W3C::Auto = "auto";
+const char* Drive::W3C::Comfort = "comfort";
+const char* Drive::W3C::Sport = "sport";
+const char* Drive::W3C::Eco = "eco";
+const char* Drive::W3C::Manual = "manual";
+const char* Drive::W3C::Winter = "winter";
+
+const char * WiperSpeedSetting::W3C::Off = "off";
+const char * WiperSpeedSetting::W3C::Once = "once";
+const char * WiperSpeedSetting::W3C::Slowest = "slowest";
+const char * WiperSpeedSetting::W3C::Slow = "slow";
+const char * WiperSpeedSetting::W3C::Middle = "middle";
+const char * WiperSpeedSetting::W3C::Fast = "fast";
+const char * WiperSpeedSetting::W3C::Fastest = "fastest";
+const char * WiperSpeedSetting::W3C::Auto = "auto";
+
+const char * ConvertibleRoofW3C::Closed = "closed";
+const char * ConvertibleRoofW3C::Closing = "closing";
+const char * ConvertibleRoofW3C::Opened = "opened";
+const char * ConvertibleRoofW3C::Opening = "opening";
+
+const char * LaneDeparture::W3C::Off = "off";
+const char * LaneDeparture::W3C::Pause = "pause";
+const char * LaneDeparture::W3C::Running = "running";
+
+const char * Security::W3C::Alarmed = "alarmed";
+const char * Security::W3C::Armed = "armed";
+const char * Security::W3C::Disarmed = "disarmed";
+const char * Security::W3C::Prearmed = "prearmed";
+
+const char * ParkingBrake::W3C::Inactive = "inactive";
+const char * ParkingBrake::W3C::Active = "active";
+const char * ParkingBrake::W3C::Error = "error";
+
+const VehicleProperty::Property VehicleProperty::NoValue = "NoValue";
+const VehicleProperty::Property VehicleProperty::VehicleSpeed = "VehicleSpeed";
+const VehicleProperty::Property VehicleProperty::EngineSpeed = "EngineSpeed";
+const VehicleProperty::Property VehicleProperty::TransmissionShiftPosition = "TransmissionShiftPosition";
+const VehicleProperty::Property VehicleProperty::TransmissionGearPosition = "TransmissionGearPostion";
+const VehicleProperty::Property VehicleProperty::TransmissionMode = "TransmissionMode";
+const VehicleProperty::Property VehicleProperty::TransmissionModeW3C = "TransmissionModeW3C";
+const VehicleProperty::Property VehicleProperty::ThrottlePosition = "ThrottlePosition";
+const VehicleProperty::Property VehicleProperty::WheelBrake = "WheelBrake";
+const VehicleProperty::Property VehicleProperty::WheelBrakePressure = "WheelBrakePressure";
+const VehicleProperty::Property VehicleProperty::SteeringWheelAngle = "SteeringWheelAngle";
+const VehicleProperty::Property VehicleProperty::SteeringWheelAngleW3C = "SteeringWheelAngleW3C";
+const VehicleProperty::Property VehicleProperty::TurnSignal = "TurnSignal";
+const VehicleProperty::Property VehicleProperty::ClutchStatus = "ClutchStatus";
+const VehicleProperty::Property VehicleProperty::EngineOilPressure = "EngineOilPressure";
+const VehicleProperty::Property VehicleProperty::EngineCoolantTemperature = "EngineCoolantTemperature";
+const VehicleProperty::Property VehicleProperty::EngineCoolantLevel = "EngineCoolantLevel";
+const VehicleProperty::Property VehicleProperty::MachineGunTurretStatus = "MachineGunTurretStatus";
+const VehicleProperty::Property VehicleProperty::AccelerationX = "AccelerationX";
+const VehicleProperty::Property VehicleProperty::AccelerationY = "AccelerationY";
+const VehicleProperty::Property VehicleProperty::AccelerationZ = "AccelerationZ";
+const VehicleProperty::Property VehicleProperty::MassAirFlow = "MassAirFlow";
+[[deprecated("Deprecated in 0.14. Use ButtonEventW3C")]]
+const VehicleProperty::Property VehicleProperty::ButtonEvent = "ButtonEvent";
+const VehicleProperty::Property VehicleProperty::AirIntakeTemperature = "AirIntakeTemperature";
+const VehicleProperty::Property VehicleProperty::BatteryVoltage = "BatteryVoltage";
+const VehicleProperty::Property VehicleProperty::BatteryCurrent = "BatteryCurrent";
+const VehicleProperty::Property VehicleProperty::BatteryChargeLevel = "BatteryChargeLevel";
+const VehicleProperty::Property VehicleProperty::InteriorTemperature = "InteriorTemperature";
+const VehicleProperty::Property VehicleProperty::ExteriorTemperature = "ExteriorTemperature";
+const VehicleProperty::Property VehicleProperty::EngineOilTemperature = "EngineOilTemperature";
+const VehicleProperty::Property VehicleProperty::EngineOilLifeRemaining = "EngineOilLifeRemaining";
+const VehicleProperty::Property VehicleProperty::EngineOilChangeIndicator= "EngineOilChangeIndicator";
+const VehicleProperty::Property VehicleProperty::VIN = "VIN";
+const VehicleProperty::Property VehicleProperty::WMI = "WMI";
+const VehicleProperty::Property VehicleProperty::TirePressure = "TirePressure";
+const VehicleProperty::Property VehicleProperty::TirePressureLow = "TirePressureLow";
+const VehicleProperty::Property VehicleProperty::TireTemperature = "TireTemperature";
+const VehicleProperty::Property VehicleProperty::VehiclePowerMode = "VehiclePowerMode";
+const VehicleProperty::Property VehicleProperty::TripMeters = "TripMeters";
+const VehicleProperty::Property VehicleProperty::CruiseControlActive = "CruiseControlActive";
+const VehicleProperty::Property VehicleProperty::CruiseControlSpeed = "CruiseControlSpeed";
+const VehicleProperty::Property VehicleProperty::LightHead = "LightHead";
+const VehicleProperty::Property VehicleProperty::LightLeftTurn = "LightLeftTurn";
+const VehicleProperty::Property VehicleProperty::LightRightTurn = "LightRightTurn";
+const VehicleProperty::Property VehicleProperty::LightParking = "LightParking";
+const VehicleProperty::Property VehicleProperty::LightFog = "LightFog";
+const VehicleProperty::Property VehicleProperty::LightHazard= "LightHazard";
+const VehicleProperty::Property VehicleProperty::LightHighBeam = "LightHighBeam";
+const VehicleProperty::Property VehicleProperty::LightBrake= "LightBrake";
+const VehicleProperty::Property VehicleProperty::LightAutomatic= "LightAutomatic";
+const VehicleProperty::Property VehicleProperty::LightDynamicHighBeam= "LightDynamicHighBeam";
+const VehicleProperty::Property VehicleProperty::InteriorLightDriver = "InteriorLightDriver";
+const VehicleProperty::Property VehicleProperty::InteriorLightCenter = "InteriorLightCenter";
+const VehicleProperty::Property VehicleProperty::InteriorLightPassenger = "InteriorLightPassenger";
+const VehicleProperty::Property VehicleProperty::InteriorLightStatus = "InteriorLightStatus";
+const VehicleProperty::Property VehicleProperty::EngineLoad = "EngineLoad";
+const VehicleProperty::Property VehicleProperty::Horn = "Horn";
+const VehicleProperty::Property VehicleProperty::FuelLevel = "FuelLevel";
+const VehicleProperty::Property VehicleProperty::FuelConsumption = "FuelConsumption";
+const VehicleProperty::Property VehicleProperty::FuelRange = "FuelRange";
+const VehicleProperty::Property VehicleProperty::FuelEconomy = "FuelEconomy";
+const VehicleProperty::Property VehicleProperty::FuelAverageEconomy = "FuelAverageEconomy";
+const VehicleProperty::Property VehicleProperty::FuelAverageConsumption = "FuelAverageConsumption";
+const VehicleProperty::Property VehicleProperty::FuelConsumptionSinceRestart = "FuelConsumptionSinceRestart";
+const VehicleProperty::Property VehicleProperty::FuelTimeSinceRestart = "FuelTimeSinceRestart";
+const VehicleProperty::Property VehicleProperty::FuelType = "FuelType";
+const VehicleProperty::Property VehicleProperty::FuelPositionSide = "FuelPositionSide";
+const VehicleProperty::Property VehicleProperty::EngineOilRemaining = "EngineOilRemaining";
+const VehicleProperty::Property VehicleProperty::ExteriorBrightness = "ExteriorBrightness";
+const VehicleProperty::Property VehicleProperty::Latitude = "Latitude";
+const VehicleProperty::Property VehicleProperty::Longitude = "Longitude";
+const VehicleProperty::Property VehicleProperty::Direction = "Direction";
+const VehicleProperty::Property VehicleProperty::Altitude = "Altitude";
+const VehicleProperty::Property VehicleProperty::VehicleWidth = "VehicleWidth";
+const VehicleProperty::Property VehicleProperty::VehicleHeight = "VehicleHeight";
+const VehicleProperty::Property VehicleProperty::VehicleLength = "VehicleLength";
+const VehicleProperty::Property VehicleProperty::VehicleType = "VehicleType";
+const VehicleProperty::Property VehicleProperty::DoorsPerRow = "DoorsPerRow";
+const VehicleProperty::Property VehicleProperty::TransmissionGearType = "TransmissionGearType";
+const VehicleProperty::Property VehicleProperty::FrontWheelRadius = "FrontWheelRadius";
+const VehicleProperty::Property VehicleProperty::RearWheelRadius = "RearWheelRadius";
+const VehicleProperty::Property VehicleProperty::WheelTrack = "WheelTrack";
+const VehicleProperty::Property VehicleProperty::BrakePressure = "BrakePressure";
+const VehicleProperty::Property VehicleProperty::Odometer = "Odometer";
+const VehicleProperty::Property VehicleProperty::DistanceTotal = "DistanceTotal";
+const VehicleProperty::Property VehicleProperty::DistanceSinceStart = "DistanceSinceStart";
+const VehicleProperty::Property VehicleProperty::TransmissionFluidLevel = "TransmissionFluidLevel";
+const VehicleProperty::Property VehicleProperty::BrakeFluidLevel = "BrakeFluidLevel";
+const VehicleProperty::Property VehicleProperty::WasherFluidLevel = "WasherFluidLevel";
+const VehicleProperty::Property VehicleProperty::WasherFluidLevelLow = "WasherFluidLevelLow";
+const VehicleProperty::Property VehicleProperty::SecurityAlertStatus = "SecurityAlertStatus";
+const VehicleProperty::Property VehicleProperty::ParkingBrakeStatus = "ParkingBrakeStatus";
+const VehicleProperty::Property VehicleProperty::ParkingBrakeStatusW3C = "ParkingBrakeStatusW3C";
+const VehicleProperty::Property VehicleProperty::ParkingLightStatus = "ParkingLightStatus";
+const VehicleProperty::Property VehicleProperty::HazardLightStatus = "HazardLightStatus";
+const VehicleProperty::Property VehicleProperty::AirbagStatus = "AirbagStatus";
+const VehicleProperty::Property VehicleProperty::AirbagDeployed = "AirbagDeployed";
+const VehicleProperty::Property VehicleProperty::AirbagActivated = "AirbagActivated";
+const VehicleProperty::Property VehicleProperty::AntilockBrakingSystem = "AntilockBrakingSystem";
+const VehicleProperty::Property VehicleProperty::AntilockBrakingSystemEnabled = "AntilockBrakingSystemEnabled";
+const VehicleProperty::Property VehicleProperty::TractionControlSystem = "TractionControlSystem";
+const VehicleProperty::Property VehicleProperty::TractionControlSystemEnabled = "TractionControlSystemEnabled";
+const VehicleProperty::Property VehicleProperty::VehicleTopSpeedLimit = "VehicleTopSpeedLimit";
+const VehicleProperty::Property VehicleProperty::DoorStatus = "DoorStatus";
+const VehicleProperty::Property VehicleProperty::DoorStatusW3C = "DoorStatusW3C";
+const VehicleProperty::Property VehicleProperty::DoorLockStatus = "DoorLockStatus";
+const VehicleProperty::Property VehicleProperty::ChildLockStatus = "ChildLockStatus";
+const VehicleProperty::Property VehicleProperty::SeatBeltStatus = "SeatBeltStatus";
+const VehicleProperty::Property VehicleProperty::WindowLockStatus = "WindowLockStatus";
+const VehicleProperty::Property VehicleProperty::OccupantStatus = "OccupantStatus";
+const VehicleProperty::Property VehicleProperty::OccupantStatusW3C = "OccupantStatusW3C";
+const VehicleProperty::Property VehicleProperty::ObstacleDistance = "ObstacleDistance";
+const VehicleProperty::Property VehicleProperty::RainSensor = "RainSensor";
+const VehicleProperty::Property VehicleProperty::WindshieldWiper = "WindshieldWiper";
+const VehicleProperty::Property VehicleProperty::WindshieldWiperSpeed = "WindshieldWiperSpeed";
+const VehicleProperty::Property VehicleProperty::WindshieldWiperSetting = "WindshieldWiperSetting";
+const VehicleProperty::Property VehicleProperty::AirflowDirection = "AirflowDirection";
+const VehicleProperty::Property VehicleProperty::AirflowDirectionW3C = "AirflowDirectionW3C";
+const VehicleProperty::Property VehicleProperty::FanSpeed = "FanSpeed";
+const VehicleProperty::Property VehicleProperty::TargetTemperature = "TargetTemperature";
+const VehicleProperty::Property VehicleProperty::AirConditioning = "AirConditioning";
+const VehicleProperty::Property VehicleProperty::AirRecirculation = "AirRecirculation";
+const VehicleProperty::Property VehicleProperty::Heater = "Heater";
+const VehicleProperty::Property VehicleProperty::Defrost = "Defrost";
+const VehicleProperty::Property VehicleProperty::DefrostWindow = "DefrostWindow";
+const VehicleProperty::Property VehicleProperty::DefrostMirror = "DefrostMirror";
+const VehicleProperty::Property VehicleProperty::SteeringWheelHeater = "SteeringWheelHeater";
+const VehicleProperty::Property VehicleProperty::SeatHeater = "SeatHeater";
+const VehicleProperty::Property VehicleProperty::SeatCooler = "SeatCooler";
+const VehicleProperty::Property VehicleProperty::WindowStatus = "WindowStatus";
+const VehicleProperty::Property VehicleProperty::Sunroof = "Sunroof";
+const VehicleProperty::Property VehicleProperty::SunroofTilt = "SunroofTilt";
+const VehicleProperty::Property VehicleProperty::ConvertibleRoof = "ConvertibleRoof";
+const VehicleProperty::Property VehicleProperty::ConvertibleRoofStatus = "ConvertibleRoofStatus";
+const VehicleProperty::Property VehicleProperty::NightMode = "NightMode";
+const VehicleProperty::Property VehicleProperty::DrivingMode = "DrivingMode";
+const VehicleProperty::Property VehicleProperty::DrivingModeW3C = "DrivingModeW3C";
+const VehicleProperty::Property VehicleProperty::KeyId = "KeyId";
+const VehicleProperty::Property VehicleProperty::Language = "Language";
+const VehicleProperty::Property VehicleProperty::MeasurementSystem = "MeasurementSystem";
+const VehicleProperty::Property VehicleProperty::MirrorSettingPan = "MirrorSettingPan";
+const VehicleProperty::Property VehicleProperty::MirrorSettingTilt= "MirrorSettingTilt";
+const VehicleProperty::Property VehicleProperty::SteeringWheelPositionSlide = "SteeringWheelPositionSlide";
+const VehicleProperty::Property VehicleProperty::SteeringWheelPositionTilt = "SteeringWheelPositionTilt";
+const VehicleProperty::Property VehicleProperty::SeatPositionRecline = "SeatPositionRecline";
+const VehicleProperty::Property VehicleProperty::SeatPositionSlide = "SeatPositionSlide";
+const VehicleProperty::Property VehicleProperty::SeatPositionCushionHeight = "SeatPositionCushionHeight";
+const VehicleProperty::Property VehicleProperty::SeatPositionHeadrest = "SeatPositionHeadrest";
+const VehicleProperty::Property VehicleProperty::SeatPositionBackCushion = "SeatPositionBackCushion";
+const VehicleProperty::Property VehicleProperty::SeatPositionSideCushion = "SeatPositionSideCushion";
+const VehicleProperty::Property VehicleProperty::DashboardIllumination = "DashboardIllumination";
+const VehicleProperty::Property VehicleProperty::GeneratedVehicleSoundMode = "GeneratedVehicleSoundMode";
+const VehicleProperty::Property VehicleProperty::DriverId = "DriverId";
+const VehicleProperty::Property VehicleProperty::PowertrainTorque = "PowertrainTorque";
+const VehicleProperty::Property VehicleProperty::AcceleratorPedalPosition = "AcceleratorPedalPosition";
+const VehicleProperty::Property VehicleProperty::Chime = "Chime";
+const VehicleProperty::Property VehicleProperty::WheelTick = "WheelTick";
+const VehicleProperty::Property VehicleProperty::IgnitionTimeOn = "IgnitionTimeOn";
+const VehicleProperty::Property VehicleProperty::IgnitionTimeOff = "IgnitionTimeOff";
+const VehicleProperty::Property VehicleProperty::YawRate = "YawRate";
+const VehicleProperty::Property VehicleProperty::ButtonEventW3C = "ButtonEventW3C";
+const VehicleProperty::Property VehicleProperty::TransmissionOilWear = "TransmissionOilWear";
+const VehicleProperty::Property VehicleProperty::TransmissionOilTemperature = "TransmissionOilTemperature";
+const VehicleProperty::Property VehicleProperty::TransmissionClutchWear = "TransmissionClutchWear";
+const VehicleProperty::Property VehicleProperty::BrakePadWear = "BrakePadWear";
+const VehicleProperty::Property VehicleProperty::BrakeFluidLevelLow = "BrakeFluidLevelLow";
+const VehicleProperty::Property VehicleProperty::MalfunctionIndicatorOn = "MalfunctionIndicatorOn";
+const VehicleProperty::Property VehicleProperty::AccumulatedEngineRuntime = "AccumulatedEngineRuntime";
+const VehicleProperty::Property VehicleProperty::DistanceSinceCodeCleared = "DistanceSinceCodeCleared";
+const VehicleProperty::Property VehicleProperty::DistanceWithMILOn = "DistanceWithMILOn";
+const VehicleProperty::Property VehicleProperty::TimeRunMILOn = "TimeRunMILOn";
+const VehicleProperty::Property VehicleProperty::TimeTroubleCodeClear = "TimeTroubleCodeClear";
+const VehicleProperty::Property VehicleProperty::VehicleDriveMode = "VehicleDriveMode";
+const VehicleProperty::Property VehicleProperty::ActiveNoiseControlMode = "ActiveNoiseControlMode";
+const VehicleProperty::Property VehicleProperty::AvailableSounds = "AvailableSounds";
+const VehicleProperty::Property VehicleProperty::EngineSoundEnhancementMode = "EngineSoundEnhancementMode";
+const VehicleProperty::Property VehicleProperty::ElectronicStabilityControlEnabled = "ElectronicStabilityControlEnabled";
+const VehicleProperty::Property VehicleProperty::ElectronicStabilityControlEngaged = "ElectronicStabilityControlEngaged";
+const VehicleProperty::Property VehicleProperty::OccupantIdentificationType = "OccupantIdentificationType";
+const VehicleProperty::Property VehicleProperty::OccupantName = "OccupantName";
+const VehicleProperty::Property VehicleProperty::AtmosphericPressure = "AtmosphericPressure";
+const VehicleProperty::Property VehicleProperty::LaneDepartureStatus = "LaneDepartureStatus";
+const VehicleProperty::Property VehicleProperty::AlarmStatus = "AlarmStatus";
+
+PropertyList VehicleProperty::mCapabilities;
+PropertyList VehicleProperty::mCustomProperties;
+
+VehicleProperty::VehicleProperty()
+{
+ REGISTERPROPERTY( VehicleSpeed, 0);
+ REGISTERPROPERTY(EngineSpeed, 0);
+ REGISTERPROPERTY(TransmissionShiftPosition, Transmission::Neutral);
+ REGISTERPROPERTY(TransmissionGearPosition, Transmission::Neutral);
+ REGISTERPROPERTY(TransmissionMode, Transmission::Normal);
+ REGISTERPROPERTY(TransmissionModeW3C, "neutral");
+ REGISTERPROPERTY(ThrottlePosition, 0);
+ REGISTERPROPERTY(WheelBrake, false);
+ REGISTERPROPERTY(WheelBrakePressure, 0);
+ REGISTERPROPERTY(SteeringWheelAngle, 0);
+ REGISTERPROPERTY(SteeringWheelAngleW3C, 0);
+ REGISTERPROPERTY(TurnSignal, TurnSignals::Off);
+ REGISTERPROPERTY(ClutchStatus, false);
+ REGISTERPROPERTY(EngineOilPressure, 0);
+ REGISTERPROPERTY(EngineOilTemperature, 0);
+ REGISTERPROPERTY(EngineOilRemaining, 0);
+ REGISTERPROPERTY(EngineOilLifeRemaining, 0);
+ REGISTERPROPERTY(EngineOilChangeIndicator, false);
+ REGISTERPROPERTY(EngineCoolantTemperature, 0);
+ REGISTERPROPERTY(EngineCoolantLevel, 0);
+ REGISTERPROPERTY(MachineGunTurretStatus, false);
+ REGISTERPROPERTY(AccelerationX, 0);
+ REGISTERPROPERTY(AccelerationY, 0);
+ REGISTERPROPERTY(AccelerationZ, 0);
+ REGISTERPROPERTY(MassAirFlow, 0);
+ REGISTERPROPERTY(ButtonEvent, ButtonEvents::NoButton);
+ REGISTERPROPERTY(AirIntakeTemperature, 0)
+ REGISTERPROPERTY(BatteryVoltage, 0);
+ REGISTERPROPERTY(BatteryCurrent, 0);
+ REGISTERPROPERTY(BatteryChargeLevel, 0);
+ REGISTERPROPERTY(InteriorTemperature, 0);
+ REGISTERPROPERTY(ExteriorTemperature, 0);
+ REGISTERPROPERTY(VIN, "");
+ REGISTERPROPERTY(WMI, "");
+ REGISTERPROPERTY(TirePressure, 0);
+ REGISTERPROPERTY(TirePressureLow, false);
+ REGISTERPROPERTY(TireTemperature, 0);
+ REGISTERPROPERTY( VehiclePowerMode, Power::Off);
+ registerPropertyPriv(TripMeters, [](){
+ TripMetersType* t = new TripMetersType();
+ BasicPropertyType<uint16_t> v(0);
+ t->append(v);
+ return t;
+ });
+
+ REGISTERPROPERTY(CruiseControlActive, false);
+ REGISTERPROPERTY(CruiseControlSpeed, 0);
+ REGISTERPROPERTY(LightHead, false);
+ REGISTERPROPERTY(LightLeftTurn, false);
+ REGISTERPROPERTY(LightRightTurn, false);
+ REGISTERPROPERTY(LightParking, false);
+ REGISTERPROPERTY(LightFog, false);
+ REGISTERPROPERTY(LightHazard, false);
+ REGISTERPROPERTY(LightHighBeam, false);
+ REGISTERPROPERTY(LightBrake, false);
+ REGISTERPROPERTY(LightAutomatic, false);
+ REGISTERPROPERTY(LightDynamicHighBeam, false);
+ REGISTERPROPERTY(InteriorLightDriver, false);
+ REGISTERPROPERTY(InteriorLightPassenger, false);
+ REGISTERPROPERTY(InteriorLightCenter, false);
+ REGISTERPROPERTY(InteriorLightStatus, false);
+ REGISTERPROPERTY(EngineLoad, 0);
+ REGISTERPROPERTY(Horn, false);
+ REGISTERPROPERTY(FuelLevel, 0);
+ REGISTERPROPERTY(FuelRange, 0);
+ REGISTERPROPERTY(FuelConsumption, 0);
+ REGISTERPROPERTY(FuelEconomy, 0);
+ REGISTERPROPERTY(FuelAverageEconomy, 0);
+ REGISTERPROPERTY(FuelAverageConsumption, 0);
+ REGISTERPROPERTY(FuelConsumptionSinceRestart, 0);
+ REGISTERPROPERTY(FuelTimeSinceRestart, 0);
+ REGISTERPROPERTY(FuelType, Fuel::Unknown);
+ REGISTERPROPERTY(FuelPositionSide, Fuel::UnknownPosition);
+ REGISTERPROPERTY(ExteriorBrightness, 0);
+ REGISTERPROPERTY(VehicleWidth, 0);
+ REGISTERPROPERTY(VehicleHeight, 0);
+ REGISTERPROPERTY(VehicleLength, 0);
+ REGISTERPROPERTY(Latitude, 0);
+ REGISTERPROPERTY(Longitude, 0);
+ REGISTERPROPERTY(Altitude, 0);
+ REGISTERPROPERTY(Direction, 0);
+ REGISTERPROPERTY(VehicleType, Vehicle::Unknown);
+ registerPropertyPriv(DoorsPerRow, []() {
+ BasicPropertyType<uint16_t> d(0);
+ DoorsPerRowType* doors = new DoorsPerRowType();
+ doors->append(d);
+ return doors;
+ });
+ REGISTERPROPERTY(TransmissionGearType, Transmission::Unknown);
+ REGISTERPROPERTY(FrontWheelRadius, 0);
+ REGISTERPROPERTY(RearWheelRadius, 0);
+ REGISTERPROPERTY(WheelTrack, 0);
+ REGISTERPROPERTY(BrakePressure, 0);
+ REGISTERPROPERTY(Odometer, 0);
+ REGISTERPROPERTY(DistanceTotal, 0);
+ REGISTERPROPERTY(DistanceSinceStart, 0);
+ REGISTERPROPERTY(TransmissionFluidLevel, 0);
+ REGISTERPROPERTY(BrakeFluidLevel, 0);
+ REGISTERPROPERTY(WasherFluidLevel, 0);
+ REGISTERPROPERTY(WasherFluidLevelLow, false);
+ REGISTERPROPERTY(SecurityAlertStatus, Security::Idle);
+ REGISTERPROPERTY(ParkingBrakeStatus, false);
+ REGISTERPROPERTY(ParkingBrakeStatusW3C, "");
+ REGISTERPROPERTY(ParkingLightStatus, false);
+ REGISTERPROPERTY(HazardLightStatus, false);
+ /// TODO: deprecated in 0.14
+ REGISTERPROPERTY(AirbagStatus, Airbag::Inactive);
+ REGISTERPROPERTY(AirbagActivated, false);
+ REGISTERPROPERTY(AirbagDeployed, false);
+
+ REGISTERPROPERTY(AntilockBrakingSystem, false);
+ REGISTERPROPERTY(AntilockBrakingSystemEnabled, false);
+ REGISTERPROPERTY(TractionControlSystem, false);
+ REGISTERPROPERTY(TractionControlSystemEnabled, false);
+ REGISTERPROPERTY(VehicleTopSpeedLimit, 0);
+
+ REGISTERPROPERTY(DoorStatus, Door::Closed);
+ REGISTERPROPERTY(DoorStatusW3C, Door::W3C::Closed);
+ REGISTERPROPERTY(DoorLockStatus, false);
+ REGISTERPROPERTY(ChildLockStatus, false);
+ REGISTERPROPERTY(SeatBeltStatus, false);
+ /// TODO: deprecated in 0.14
+ REGISTERPROPERTY(OccupantStatus, Seat::Vacant);
+ REGISTERPROPERTY(OccupantStatusW3C, Seat::W3C::Vacant);
+ REGISTERPROPERTY(WindowLockStatus, false);
+ REGISTERPROPERTY(ObstacleDistance, 0);
+
+ REGISTERPROPERTY(RainSensor, 0);
+ REGISTERPROPERTY(WindshieldWiper, Window::Off);
+ REGISTERPROPERTY(WindshieldWiperSpeed, WiperSpeedSetting::W3C::Off);
+ REGISTERPROPERTY(WindshieldWiperSetting, WiperSpeedSetting::W3C::Off);
+ REGISTERPROPERTY(AirflowDirection, HVAC::Front);
+ REGISTERPROPERTY(AirflowDirectionW3C, HVAC::W3C::FloorPanel);
+ REGISTERPROPERTY(FanSpeed, 0);
+ REGISTERPROPERTY(TargetTemperature, 0);
+ REGISTERPROPERTY(AirConditioning, false);
+ REGISTERPROPERTY(AirRecirculation, false);
+ REGISTERPROPERTY(Heater, false);
+
+ REGISTERPROPERTY(Defrost, false);
+ REGISTERPROPERTY(DefrostWindow, false);
+ REGISTERPROPERTY(DefrostMirror, false);
+
+ REGISTERPROPERTY(SteeringWheelHeater, false);
+ REGISTERPROPERTY(SeatHeater, 0);
+ REGISTERPROPERTY(SeatCooler, false);
+ REGISTERPROPERTY(WindowStatus, 100);
+ REGISTERPROPERTY(Sunroof, 0);
+ REGISTERPROPERTY(SunroofTilt, 0);
+ REGISTERPROPERTY(ConvertibleRoof, false);
+ REGISTERPROPERTY(ConvertibleRoofStatus, "");
+
+ REGISTERPROPERTY(NightMode, false);
+ REGISTERPROPERTY(DrivingMode, Driving::None);
+ REGISTERPROPERTY(DrivingModeW3C, false);
+ REGISTERPROPERTY(KeyId, "");
+ REGISTERPROPERTY(Language, "");
+ REGISTERPROPERTY(MeasurementSystem, Measurement::Metric);
+ REGISTERPROPERTY(MirrorSettingPan, 0);
+ REGISTERPROPERTY(MirrorSettingTilt, 0);
+ REGISTERPROPERTY(SteeringWheelPositionSlide, 0);
+ REGISTERPROPERTY(SteeringWheelPositionTilt, 0);
+ REGISTERPROPERTY(SeatPositionRecline, 0);
+ REGISTERPROPERTY(SeatPositionSlide, 0);
+ REGISTERPROPERTY(SeatPositionCushionHeight, 0);
+ REGISTERPROPERTY(SeatPositionHeadrest, 0);
+ REGISTERPROPERTY(SeatPositionBackCushion, 0);
+ REGISTERPROPERTY(SeatPositionSideCushion, 0);
+ REGISTERPROPERTY(DashboardIllumination, 0);
+ REGISTERPROPERTY(GeneratedVehicleSoundMode, Vehicle::Normal);
+ REGISTERPROPERTY(DriverId, "");
+ REGISTERPROPERTY(PowertrainTorque, 0);
+ REGISTERPROPERTY(AcceleratorPedalPosition, 0);
+ REGISTERPROPERTY(Chime, false);
+ REGISTERPROPERTY(WheelTick, 0);
+ REGISTERPROPERTY(IgnitionTimeOff, 0);
+ REGISTERPROPERTY(IgnitionTimeOn, 0);
+ REGISTERPROPERTY(YawRate, 0);
+ registerPropertyPriv(ButtonEventW3C, [](){
+ ButtonEventW3CType* t = new ButtonEventW3CType();
+ std::string k;
+ StringPropertyType v;
+ t->append(k, v);
+ return t;
+ });
+ REGISTERPROPERTY(TransmissionOilWear, 0);
+ REGISTERPROPERTY(TransmissionOilTemperature, 0);
+ REGISTERPROPERTY(TransmissionClutchWear, 0);
+ REGISTERPROPERTY(BrakePadWear, 0);
+ REGISTERPROPERTY(BrakeFluidLevelLow, false);
+ REGISTERPROPERTY(MalfunctionIndicatorOn, false);
+ REGISTERPROPERTY(AccumulatedEngineRuntime, 0);
+ REGISTERPROPERTY(DistanceSinceCodeCleared, 0);
+ REGISTERPROPERTY(DistanceWithMILOn, 0);
+ REGISTERPROPERTY(TimeRunMILOn, 0);
+ REGISTERPROPERTY(TimeTroubleCodeClear, 0);
+ REGISTERPROPERTY(VehicleDriveMode, "");
+ REGISTERPROPERTY(ActiveNoiseControlMode, false);
+ registerPropertyPriv(AvailableSounds, [](){
+ AvailableSoundsType* t = new AvailableSoundsType();
+ StringPropertyType v;
+ t->append(v);
+ return t;
+ });
+ REGISTERPROPERTY(EngineSoundEnhancementMode, "");
+ REGISTERPROPERTY(ElectronicStabilityControlEnabled, false);
+ REGISTERPROPERTY(ElectronicStabilityControlEngaged, false);
+ REGISTERPROPERTY(OccupantIdentificationType, Seat::W3C::Pin);
+ REGISTERPROPERTY(OccupantName, "");
+ REGISTERPROPERTY(AtmosphericPressure, 0);
+ REGISTERPROPERTY(LaneDepartureStatus, "");
+ REGISTERPROPERTY(AlarmStatus, "");
+}
+
+void VehicleProperty::factory()
+{
+ if(!thereCanOnlyBeOne)
+ thereCanOnlyBeOne = amb::make_unique(new VehicleProperty());
+}
+
+PropertyList VehicleProperty::capabilities()
+{
+ return mCapabilities;
+}
+
+PropertyList VehicleProperty::customProperties()
+{
+ return mCustomProperties;
+}
+
+AbstractPropertyType* VehicleProperty::getPropertyTypeForPropertyNameValue(VehicleProperty::Property name, std::string value)
+{
+ if(registeredPropertyFactoryMap.count(name) > 0)
+ {
+ VehicleProperty::PropertyTypeFactoryCallback cb = registeredPropertyFactoryMap[name];
+ if ( cb != nullptr )
+ {
+ AbstractPropertyType* type = cb();
+ if(type == nullptr)
+ {
+ throw std::runtime_error("Cannot return NULL in a PropertyTypeFactory");
+ }
+
+ if(value != "" )
+ {
+ type->fromString(value);
+ }
+
+ return type;
+ }
+ }
+
+ DebugOut(DebugOut::Warning) << "Property not found: " << name << endl;
+
+ return nullptr;
+}
+
+bool VehicleProperty::registerProperty(VehicleProperty::Property name, VehicleProperty::PropertyTypeFactoryCallback factory)
+{
+ if(!contains(mCustomProperties,name))
+ {
+ mCustomProperties.push_back(name);
+
+ return registerPropertyPriv(name, factory);
+ }
+
+ return false;
+}
+
+bool VehicleProperty::registerPropertyPriv(VehicleProperty::Property name, VehicleProperty::PropertyTypeFactoryCallback factory)
+{
+ if(contains(mCapabilities,name))
+ {
+ DebugOut(0)<<__FUNCTION__<<" ERROR: property '"<<name<<"' already registered."<<endl;
+ return false;
+ }
+
+ registeredPropertyFactoryMap[name] = factory;
+ mCapabilities.push_back(name);
+
+ return true;
+
+}
+
+
+
diff --git a/lib/vehicleproperty.h b/lib/vehicleproperty.h
new file mode 100644
index 00000000..ced4a40f
--- /dev/null
+++ b/lib/vehicleproperty.h
@@ -0,0 +1,1151 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef VEHICLEPROPERTY_H
+#define VEHICLEPROPERTY_H
+
+#include "nullptr.h"
+#include <string>
+#include <list>
+#include <set>
+#include <sstream>
+#include <map>
+#include <functional>
+#include "abstractpropertytype.h"
+#include "mappropertytype.hpp"
+
+namespace ButtonEvents {
+enum ButtonEventType {
+ NoButton = 0,
+ PlayButton = 1,
+ SkipButton = 1 << 1,
+ PrevButton = 1 << 2,
+ PauseButton = 1 << 3,
+ Preset1Button = 1 << 4,
+ Preset2Button = 1 << 5,
+ Preset3Button = 1 << 6,
+ Preset4Button = 1 << 7,
+ StopButton = 1 << 8,
+ NavigateUpButton = 1 << 9,
+ NavigateDownButton = 1 << 10,
+ NavigateLeftButton = 1 << 11,
+ NavigateRightButton = 1 << 12
+};
+
+namespace W3C
+{
+extern const char* Home;
+extern const char* Back;
+extern const char* Search;
+extern const char* Call;
+extern const char* EndCall;
+extern const char* MediaPlay;
+extern const char* MediaNext;
+extern const char* MediaPrevious;
+extern const char* MediaPause;
+extern const char* VoiceRecognize;
+extern const char* Enter;
+extern const char* Left;
+extern const char* Right;
+extern const char* Up;
+extern const char* Down;
+}
+}
+
+namespace TurnSignals {
+enum TurnSignalType
+{
+ Off=0,
+ Right=1,
+ Left=2,
+ Hazard=3
+};
+}
+
+namespace Transmission {
+enum TransmissionPositions
+{
+ Neutral = 0,
+ First,
+ Second,
+ Third,
+ Forth,
+ Fifth,
+ Sixth,
+ Seventh,
+ Eighth,
+ Ninth,
+ Tenth,
+ CVT = 64,
+ Drive = 96,
+ Reverse = 128,
+ Park = 255
+
+};
+/** TODO: deprecate in 0.14. Replaced with Drive::Mode: **/
+enum Mode {
+ Normal=0,
+ Sports = 1,
+ Economy = 2,
+ OEMCustom1 = 3,
+ OEMCustom2 = 4
+};
+
+enum Type {
+ Unknown = -1,
+ Auto = 0,
+ Manual = 1,
+ CV = 2
+};
+
+namespace W3C
+{
+extern const char* Park;
+extern const char* Reverse;
+extern const char* Neutral;
+extern const char* Low;
+extern const char* Drive;
+extern const char* Overdrive;
+}
+}
+
+namespace Power {
+/**< Vehicle Power Modes
+ * Off = Vehicle is off and key is in the "off" position.
+ * Accessory1 = Vehicle is off and key is in Accessory1 position.
+ * Accessory2 = Vehicle is off and key is in Accessory2 position.
+ * Run = Vehichle is running. Key is in the running position.
+ */
+enum Modes
+{
+ Off = 0,
+ Accessory1 = 1,
+ Accessory2 = 2,
+ Run = 3
+};
+}
+
+namespace Fuel{
+enum Type
+{
+ Unknown = -1,
+ Gasoline = 0,
+ High_Octane,
+ Diesel,
+ Electric,
+ Hydrogen
+};
+
+enum RefuelPosition
+{
+ UnknownPosition = -1,
+ Left = 0,
+ Right,
+ Front,
+ Rear
+};
+}
+
+namespace Vehicle {
+enum Type
+{
+ Unknown = -1,
+ Sedan = 0,
+ Coupe,
+ Cabriole,
+ Roadster,
+ SUV,
+ Truck
+};
+enum SoundMode {
+ Normal = 0,
+ Quiet = 1,
+ Sportive = 2
+};
+}
+
+namespace Security {
+enum Status
+{
+ Idle = 0,
+ Armed,
+ AlarmDetected
+};
+
+namespace W3C
+{
+extern const char * Disarmed;
+extern const char * Prearmed;
+extern const char * Armed;
+extern const char * Alarmed;
+}
+
+}
+
+namespace Airbag {
+
+enum Status
+{
+ Inactive = 0,
+ Active,
+ Deployed
+};
+
+}
+
+namespace Door
+{
+enum Status
+{
+ Closed = 0,
+ Open,
+ Ajar
+};
+namespace W3C
+{
+extern const char * Closed;
+extern const char * Open;
+extern const char * Ajar;
+}
+}
+
+namespace Seat
+{
+
+enum Occupant
+{
+ Vacant = 0,
+ Child,
+ Adult
+};
+namespace W3C
+{
+extern const char * Vacant;
+extern const char * Child;
+extern const char * Adult;
+
+extern const char * Pin;
+extern const char * Keyfob;
+extern const char * Bluetooth;
+extern const char * NFC ;
+extern const char * Fingerprint;
+extern const char * Camera;
+extern const char * Voice;
+}
+
+
+}
+
+namespace Window
+{
+enum WiperSpeed
+{
+ Off = 0,
+ Slowest = 1,
+ Fastest = 5,
+ Auto = 10
+};
+}
+
+namespace ConvertibleRoofW3C
+{
+extern const char * Opened;
+extern const char * Opening;
+extern const char * Closed;
+extern const char * Closing;
+}
+
+namespace WiperSpeedSetting
+{
+namespace W3C
+{
+extern const char * Off;
+extern const char * Once;
+extern const char * Slowest;
+extern const char * Slow;
+extern const char * Middle;
+extern const char * Fast;
+extern const char * Fastest;
+extern const char * Auto;
+}
+}
+
+namespace HVAC
+{
+enum AirflowDirection
+{
+ FrontPanel=0,
+ FloorDuct = 1,
+ Front = 1 << 1,
+ Defroster = 1 << 2
+
+};
+
+namespace W3C
+{
+extern const char * FloorPanel;
+extern const char * FloorDuct;
+extern const char * Bilevel;
+extern const char * DefrostFloor;
+}
+}
+
+namespace Driving
+{
+enum Mode
+{
+ None = 0,
+ Driving
+};
+}
+
+namespace Drive
+{
+enum Mode {
+ Normal=0,
+ Sports = 1,
+ Economy = 2,
+ OEMCustom1 = 3,
+ OEMCustom2 = 4
+};
+
+namespace W3C
+{
+extern const char* Comfort;
+extern const char* Auto;
+extern const char* Sport;
+extern const char* Eco;
+extern const char* Manual;
+extern const char* Winter;
+}
+
+}
+
+namespace Measurement
+{
+enum Type
+{
+ Metric = 0,
+ ImperialUS = 1,
+ ImperialUK = 2
+};
+}
+
+namespace LaneDeparture
+{
+namespace W3C
+{
+extern const char * Off;
+extern const char * Pause;
+extern const char * Running;
+}
+}
+
+namespace ParkingBrake
+{
+namespace W3C
+{
+extern const char * Inactive;
+extern const char * Active;
+extern const char * Error;
+}
+}
+
+#include <boost/preprocessor/comma.hpp>
+
+#define PROPERTYTYPE(property, propertyType, baseClass, valueType) \
+ class propertyType : public baseClass { \
+ public: propertyType(): baseClass(property) {} \
+ propertyType(valueType val) : baseClass(property, val) {} \
+ using baseClass::operator=; \
+ };
+
+#define PROPERTYTYPE1(property, propertyType, baseClass, valueType) \
+ class propertyType : public baseClass { \
+ public: propertyType(): baseClass(#property) {} \
+ propertyType(valueType val) : baseClass(#property, val) {} \
+ };
+
+#define PROPERTYTYPEBASIC(property, valueType) \
+ class property ## Type : public BasicPropertyType<valueType> { \
+ public: property ## Type(): BasicPropertyType(property) {} \
+ property ## Type(valueType val) : BasicPropertyType(property, val) {} \
+ using BasicPropertyType<valueType>::operator=; \
+ };
+
+#define PROPERTYTYPEBASIC1(property, valueType) \
+ class property ## Type : public BasicPropertyType<valueType> { \
+ public: property ## Type(): BasicPropertyType( #property) {} \
+ property ## Type(valueType val) : BasicPropertyType(#property, val) {} \
+ };
+
+#define PROPERTYTYPENOVAL(property, propertyType, baseClass) \
+ class propertyType : public baseClass { \
+ public: propertyType(): baseClass(property) {} \
+ };
+
+class VehicleProperty;
+
+
+typedef std::vector<std::string> PropertyList;
+typedef std::set<std::string> PropertySet;
+
+class VehicleProperty
+{
+
+public:
+
+ /*!
+ * \brief factory constructs a static instance of VehicleProperty. This should be called once before VehicleProperty is used in the app
+ */
+ static void factory();
+
+ typedef std::string Property;
+
+ /*!
+ * \brief PropertyTypeFactoryCallback callback used to construct a AbstractPropertyType for a property
+ * \see registerProperty
+ */
+ typedef std::function<AbstractPropertyType* (void)> PropertyTypeFactoryCallback;
+
+ /// Various property types:
+
+ static const Property NoValue;
+
+ /**< Vehicle Velocity in km/h */
+ static const Property VehicleSpeed;
+ PROPERTYTYPE(VehicleSpeed, VehicleSpeedType, BasicPropertyType<uint16_t>, uint16_t)
+ //typedef BasicPropertyType<uint16_t> VehicleSpeedType;
+
+ /**< Engine Speed in rotations per minute */
+ static const Property EngineSpeed;
+ PROPERTYTYPE(EngineSpeed, EngineSpeedType, BasicPropertyType<uint16_t>, uint16_t)
+ //typedef BasicPropertyType<uint16_t> EngineSpeedType;
+
+ /**< Transmission Shift Position
+ * 0 = Neutral
+ * 1 = 1st
+ * 2 = 2nd
+ * ...
+ * 96 = Drive
+ * 128 = Reverse
+ * 255 = Park
+ */
+ static const Property TransmissionShiftPosition;
+ PROPERTYTYPE(TransmissionShiftPosition, TransmissionShiftPositionType,
+ BasicPropertyType<Transmission::TransmissionPositions>, Transmission::TransmissionPositions )
+ //typedef BasicPropertyType<Transmission::TransmissionPositions> TransmissionShiftPositionType;
+
+ /**< Transmission Gear Position
+ * 0 = Neutral
+ * 1 = 1st
+ * 2 = 2nd
+ * ...
+ * 64 = CVT
+ * 128 = Reverse
+ */
+ static const Property TransmissionGearPosition;
+ PROPERTYTYPE(TransmissionGearPosition, TransmissionGearPositionType,
+ BasicPropertyType<Transmission::TransmissionPositions>, Transmission::TransmissionPositions)
+ //typedef BasicPropertyType<Transmission::TransmissionPositions> TransmissionGearPositionType;
+
+ /// TODO: deprecate in 0.14. Replaced by Drive::Mode
+ static const Property TransmissionMode;
+ PROPERTYTYPE(TransmissionMode, TransmissionModeType,
+ BasicPropertyType<Transmission::Mode>, Transmission::Mode)
+ //typedef BasicPropertyType<Transmission::Mode> TransmissionModeType;
+
+ /**< TransmissionModeW3C
+ * see Transmission::W3C::Park, Transmission::W3C::Drive, etc
+ */
+ static const Property TransmissionModeW3C;
+ PROPERTYTYPE(TransmissionModeW3C, TransmissionModeW3CType, StringPropertyType, std::string)
+
+ /**< Throttle position 0-100% */
+ static const Property ThrottlePosition;
+ PROPERTYTYPE(ThrottlePosition, ThrottlePositionType, BasicPropertyType<uint16_t> , uint16_t)
+ //typedef BasicPropertyType<uint16_t> ThrottlePositionType;
+
+ /**< Wheel brake position. Engaged = true, Idle = false */
+ static const Property WheelBrake;
+ PROPERTYTYPE(WheelBrake, WheelBrakeType, BasicPropertyType<bool>, bool)
+ //typedef BasicPropertyType<bool> WheelBrakeType;
+
+ static const Property WheelBrakePressure;
+ PROPERTYTYPE(WheelBrakePressure, WheelBrakePressureType, BasicPropertyType<uint16_t>, uint16_t)
+ //typedef BasicPropertyType<uint16_t> WheelBrakePressureType;
+
+ /**< Steering wheel angle (0-359)
+ * TODO: Deprecate in 0.14. Replace with SteeringWheelAngleW3C
+ */
+ static const Property SteeringWheelAngle;
+ PROPERTYTYPE(SteeringWheelAngle, SteeringWheelAngleType, BasicPropertyType<uint16_t>, uint16_t)
+
+ /// TODO: Rename to "SteeringWheel" in 0.14
+ static const Property SteeringWheelAngleW3C;
+ PROPERTYTYPEBASIC(SteeringWheelAngleW3C, int16_t)
+
+ /**< 0=off, 1=right, 2=left, 3=hazard */
+ static const Property TurnSignal;
+ PROPERTYTYPEBASIC(TurnSignal, TurnSignals::TurnSignalType)
+
+ /**< Clutch pedal status 0=off, 1=on */
+ static const Property ClutchStatus;
+ PROPERTYTYPE(ClutchStatus, ClutchStatusType,BasicPropertyType<bool>,bool)
+
+ /**< Oil pressure TODO: units */
+ static const Property EngineOilPressure;
+ PROPERTYTYPE(EngineOilPressure, EngineOilPressureType, BasicPropertyType<uint16_t>, uint16_t)
+
+ /**< Engine coolant temperature in degrees celcius **/
+ static const Property EngineCoolantTemperature;
+ PROPERTYTYPEBASIC(EngineCoolantTemperature, int16_t)
+
+ static const Property EngineCoolantLevel;
+ PROPERTYTYPE(EngineCoolantLevel, EngineCoolantLevelType, BasicPropertyType<uint>, uint)
+
+ /**< 0=off, 1=on */
+ static const Property MachineGunTurretStatus;
+ PROPERTYTYPEBASIC(MachineGunTurretStatus, bool)
+
+ static const Property AccelerationX;
+ PROPERTYTYPEBASIC(AccelerationX, int16_t)
+
+ static const Property AccelerationY;
+ PROPERTYTYPEBASIC(AccelerationY, int16_t)
+
+ static const Property AccelerationZ;
+ PROPERTYTYPEBASIC(AccelerationZ, int16_t)
+
+ /**< Mass Air Flow. grams/sec */
+ static const Property MassAirFlow;
+ PROPERTYTYPE(MassAirFlow, MassAirFlowType, BasicPropertyType<uint16_t>, uint16_t)
+ //typedef BasicPropertyType<uint16_t> MassAirFlowType;
+
+ /**< Button Event @see ButtonEvents::ButtonEventType */
+ ///TODO: deprecated. Use ButtonEventW3C. Remove in 0.14
+ static const Property ButtonEvent;
+ PROPERTYTYPE(ButtonEvent, ButtonEventType, BasicPropertyType<ButtonEvents::ButtonEventType>, ButtonEvents::ButtonEventType)
+
+ static const Property ButtonEventW3C;
+ class ButtonEventW3CType: public MapPropertyType<StringPropertyType>
+ {
+ public:
+ ButtonEventW3CType() : MapPropertyType(ButtonEventW3C) {}
+ };
+
+
+ /**< Air intake temperature in degrees celcius */
+ static const Property AirIntakeTemperature;
+ PROPERTYTYPE(AirIntakeTemperature, AirIntakeTemperatureType, BasicPropertyType<int>, int)
+ //typedef BasicPropertyType<int> AirIntakeTemperatureType;
+
+ /**< Battery voltage in volts */
+ static const Property BatteryVoltage;
+ PROPERTYTYPE(BatteryVoltage, BatteryVoltageType, BasicPropertyType<double>, double)
+ //typedef BasicPropertyType<double> BatteryVoltageType;
+
+ static const Property BatteryCurrent;
+ PROPERTYTYPE(BatteryCurrent, BatteryCurrentType, BasicPropertyType<double>, double)
+ //typedef BasicPropertyType<double> BatteryCurrentType;
+
+ static const Property BatteryChargeLevel;
+ PROPERTYTYPEBASIC(BatteryChargeLevel, uint16_t)
+
+ /**< Interior Air Temperature in degrees celcius */
+ static const Property InteriorTemperature;
+ PROPERTYTYPE(InteriorTemperature, InteriorTemperatureType, BasicPropertyType<int>, int)
+ //typedef BasicPropertyType<int> InteriorTemperatureType;
+
+ static const Property ExteriorTemperature;
+ PROPERTYTYPE(ExteriorTemperature, ExteriorTemperatureType, BasicPropertyType<int>, int)
+ //typedef BasicPropertyType<int> ExteriorTemperatureType;
+
+ static const Property EngineOilTemperature;
+ PROPERTYTYPEBASIC(EngineOilTemperature, int)
+
+ static const Property EngineOilRemaining;
+ PROPERTYTYPEBASIC(EngineOilRemaining, uint16_t)
+
+ static const Property EngineOilLifeRemaining;
+ PROPERTYTYPEBASIC(EngineOilLifeRemaining, uint16_t)
+
+ static const Property EngineOilChangeIndicator;
+ PROPERTYTYPEBASIC(EngineOilChangeIndicator, bool)
+
+ /**< Vehicle Identification Number (ISO 3779) 17 chars**/
+ static const Property VIN;
+ PROPERTYTYPE(VIN, VINType, StringPropertyType, std::string)
+ //class VINType: public StringPropertyType { public: VINType(std::string val):StringPropertyType(VIN,val){} };
+
+ /**< World Manufacturer Identifier (SAE) 3 characters. */
+ static const Property WMI;
+ PROPERTYTYPE(WMI, WMIType, StringPropertyType, std::string)
+ //class WMIType: public StringPropertyType { public: WMIType(std::string val):StringPropertyType(WMI,val){} };
+
+ /**< Tire pressure in kPa */
+ static const Property TirePressure;
+ PROPERTYTYPEBASIC(TirePressure, uint16_t)
+
+ /**< Tire pressure low */
+ static const Property TirePressureLow;
+ PROPERTYTYPEBASIC(TirePressureLow, bool)
+
+ /**< Tire temperature in degrees C */
+ static const Property TireTemperature;
+ PROPERTYTYPEBASIC(TireTemperature, int16_t)
+
+ /**< Vehicle Power Mode.
+ *@see Power::Modes
+ */
+ static const Property VehiclePowerMode;
+ PROPERTYTYPE(VehiclePowerMode, VehiclePowerModeType, BasicPropertyType<Power::Modes>, Power::Modes)
+ //typedef BasicPropertyType<Power::PowerModes> VehiclePowerModeType;
+
+ static const Property TripMeters;
+ PROPERTYTYPE(TripMeters, TripMetersType, ListPropertyType<BasicPropertyType<uint16_t> >, uint16_t)
+ //typedef ListPropertyType<BasicPropertyType<uint16_t> > TripMetersType;
+
+ static const Property CruiseControlActive;
+ PROPERTYTYPE(CruiseControlActive, CruiseControlActiveType, BasicPropertyType<bool>, bool)
+ //typedef BasicPropertyType<bool> CruiseControlActiveType;
+
+ static const Property CruiseControlSpeed;
+ PROPERTYTYPE(CruiseControlSpeed, CruiseControlSpeedType, BasicPropertyType<uint16_t>, uint16_t)
+ //typedef BasicPropertyType<uint16_t> CruiseControlSpeedType;
+
+ static const Property LightHead;
+ PROPERTYTYPE(LightHead, LightHeadType, BasicPropertyType<bool>, bool)
+ static const Property LightRightTurn;
+ PROPERTYTYPE(LightRightTurn, LightRightTurnType, BasicPropertyType<bool>, bool)
+ static const Property LightLeftTurn;
+ PROPERTYTYPE(LightLeftTurn, LightLeftTurnType, BasicPropertyType<bool>, bool)
+ static const Property LightBrake;
+ PROPERTYTYPE(LightBrake, LightBrakeType, BasicPropertyType<bool>, bool)
+ static const Property LightFog;
+ PROPERTYTYPE(LightFog, LightFogType, BasicPropertyType<bool>, bool)
+ static const Property LightHazard;
+ PROPERTYTYPE(LightHazard, LightHazardType, BasicPropertyType<bool>, bool)
+ static const Property LightParking;
+ PROPERTYTYPE(LightParking, LightParkingType, BasicPropertyType<bool>, bool)
+ static const Property LightHighBeam;
+ PROPERTYTYPE(LightHighBeam, LightHighBeamType, BasicPropertyType<bool>, bool)
+ static const Property LightAutomatic;
+ PROPERTYTYPEBASIC(LightAutomatic, bool)
+ static const Property LightDynamicHighBeam;
+ PROPERTYTYPEBASIC(LightDynamicHighBeam, bool)
+
+ ///TODO: deprecated. Use InteriorLightStatus which is zoned. Remove in 0.14
+ static const Property InteriorLightDriver;
+ PROPERTYTYPE(InteriorLightDriver, InteriorLightDriverType, BasicPropertyType<bool>, bool)
+ ///TODO: deprecated. Use InteriorLightStatus which is zoned. Remove in 0.14
+ static const Property InteriorLightCenter;
+ PROPERTYTYPE(InteriorLightCenter, InteriorLightCenterType, BasicPropertyType<bool>, bool)
+ ///TODO: deprecated. Use InteriorLightStatus which is zoned. Remove in 0.14
+ static const Property InteriorLightPassenger;
+ PROPERTYTYPE(InteriorLightPassenger, InteriorLightPassengerType, BasicPropertyType<bool>, bool)
+
+ static const Property InteriorLightStatus;
+ PROPERTYTYPEBASIC(InteriorLightStatus, bool)
+
+ static const Property EngineLoad;
+ PROPERTYTYPE(EngineLoad, EngineLoadType, BasicPropertyType<uint16_t>, uint16_t)
+
+ static const Property Horn;
+ PROPERTYTYPE(Horn, HornType, BasicPropertyType<bool>, bool)
+
+ static const Property FuelLevel;
+ PROPERTYTYPE(FuelLevel, FuelLevelType, BasicPropertyType<uint16_t>, uint16_t)
+
+ static const Property FuelRange;
+ PROPERTYTYPE(FuelRange, FuelRangeType, BasicPropertyType<uint16_t> , uint16_t)
+
+ static const Property FuelConsumption;
+ PROPERTYTYPE(FuelConsumption, FuelConsumptionType, BasicPropertyType<uint>, uint)
+
+ static const Property FuelEconomy;
+ PROPERTYTYPE(FuelEconomy, FuelEconomyType, BasicPropertyType<uint16_t>, uint16_t)
+
+ static const Property FuelAverageEconomy;
+ PROPERTYTYPE(FuelAverageEconomy, FuelAverageEconomyType, BasicPropertyType<uint16_t> , uint16_t)
+
+ static const Property FuelAverageConsumption;
+ PROPERTYTYPEBASIC(FuelAverageConsumption, uint)
+
+ static const Property FuelTimeSinceRestart;
+ PROPERTYTYPEBASIC(FuelTimeSinceRestart, uint)
+
+ static const Property FuelConsumptionSinceRestart;
+ PROPERTYTYPEBASIC(FuelConsumptionSinceRestart, uint)
+
+ static const Property FuelType;
+ PROPERTYTYPE(FuelType, FuelTypeType, BasicPropertyType<Fuel::Type>, Fuel::Type)
+
+ static const Property FuelPositionSide;
+ PROPERTYTYPE(FuelPositionSide, FuelPositionSideType, BasicPropertyType<Fuel::RefuelPosition>, Fuel::RefuelPosition)
+
+ static const Property ExteriorBrightness;
+ PROPERTYTYPE(ExteriorBrightness, ExteriorBrightnessType, BasicPropertyType<uint16_t>, uint16_t)
+
+ static const Property Latitude;
+ PROPERTYTYPE(Latitude, LatitudeType, BasicPropertyType<double>, double)
+
+ static const Property Longitude;
+ PROPERTYTYPE(Longitude, LongitudeType, BasicPropertyType<double>, double)
+
+ static const Property Altitude;
+ PROPERTYTYPE(Altitude, AltitudeType, BasicPropertyType<double> , double)
+
+ static const Property Direction;
+ PROPERTYTYPE(Direction, DirectionType, BasicPropertyType<uint16_t>, uint16_t)
+
+ static const Property VehicleWidth;
+ PROPERTYTYPE(VehicleWidth, VehicleWidthType, BasicPropertyType<uint>, uint)
+ static const Property VehicleHeight;
+ PROPERTYTYPE(VehicleHeight, VehicleHeightType, BasicPropertyType<uint>, uint)
+ static const Property VehicleLength;
+ PROPERTYTYPE(VehicleLength, VehicleLengthType, BasicPropertyType<uint>, uint)
+
+ static const Property VehicleType;
+ PROPERTYTYPE(VehicleType, VehicleTypeType, BasicPropertyType<Vehicle::Type>, Vehicle::Type)
+
+ static const Property DoorsPerRow;
+ PROPERTYTYPE(DoorsPerRow, DoorsPerRowType, ListPropertyType<BasicPropertyType<uint16_t> >, uint16_t)
+
+ static const Property TransmissionGearType;
+ PROPERTYTYPE(TransmissionGearType, TransmissionGearTypeType, BasicPropertyType<Transmission::Type>, Transmission::Type)
+
+ static const Property FrontWheelRadius;
+ PROPERTYTYPE(FrontWheelRadius, FrontWheelRadiusType, BasicPropertyType<uint16_t>, uint16_t)
+ static const Property RearWheelRadius;
+ PROPERTYTYPE(RearWheelRadius, RearWheelRadiusType, BasicPropertyType<uint16_t>, uint16_t)
+
+ static const Property WheelTrack;
+ PROPERTYTYPE(WheelTrack, WheelTrackType, BasicPropertyType<uint>, uint)
+
+ static const Property BrakePressure;
+ PROPERTYTYPEBASIC(BrakePressure, uint16_t)
+
+ /// TODO: deprecated. remove in 0.14. Use DistanceTotal
+ static const Property Odometer;
+ PROPERTYTYPEBASIC(Odometer, uint)
+
+ static const Property DistanceTotal;
+ PROPERTYTYPEBASIC(DistanceTotal, uint)
+
+ static const Property DistanceSinceStart;
+ PROPERTYTYPEBASIC(DistanceSinceStart, uint)
+
+ /**< Transmission Fluid Level 0-100%.
+ **/
+ static const Property TransmissionFluidLevel;
+ PROPERTYTYPEBASIC(TransmissionFluidLevel, uint16_t)
+
+ static const Property TransmissionOilWear;
+ PROPERTYTYPEBASIC(TransmissionOilWear, uint16_t)
+
+ static const Property TransmissionOilTemperature;
+ PROPERTYTYPEBASIC(TransmissionOilTemperature, int16_t)
+
+ static const Property TransmissionClutchWear;
+ PROPERTYTYPEBASIC(TransmissionClutchWear, uint16_t)
+
+ /**< Brake Fluid Level 0-100%.
+ **/
+ static const Property BrakeFluidLevel;
+ PROPERTYTYPEBASIC(BrakeFluidLevel, uint16_t)
+
+ /**< Washer Fluid Level 0-100%.
+ **/
+ static const Property WasherFluidLevel;
+ PROPERTYTYPEBASIC(WasherFluidLevel, uint16_t)
+
+ static const Property WasherFluidLevelLow;
+ PROPERTYTYPEBASIC(WasherFluidLevelLow, bool)
+
+ ///TODO: Depreciated in 0.14. Use AlarmStatus
+ static const Property SecurityAlertStatus;
+ PROPERTYTYPEBASIC(SecurityAlertStatus, Security::Status)
+
+ /**< Parking Brake Status
+ * status of parking break active (true) or inactive (false)
+ * TODO: Deprecated in 0.14.
+ */
+ static const Property ParkingBrakeStatus;
+ PROPERTYTYPEBASIC(ParkingBrakeStatus, bool)
+
+ /*!
+ * \brief ParkingBrakeStatusW3C use with ParkingBrake::W3C::*
+ */
+ static const Property ParkingBrakeStatusW3C;
+ PROPERTYTYPE(ParkingBrakeStatusW3C, ParkingBrakeStatusW3CType, StringPropertyType, std::string)
+
+ /**< Parking Light Status
+ * status of parking lights active (true) or inactive (false)
+ */
+ static const Property ParkingLightStatus;
+ PROPERTYTYPEBASIC(ParkingLightStatus,bool)
+
+ /**< Hazard Lights Status
+ * status of parking lights active (true) or inactive (false)
+ */
+ static const Property HazardLightStatus;
+ PROPERTYTYPEBASIC(HazardLightStatus, bool)
+
+ static const Property AntilockBrakingSystem;
+ PROPERTYTYPEBASIC(AntilockBrakingSystem, bool)
+
+ static const Property AntilockBrakingSystemEnabled;
+ PROPERTYTYPEBASIC(AntilockBrakingSystemEnabled, bool)
+
+ static const Property TractionControlSystem;
+ PROPERTYTYPEBASIC(TractionControlSystem, bool)
+
+ static const Property TractionControlSystemEnabled;
+ PROPERTYTYPEBASIC(TractionControlSystemEnabled, bool)
+
+ static const Property VehicleTopSpeedLimit;
+ PROPERTYTYPEBASIC(VehicleTopSpeedLimit,uint16_t)
+
+ ///TODO: Deprecated in 0.14
+ static const Property AirbagStatus;
+ PROPERTYTYPEBASIC(AirbagStatus, Airbag::Status)
+
+ static const Property AirbagActivated;
+ PROPERTYTYPEBASIC(AirbagActivated, bool)
+
+ static const Property AirbagDeployed;
+ PROPERTYTYPEBASIC(AirbagDeployed, bool)
+
+ /// TODO: deprecate in 0.14. Use DoorStatusW3C
+ static const Property DoorStatus;
+ PROPERTYTYPEBASIC(DoorStatus, Door::Status)
+
+ /*!
+ * \brief DoorStatusW3C
+ * use with Door::W3C::*
+ */
+ static const Property DoorStatusW3C;
+ PROPERTYTYPE(DoorStatusW3C, DoorStatusW3CType, StringPropertyType, std::string)
+
+ static const Property DoorLockStatus;
+ PROPERTYTYPEBASIC(DoorLockStatus, bool)
+
+ static const Property ChildLockStatus;
+ PROPERTYTYPEBASIC(ChildLockStatus, bool)
+
+ static const Property SeatBeltStatus;
+ PROPERTYTYPEBASIC(SeatBeltStatus, bool)
+
+ static const Property WindowLockStatus;
+ PROPERTYTYPEBASIC(WindowLockStatus, bool)
+
+ ///TODO Deprecated in 0.14
+ static const Property OccupantStatus;
+ PROPERTYTYPEBASIC(OccupantStatus, Seat::Occupant)
+
+ static const Property OccupantStatusW3C;
+ PROPERTYTYPE(OccupantStatusW3C, OccupantStatusW3CType, StringPropertyType, std::string)
+
+ static const Property ObstacleDistance;
+ PROPERTYTYPEBASIC(ObstacleDistance, double)
+
+ static const Property RainSensor;
+ PROPERTYTYPEBASIC(RainSensor, uint16_t)
+
+ ///TODO Deprecated in 0.14. Use WinshieldWiperSpeed
+ static const Property WindshieldWiper;
+ PROPERTYTYPEBASIC(WindshieldWiper, Window::WiperSpeed)
+
+ /*!
+ * \brief WindshieldWiperSpeed
+ * Use WiperSpeedSetting::W3C::* for value
+ */
+ static const Property WindshieldWiperSpeed;
+ PROPERTYTYPE(WindshieldWiperSpeed, WindshieldWiperSpeedType, StringPropertyType, std::string)
+
+ /*!
+ * \brief WindshieldWiperSetting
+ * Use WiperSpeedSetting::W3C::* for value
+ */
+ static const Property WindshieldWiperSetting;
+ PROPERTYTYPE(WindshieldWiperSetting, WindshieldWiperSettingType, StringPropertyType, std::string)
+
+ /// TODO: Deprecated. Remove in 0.14
+ static const Property AirflowDirection;
+ PROPERTYTYPEBASIC(AirflowDirection,HVAC::AirflowDirection)
+
+ static const Property AirflowDirectionW3C;
+ PROPERTYTYPE(AirflowDirectionW3C, AirflowDirectionW3CType, StringPropertyType, std::string)
+
+ static const Property FanSpeed;
+ PROPERTYTYPEBASIC(FanSpeed, uint16_t)
+
+ static const Property TargetTemperature;
+ PROPERTYTYPEBASIC(TargetTemperature, int)
+
+ static const Property AirConditioning;
+ PROPERTYTYPEBASIC(AirConditioning,bool)
+
+ static const Property AirRecirculation;
+ PROPERTYTYPEBASIC(AirRecirculation,bool)
+
+ static const Property Heater;
+ PROPERTYTYPEBASIC(Heater, bool)
+
+ /// TODO: deprecated. remove in 0.14
+ static const Property Defrost;
+ PROPERTYTYPEBASIC(Defrost, bool )
+
+ static const Property DefrostWindow;
+ PROPERTYTYPEBASIC(DefrostWindow, bool )
+
+ static const Property DefrostMirror;
+ PROPERTYTYPEBASIC(DefrostMirror, bool )
+
+ static const Property SteeringWheelHeater;
+ PROPERTYTYPEBASIC(SteeringWheelHeater,bool)
+ //typedef BasicPropertyType<bool> SteeringWheelHeaterType;
+
+ static const Property SeatHeater;
+ PROPERTYTYPEBASIC(SeatHeater,int)
+ //typedef BasicPropertyType<bool> SeatHeaterType;
+
+ static const Property SeatCooler;
+ PROPERTYTYPEBASIC(SeatCooler,bool)
+// /typedef BasicPropertyType<bool> SeatCoolerType;
+
+ static const Property WindowStatus;
+ PROPERTYTYPEBASIC(WindowStatus, uint16_t)
+
+ static const Property Sunroof;
+ PROPERTYTYPEBASIC(Sunroof, uint16_t)
+ //typedef BasicPropertyType<uint16_t> SunroofType;
+
+ static const Property SunroofTilt;
+ PROPERTYTYPEBASIC(SunroofTilt,uint16_t)
+ //typedef BasicPropertyType<uint16_t> SunroofTiltType;
+
+ static const Property ConvertibleRoof;
+ PROPERTYTYPEBASIC(ConvertibleRoof, bool)
+
+ /*!
+ * \brief ConvertibleRoofStatus use with ConvertibleRoofW3C::*
+ */
+ static const Property ConvertibleRoofStatus;
+ PROPERTYTYPE(ConvertibleRoofStatus, ConvertibleRoofStatusType, StringPropertyType, std::string)
+
+ static const Property NightMode;
+ PROPERTYTYPEBASIC(NightMode, bool)
+
+ static const Property DrivingMode;
+ PROPERTYTYPEBASIC(DrivingMode, Driving::Mode)
+
+ static const Property DrivingModeW3C;
+ PROPERTYTYPEBASIC(DrivingModeW3C, bool)
+
+ static const Property KeyId;
+ PROPERTYTYPE(KeyId, KeyIdType, StringPropertyType, std::string)
+
+ static const Property Language;
+ PROPERTYTYPE(Language, LanguageType, StringPropertyType, std::string)
+
+ static const Property MeasurementSystem;
+ PROPERTYTYPEBASIC(MeasurementSystem, Measurement::Type)
+
+ static const Property MirrorSettingPan;
+ static const Property MirrorSettingTilt;
+
+ PROPERTYTYPEBASIC(MirrorSettingPan, uint16_t)
+ PROPERTYTYPEBASIC(MirrorSettingTilt, uint16_t)
+
+ static const Property SteeringWheelPositionSlide;
+ static const Property SteeringWheelPositionTilt;
+
+ PROPERTYTYPEBASIC(SteeringWheelPositionSlide, uint16_t)
+ PROPERTYTYPEBASIC(SteeringWheelPositionTilt, uint16_t)
+
+ static const Property SeatPositionRecline;
+ static const Property SeatPositionSlide;
+ static const Property SeatPositionCushionHeight;
+ static const Property SeatPositionHeadrest;
+ static const Property SeatPositionBackCushion;
+ static const Property SeatPositionSideCushion;
+
+ PROPERTYTYPEBASIC(SeatPositionRecline, uint16_t)
+ PROPERTYTYPEBASIC(SeatPositionSlide, uint16_t)
+ PROPERTYTYPEBASIC(SeatPositionCushionHeight, uint16_t)
+ PROPERTYTYPEBASIC(SeatPositionHeadrest, uint16_t)
+ PROPERTYTYPEBASIC(SeatPositionBackCushion, uint16_t)
+ PROPERTYTYPEBASIC(SeatPositionSideCushion, uint16_t)
+
+ static const Property DashboardIllumination;
+ PROPERTYTYPEBASIC(DashboardIllumination, uint16_t)
+
+ static const Property GeneratedVehicleSoundMode;
+ PROPERTYTYPEBASIC(GeneratedVehicleSoundMode, Vehicle::SoundMode)
+
+ static const Property DriverId;
+ PROPERTYTYPE(DriverId, DriverIdType, StringPropertyType, std::string)
+
+ static const Property PowertrainTorque;
+ PROPERTYTYPEBASIC(PowertrainTorque, uint16_t)
+
+ static const Property AcceleratorPedalPosition;
+ PROPERTYTYPEBASIC(AcceleratorPedalPosition, uint16_t)
+
+ static const Property Chime;
+ PROPERTYTYPEBASIC(Chime, bool)
+
+ static const Property WheelTick;
+ PROPERTYTYPEBASIC(WheelTick, uint)
+
+ static const Property IgnitionTimeOn;
+ PROPERTYTYPEBASIC(IgnitionTimeOn, uint64_t)
+
+ static const Property IgnitionTimeOff;
+ PROPERTYTYPEBASIC(IgnitionTimeOff, uint64_t)
+
+ static const Property YawRate;
+ PROPERTYTYPEBASIC(YawRate, int16_t)
+
+ static const Property BrakePadWear;
+ PROPERTYTYPEBASIC(BrakePadWear, uint16_t)
+
+ static const Property BrakeFluidLevelLow;
+ PROPERTYTYPEBASIC(BrakeFluidLevelLow, bool)
+
+ static const Property BrakesWorn;
+ PROPERTYTYPEBASIC(BrakesWorn, bool)
+
+ static const Property MalfunctionIndicatorOn;
+ PROPERTYTYPEBASIC(MalfunctionIndicatorOn, bool)
+
+ static const Property AccumulatedEngineRuntime;
+ PROPERTYTYPEBASIC(AccumulatedEngineRuntime, uint32_t)
+
+ static const Property DistanceSinceCodeCleared;
+ PROPERTYTYPEBASIC(DistanceSinceCodeCleared, uint32_t)
+
+ static const Property DistanceWithMILOn;
+ PROPERTYTYPEBASIC(DistanceWithMILOn, uint32_t)
+
+ static const Property TimeRunMILOn;
+ PROPERTYTYPEBASIC(TimeRunMILOn, uint32_t)
+
+ static const Property TimeTroubleCodeClear;
+ PROPERTYTYPEBASIC(TimeTroubleCodeClear, uint32_t)
+
+ static const Property VehicleDriveMode;
+ PROPERTYTYPE(VehicleDriveMode, VehicleDriveModeType, StringPropertyType, std::string)
+
+ static const Property ActiveNoiseControlMode;
+ PROPERTYTYPEBASIC(ActiveNoiseControlMode, bool)
+
+ static const Property AvailableSounds;
+ PROPERTYTYPE(AvailableSounds, AvailableSoundsType, ListPropertyType<StringPropertyType>, StringPropertyType)
+
+ static const Property EngineSoundEnhancementMode;
+ PROPERTYTYPE(EngineSoundEnhancementMode, EngineSoundEnhancementModeType, StringPropertyType, std::string)
+
+ static const Property ElectronicStabilityControlEnabled;
+ PROPERTYTYPEBASIC(ElectronicStabilityControlEnabled, bool)
+
+ static const Property ElectronicStabilityControlEngaged;
+ PROPERTYTYPEBASIC(ElectronicStabilityControlEngaged, bool)
+
+ static const Property OccupantIdentificationType;
+ PROPERTYTYPE(OccupantIdentificationType, OccupantIdentificationTypeType, StringPropertyType, std::string)
+
+ static const Property OccupantName;
+ PROPERTYTYPE(OccupantName, OccupantNameType, StringPropertyType, std::string)
+
+ static const Property AtmosphericPressure;
+ PROPERTYTYPEBASIC(AtmosphericPressure, uint16_t)
+
+ static const Property LaneDepartureStatus;
+ PROPERTYTYPE(LaneDepartureStatus, LaneDepartureStatusType, StringPropertyType, std::string)
+
+ /*!
+ * \brief AlarmStatus. Use with Security::W3C*
+ */
+ static const Property AlarmStatus;
+ PROPERTYTYPE(AlarmStatus, AlarmStatusType, StringPropertyType, std::string)
+
+ //static const Property Lane
+
+ /** END PROPERTIES **/
+
+ /*!
+ * \brief capabilities
+ * \return returns list of all registered properties
+ * \see VehicleProperty::registerProperty
+ */
+ static PropertyList capabilities();
+
+ /*!
+ * \brief customProperties
+ * \return returns list of custom properties defined by plugins using VehicleProperty::registerProperty
+ */
+ static PropertyList customProperties();
+
+ /*! \brief getPropertyTypeForPropertyNameValue returns an AbstractPropertyType* for the property name
+ * with the value specified by 'value'. Ownership of the returned AbstractPropertyType* is
+ * transfered to the caller.
+ */
+ static AbstractPropertyType* getPropertyTypeForPropertyNameValue(Property name, std::string value="");
+
+ /*! \brief registerProperty registers properties with the Vehicle Property system. Returns true if property
+ * has been registered successfully.
+ * \param name - name of property. Name cannot match any existing property or it will be rejected and
+ * this method will return false.
+ * \param factor - callback function that returns an AbstractPropertyType representation of the value.
+ * custom properties will need to return a custom AbstractPropertyType based object.
+ * \example :
+ *
+ * #include <vehicleproperty.h>
+ * #include <abstractpropertytype.h>
+ *
+ * //Somewhere in a source plugin:
+ * ...
+ * Property VehicleJetEngineStatus = "VehicleJetEngineStatus";
+ * VehicleProperty::registerProperty(VehicleJetEngineStatus, [](){return new BasicPropertyType<bool>(VehicleJetEngineStatus, false);});
+ * ...
+ * //other initialization
+ */
+ static bool registerProperty(Property name, PropertyTypeFactoryCallback factory);
+
+
+
+private:
+
+ VehicleProperty();
+
+ static std::unique_ptr<VehicleProperty> thereCanOnlyBeOne;
+
+ static bool registerPropertyPriv(Property name, PropertyTypeFactoryCallback factory);
+
+ static std::map<Property, PropertyTypeFactoryCallback> registeredPropertyFactoryMap;
+ static PropertyList mCapabilities;
+ static PropertyList mCustomProperties;
+};
+
+#endif // VEHICLEPROPERTY_H
+
+
diff --git a/packaging.in/CMakeLists.txt b/packaging.in/CMakeLists.txt
new file mode 100644
index 00000000..628eef22
--- /dev/null
+++ b/packaging.in/CMakeLists.txt
@@ -0,0 +1,25 @@
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/amb.manifest.in.xml ${CMAKE_SOURCE_DIR}/packaging/amb.manifest @ONLY)
+
+find_program(rpmbuild rpmbuild /usr/bin)
+if(rpmbuild)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/automotive-message-broker.spec.in ${CMAKE_SOURCE_DIR}/packaging/automotive-message-broker.spec @ONLY)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.tizen.in ${CMAKE_SOURCE_DIR}/packaging/config.tizen @ONLY)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/automotive-message-broker.changes.in ${CMAKE_SOURCE_DIR}/packaging/automotive-message-broker.changes @ONLY)
+endif(rpmbuild)
+
+find_program(debuild debuild /usr/bin)
+if(debuild)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/debian/control.debian.in ${CMAKE_SOURCE_DIR}/debian/control @ONLY)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/debian/libamb.debian.install ${CMAKE_SOURCE_DIR}/debian/libamb.install @ONLY)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/debian/libamb-dev.debian.install ${CMAKE_SOURCE_DIR}/debian/libamb-dev.install @ONLY)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/debian/automotive-message-broker.debian.install ${CMAKE_SOURCE_DIR}/debian/automotive-message-broker.install @ONLY)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/debian/automotive-message-broker-plugins.debian.install ${CMAKE_SOURCE_DIR}/debian/automotive-message-broker-plugins.install @ONLY)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog ${CMAKE_SOURCE_DIR}/debian/changelog @ONLY)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/debian/rules ${CMAKE_SOURCE_DIR}/debian/rules @ONLY)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/debian/automotive-message-broker-plugins-bluemonkey.debian.install
+ ${CMAKE_SOURCE_DIR}/debian/automotive-message-broker-plugins-bluemonkey.install @ONLY)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/debian/automotive-message-broker-plugins-bluetooth.debian.install
+ ${CMAKE_SOURCE_DIR}/debian/automotive-message-broker-plugins-bluetooth.install @ONLY)
+ configure_file (${CMAKE_CURRENT_SOURCE_DIR}/debian/automotive-message-broker-plugins-qtmainloop.debian.install
+ ${CMAKE_SOURCE_DIR}/debian/automotive-message-broker-plugins-qtmainloop.install @ONLY)
+endif(debuild)
diff --git a/packaging.in/amb.manifest.in.xml b/packaging.in/amb.manifest.in.xml
new file mode 100644
index 00000000..713efdea
--- /dev/null
+++ b/packaging.in/amb.manifest.in.xml
@@ -0,0 +1,63 @@
+<manifest>
+ <define>
+ <domain name="AMB" />
+ <provide>
+ <label name="AMB::readall" />
+ <label name="AMB::writeall" />
+ <label name="AMB::machinegun" />
+ </provide>
+ <request>
+ <smack request="_" type="rwxatl" />
+ <smack request="User" type="w" />
+ <smack request="System" type="wx" />
+ <smack request="System::Run" type="rwxat" />
+ <smack request="System::Shared" type="rx" />
+ <smack request="AMB::readall" type="rw" />
+ <smack request="AMB::writeall" type="rw" />
+ <smack request="AMB::machinegun" type="rw" />
+ </request>
+ <permit>
+ <smack permit="_" type="w" />
+ <smack permit="System" type="rwx" />
+ <smack permit="User" type="w" />
+ </permit>
+ </define>
+ <assign>
+ <dbus name="org.automotive.message.broker" own="AMB" bus="system">
+ <!--<node name="*/0/MachineGunTurretStatus" >
+ <interface name="org.freedesktop.DBus.Properties">
+ <method name="Set" >
+ <annotation name="com.tizen.smack" value="AMB::machinegun" />
+ </method>
+ </interface>
+ </node>
+ <node name="*" >
+ <interface name="org.freedesktop.DBus.Properties">
+ <method name="Set" >
+ <annotation name="com.tizen.smack" value="AMB::writeall" />
+ </method>
+ </interface>
+ </node>
+ -->
+ <!--<node name="*" >
+ <interface name="org.freedesktop.DBus.Properties">
+ <method name="Get" >
+ <annotation name="com.tizen.smack" value="AMB::readall" />
+ </method>
+ </interface>
+ </node>
+ <node name="*" >
+ <interface name="org.freedesktop.DBus.Properties">
+ <method name="GetAll" >
+ <annotation name="com.tizen.smack" value="AMB::readall" />
+ </method>
+ </interface>
+ </node>-->
+ </dbus>
+ <filesystem path="/usr/bin/ambd" exec_label="AMB" />
+ <filesystem path="@LIB_INSTALL_DIR@*" label="_" />
+ </assign>
+ <request>
+ <domain name="AMB" />
+ </request>
+</manifest>
diff --git a/packaging.in/amb.manifest.plugins b/packaging.in/amb.manifest.plugins
new file mode 100644
index 00000000..9137c87d
--- /dev/null
+++ b/packaging.in/amb.manifest.plugins
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+</manifest>
diff --git a/packaging.in/ambd.conf.upstart b/packaging.in/ambd.conf.upstart
new file mode 100755
index 00000000..ebec0056
--- /dev/null
+++ b/packaging.in/ambd.conf.upstart
@@ -0,0 +1,25 @@
+# ambd - ambd job file
+
+description "ambd service"
+author "Me <myself@i.com>"
+
+# Stanzas
+#
+# Stanzas control when and how a process is started and stopped
+# See a list of stanzas here: http://upstart.ubuntu.com/wiki/Stanzas#respawn
+
+start on stopped rc
+stop on stopping bluetooth
+
+# Automatically restart process if crashed
+respawn
+
+# Essentially lets upstart know the process will detach itself to the background
+expect fork
+
+# Run before process
+pre-start script
+end script
+
+# Start the process
+exec ambd -c /etc/ambd/config.tripzero -l /home/ubuntu/ambd.log -D -d5
diff --git a/packaging.in/ambd.service.systemd b/packaging.in/ambd.service.systemd
new file mode 100644
index 00000000..679ba941
--- /dev/null
+++ b/packaging.in/ambd.service.systemd
@@ -0,0 +1,17 @@
+#
+# ambd systemd service unit file
+#
+
+[Unit]
+Description=Automotive Message Broker
+After=syslog.target
+
+[Service]
+Type=dbus
+BusName=org.automotive.message.broker
+ExecStart=/usr/bin/ambd
+
+[Install]
+WantedBy=multi-user.target
+
+
diff --git a/packaging.in/ambd.service.systemd.tizen b/packaging.in/ambd.service.systemd.tizen
new file mode 100644
index 00000000..fbda56ed
--- /dev/null
+++ b/packaging.in/ambd.service.systemd.tizen
@@ -0,0 +1,18 @@
+#
+# ambd systemd service unit file
+#
+
+[Unit]
+Description=Automotive Message Broker
+Wants=bluetooth.service
+
+[Service]
+Type=dbus
+BusName=org.automotive.message.broker
+Environment=LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so
+ExecStart=/usr/bin/ambd -c /etc/ambd/config.tizen
+
+[Install]
+WantedBy=multi-user.target
+
+
diff --git a/packaging.in/automotive-message-broker.changes.in b/packaging.in/automotive-message-broker.changes.in
new file mode 100644
index 00000000..7f07f346
--- /dev/null
+++ b/packaging.in/automotive-message-broker.changes.in
@@ -0,0 +1,874 @@
+* Thu Nov 05 2014 tripzero <kevron.m.rees@intel.com> submit/tizen/20141029.180744-6-gfa57967
+- updated docs. added deleted callback
+- updated chlog
+- fixed obd2 disconnect bug
+- fixed bluemonkey config path
+- fixed spec to install qtmainloop with bluemonkey plugin
+- fixed FanSpeedLevel name
+- update cache of dbus properties even if not currently registered
+- fixed battery ChargeLevel type error
+- fixed Temperature interface name
+- updated spec
+- version bump 0.11.904
+- fixed regression in cangen plugin
+- fixed regression in cangen plugin
+- version bump 0.11.904
+- dbus plugin will cache. updating release notes
+- fixed Obd2Connected
+- fixed database playback
+- 0.12 final
+- added mainpage for lib documentation
+- disable dbus property rules
+
+* Mon Oct 13 2014 tripzero <kevron.m.rees@intel.com> submit/tizen_ivi/20141001.165128-11-g4c16abd
+- some opencvlux fixes
+- use pure dlopen to open source/sink plugins
+- additional fixes to opencv plugin
+- version bump 0.11.903
+- updated release notes
+- cleaned up unused code block
+- updated chlog and spec version
+- removed all libtool usage
+- use set instead of list in cmake for better compatibility
+- 0.11.903 bump
+
+* Wed Oct 01 2014 tripzero <kevron.m.rees@intel.com> submit/tizen/20140919.161146-9-g0e92e8f
+- fix lib install dir for qtmainloop plugin
+- reference amb.idl in dbus docs
+- fixed obd2 bluetooth for bluez5
+- updated chlog
+- fixed opencvlux plugin
+- version bump 0.11.902
+- use smart pointer in opencvlux
+- fixed install path for amb.idl
+
+* Fri Sep 19 2014 tripzero <kevron.m.rees@intel.com> submit/tizen/20140916.213438-15-g734500b
+- bump version
+- fixed up bluez5 support code
+- bluemonkey enhancements
+- multi-arch support
+- multi-arch support
+- add usebluez5 flag to cmake
+- fixes for bluemonkey and wheel
+- disabled irc in bluemonkey
+- removed generated files
+- point at franca docs for dbus
+- convert bluemonkey script to be qml based engine
+- version bump
+- fixed up bluemonkey configuration
+- manual merge
+- fixed crash in murphy plugin
+- fix to spec
+- fixed lib install dir for qtmainloop plugin
+- updated spec for 0.11.901
+
+* Tue Sep 02 2014 tripzero <kevron.m.rees@intel.com> submit/tizen/20140820.174605-9-g7f1852a
+- DBus signaller will combine duplicate signals for same object path
+- Fixed issue with Murphy plugin using wronge type for certain Properties.
+- Some fixes and performance tweaks.
+- version bump 0.11.812
+- fixed periodic crash when sending dbus signal
+- cleaned up debug output
+- updated to upstream 0.11.812
+- fixed up test plugin
+- made some of the dbus API compliant with w3c auto-bg specification
+- enginecoolant should be signed
+- version bump 0.11.900. We are now beta
+- fix for wheel plugin
+- fixed frequency option in dbus plugin
+- fixed up database plugin
+
+* Wed Aug 20 2014 tripzero <kevron.m.rees@intel.com> submit/tizen_ivi/20140612.200613@a721703
+- Merge branch '0.12' into tizen
+- Merge pull request #19 from tripzero/master
+- Merge branch '0.12' into tizen
+- version bump 0.11.811
+- removed docs
+- Update RELEASE
+- Version bump 0.11.811
+- added tools
+- priority queues
+- cleaned up documents. idl is the authority
+- added asyncqueue. Made updateProperty() thread safe
+- updated docs
+- created franca idl doc
+- some performance tweaks to core and dbussignaller
+- add rule to only generate dbus docs from idl
+- fixed crash when gpsnmea gets blank gprmc messages
+- removed client library stubs
+- cleaned up debug output
+- fixed periodic crash when sending dbus signal
+- version bump 0.11.812
+- Some fixes and performance tweaks.
+- Fixed issue with Murphy plugin using wronge type for certain Properties.
+- DBus signaller will combine duplicate signals for same object path
+- Merge pull request #17 from tripzero/master
+- automotive-message-broker should not depend on qt
+- removed docs
+- Update RELEASE
+- Version bump 0.11.811
+- added tools
+- priority queues
+- cleaned up documents. idl is the authority
+- added asyncqueue. Made updateProperty() thread safe
+- updated docs
+- created franca idl doc
+- some performance tweaks to core and dbussignaller
+- add rule to only generate dbus docs from idl
+- fixed crash when gpsnmea gets blank gprmc messages
+- removed client library stubs
+- Merge branch '0.12' into tizen
+- multiple dbus properties can support the same amb property
+- Merge branch '0.12' into tizen
+- fixed missing symbol
+- Merge branch '0.12' into tizen
+- use const string ref
+- Updated spec
+- Merge branch '0.12' into tizen
+- fix libamb label
+- added support for lambda subscriptions. initial bluetooth5 support in obd2 plugin
+- updated docs to reflect change to vehicle and engine speed
+- updated Vehicle and EngineSpeed interfaces to match w3c vehicle data draft spec. Old attributes exist for compatibility
+- version bump 0.11.810
+- added SteeringWheelAngle
+- added stub ambclient code
+- Merge branch '0.12' into tizen
+- added more debug to bluetooth
+- Merge branch '0.12' into tizen
+- use gio for watching fd
+- Merge branch '0.12' into tizen
+- updated method signature
+- got bluez5 client somewhat working
+- Merge branch '0.12' into tizen
+- updated spec
+- fixed a GVS error
+- Merge branch '0.12' into tizen
+- add ambbt service file
+- added service record for spp
+- Merge branch '0.12' into tizen
+- added dbus system config
+- door lock are not readonly
+- Merge branch '0.12' into tizen
+- registerProfile after registering the dbus object
+- Merge branch '0.12' into tizen
+- corrected signature call to RegisterProfile
+- Merge branch '0.12' into tizen
+- updated spec to install bluetooth plugin
+- load non-SinkManager plugins
+- Merge branch '0.12' into tizen
+- check if registerProfile is valid
+- initial bluetooth plugin
+- fix cmake file
+- manual merge
+- reworked tests in gpsnmea
+- deprecated gpsd plugin
+- fixed checksum()
+- make unhandled nmea messages level 7 to avoid spamming
+- change to example and dbus plugins
+- removed mcmodel compile option. added VideoLogging property to opencv plugin
+- Merge branch '0.12' into tizen
+- fixed crasher in gpsnmea
+- Merge branch '0.12' into tizen
+- fixed compile errors in database and murphy plugins
+- Merge branch '0.12' into tizen
+- fixed compile errors in obd2 plugin
+- Merge branch '0.12' into tizen
+- install canobserver header
+- fixed some compile errors
+- updated some docs and added testing document
+- Update README
+- updated changelog and spec
+- added velocity text to framewriter
+- use vector where possible
+
+* Wed Apr 16 2014 tripzero <kevron.m.rees@intel.com> submit/tizen/20140326.195506@13f13b0
+- use debugout for errors instead of cerr
+- use mjpg codec
+- enable usage of different routing engines via config
+- version bump 0.11.809
+- use monotonic clock
+- removed build files from src
+- use c++11 chrono for time
+- updated spec
+- minor tweak to readme
+- Merge pull request #16 from OlivierDelbeke/master
+- Merge branch '0.12' into tizen
+- fixed up gpsnmea to work with devices with very fragmented nmea messages
+- Added the possibility to specify the baudrate of the GPS NMEA device
+- fixed runtime errors and warnings with dbus plugin
+- Updated plugins to work without the now deprecated setSupported() call.
+- fixed compile errors in various plugins
+- Update README
+- Merge pull request #15 from e8johan/master
+- some core changes as well as additions to opencv plugin
+- added SimCommand backdoor to the gen plugin
+- added cangen example config
+- Merge branch '0.12' into tizen
+- fixed invalidating of iterator in ranged for looop
+- updated chlog
+- Fixed warning about enabling c++11 for C sources
+- Removed stray files.
+- Fixed error messages for libtool to indicate that it is libltdl that is missing.
+
+* Fri Mar 21 2014 tripzero <kevron.m.rees@intel.com> submit/tizen/20140320.231725@5748dc3
+- added cansim plugin
+- added cansim, cangen plugins
+
+* Thu Mar 20 2014 tripzero <kevron.m.rees@intel.com> submit/tizen/20140319.172635@8669b09
+- version bump 0.11.808
+- fixed issue with complex objects only firing the last property and dropping all others
+- fixed throw when trying to parse empty speed
+- do not crash if connection has not been established
+- version bump 0.11.807
+- only listen to specified paths
+- reenabled ico vehicle plugin
+- Added incomplete message to gpsnmea test
+- playing with videowriter in cv plugin
+- updated chlog and spec
+
+* Thu Mar 13 2014 tripzero <kevron.m.rees@intel.com> submit/tizen/20140305.213149@afb8a15
+- fixed random crash when process subscribes to an object interface
+- fixed debug output statement
+- added more debug output to murphy plugin
+
+* Wed Mar 05 2014 tripzero <kevron.m.rees@intel.com> submit/tizen/20140224.190956@6425ef6
+- Merge branch '0.12' into tizen
+- Remove performance from dbusconfig. fix crasher in varianttype.
+- added more debug to gpsnmea. example source default return for set operations.
+- added support for string and double in amb-set
+- make startOnLoad and playbackOnLoad work with 'true' or 'false'
+- fixed amb-set
+- amb-listen works. zone attribute included in all signals.
+- updated chlog
+
+* Thu Feb 24 2014 - <kevron.m.rees@intel.com>
+- 0.11.805 release
+- updated smack rules to allow murphy socket connection
+
+* Fri Feb 14 2014 - <kevron.m.rees@intel.com>
+- 0.11.804 release
+
+* Tue Feb 11 2014 - <kevron.m.rees@intel.com>
+- 0.11.803 release
+
+* Wed Feb 05 2014 - <kevron.m.rees@intel.com>
+- fixed missing symbol issue in murphy plugin
+
+* Tue Feb 04 2014 - <kevron.m.rees@intel.com>
+- 0.11.802 release
+
+* Fri Jan 31 2014 - <kevron.m.rees@intel.com>
+- 0.11.801 release
+
+* Tue Jan 28 2014 - <kevron.m.rees@intel.com>
+- 0.11.800 release
+
+* Wed Jan 09 2014 - <kevron.m.rees@intel.com>
+- Fixed up tree so obs can build it
+
+* Wed Jan 08 23:41:34 UTC 2014 - tracy.graydon@intel.com
+- Fix the date in the previous changelog entry to make OBS happy
+
+* Wed Jan 08 2014 - <kevron.m.rees@intel.com>
+- Upstream 0.10.902
+- Temporarily install rule-less manifest so security=none works
+
+* Thu Dec 19 2013 - <kevron.m.rees@intel.com>
+- New upstream release 0.10.901
+- Fixed packaging to install manifests for all subpackages
+- Fix for TIVI-2324
+
+* Mon Dec 16 2013 - <kevron.m.rees@intel.com>
+- New upstream release 0.10.900 ("challenger" beta)
+- Fixed manifest so ambd now runs as new AMB domain
+- Cleaned up tree
+
+* Fri Nov 22 2013 - <kevron.m.rees@intel.com>
+- New upstream release 0.10.805 ("challenger" alpha)
+- Install smack manifest file
+
+* Thu Nov 21 2013 - <kevron.m.rees@intel.com>
+- New upstream release 0.10.804 ("challenger" alpha)
+- Fixes TIVI-2081, TIVI-2122
+- Cleaned up branch with new release patches
+
+* Fri Nov 11 2013 - <kevron.m.rees@intel.com>
+- New upstream release 0.10.803 ("challenger" alpha)
+
+* Thu Nov 04 2013 - <kevron.m.rees@intel.com>
+- New upstream release 0.10.802 ("challenger" alpha)
+- added tizen specialized systemd service file
+
+* Tue Oct 16 2013 - <kevron.m.rees@intel.com>
+- New upstream release 0.10.800 ("challenger" alpha)
+- Changes DBus API with the concent of zones
+- New location plugin that uses nmea devices
+- updated packaging
+- lots more docs are now available in the docs package
+
+* Thu Sep 12 2013 - <kevron.m.rees@intel.com>
+- Official 0.10.0 ("chevelle") release
+- added LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so to fix opencvlux plugin issues
+
+* Tue Sep 10 2013 - <kevron.m.rees@intel.com>
+- New upstream release 0.9.19 ("chevelle" beta).
+- upstream changed time and sequence data types.
+
+* Mon Sep 09 2013 - <kevron.m.rees@intel.com>
+- New upstream release 0.9.18 ("chevelle" beta).
+- upstream added "sequence" properties to dbus api.
+- Make manager interface register last (workaround for dbus race condition).
+
+* Thu Sep 05 2013 - <kevron.m.rees@intel.com>
+- New upstream release 0.9.17 ("chevelle" beta)
+- new version fixes systemd race condition with dbus
+
+* Tue Sep 03 2013 - <kevron.m.rees@intel.com>
+- Fixed TIVI-1708
+- New upstream release 0.9.16 ("chevelle" beta)
+
+
+* Thu Aug 23 2013 - <kevron.m.rees@intel.com>
+- New upstream 0.9.15 ("chevelle" beta)
+- new GetHistory call
+- fixed some minor issues with properties registering on dbus
+- added smack manifest with AMB domain (disabled currently)
+- reenabled murphy plugin
+
+* Tue Aug 13 2013 - <kevron.m.rees@intel.com>
+- New upstream release 0.9.13 ("chevelle" beta)
+- Enabled murphy plugin by default
+- Fixed memory smashing bug with json parsing
+- Added support for additional buttons in wheel plugin
+
+* Tue Jul 30 2013 - <kevron.m.rees@intel.com>
+- New upstreadm release 0.9.11 ("chevelle" beta)
+
+* Tue Jul 30 2013 - <kevron.m.rees@intel.com>
+- Fixed rmplint errors
+
+* Mon Jul 29 2013 - <kevron.m.rees@intel.com
+- fixed findProperty call to return object names not objects that match amb property names
+- added list dbus call
+
+* Fri Jul 19 15:09:00 PST 2013 - <kevron.m.rees@intel.com>
+- readded .gbs.conf file to point to upstream branch
+- set upstream branch to track upstream so gbs will stop complaining
+- recreated tizen branch from upstream
+- submitting to tizen build
+- added fix for compiling with gcc 4.7.0
+
+* Thu Jul 18 10:39:00 PST 2013 - <kevron.m.rees@intel.com>
+- version 0.9.9 ("chevelle" beta)
+
+* Wed Jul 17 13:21:00 PST 2013 - <kevron.m.rees@intel.com>
+- Fix for bug TIVI-1427
+
+* Thu Jul 11 11:13:00 PST 2013 - <kevron.m.rees@intel.com>
+- Fix for bug TIVI-1175
+
+* Mon Jul 08 18:48:00 PST 2013 - <kevron.m.rees@intel.com>
+- Fixed dbus policy example
+
+* Fri Jun 28 11:06:00 PST 2013 - <kevron.m.rees@intel.com>
+- Fixed segfault on timeout reply
+
+* Wed Jun 26 13:40:00 UTC 2013 - <kevron.m.rees@intel.com>
+- Fixed systemd startup issue
+- Merged in latest upstream fixes from the 0.10 branch
+
+* Thu Jun 20 22:38:34 UTC 2013 - tracy.graydon@intel.com
+- Fix up a couple of deps and a spec parsing issue
+
+* Tue Jun 18 11:12:00 PST 2013 - <kevron.m.rees@intel.com>
+- New upstream version 0.9.8 (0.10 alpha) "chevelle"
+
+* Mon Jun 03 10:47:00 PST 2013 - <kevron.m.rees@intel.com>
+- submitting to tizen build
+
+* Tue May 21 11:19:00 PST 2013 - <kevron.m.rees@intel.com>
+- Updated to latest upstream on the 0.9 branch
+- disabled gpsd plugin since we don't have a modern version of gpsd on tizen
+
+* Thu Mar 21 16:02:00 PST 2013 - <kevron.m.rees@intel.com>
+- Fix for performance issues in opencvlux plugin
+- Murphy code added but not built by default yet
+
+* Tue Mar 19 11:09:00 PST 2013 - <kevron.m.rees@intel.com>
+- Fix for JIRA TIVI-525
+
+* Mon Mar 18 14:23:00 PST 2013 - <kevron.m.rees@intel.com>
+- Merged upstream bug fixes from 0.8.0 branch.
+
+* Thu Mar 07 13:40:00 PST 2013 - <kevron.m.rees@intel.com>
+- new beta releast 0.7.9
+
+* Wed Feb 06 10:38:00 PST 2013 - <kevron.m.rees@intel.com>
+- dbus fixes
+- compiler fixes
+
+* Thu Jan 24 14:44:00 UTC 2013 - <kevron_m_rees@linux.intel.com>
+- memory usage fixes
+
+* Mon Jan 21 10:57:00 UTC 2013 - <kevron_m_rees@linux.intel.com>
+- updated to 0.6.9
+
+
+* Wed Jan 3 10:57:00 UTC 2013 - <kevron_m_rees@linux.intel.com> 3718d3f
+- updated spec to include database package
+
+* Fri Dec 7 23:19:19 UTC 2012 - tracy.graydon@intel.com
+- Add libuuid-devel dep and a couple of minor spec changes to fix build issue
+
+* Thu Dec 06 2012 tripzero <kevron_m_rees@linux.intel.com> b1870c5
+- version bump and install sysvinit
+- uuidhelper
+- fixed initiation of sequence and timestamp defaults
+- example requests ranged from 10s ago after 10s timeout
+- do not blow up if baud is empty
+- version bump 0.6.0
+- fixed tpms plugin
+- Updated todo
+- worked out some bugs with websocket source and sink
+- getRanged works with database sink
+- database plugin works
+- set precision before writing to debug
+- refactored how timestamp and sequence are stored: moved to AbstractProperty
+- fixed merge
+- Merge branch 'malcom'
+- register air intake
+- Change so websocketsink now reports the proper list of supported properties
+- Fix for WMI pid being returned as true when engine coolant temp is selected
+- fixed potential Obd2Amb bug
+- Change for updateProperty shouldn't be called if there is a pending reply
+- check for property changed in core, but don't use right now
+- Change so getPropertyAsync is properly replied to in obd2source
+- fixed currenttime bugs
+- added multisource test script in examples and added --log option
+- worked some debug messages
+- added air intake temp property to obd2source
+- Fix for CopyMe<T> having an error in its constructor paramter
+- Change so re-subscribing to a pid, removes it from the blacklist if it has been tagged as invalid
+- Change for blacklisting OBD2 pids that return NODATA
+- Change for debugging random disconnects
+- Addition for using the bluez bluetooth disconnect feature when OBD disconnects
+- added disconnect call to bluetooth
+- Change so BT rfcomm port name is re-reqested every time a connect is requested
+- register OBD2Connect property
+- Change for removing extra debug output, and fixing disconnect on device removal
+- Fix for an issue where a NODATA response from an OBD2 tool would cause a disconnect
+- Addition of feature to disconnect from OBD port on failure, and reconnect only on new incoming subscriptions
+- Addition of getPropertyAsync and setProperty support through websocketsource
+- Addition of getPropertyAsync and setProperty support through websocketsource
+- initial sequence and timestamp support
+- fixed tryParse returning false issue
+- stub databasekink
+- Fix copy/paste issue preventing OBD2Source from supporting Engine Speed
+- endl
+- Fix for high CPU usage due to change in how updateProperties was called
+- clean up sources and sinks
+- Addition of method for shutting down OBD thread upon closure
+- fixed example config
+- enabled obd2 by default for now
+- fixed include
+- Addition of disconnect on last unsubscribe and extra debugging
+- Continuation of Kevron's refactoring, including connect on first subscribe
+- initial placeholder for database plugin
+- Update plugins/obd2plugin/README
+- Merge branch 'master' of https://github.com/otcshare/automotive-message-broker
+- updated obd2source readme
+- start of obd2 refactoring
+- fixed todo merge
+- todo updated
+
+* Mon Dec 03 2012 tripzero <kevron_m_rees@linux.intel.com> submit/release/20121112.191808@cbfefb5
+- version bump in spec
+- version bump 0.6.0
+- updated changes
+- todo updated
+
+* Fri Nov 02 2012 tripzero <kevron_m_rees@linux.intel.com> 1.0_branch@7de9474
+- new version
+- Manual merge
+- Merge branch 'master' of github.com:otcshare/automotive-message-broker into release
+- version bump 0.5.0
+- added getHistory support to websocket sink plugin and added api to test api.js
+- Adding json-glib as a runtime requirement.
+- added a bunch of properties and consolodated some things in obd2source
+- updated tpms plugin so it compiles
+- refactored setProperty: made it async with callback
+- updated todo
+- some enhancements to obd2source
+- updated TODO
+- configurable bt adapter
+- Update TODO
+- Update README
+- Update spec file: - Use valid Tizen Group - Fix typo - Use macro instead of hardcoded path in %install section
+- Merge branch 'master' of https://github.com/otcshare/automotive-message-broker
+- report why cannot connect to obdII device
+- solved possible memory leak in websocketsink
+- TPMS compile switch with default OFF
+- fixed websocketsource. possibly removed mem leak
+- gracefully handle no-root and no-device situations
+- added light status and updated fuel docs
+- cruise control properties
+- fix kPa
+- pressures all in kPa
+- updates to support all 4 tires and pressures
+- some basic info about the plugin
+- convert tire types to float
+- merge
+- merge
+- fix typo
+- add tire temperature parameters
+- tire temperature values added
+- tire temperature values added
+- tire temperature values added
+- working USB TPMS sensor reading
+- only export dbus properties that are supported
+- USB module compile & link from TPMS plugin
+- added trip meter property
+- changed trip meter to finite set of trips
+- made adding properties more straightforward
+- cleanup
+- adding files for TPMS USB framework
+- basic TPMS plugin framework without USB sensor interaction
+- changes to allow build on Ubuntu 12.04
+- added property registration system
+- Merge branch 'master' of github.com:otcshare/automotive-message-broker
+- property changes
+- removed 100ms delay
+- Merge branch 'master' of https://github.com/otcshare/automotive-message-broker
+- removed 500ms blocking call when sending things to obd2
+- fixed spec from merge
+- more changes to changes
+- Merge changes
+- Merge changes
+- Merge changes
+- Merge "added maketag"
+- Merge changes Ibab9e115,I4028a068,Iaec87c6c,I03a7ebde,I2ca0262d,I65c6147e,Ie1f8ec4e,I8bf5640b,I8a6ed52b,Iba369a37
+- Merge changes Iba9f4a4a,Ic07308c7,Icfe8b20e,Ic0d8a7d4
+- Merge "Update README"
+- Merge "added tire pressure properties"
+- Merge "fixed up engine coolant down button"
+- updated chlog
+- Merge branch 'upstream' into release
+- mkdir first
+- Merge branch 'upstream' into release
+- make link
+- Merge branch 'upstream' into release
+- updated version number in spec
+- updated chlog
+- updated spec
+- Merge branch 'upstream' into release
+- updated chlog
+- Merge branch 'upstream' into release
+- updated changelog
+- Merge branch 'upstream' into release
+- changelog update
+
+* Mon Oct 01 2012 tripzero <kevron_m_rees@linux.intel.com> submit/release/20121001.202146@cd77669
+- fixed merge
+- changes
+- Merge branch 'upstream' into release
+- added packaging directory
+
+* Mon Oct 01 2012 tripzero <kevron_m_rees@linux.intel.com> submit/release/20120926.232908@e180e9d
+- updated spec version
+- Merge branch 'upstream' into release
+- changes
+- version bump
+- report out property updates per second
+- removed glibmm requirement
+- made obd2 updates happen on an idle callback
+- obdII is b0rked but getting closer
+- Update docs/runningstatus.txt
+- only sleep if list is empty
+- integrated obdII source with mainloop
+- updated draft running status dbus doc
+- updated TODO
+- Added debug output confirming set working
+- Fix for "set" requests
+- added maketag
+- updated chlog
+- mkdir first
+- make link
+- updated version number in spec
+- updated chlog
+- updated spec
+- updated chlog
+- updated changelog
+- changelog update
+- added packaging directory
+
+* Wed Sep 26 2012 tripzero <kevron_m_rees@linux.intel.com> ba9f4a4
+- atsp0 ftw
+- fixed compile errors introduced by foolishly merging
+- fixed mergers
+- obd source support bluetooth devices
+- Update README
+- config required to construct plugins. device config added to wheel plugin
+- added tire pressure properties
+- fixed up engine coolant down button
+- added maketag
+- updated chlog
+- mkdir first
+- make link
+- updated version number in spec
+- updated chlog
+- updated spec
+- updated chlog
+- updated changelog
+- changelog update
+- added packaging directory
+
+* Fri Sep 14 2012 tripzero <kevron_m_rees@linux.intel.com> submit/release/20120912.232202@8d10311
+- Merge branch 'upstream' into release
+- fixed config
+- mkdir first
+- Merge branch 'upstream' into release
+- make link
+- don't do dbus by default
+- don't install service in wrong place
+- Merge branch 'upstream' into release
+- updated version number in spec
+- install service in right place so it starts
+- version bump 0.3
+- Add button event generation for Button[1-4]Preset to wheel plugin Make demo sink plugin listen for the above ButtonEvents Make rundemo script react to the above buttons
+- Add hard-coded calibration values to wheel plugin for G27 racing wheel
+- Fixed one last printf
+- Merge remote-tracking branch 'origin/master'
+- added debug
+- Fix for const_iterator that should be iterator
+- Fix for const_iterator that should be iterator
+- fixed capabilities
+- Fix for only a single subscription being operated on
+- Fix for only a single subscription being operated on
+- added mg to example plugin
+- updated chlog
+
+* Wed Sep 12 2012 tripzero <kevron_m_rees@linux.intel.com> submit/release/20120912.231933@81ea024
+- updated spec
+- Merge branch 'upstream' into release
+- updated chlog
+- fixed compile error
+
+* Wed Sep 12 2012 tripzero <kevron_m_rees@linux.intel.com> submit/release/20120911.205626@03b4484
+- Merge branch 'upstream' into release
+- Merge branch 'mal'
+- made awesome debugout
+- Code cleanup, comments, and change of ALL printf's to DebugOut() calls
+- adding democonfig
+- Fix for typo in config
+- Addition of obdsource
+- Change for websocket options
+- simple rundemo script
+- Addition of all OBD2 properties in the TODO file, async and standard requests
+- updated changelog
+- Fix
+
+* Tue Sep 11 2012 tripzero <kevron_m_rees@linux.intel.com> submit/release/20120911.205626@d545a4c
+- Merge branch 'upstream' into release
+- updated examples with more properties
+- demosink uses strings for turn signal
+- added wheel example and fixed example websocketsource config
+- fixed enums in wheel
+- Merge branch 'mal'
+- Merge branch 'master' of https://github.com/malcom2073/automotive-message-broker into mal
+- fixed up AbstractPropertyType so it can use enums
+- Fix for bug involving websocket messages being incomplete
+- changelog update
+- Merge branch 'master' of https://github.com/malcom2073/automotive-message-broker into mal
+- Fix for bad if/else statements found by Kevron
+- Addition of new obd2 plugin
+
+* Mon Sep 10 2012 tripzero <kevron_m_rees@linux.intel.com> submit/release/20120910.223349@2021380
+- Merge branch 'upstream' into release
+- const value()
+- fixed websocketsource cmake
+- added packaging directory
+- added more properties
+- Addition of only requesting OBD2 values after a subscription request
+- Change in the libwebsocket_write call to fix string length, due to passing a pointer in the middle of a string.
+- Fix for huge memory leak, and more config changes
+- Changes for new config values
+- made setConfiguration virtual
+- Change for setConfiguration to be handled properly for settings
+- new configuration format
+- added button events
+- Fix compile error due to const iterator issues in websocketsinkmanager
+- added todo
+- moved example configs to subfolder. updated readme
+- fix the target_link_library for example plugins
+- Code cleanup
+- Fix for GIOChannel watch's hanging around longer than they should be
+- fixed parallalel building and make install
+- install all the files
+- fixed printhelp() with config option. thanks geoffroy
+- Fix for gioPolling final
+- Fix for some weird issues with the switch
+- Change for gioPollingFunc to keep it from blocking
+- Changed where obd2plugin looks for obdlib.h
+- Merge branch 'master' of https://github.com/malcom2073/automotive-message-broker into mal2
+- Change for switch falling through
+- Change for GIO to only poll libwebsockets when it actually needs to
+- Change for GIO to only poll libwebsockets when it actually needs to
+- fixed type for transshift/gear part 2
+- fixed type for transshift/gear
+- Fix for bad if/else statements found by Kevron
+- Fix for bad if/else statements found by Kevron
+- Fix for bad if/else statements found by Kevron
+- use nullptr.h
+- define nullptr if using < gcc 4.6
+- Addition of new obd2 plugin
+- Addition of new obd2 plugin
+- fixed dbus plugin not to use the temp pointer
+- some additional updates
+- use pointer to avoid implicit casting fail
+- Merge branch 'mal'; commit '1aad5d5' into propertytype
+- Fixes for new AbstractPropertyType
+- it compiles
+- added missings
+- more updating. still broken
+- Add two new configs for source/sink websocket tests
+- sinks auto-register with the routing engine
+- Fixes for issues concerning subscriptions and websocketsource
+- example sink reacts to supported changed
+- Changes to allow websocketsourceplugin to operate properly, and load from a config file
+- subscribeToProperty being called on the source now
+- some more changes
+- Addition of new websocketsource plugin
+- Fixing a bug where a AMBD property request was being replied as a genivi request
+- major breakage ahead...
+- example supports engine coolant
+- example does throttle
+- Fix for subscriptions not working properly due to non-standard AMB properties not being supported
+- Addition of handling of generic string properties. If they're supported by AMBD, they'll be supported through
+- added capabilities call to VehicleProperty
+- checked in a small fix to the api.js to handle when the service doesn't return the proper acknowledgement on unsubscribe
+- added signal handler for sigterm and sigint
+- fixed types expressed in the example source plugin
+- updated example to produce fake data for wheel and transmission shift properties
+- Merge pull request #7 from malcom2073/master
+- Addition of new debugging output, and better error handling
+- Added unsubscribe supportedeventtype
+- Addition of getSupportedEventTypes with no data field for listing supported properties
+- Code formatting cleanup
+- Changes for unsubscribe to work properly, as well as getSupportedEventTypes
+- Fix for current subscription changes to api.js. Added steering wheel angle and transmission status
+- Clean up the boost::any casting a bit Fulfill property get requests
+- Add event propogation of all data items from the wheel
+- change get and set to allow an array of events, added subscribe and unsubscribe for an array of events, upgraded the index.html tester to all selecting a list of any events to do get, subscribe, and unsubscribe on. Added an input field for each event to allow the tester to set the value to whatever they want. The fields update on get or a valuechanged event on subscribe, when the value changes it flashes red so you can confirm the data is coming in easily.
+- Change for subscription requests to now operate properly
+- Make the boost::any conversions actually work in WheelSource
+- fixed unsubscribe
+- Make WheelPlugin actually read JS events, print out event info Make basic framework for processing received JS events TODO: Button/Axis mapping to VehicleProperty values
+- Add PropertySet typedef to VehicleProperty
+- made VehicleProperty::Property strings
+- added vehiclespeed property
+- Merge remote-tracking branch 'origin/master' into wheelsource
+- Make wheelsourceplugin actually read JS events (currently just prints out)
+- Merge pull request #6 from malcom2073/master
+- Slight change to support uuid string transactionids from the client websocket
+- Changes to support latest websocket protocol api. Now supports running_status_speedometer and running_status_engine_speed
+- in api.js, changed transactionid to a uuid
+- in api.js, changed transactionid to a uuid
+- added better comments to api.js and moved server test code into subdir
+- added better comments to api.js and moved server test code into subdir
+- made websockets work out of the box
+- made websockets work out of the box
+- Additions for creating new WebsockSink class instances per tcp connection
+- missing files added
+- missing files added
+- added check header so cmake will fail if you are missing libwebsockets
+- added check header so cmake will fail if you are missing libwebsockets
+- added set functionality, the basics are in place for hooking up the backend service
+- added set functionality, the basics are in place for hooking up the backend service
+- latest vehicle api supports getevent types and get
+- latest vehicle api supports getevent types and get
+- Update README
+- Update README
+- Update README
+- Update README
+- Merge pull request #5 from malcom2073/master
+- Update README
+- Update README
+- Update README
+- Update README
+- Name change for tcpsink to be websocketsink
+- Merge pull request #4 from malcom2073/master
+- Change for websocket port to be 7681
+- Merge remote-tracking branch 'origin'
+- Add opening of joystick dev file, and reading of various JS info
+- Add opening of joystick dev file, and reading of various JS info
+- Changes for api.js to set protocol, config to include tcpsink plugin, and tcpsinkplugin to handle incoming json requests
+- initial working dbus plugin
+- Merge branch 'par_build_fix'
+- added properties to support wheel
+- Fix parallel build issue (issue #3)
+- mikeleib'd
+- adding missing files
+- updated dbus plugin
+- Fix tcpsinkplugin build on glib 2.32.3
+- Update README
+- added reference/test javascript api to websocket plugin
+- dbus plugin updates
+- added dbus sink subdir
+- Merge pull request #2 from malcom2073/master
+- Initial commit of tcpsink, a websocket providing sink plugin.
+- added dbus plugin
+- Merge pull request #1 from jausmus/wheelsource
+- Add wheel plugin subdir for wheel source plugin Modify plugins/CMakeLists.txt to include wheel subdir
+- added some properties to support the logitec wheel
+- changed async reply callback argument
+- added async and sync property getter
+- fixed compile error due to hardcoded path
+- missing this
+- basic routing working
+- adding example config
+- use map instead of unordered_map
+- cleaned up headers
+- added abstract routing engine class
+- revamped plugin interfaces
+- more progress on core
+- missed these files
+- more progress
+- more code added to core
+- started core routing engine
+- plugins load ftw
+- Merge branch 'master' of https://github.com/otcshare/automotive-message-broker
+- updated architecture presentation
+- initial config reading
+- a bit more progress on the plugin loader
+- some serious changes
+- acceleration type double
+- set default values for each property
+- fixed dbus signal emition
+- Fixed pkgconfig and header issues
+- Merge branch 'master' of github.com:otcshare/automotive-message-broker
+- Version bump 0.2
+- Version bump 0.2
+- removed wheeltick from docs
+- removed wheeltick
+- more properties added to running status
+- added engine oil property stub
+- added new properties and assignment overloads
+- lots of new properties to running status
+- trip meter property
+- Merge branch 'master' of github.com:otcshare/automotive-message-broker
+- some changes to abstract property
+- Updated readme with project description.
+- added explainatory presentation document
+- added fuel economy property
+- added EngineSpeed and VehiclePowerMode properties
+- some updates to docs
+- added README
+- added COPYING file with license
+- all files have license comments
+- fixed compile errors and added dist target
+- fixed crasher; implemented setProperty; updated Docs
+- added runtime options
+- cleanup and project rename
+- initial add
+- initial project import from KDevelop
+
diff --git a/packaging.in/automotive-message-broker.spec.in b/packaging.in/automotive-message-broker.spec.in
new file mode 100644
index 00000000..bce7a026
--- /dev/null
+++ b/packaging.in/automotive-message-broker.spec.in
@@ -0,0 +1,410 @@
+%bcond_without qt5
+
+Name: automotive-message-broker
+Summary: Automotive Message Broker is a vehicle network abstraction system
+Version: @PROJECT_VERSION@
+Release: 0
+Group: Automotive/Service
+License: LGPL-2.1
+URL: https://github.com/otcshare/automotive-message-broker
+Source0: %{name}-%{version}.tar.bz2
+Requires: automotive-message-broker-plugins
+Requires: automotive-message-broker-plugins-murphy
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+Requires: default-ac-domains
+Requires: dbus-python
+Requires: python-curses
+Requires: python-gobject
+BuildRequires: cmake
+BuildRequires: boost-devel
+BuildRequires: pkgconfig(json)
+BuildRequires: libtool-ltdl-devel
+BuildRequires: pkgconfig(libwebsockets)
+BuildRequires: pkgconfig(uuid)
+BuildRequires: pkgconfig(sqlite3)
+BuildRequires: pkgconfig(glib-2.0)
+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
+BuildRequires: qt5-qtdbus-devel
+BuildRequires: qt5-qtnetwork-devel
+BuildRequires: qt5-qtdeclarative-devel
+BuildRequires: qt5-plugin-bearer-generic
+BuildRequires: qt5-plugin-bearer-connman
+BuildRequires: qt5-plugin-bearer-nm
+BuildRequires: qt5-plugin-sqldriver-sqlite
+%endif
+
+%description
+Automotive Message Broker is a vehicle network abstraction system.
+It brokers information from the vehicle to applications.
+
+%package devel
+Summary: Automotive Message Broker development files
+Group: Automotive/API
+Requires: %{name} = %{version}-%{release}
+Requires: libuuid-devel
+Requires: boost-devel
+
+%description devel
+Development files for the automotive-message-broker
+
+%package doc
+Summary: Documentation for the automotive-message-broker API
+Group: Automotive/Documentation
+Requires: %{name} = %{version}-%{release}
+
+%description doc
+Document files that describe the D-Bus API exposed by automotive-message-broker
+
+%if %{with qt5}
+%package plugins-qtmainloop
+Summary: qt5 mainloop plugin
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires: qt5-qtcore
+
+%description plugins-qtmainloop
+Qt mainloop plugin enables qt-based source and sink plugins to run using qt mainloop
+
+%package plugins-websocket
+Summary: Websocket source and sink plugins
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires: libwebsockets
+Requires: qt5-qtcore
+
+%description plugins-websocket
+websocket source and sink plugins
+
+%package plugins-opencvlux
+Summary: Plugin for simulating ExteriorBrightness using a common webcam
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires: opencv
+
+%description plugins-opencvlux
+Plugin for simulating ExteriorBrightness using a common webcam
+
+%package plugins-bluetooth
+Summary: Interface to AMB over bluetooth
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description plugins-bluetooth
+Bluetooth SPP server interface
+%endif
+
+%package plugins
+Summary: Various plugins for automotive-message-broker
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description plugins
+Collection of plugins for automotive-message-broker. Contains example, demo and dbus plugins.
+
+%package plugins-common
+Summary: Common plugin library
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description plugins-common
+library containing a kitchen-sink of common utility functions
+
+%package plugins-obd2
+Summary: OBD-II plugin
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires: %{name}-plugins-common = %{version}-%{release}
+
+%description plugins-obd2
+OBD-II plugin that uses ELM 327-compatible scantools to access vehicle data
+
+%package plugins-wheel
+Summary: Source plugin for using the Logitech G27 racing wheel
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description plugins-wheel
+source plugin for using the Logitech G27 racing wheel package
+
+%package plugins-database
+Summary: Database logging plugin for automotive-message-broker
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires: sqlite
+
+%description plugins-database
+Database logging plugin for automotive-message-broker package
+
+%package plugins-murphy
+Summary: Plugin for integration with the murphy policy system
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires: murphy
+
+%description plugins-murphy
+Plugin for integration with the murphy policy system package
+
+%package plugins-gpsnmea
+Summary: Plugin that provides gps data from nmea devices
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description plugins-gpsnmea
+Plugin that provides location data from nmea devices including bluetooth
+
+%package plugins-test
+Summary: Plugin that tests AMB code
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description plugins-test
+Plugin that tests some internal AMB code and plugin functionality. This plugin will assert if something is wrong.
+
+%package plugins-cangen
+Summary: Plugin that generates CAN data
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description plugins-cangen
+CAN frames generator plug-in for the AMB CAN Simulator
+
+%package plugins-cansim
+Summary: CAN frames listener plug-in for the AMB CAN Simulator
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description plugins-cansim
+CAN frames listener plug-in for the AMB CAN Simulator package
+
+%if %{with qt5}
+%package plugins-bluemonkey
+Summary: javascript plugin engine
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires: qt5-qtdeclarative
+Requires: %{name}-plugins-qtmainloop
+
+%description plugins-bluemonkey
+Engine for creating scriptable plugins for AMB
+
+%package -n bluemonkey-modules-db
+Summary: javascript plugin engine db module
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires: qt5-plugin-sqldriver-sqlite
+
+%description -n bluemonkey-modules-db
+Engine for creating scriptable plugins for AMB - db module
+
+%package -n bluemonkey-modules-dbus
+Summary: javascript plugin engine dbus module
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires: qt5-qtdbus
+
+%description -n bluemonkey-modules-dbus
+Engine for creating scriptable plugins for AMB - dbus module
+
+%endif
+
+%package xwalk-vehicle-extension
+Summary: crosswalk vehicle API extension
+Group: Automotive/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires: crosswalk
+
+%description xwalk-vehicle-extension
+Crosswalk vehicle API extension based on the W3C Automotive Business Group Vehicle and Data API Specification
+
+%prep
+%setup -q -n %{name}-%{version}
+
+%build
+%cmake \
+ -Dxwalk_vehicle_extension=ON \
+ -DXWALK_EXTENSION_PATH=/tizen-extensions-crosswalk \
+%if %{with qt5}
+ -Dqtmainloop=ON \
+ -Dopencvlux_plugin=ON \
+ -Dwebsocket_plugin=ON \
+ -Dbluetooth_plugin=ON \
+ -Dbluemonkey_plugin=ON \
+%endif
+ -Ddatabase_plugin=ON \
+ -Dmurphy_plugin=ON \
+ -Dobd2_plugin=ON \
+ -Dtest_plugin=ON \
+ -Dgpsnmea_plugin=ON \
+ -Dcangen_plugin=ON \
+ -Dcansim_plugin=ON \
+ -Dusebluez5=ON \
+ -Denable_docs=ON
+
+
+%__make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+mkdir -p %{buildroot}%{_unitdir}/network.target.wants
+cp packaging.in/ambd.service.systemd.tizen %{buildroot}%{_unitdir}/ambd.service
+ln -s ../ambd.service %{buildroot}%{_unitdir}/network.target.wants/ambd.service
+%install_service multi-user.target.wants ambd.service
+
+cp packaging/config.tizen %{buildroot}%{_sysconfdir}/ambd/
+
+%post -p /sbin/ldconfig
+%postun -p /sbin/ldconfig
+
+%post plugins -p /sbin/ldconfig
+%postun plugins -p /sbin/ldconfig
+
+%files
+%defattr(-,root,root,-)
+%manifest packaging/amb.manifest
+%config %{_sysconfdir}/ambd/config
+%config %{_sysconfdir}/ambd/config.tizen
+%config %{_sysconfdir}/ambd/examples/*
+%{_bindir}/ambd
+%{_libdir}/libamb.so*
+%{_unitdir}/ambd.service
+%{_unitdir}/network.target.wants/ambd.service
+%{_unitdir}/multi-user.target.wants/ambd.service
+%{_bindir}/amb-get
+%{_bindir}/amb-get-history
+%{_bindir}/amb-set
+%{_bindir}/amb-listen
+%{_bindir}/ambctl
+
+%files devel
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_includedir}/amb/*.h
+%{_includedir}/amb/*.hpp
+%{_libdir}/pkgconfig/*.pc
+
+%if %{with qt5}
+%files plugins-qtmainloop
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/qtmainloopplugin.so
+
+%files plugins-websocket
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/websocketsource.so
+%{_libdir}/%{name}/websocketsink.so
+
+%files plugins-opencvlux
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/opencvluxplugin.so
+%{_sysconfdir}/ambd/plugins.d/opencvlux
+
+%files plugins-bluetooth
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/bluetoothplugin.so
+%config %{_sysconfdir}/dbus-1/system.d/ambbt.conf
+%{_sysconfdir}/ambd/plugins.d/bluetooth
+%{_bindir}/testAmbBt
+%endif
+
+%files plugins
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/examplesourceplugin.so
+%{_libdir}/%{name}/examplesinkplugin.so
+%{_libdir}/%{name}/dbussinkplugin.so
+%{_libdir}/%{name}/demosinkplugin.so
+%config %{_sysconfdir}/dbus-1/system.d/amb.conf
+%{_sysconfdir}/ambd/plugins.d/dbus
+%{_sysconfdir}/ambd/plugins.d/examplesink
+%{_sysconfdir}/ambd/plugins.d/examplesource
+
+%files plugins-common
+%manifest packaging.in/amb.manifest.plugins
+%defattr(-,root,root,-)
+%{_libdir}/libamb-plugins-common.so
+
+%files plugins-wheel
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/wheelsourceplugin.so
+
+%files plugins-obd2
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/obd2sourceplugin.so
+%{_sysconfdir}/ambd/plugins.d/obd2
+
+%files plugins-database
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/databasesinkplugin.so
+%{_sysconfdir}/ambd/plugins.d/database
+
+%files plugins-murphy
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/murphysourceplugin.so
+
+%files plugins-gpsnmea
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/gpsnmea.so
+
+%files doc
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%doc %{_docdir}/%{name}/*
+
+%files plugins-test
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/testplugin.so
+
+%files plugins-cangen
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/cangenplugin.so
+%{_bindir}/gen-set
+
+%files plugins-cansim
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/cansimplugin.so
+
+
+%if %{with qt5}
+
+%files plugins-bluemonkey
+%defattr(-,root,root,-)
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/bluemonkeyplugin.so
+%config %{_sysconfdir}/ambd/bluemonkey
+%{_sysconfdir}/ambd/plugins.d/bluemonkey
+
+%files -n bluemonkey-modules-db
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/bluemonkeyDbModule.so
+
+%files -n bluemonkey-modules-dbus
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/%{name}/bluemonkeyDBusModule.so
+
+%endif
+
+%files xwalk-vehicle-extension
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/tizen-extensions-crosswalk/*
+%{_datadir}/%{name}/xwalk/examples/*
diff --git a/packaging.in/config.tizen.in b/packaging.in/config.tizen.in
new file mode 100644
index 00000000..e299cb3b
--- /dev/null
+++ b/packaging.in/config.tizen.in
@@ -0,0 +1,18 @@
+{
+"sources" :
+ [
+ {
+ "name" : "Murphy Source",
+ "path" : "@PLUGIN_INSTALL_PATH@/murphysourceplugin.so",
+ "address" : "unxs:/tmp/murphy/amb"
+ }
+ ],
+"sinks":
+ [
+ {
+ "name" : "DBusSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so"
+ }
+ ]
+}
+
diff --git a/packaging.in/debian/automotive-message-broker-plugins-bluemonkey.debian.install b/packaging.in/debian/automotive-message-broker-plugins-bluemonkey.debian.install
new file mode 100644
index 00000000..9e14b1d2
--- /dev/null
+++ b/packaging.in/debian/automotive-message-broker-plugins-bluemonkey.debian.install
@@ -0,0 +1,5 @@
+debian/tmp/@PLUGIN_INSTALL_PATH@/bluemonkeyplugin.so
+debian/tmp/@PLUGIN_INSTALL_PATH@/bluemonkeyDbModule.so
+debian/tmp/@PLUGIN_INSTALL_PATH@/bluemonkeyDBusModule.so
+debian/tmp/etc/ambd/bluemonkey/config.js
+debian/tmp/etc/ambd/plugins.d/bluemonkey
diff --git a/packaging.in/debian/automotive-message-broker-plugins-bluetooth.debian.install b/packaging.in/debian/automotive-message-broker-plugins-bluetooth.debian.install
new file mode 100644
index 00000000..409d1ab6
--- /dev/null
+++ b/packaging.in/debian/automotive-message-broker-plugins-bluetooth.debian.install
@@ -0,0 +1,3 @@
+debian/tmp/@PLUGIN_INSTALL_PATH@/bluetoothplugin.so
+debian/tmp/usr/bin/testAmbBt
+
diff --git a/packaging.in/debian/automotive-message-broker-plugins-qtmainloop.debian.install b/packaging.in/debian/automotive-message-broker-plugins-qtmainloop.debian.install
new file mode 100644
index 00000000..9691ea63
--- /dev/null
+++ b/packaging.in/debian/automotive-message-broker-plugins-qtmainloop.debian.install
@@ -0,0 +1,3 @@
+debian/tmp/@PLUGIN_INSTALL_PATH@/qtmainloopplugin.so
+
+
diff --git a/packaging.in/debian/automotive-message-broker-plugins.debian.install b/packaging.in/debian/automotive-message-broker-plugins.debian.install
new file mode 100644
index 00000000..3253b6b3
--- /dev/null
+++ b/packaging.in/debian/automotive-message-broker-plugins.debian.install
@@ -0,0 +1,5 @@
+debian/tmp/@PLUGIN_INSTALL_PATH@/examplesourceplugin.so
+debian/tmp/@PLUGIN_INSTALL_PATH@/examplesinkplugin.so
+debian/tmp/@PLUGIN_INSTALL_PATH@/dbussinkplugin.so
+debian/tmp/@PLUGIN_INSTALL_PATH@/demosinkplugin.so
+debian/tmp/etc/dbus-1/system.d/amb.conf
diff --git a/packaging.in/debian/automotive-message-broker.debian.install b/packaging.in/debian/automotive-message-broker.debian.install
new file mode 100644
index 00000000..99738b44
--- /dev/null
+++ b/packaging.in/debian/automotive-message-broker.debian.install
@@ -0,0 +1,3 @@
+debian/tmp/usr/bin/ambd
+debian/tmp/usr/bin/ambctl
+debian/tmp/etc/ambd/config
diff --git a/packaging.in/debian/changelog b/packaging.in/debian/changelog
new file mode 100644
index 00000000..365f092a
--- /dev/null
+++ b/packaging.in/debian/changelog
@@ -0,0 +1,5 @@
+automotive-message-broker (@PROJECT_VERSION@) utopic; urgency=low
+
+ * @PROJECT_VERSION@ release
+
+ -- Kevron Rees <tripzero.kev@gmail.com> Tue, 30 Dec 2014 15:17:51 -0700
diff --git a/packaging.in/debian/control.debian.in b/packaging.in/debian/control.debian.in
new file mode 100644
index 00000000..b4d6b5f8
--- /dev/null
+++ b/packaging.in/debian/control.debian.in
@@ -0,0 +1,66 @@
+Source: automotive-message-broker
+Section: Utilities
+Priority: extra
+Maintainer: Kevron Rees <tripzero.kev@gmail.com>
+Build-Depends: build-essential, debhelper (>= 8.0.0), cdbs, pkg-config, libltdl-dev, cmake, libboost-dev, uuid-dev, libglib2.0-dev, qtbase5-dev
+Standards-Version: 3.9.2
+Homepage: https://01.org/automotive-message-broker
+Vcs-Git: git@github.com:otcshare/automotive-message-broker.git
+Vcs-Browser: http://github.com/otcshare/automotive-message-broker.git
+
+Package: libamb
+Architecture: i386
+Version: @PROJECT_VERSION@
+Depends: ${shlibs:Depends}, ${misc:Despends}
+Description: Supporting amb library
+
+Package: libamb-dev
+Section: devel
+Architecture: i386
+Version: @PROJECT_VERSION@
+Depends: libamb, uuid-dev, libjson-c-dev
+Description: Vehicle data abstraction and multiplexing daemon
+ Vehicle data abstraction and multiplexing plugin framework
+ which provides a communications interface to CAN, OBDII and GPS devices using
+ TCP, bluetooth or USB
+
+Package: automotive-message-broker
+Architecture: i386
+Version: @PROJECT_VERSION@
+Depends: ${shlibs:Depends}, ${misc:Depends}, libamb
+Description: Vehicle data abstraction and multiplexing daemon
+ Vehicle data abstraction and multiplexing daemon implemented as
+ plugin framework that communicates to OBDII and GPS devices
+
+Package: automotive-message-broker-plugins
+Architecture: i386
+Version: @PROJECT_VERSION@
+Depends: ${shlibs:Depends}, ${misc:Depends}, libamb
+Description: Vehicle data abstraction and multiplexing daemon
+ Vehicle data abstraction and multiplexing daemon implemented as
+ plugin framework that communicates to OBDII and GPS devices
+
+Package: automotive-message-broker-plugins-qtmainloop
+Architecture: i386
+Version: @PROJECT_VERSION@
+Depends: ${shlibs:Depends}, ${misc:Depends}, libamb
+Description: Vehicle data abstraction and multiplexing daemon
+ Vehicle data abstraction and multiplexing daemon implemented as
+ plugin framework that communicates to OBDII and GPS devices
+
+Package: automotive-message-broker-plugins-bluemonkey
+Architecture: i386
+Version: @PROJECT_VERSION@
+Depends: ${shlibs:Depends}, ${misc:Depends}, libamb, automotive-message-broker-plugins-qtmainloop
+Description: Vehicle data abstraction and multiplexing daemon
+ Vehicle data abstraction and multiplexing daemon implemented as
+ plugin framework that communicates to OBDII and GPS devices
+
+Package: automotive-message-broker-plugins-bluetooth
+Architecture: i386
+Version: @PROJECT_VERSION@
+Depends: ${shlibs:Depends}, ${misc:Depends}, libamb, automotive-message-broker-plugins-qtmainloop
+Description: Vehicle data abstraction and multiplexing daemon
+ Vehicle data abstraction and multiplexing daemon implemented as
+ plugin framework that communicates to OBDII and GPS devices
+
diff --git a/packaging.in/debian/libamb-dev.debian.install b/packaging.in/debian/libamb-dev.debian.install
new file mode 100644
index 00000000..455bf20a
--- /dev/null
+++ b/packaging.in/debian/libamb-dev.debian.install
@@ -0,0 +1,3 @@
+debian/tmp/@INCLUDE_INSTALL_DIR@/amb/*.h
+debian/tmp/@INCLUDE_INSTALL_DIR@/amb/*.hpp
+debian/tmp/@LIB_INSTALL_DIR@/pkgconfig/*.pc
diff --git a/packaging.in/debian/libamb.debian.install b/packaging.in/debian/libamb.debian.install
new file mode 100644
index 00000000..53f200d8
--- /dev/null
+++ b/packaging.in/debian/libamb.debian.install
@@ -0,0 +1 @@
+debian/tmp/@LIB_INSTALL_DIR@/libamb.so*
diff --git a/packaging.in/debian/rules b/packaging.in/debian/rules
new file mode 100755
index 00000000..451f74aa
--- /dev/null
+++ b/packaging.in/debian/rules
@@ -0,0 +1,21 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+export DH_VERBOSE=1
+
+# in template file --AC
+#%:
+# dh $@
+
+#all the rest copied from trip0's libobd debian/rules file --AC
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/cmake.mk
+
+DEB_CMAKE_NORMAL_ARGS += -Dbluemonkey_plugin=ON -Dbluetooth_plugin=ON -Dqtmainloop=ON
+DEB_BUILD_OPTIONS += parallel=8
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
new file mode 100644
index 00000000..6b119c83
--- /dev/null
+++ b/plugins/CMakeLists.txt
@@ -0,0 +1,53 @@
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs})
+
+set(examplesourceplugin_headers exampleplugin.h)
+set(examplesourceplugin_sources exampleplugin.cpp)
+
+add_library(examplesourceplugin MODULE ${examplesourceplugin_sources})
+set_target_properties(examplesourceplugin PROPERTIES PREFIX "")
+target_link_libraries(examplesourceplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries})
+
+
+set(examplesinkplugin_headers examplesink.h)
+set(examplesinkplugin_sources examplesink.cpp)
+
+add_library(examplesinkplugin MODULE ${examplesinkplugin_sources})
+set_target_properties(examplesinkplugin PROPERTIES PREFIX "")
+target_link_libraries(examplesinkplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries})
+
+install(TARGETS examplesinkplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+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})
+
+
+if(enable_docs)
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/plugins.in.idl ${CMAKE_CURRENT_BINARY_DIR}/plugins.idl @ONLY)
+endif(enable_docs)
+
+add_subdirectory(common)
+
+add_subdirectory(wheel)
+add_subdirectory(dbus)
+add_subdirectory(websocket)
+add_subdirectory(obd2plugin)
+add_subdirectory(demosink)
+add_subdirectory(database)
+add_subdirectory(opencvlux)
+add_subdirectory(murphyplugin)
+add_subdirectory(testplugin)
+add_subdirectory(bluemonkey)
+add_subdirectory(gpsnmea)
+add_subdirectory(openxc)
+add_subdirectory(bluetooth)
+add_subdirectory(cansimplugin)
+add_subdirectory(cangenplugin)
+add_subdirectory(chrony)
diff --git a/plugins/bluemonkey/CMakeLists.txt b/plugins/bluemonkey/CMakeLists.txt
new file mode 100644
index 00000000..f829d4fc
--- /dev/null
+++ b/plugins/bluemonkey/CMakeLists.txt
@@ -0,0 +1,81 @@
+if(bluemonkey_plugin)
+
+message(STATUS "enabling bluemonkey plugin")
+
+set(qtmainloop ON CACHE INTERNAL "")
+
+find_package(Qt5Core REQUIRED)
+find_package(Qt5Network REQUIRED)
+find_package(Qt5Qml REQUIRED)
+if(Qt5Core_FOUND)
+ set(QT_INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS} ${Qt5Qml_INCLUDE_DIRS})
+ set(QT_LIBRARIES ${Qt5Core_LIBRARIES} ${Qt5Network_LIBRARIES} ${Qt5Qml_LIBRARIES})
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
+ add_definitions(${Qt5Core_DEFINITIONS})
+ add_definitions(-DQT_NO_KEYWORDS)
+ add_definitions(-DUSE_QT_CORE)
+endif(Qt5Core_FOUND)
+
+set(CMAKE_AUTOMOC ON)
+
+find_library(communi NAMES Communi)
+
+if(communi)
+ message(STATUS "enabling irc bluemonkey module")
+ set(communi_INCLUDE_DIRS /usr/include/qt5/Communi)
+ set(communi_LIBRARIES -lCommuni)
+ add_definitions(-DCOMMUNI_SHARED)
+
+ add_library(bluemonkeyIrcModule MODULE irccoms.cpp)
+ set_target_properties(bluemonkeyIrcModule PROPERTIES PREFIX "")
+ target_link_libraries(bluemonkeyIrcModule ${link_libraries} amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${QT_LIBRARIES} ${communi_LIBRARIES})
+ install(TARGETS bluemonkeyIrcModule LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+endif(communi)
+
+find_package(Qt5Sql)
+
+if(Qt5Sql_FOUND)
+ message(STATUS "enabling database bluemonkey module")
+ add_library(bluemonkeyDbModule MODULE db.cpp)
+ set_target_properties(bluemonkeyDbModule PROPERTIES PREFIX "")
+ target_link_libraries(bluemonkeyDbModule ${link_libraries} amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${QT_LIBRARIES} ${Qt5Sql_LIBRARIES})
+ install(TARGETS bluemonkeyDbModule LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+endif()
+
+find_package(Qt5DBus)
+
+if(Qt5DBus_FOUND)
+ message(STATUS "enabling dbus bluemonkey module")
+ add_library(bluemonkeyDBusModule MODULE bmdbus.cpp)
+ set_target_properties(bluemonkeyDBusModule PROPERTIES PREFIX "")
+ target_link_libraries(bluemonkeyDBusModule ${link_libraries} amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${QT_LIBRARIES} ${Qt5DBus_LIBRARIES})
+ set(QT_INCLUDE_DIRS ${QT_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS})
+ install(TARGETS bluemonkeyDBusModule LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+endif()
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${communi_INCLUDE_DIRS} ${QT_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/plugins/common)
+
+set(bluemonkeyplugin_headers bluemonkey.h authenticate.h)
+set(bluemonkeyplugin_sources bluemonkey.cpp authenticate.cpp)
+
+add_library(bluemonkeyplugin MODULE ${bluemonkeyplugin_sources})
+set_target_properties(bluemonkeyplugin PROPERTIES PREFIX "")
+target_link_libraries(bluemonkeyplugin dl amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${QT_LIBRARIES} ${communi_LIBRARIES} amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common)
+
+set(config_files ${CMAKE_CURRENT_BINARY_DIR}/config.js)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.js ${CMAKE_CURRENT_BINARY_DIR}/config.js @ONLY)
+
+install(TARGETS bluemonkeyplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+install (FILES ${config_files} DESTINATION /etc/ambd/bluemonkey)
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_BINARY_DIR}/bluemonkey.README.md @ONLY)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/bluemonkey.in.idl ${CMAKE_CURRENT_BINARY_DIR}/docs/bluemonkey.idl @ONLY)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/bluemonkey.in.json ${CMAKE_CURRENT_BINARY_DIR}/bluemonkey @ONLY)
+
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/bluemonkey DESTINATION ${PLUGIN_SEGMENT_INSTALL_PATH})
+
+set(bluemonkey_doc_files ${CMAKE_CURRENT_BINARY_DIR}/bluemonkey.README.md)
+
+install (FILES ${bluemonkey_doc_files} DESTINATION ${DOC_INSTALL_DIR}/plugins)
+
+endif(bluemonkey_plugin)
diff --git a/plugins/bluemonkey/Doxyfile.in b/plugins/bluemonkey/Doxyfile.in
new file mode 100644
index 00000000..ee0e2735
--- /dev/null
+++ b/plugins/bluemonkey/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/bluemonkey/README b/plugins/bluemonkey/README
new file mode 100644
index 00000000..77748294
--- /dev/null
+++ b/plugins/bluemonkey/README
@@ -0,0 +1,31 @@
+# Bluemonkey Plugin {#bluemonkey_plugin}
+
+[TOC]
+# Bluemonkey Plugin
+Version: @PROJECT_VERSION@
+
+Bluemonkey is a javascript rendering engine that allows the scripting of source plugin behavior in javascript.
+
+To use the OBD-II Source plugin, add the following config to your /etc/ambd/config:
+
+~~~~~~~~~~~~~{.js}
+{
+ "name" : "bluemonkey",
+ "path" : "@PLUGIN_INSTALL_PATH@/bluemonkeyplugin.so",
+ "config" : "/etc/ambd/bluemonkey/config.js"
+}
+~~~~~~~~~~~~~
+
+# Configuration Key Definitions:
+
+| Key | Definition | Default Value |
+| :---------------- | :---------------------------------------------------------------------- | :----------------- |
+| "name" | Name of plugin | |
+| "path" | Path to plugin on the filesystem | |
+| "config" | Path to the bluemonkey configuration script | "0" |
+
+
+# Bluemonkey Javascript API:
+
+see bluemonkey.idl
+
diff --git a/plugins/bluemonkey/agent.cpp b/plugins/bluemonkey/agent.cpp
new file mode 100644
index 00000000..85e26ddd
--- /dev/null
+++ b/plugins/bluemonkey/agent.cpp
@@ -0,0 +1,41 @@
+#include "agent.h"
+#include <debugout.h>
+#include <QTimer>
+#include <QScriptEngine>
+
+BluemonkeyAgent::BluemonkeyAgent(QScriptEngine *engine)
+ :QScriptEngineAgent(engine)
+{
+}
+
+void BluemonkeyAgent::scriptLoad(qint64 id, const QString &program, const QString &fileName, int baseLineNumber)
+{
+ DebugOut()<<"executing script"<<endl;
+
+ QTimer *timer = new QTimer();
+ timer->setSingleShot(true);
+ timer->connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
+ timer->start(5000);
+
+ timerIdMap[timer] = id;
+}
+
+void BluemonkeyAgent::timeout()
+{
+ quint64 id = timerIdMap[sender()];
+
+ if(idList.contains(id))
+ {
+ DebugOut()<<"script aborted evaluation. timed out."<<endl;
+ engine()->abortEvaluation();
+ }
+
+ timerIdMap.remove(sender());
+
+ sender()->deleteLater();
+}
+
+void BluemonkeyAgent::scriptUnload(qint64 id)
+{
+ idList.removeAll(id);
+}
diff --git a/plugins/bluemonkey/agent.h b/plugins/bluemonkey/agent.h
new file mode 100644
index 00000000..840cc534
--- /dev/null
+++ b/plugins/bluemonkey/agent.h
@@ -0,0 +1,24 @@
+#ifndef AGENT_H_
+#define AGENT_H_
+
+#include <QScriptEngineAgent>
+#include <QObject>
+
+class BluemonkeyAgent: public QObject, public QScriptEngineAgent
+{
+ Q_OBJECT
+public:
+ BluemonkeyAgent(QScriptEngine* engine);
+ void scriptLoad (qint64 id, const QString &program, const QString &fileName, int baseLineNumber );
+ void scriptUnload(qint64 id);
+
+private Q_SLOTS:
+ void timeout();
+
+private:
+ QList<quint64> idList;
+ QMap<QObject*,quint64> timerIdMap;
+};
+
+
+#endif
diff --git a/plugins/bluemonkey/authSettings.js b/plugins/bluemonkey/authSettings.js
new file mode 100644
index 00000000..f68a0d54
--- /dev/null
+++ b/plugins/bluemonkey/authSettings.js
@@ -0,0 +1 @@
+auth.pin = "1234"
diff --git a/plugins/bluemonkey/authenticate.cpp b/plugins/bluemonkey/authenticate.cpp
new file mode 100644
index 00000000..81a540fd
--- /dev/null
+++ b/plugins/bluemonkey/authenticate.cpp
@@ -0,0 +1,54 @@
+#include "authenticate.h"
+#include <QSettings>
+#include <QJSEngine>
+#include <QFile>
+#include <QtDebug>
+
+Authenticate::Authenticate(std::map<std::string, std::string> config, QObject *parent) :
+ QObject(parent)
+{
+ QSettings settings;
+ authorized = settings.value("authorized").toStringList();
+
+ QJSEngine engine;
+
+ QJSValue eventEngineValue = engine.newQObject(this);
+ engine.globalObject().setProperty("auth", eventEngineValue);
+
+ QString str = config["authSettings"].c_str();
+
+ QFile file(str);
+ if(!file.open(QIODevice::ReadOnly))
+ {
+ qDebug()<<"failed to open config file: "<<str;
+ return;
+ }
+
+ QString script = file.readAll();
+
+ file.close();
+
+ engine.evaluate(script);
+
+}
+
+bool Authenticate::isAuthorized(QString prefix)
+{
+ return(authorized.contains(prefix));
+}
+
+bool Authenticate::authorize(QString prefix, QString password)
+{
+ if(password == mPin && !authorized.contains(prefix))
+ {
+ authorized.append(prefix);
+ QSettings settings;
+ settings.setValue("authorized", authorized);
+ qDebug("authorized");
+
+ return true;
+ }
+
+ qDebug("failed to authorize or already authorized");
+ return false;
+}
diff --git a/plugins/bluemonkey/authenticate.h b/plugins/bluemonkey/authenticate.h
new file mode 100644
index 00000000..df842833
--- /dev/null
+++ b/plugins/bluemonkey/authenticate.h
@@ -0,0 +1,28 @@
+#ifndef AUTHENTICATE_H
+#define AUTHENTICATE_H
+
+#include <QObject>
+#include <QStringList>
+#include <map>
+#include <string>
+
+class Authenticate : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString pin READ pin WRITE setPin)
+public:
+ explicit Authenticate(std::map<std::string, std::string> config, QObject *parent = 0);
+ void setPin(QString p) { mPin = p; }
+ QString pin() { return mPin; }
+
+
+public Q_SLOTS:
+ bool isAuthorized(QString prefix);
+ bool authorize(QString prefix, QString pin);
+
+private:
+ QStringList authorized;
+ QString mPin;
+};
+
+#endif // AUTHENTICATE_H
diff --git a/plugins/bluemonkey/bluemonkey.cpp b/plugins/bluemonkey/bluemonkey.cpp
new file mode 100644
index 00000000..c4078343
--- /dev/null
+++ b/plugins/bluemonkey/bluemonkey.cpp
@@ -0,0 +1,600 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "bluemonkey.h"
+#include "abstractroutingengine.h"
+#include "ambplugin.h"
+#include "debugout.h"
+
+#include "dbusplugin.h"
+#include "dbusexport.h"
+
+#include <QJsonDocument>
+#include <QJSEngine>
+#include <QDateTime>
+#include <QString>
+#include <QFile>
+#include <QTimer>
+#include <QtQml>
+
+#include <dlfcn.h>
+
+#define foreach Q_FOREACH
+
+typedef std::map<std::string, QObject*> create_bluemonkey_module_t(std::map<std::string, std::string> config, QObject* parent);
+
+extern "C" void create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ auto plugin = new AmbPlugin<BluemonkeySink>(routingengine, config);
+ plugin->init();
+}
+
+QVariant gvariantToQVariant(GVariant *value)
+{
+ GVariantClass c = g_variant_classify(value);
+ if(c == G_VARIANT_CLASS_BOOLEAN)
+ return QVariant((bool) g_variant_get_boolean(value));
+
+ else if(c == G_VARIANT_CLASS_BYTE)
+ return QVariant((char) g_variant_get_byte(value));
+
+ else if(c == G_VARIANT_CLASS_INT16)
+ return QVariant((int) g_variant_get_int16(value));
+
+ else if(c == G_VARIANT_CLASS_UINT16)
+ return QVariant((unsigned int) g_variant_get_uint16(value));
+
+ else if(c == G_VARIANT_CLASS_INT32)
+ return QVariant((int) g_variant_get_int32(value));
+
+ else if(c == G_VARIANT_CLASS_UINT32)
+ return QVariant((unsigned int) g_variant_get_uint32(value));
+
+ else if(c == G_VARIANT_CLASS_INT64)
+ return QVariant((long long) g_variant_get_int64(value));
+
+ else if(c == G_VARIANT_CLASS_UINT64)
+ return QVariant((unsigned long long) g_variant_get_uint64(value));
+
+ else if(c == G_VARIANT_CLASS_DOUBLE)
+ return QVariant(g_variant_get_double(value));
+
+ else if(c == G_VARIANT_CLASS_STRING)
+ return QVariant(g_variant_get_string(value, NULL));
+
+ else if(c == G_VARIANT_CLASS_ARRAY)
+ {
+ gsize dictsize = g_variant_n_children(value);
+ QVariantList list;
+ for (int i=0; i<dictsize; i++)
+ {
+ GVariant *childvariant = g_variant_get_child_value(value, i);
+ GVariant *innervariant = g_variant_get_variant(childvariant);
+ list.append(gvariantToQVariant(innervariant));
+ }
+ return list;
+ }
+
+ else
+ return QVariant::Invalid;
+
+}
+
+AbstractPropertyType* qVariantToAbstractPropertyType(QString name, QVariant var)
+{
+ if(!var.isValid())
+ return nullptr;
+
+ if(var.type() == QVariant::UInt)
+ return new BasicPropertyType<uint>(name.toStdString(), var.toUInt());
+ else if(var.type() == QVariant::Double)
+ return new BasicPropertyType<double>(name.toStdString(), var.toDouble());
+ else if(var.type() == QVariant::Bool)
+ return new BasicPropertyType<bool>(name.toStdString(), var.toBool());
+ else if(var.type() == QVariant::Int)
+ return new BasicPropertyType<int>(name.toStdString(), var.toInt());
+ else if(var.type() == QVariant::String)
+ return new StringPropertyType(name.toStdString(), var.toString().toStdString());
+ else if(var.type() == QVariant::List && var.toList().count())
+ {
+ QVariant subVariant = var.toList().at(0);
+ if(subVariant.type() == QVariant::UInt)
+ return new ListPropertyType<BasicPropertyType<uint>>(name.toStdString(), subVariant.toUInt());
+ else if(subVariant.type() == QVariant::Double)
+ return new ListPropertyType<BasicPropertyType<double>>(name.toStdString(), subVariant.toDouble());
+ else if(subVariant.type() == QVariant::Bool)
+ return new ListPropertyType<BasicPropertyType<bool>>(name.toStdString(), subVariant.toBool());
+ else if(subVariant.type() == QVariant::Int)
+ return new ListPropertyType<BasicPropertyType<int>>(name.toStdString(), subVariant.toInt());
+ else if(subVariant.type() == QVariant::String)
+ return new ListPropertyType<StringPropertyType>(name.toStdString(), subVariant.toString().toStdString());
+ }
+ return nullptr;
+}
+
+QVariant toQVariant(AbstractPropertyType* val)
+{
+ QVariantMap value;
+
+ value["name"] = val->name.c_str();
+ value["zone"] = val->zone;
+ value["source"] = val->sourceUuid.c_str();
+ value["timestamp"] = val->timestamp;
+ value["sequence"] = val->sequence;
+ value["value"] = gvariantToQVariant(val->toVariant());
+
+ return value;
+}
+
+class BluemonkeyDBusInterface: public DBusSink
+{
+public:
+ BluemonkeyDBusInterface(std::string ifaceName, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink(ifaceName, re, connection)
+ {
+
+ }
+};
+
+BluemonkeySink::BluemonkeySink(AbstractRoutingEngine* e, map<string, string> config, AbstractSource &parent)
+ : QObject(0), AmbPluginImpl(e, config, parent), engine(nullptr), mSilentMode(false)
+{
+ QTimer::singleShot(1,this,SLOT(reloadEngine()));
+
+ auth = new Authenticate(config, this);
+}
+
+BluemonkeySink::~BluemonkeySink()
+{
+ Q_FOREACH(void* module, modules)
+ {
+ dlclose(module);
+ }
+
+ engine->deleteLater();
+}
+
+
+PropertyList BluemonkeySink::subscriptions()
+{
+
+}
+
+void BluemonkeySink::supportedChanged(const PropertyList & supportedProperties)
+{
+ DebugOut()<<"supported changed"<<endl;
+}
+
+void BluemonkeySink::propertyChanged(AbstractPropertyType * value)
+{
+
+}
+
+const string BluemonkeySink::uuid() const
+{
+ return "bluemonkey";
+}
+
+int BluemonkeySink::supportedOperations()
+{
+ return AbstractSource::Get | AbstractSource::Set;
+}
+
+QObject *BluemonkeySink::subscribeTo(QString str)
+{
+ return new Property(str.toStdString(), "", routingEngine, Zone::None, this);
+}
+
+QObject *BluemonkeySink::subscribeTo(QString str, int zone, QString srcFilter)
+{
+ return new Property(str.toStdString(), srcFilter, routingEngine, zone, this);
+}
+
+QObject* BluemonkeySink::subscribeTo(QString str, int zone)
+{
+ return new Property(str.toStdString(), "", routingEngine, zone, this);
+}
+
+
+QStringList BluemonkeySink::sourcesForProperty(QString property)
+{
+ std::vector<std::string> list = routingEngine->sourcesForProperty(property.toStdString());
+ QStringList strList;
+ for(auto itr : list)
+ {
+ strList<<itr.c_str();
+ }
+
+ return strList;
+}
+
+QStringList BluemonkeySink::supportedProperties()
+{
+ PropertyList props = routingEngine->supported();
+ QStringList strList;
+ for(auto p : props)
+ {
+ strList<<p.c_str();
+ }
+
+ return strList;
+}
+
+
+bool BluemonkeySink::authenticate(QString pass)
+{
+
+}
+
+void BluemonkeySink::loadConfig(QString str)
+{
+ QFile file(str);
+ if(!file.open(QIODevice::ReadOnly))
+ {
+ DebugOut(DebugOut::Error)<<"failed to open config file: "<<str.toStdString()<<endl;
+ return;
+ }
+
+ QString script = file.readAll();
+
+ file.close();
+
+ DebugOut(7)<<"evaluating script: "<<script.toStdString()<<endl;
+
+ QJSValue val = engine->evaluate(script);
+
+ DebugOut()<<val.toString().toStdString()<<endl;
+
+ if(val.isError())
+ {
+ DebugOut(DebugOut::Error) << val.property("name").toString().toStdString() << endl;
+ DebugOut(DebugOut::Error) << val.property("message").toString().toStdString() << endl;
+ DebugOut(DebugOut::Error) << str.toStdString() << ":" <<val.property("lineNumber").toString().toStdString() << endl;
+ }
+}
+
+bool BluemonkeySink::loadModule(QString path)
+{
+ void* handle = dlopen(path.toUtf8().data(), RTLD_LAZY);
+
+ if(!handle)
+ {
+ DebugOut(DebugOut::Warning) << "bluemonkey load module failed: " << dlerror() << endl;
+ return false;
+ }
+
+ if(modules.contains(handle))
+ return false;
+
+ modules.push_back(handle);
+
+ void* c = dlsym(handle, "create");
+
+ if(!c)
+ {
+ DebugOut(DebugOut::Warning) << "bluemonkey load module failed: " << path.toStdString() << " " << dlerror() << endl;
+ return false;
+ }
+
+ create_bluemonkey_module_t* create = (create_bluemonkey_module_t*)(c);
+
+ std::map<std::string, QObject*> exports = create(configuration, this);
+
+ for(auto i : exports)
+ {
+ std::string obj = i.first;
+ if(!engine->globalObject().hasProperty(obj.c_str()))
+ {
+ QJSValue val = engine->newQObject(i.second);
+ engine->globalObject().setProperty(obj.c_str(), val);
+ }
+ }
+
+ return true;
+}
+
+void BluemonkeySink::reloadEngine()
+{
+ if(engine)
+ engine->deleteLater();
+
+ engine = new QJSEngine();
+
+ QJSValue value = engine->newQObject(this);
+ engine->globalObject().setProperty("bluemonkey", value);
+
+ QThread* thread = new QThread(this);
+
+ engine->moveToThread(thread);
+
+ thread->start();
+
+ loadConfig(configuration["config"].c_str());
+}
+
+void BluemonkeySink::writeProgram(QString program)
+{
+
+ QJSEngine temp;
+ QJSValue result = temp.evaluate(program);
+ if(result.isError())
+ {
+ DebugOut(DebugOut::Error)<<"Syntax error in program: "<<result.toString().toStdString()<<endl;
+ return;
+ }
+
+ QFile file(configuration["customPrograms"].c_str());
+
+ if(!file.open(QIODevice::ReadWrite | QIODevice::Append))
+ {
+ DebugOut(DebugOut::Error)<<"failed to open file: "<<file.fileName().toStdString()<<endl;
+ return;
+ }
+
+ file.write(program.toUtf8());
+ file.write("\n");
+
+ file.close();
+}
+
+void BluemonkeySink::log(QString str)
+{
+ DebugOut()<<str.toStdString()<<endl;
+}
+
+QObject *BluemonkeySink::createTimer()
+{
+ return new QTimer(this);
+}
+
+QObject *BluemonkeySink::createQObject()
+{
+ return new QObject(this);
+}
+
+void BluemonkeySink::getHistory(QStringList properties, QDateTime begin, QDateTime end, QJSValue cbFunction)
+{
+ double b = (double)begin.toMSecsSinceEpoch() / 1000.0;
+ double e = (double)end.toMSecsSinceEpoch() / 1000.0;
+ AsyncRangePropertyRequest request;
+ request.timeBegin = b;
+ request.timeEnd = e;
+
+ PropertyList reqlist;
+
+ foreach(QString prop, properties)
+ {
+ reqlist.push_back(prop.toStdString());
+ }
+
+ request.properties = reqlist;
+ request.completed = [&cbFunction](AsyncRangePropertyReply* reply)
+ {
+ if(!reply->success)
+ {
+ DebugOut(DebugOut::Error)<<"bluemoney get history call failed"<<endl;
+ return;
+ }
+
+ if(cbFunction.isCallable())
+ {
+ QVariantList list;
+
+ for(auto val : reply->values)
+ {
+ list.append(toQVariant(val));
+ }
+
+ QJSValue val = cbFunction.engine()->toScriptValue<QVariantList>(list);
+
+ cbFunction.call(QJSValueList()<<val);
+
+ }
+
+ delete reply;
+ };
+
+ routingEngine->getRangePropertyAsync(request);
+}
+
+void BluemonkeySink::createCustomProperty(QString name, QJSValue defaultValue, int zone)
+{
+ QVariant var = defaultValue.toVariant();
+
+ DebugOut() << "Variant value for: " << name.toStdString() << " is " << defaultValue.toString().toStdString() << endl;
+
+ auto create = [name, var]() -> AbstractPropertyType*
+ {
+ return qVariantToAbstractPropertyType(name, var);
+ };
+
+ addPropertySupport(zone, create);
+
+ AsyncSetPropertyRequest request;
+ request.property = name.toStdString();
+ request.zoneFilter = zone;
+ request.value = VehicleProperty::getPropertyTypeForPropertyNameValue(name.toStdString(), defaultValue.toString().toStdString());
+
+ routingEngine->updateSupported(supported(), PropertyList(), &source);
+ routingEngine->setProperty(request);
+}
+
+void BluemonkeySink::exportInterface(QString name, QJSValue properties)
+{
+ std::unordered_map<std::string, std::string> propertiesMap;
+
+ QVariantList tempProps = properties.toVariant().toList();
+
+ DebugOut() << "num keys: " << tempProps.size() << endl;
+
+ Q_FOREACH(QVariant i, tempProps)
+ {
+ QVariantMap obj = i.toMap();
+ propertiesMap[obj.firstKey().toStdString()] = obj.first().toString().toStdString();
+ }
+
+ DebugOut() << "exporting new dbus interface: " << name.toStdString() << endl;
+ auto exporter = amb::Exporter::instance();
+ exporter->exportProperty<DBusSink>(name.toStdString(), propertiesMap, routingEngine);
+}
+
+QVariant Property::value()
+{
+ return mValue ? gvariantToQVariant(mValue->toVariant()) : QVariant::Invalid;
+}
+
+void Property::setValue(QVariant v)
+{
+ if(v.type() == QVariant::List || v.type() == QVariant::Map)
+ {
+
+ QJsonDocument doc = QJsonDocument::fromVariant(v);
+
+ QString json = doc.toJson();
+
+ mValue->fromString(json.toStdString());
+ }
+ else
+ {
+ QString tempVal = v.toString();
+ mValue->fromString(tempVal.toStdString());
+ }
+
+ AsyncSetPropertyRequest request;
+ request.property = mValue->name;
+ request.value = mValue->copy();
+ request.completed = [&](AsyncPropertyReply* reply)
+ {
+ if(reply->success)
+ {
+ propertyChanged(reply->value);
+ }
+ else
+ {
+ DebugOut(DebugOut::Warning) << "Error, trying to set value: " << reply->error << endl;
+ }
+ delete reply;
+ };
+ routingEngine->setProperty(request);
+}
+
+void Property::getHistory(QDateTime begin, QDateTime end, QJSValue cbFunction)
+{
+ double b = (double)begin.toMSecsSinceEpoch() / 1000.0;
+ double e = (double)end.toMSecsSinceEpoch() / 1000.0;
+ AsyncRangePropertyRequest request;
+ request.timeBegin = b;
+ request.timeEnd = e;
+
+ PropertyList reqlist;
+ reqlist.push_back(mValue->name);
+
+ request.properties = reqlist;
+ request.completed = [&cbFunction](AsyncRangePropertyReply* reply)
+ {
+ if(!reply->success)
+ {
+ DebugOut(DebugOut::Error)<<"bluemoney get history call failed"<<endl;
+ return;
+ }
+
+ if(cbFunction.isCallable())
+ {
+ QVariantList list;
+
+ for(auto val : reply->values)
+ {
+ list.append(toQVariant(val));
+ }
+
+ QJSValue val = cbFunction.engine()->toScriptValue<QVariantList>(list);
+ cbFunction.call(QJSValueList()<<val);
+
+ }
+
+ delete reply;
+ };
+
+ routingEngine->getRangePropertyAsync(request);
+}
+
+Property::Property(VehicleProperty::Property prop, QString srcFilter, AbstractRoutingEngine* re, Zone::Type zone, QObject *parent)
+ :QObject(parent), AbstractSink(re, std::map<std::string,std::string>()),mValue(nullptr), mUuid(amb::createUuid()), mZone(zone)
+{
+ setType(prop.c_str());
+}
+
+QString Property::name()
+{
+ return mValue->name.c_str();
+}
+
+void Property::setType(QString t)
+{
+ if(mValue && name() != "")
+ routingEngine->unsubscribeToProperty(name().toStdString(), this);
+
+ routingEngine->subscribeToProperty(t.toStdString(), this);
+
+ mValue = VehicleProperty::getPropertyTypeForPropertyNameValue(t.toStdString());
+
+ if(!mValue)
+ return;
+
+ AsyncPropertyRequest request;
+ request.property = mValue->name;
+ request.completed = [this](AsyncPropertyReply* reply)
+ {
+ if(reply->success)
+ propertyChanged(reply->value);
+
+ delete reply;
+ };
+
+ routingEngine->getPropertyAsync(request);
+}
+
+void Property::propertyChanged(AbstractPropertyType *value)
+{
+ if(value->zone != mZone)
+ return;
+
+ if(mValue)
+ {
+ delete mValue;
+ }
+ mValue = value->copy();
+
+ changed(gvariantToQVariant(mValue->toVariant()));
+}
+
+
+QVariant BluemonkeySink::zonesForProperty(QString prop, QString src)
+{
+ PropertyInfo info = routingEngine->getPropertyInfo(prop.toStdString(), src.toStdString());
+
+ QVariantList list;
+
+ for(auto i : info.zones())
+ {
+ list << i;
+ }
+
+ return list;
+}
diff --git a/plugins/bluemonkey/bluemonkey.h b/plugins/bluemonkey/bluemonkey.h
new file mode 100644
index 00000000..f08e9002
--- /dev/null
+++ b/plugins/bluemonkey/bluemonkey.h
@@ -0,0 +1,168 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef BluemonkeySink_H
+#define BluemonkeySink_H
+
+#include <abstractsource.h>
+#include <ambpluginimpl.h>
+#include <uuidhelper.h>
+
+#include <map>
+
+#include <QObject>
+#include <QVariant>
+#include <QJsonDocument>
+#include <QDateTime>
+#include <QJSValue>
+#include <QThread>
+
+#include "authenticate.h"
+
+class QJSEngine;
+
+class Property: public QObject, public AbstractSink
+{
+ Q_OBJECT
+ Q_PROPERTY(QString name READ name)
+ Q_PROPERTY(QString source READ source)
+ Q_PROPERTY(double timestamp READ timestamp)
+ Q_PROPERTY(QVariant value READ value WRITE setValue)
+ Q_PROPERTY(int zone READ zone)
+
+public:
+ Property(VehicleProperty::Property, QString srcFilter, AbstractRoutingEngine * re, Zone::Type zone = Zone::None, QObject * parent = 0);
+
+ QString name();
+ void setType(QString t);
+
+ QString source()
+ {
+ return mValue->sourceUuid.c_str();
+ }
+
+ double timestamp()
+ {
+ return mValue->timestamp;
+ }
+
+ virtual PropertyList subscriptions() { return PropertyList(); }
+ virtual void supportedChanged(const PropertyList &)
+ {
+ DebugOut()<<"Bluemonkey Property Supported Changed"<<endl;
+ }
+
+ virtual void propertyChanged(AbstractPropertyType* value);
+
+ virtual const std::string uuid() { return mUuid; }
+
+ QVariant value();
+ void setValue(QVariant v);
+
+ void getHistory(QDateTime begin, QDateTime end, QJSValue cbFunction);
+
+ Zone::Type zone() { return mZone; }
+
+Q_SIGNALS:
+
+ void changed(QVariant val);
+
+private:
+ AbstractPropertyType* mValue;
+ const std::string mUuid;
+ Zone::Type mZone;
+
+};
+
+class BluemonkeySink : public QObject, public AmbPluginImpl
+{
+Q_OBJECT
+
+public:
+ using AmbPluginImpl::setProperty;
+ using QObject::setProperty;
+
+ BluemonkeySink(AbstractRoutingEngine* e, map<string, string> config, AbstractSource& parent);
+ ~BluemonkeySink();
+ virtual PropertyList subscriptions();
+ virtual void supportedChanged(const PropertyList & supportedProperties);
+ virtual void propertyChanged(AbstractPropertyType* value);
+ virtual const std::string uuid() const;
+
+ virtual int supportedOperations();
+
+private: //source privates
+
+ PropertyList mSupported;
+ std::list<AbstractPropertyType*> propertyValueCache;
+
+
+public Q_SLOTS:
+
+ QObject* subscribeTo(QString str);
+ QObject* subscribeTo(QString str, int zone);
+ QObject* subscribeTo(QString str, int zone, QString srcFilter);
+
+ QStringList sourcesForProperty(QString property);
+ QVariant zonesForProperty(QString property, QString src);
+
+ QStringList supportedProperties();
+
+ bool authenticate(QString pass);
+
+ void loadConfig(QString str);
+
+ bool loadModule(QString path);
+
+ void reloadEngine();
+
+ void writeProgram(QString program);
+
+ void log(QString str);
+
+ QObject* createTimer();
+ QObject* createQObject();
+
+ void getHistory(QStringList properties, QDateTime begin, QDateTime end, QJSValue cbFunction);
+
+ void setSilentMode(bool m)
+ {
+ mSilentMode = m;
+ }
+
+ void createCustomProperty(QString name, QJSValue defaultValue)
+ {
+ createCustomProperty(name, defaultValue, Zone::None);
+ }
+
+ void createCustomProperty(QString name, QJSValue defaultValue, int zone);
+
+ void exportInterface(QString name, QJSValue properties);
+
+private:
+ QList<void*> modules;
+ QJSEngine* engine;
+ QStringList configsToLoad;
+
+ Authenticate* auth;
+ bool mSilentMode;
+};
+
+
+#endif // BluemonkeySink_H
diff --git a/plugins/bluemonkey/bluemonkey.in.idl b/plugins/bluemonkey/bluemonkey.in.idl
new file mode 100644
index 00000000..f092f0e7
--- /dev/null
+++ b/plugins/bluemonkey/bluemonkey.in.idl
@@ -0,0 +1,198 @@
+/*!
+ * \tableofcontents
+ * \file bluemonkey.idl
+ * \section bluemonkey Bluemonkey Javascript API Documentation
+ * \version @PROJECT_VERSION@
+ *
+ * \section bluemonkey_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.
+ *
+ * the bluemonkey script engine is powered by Qt QML's javascript engine. It supports QObject types as well
+ * as ECMA script (javascript). All QObject properties, slots, and signals are available in javascript.
+ * \see Qt's QMetaObject system for additional details
+ *
+ * \section bluemonkey_properties Properties
+ * Bluemonkey uses internal property names (not DBus API interface names). These properties are defined in
+ * lib/vehicleproperty.h. There are mappings from AMB internal property names to DBus API properties in the
+ * <a href="ambdbusmappings_8idl">mappings documentation</a>. The mappings comes in handy when you want to implement properties that are
+ * exported as an DBus API interface (ie, org.automotive.VehicleSpeed).
+ * \section bluemonkey_example Example bluemonkey script
+ * \code
+ * var speedProperty = bluemonkey.subscribeTo("VehicleSpeed");
+ *
+ * var testTimer = bluemonkey.createTimer();
+ * testTimer.interval = 3000;
+ * testTimer.singleShot = false;
+ * testTimer.timeout.connect(function() {
+ * //VehicleSpeed
+ * speedProperty.value = Math.floor((Math.random() * 100) + 1);
+ * });
+ * testTimer.start();
+ * \endcode
+ * \section bluemonkey_js_api Javascript API documentation
+ * Javascript API documentation is found in bluemonkey.idl and is described using WebIDL. Plugin configuration documentation can be found in bluemonkey.README.
+ */
+
+ /*!
+ *
+ * \name @PROJECT_NAME@ Bluemonkey interface documentation
+ * \version @PROJECT_VERSION@
+ * \brief
+ */
+
+/*!
+ * \brief Entry point for bluemonkey
+ */
+partial interface Navigator {
+ readonly attribute Bluemonkey bluemonkey;
+};
+
+/*!
+ * \brief Bluemonkey interface
+ * Bluemonkey provides AMB plugin-like interfaces and allows the loading of other modules, timers, and QObject creation.
+ * Typical usage is such:
+ * \code
+ * var speedProperty = bluemonkey.subscribeTo("VehicleSpeed");
+ * bluemonkey.log("Current speed: " + speedProperty.value);
+ * \endcode
+ */
+interface Bluemonkey {
+ /*!
+ * \brief subscribe to a property
+ * \returns PropertyInterface representing the property
+ */
+ PropertyInterface subscribeTo(DOMString propertyName, optional unsigned short zone, optional DOMString source);
+
+ /*!
+ * \brief return the AMB sources that provide propertyName
+ */
+ DOMString[] sourcesForProperty(DOMString propertyName);
+
+ /*!
+ * \brief returns the available zones that contians propertyName
+ */
+ unsigned short[] zonesForProperty(DOMString propertyName);
+
+ /*!
+ * \brief return supported properties
+ */
+ DOMString[] supportedProperties();
+
+ /*!
+ * \brief load another script
+ */
+ void loadConfig(DOMString configFile);
+
+ /*!
+ * \brief load a bluemonkey module
+ */
+ void loadModule(DOMString moduleFile);
+
+ /*!
+ * \brief log text to AMB output
+ */
+ void log(DOMString text);
+
+ /*!
+ * \brief create a QTimer
+ * \return QTimer object
+ */
+ QTimer createTimer();
+
+ /*!
+ * \brief create a QObject
+ * \return empty QObject
+ */
+ QObject createQObject();
+
+ /*!
+ * \brief return logged data between "begin" and "end"
+ */
+ void getHistory(DOMString[] properties, Date begin, Date end, HistoryCallback callback);
+
+ /*!
+ * \brief creates a custom property
+ */
+ void createCustomProperty(DOMString name, any value, optional unsigned short zone);
+
+ /*!
+ * \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
+ */
+ readonly attribute DOMString type;
+
+ /*!
+ * \brief zone in the vehicle where this property is located
+ */
+ readonly attribute unsigned short zone;
+
+ /*!
+ * \brief value for this property
+ */
+ readonly attribute any value;
+
+ /*!
+ * \brief source where this property came from
+ */
+ readonly attribute DOMString source;
+
+ /*!
+ * \brief timestamp when this property last changed
+ */
+ readonly attribute DOMTimestamp timestamp;
+
+ /*!
+ * \brief changed signal
+ */
+ 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);
+};
+
+/*!
+* \brief Signal represents an way to connect to Qt signals and get a javascript callback
+*/
+interface Signal {
+ /*!
+ * \brief connect to this signal.
+ * callback will be called whenever the signal is emitted.
+ */
+ 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
+ */
+ attribute DOMString AmbPropertyName;
+
+ /*!
+ * \brief name you want to export as a DBus property
+ */
+ attribute DOMString DBusPropertyName;
+}
+
+callback ChangedCallback = void(any value); ();
+
+callback HistoryCallback = void(PropertyInterface[] data); ();
+
diff --git a/plugins/bluemonkey/bluemonkey.in.json b/plugins/bluemonkey/bluemonkey.in.json
new file mode 100644
index 00000000..9c1b8c7c
--- /dev/null
+++ b/plugins/bluemonkey/bluemonkey.in.json
@@ -0,0 +1,6 @@
+{
+ "name" : "Bluemonkey",
+ "path" : "@PLUGIN_INSTALL_PATH@/bluemonkeyplugin.so",
+ "enabled" : false,
+ "config" : "/etc/ambd/bluemonkey/config.js"
+}
diff --git a/plugins/bluemonkey/bmdbus.cpp b/plugins/bluemonkey/bmdbus.cpp
new file mode 100644
index 00000000..41a3dd1a
--- /dev/null
+++ b/plugins/bluemonkey/bmdbus.cpp
@@ -0,0 +1,56 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "bmdbus.h"
+
+#include <debugout.h>
+
+#include <QDBusInterface>
+#include <QDBusConnection>
+
+extern "C" std::map<std::string, QObject*> create(std::map<std::string, std::string> config, QObject* parent)
+{
+ std::map<std::string, QObject*> moduleInstances;
+ moduleInstances["dbus"] = new BMDBus(parent);
+ return moduleInstances;
+}
+
+BMDBus::BMDBus(QObject *parent)
+ :QObject(parent)
+{
+
+}
+
+QObject *BMDBus::createInterface(const QString &service, const QString &path, const QString &interface, BMDBus::Connection bus)
+{
+ return new QDBusInterface(service, path, interface, bus == Session ? QDBusConnection::sessionBus() : QDBusConnection::systemBus(), this);
+}
+
+
+bool BMDBus::exportObject(const QString &path, const QString &interface, BMDBus::Connection bus, QObject * object)
+{
+ QDBusConnection con = bus == Session ? QDBusConnection::sessionBus( ): QDBusConnection::systemBus();
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
+ con.registerObject(path, interface, object, QDBusConnection::ExportAllContents);
+#else
+ DebugOut(DebugOut::Warning) << "BMDBus::exportObject() interface is ignored in qt 5.4 and lower" << endl;
+ con.registerObject(path, object, QDBusConnection::ExportAllContents);
+#endif
+
+}
diff --git a/plugins/bluemonkey/bmdbus.h b/plugins/bluemonkey/bmdbus.h
new file mode 100644
index 00000000..7b4dbebd
--- /dev/null
+++ b/plugins/bluemonkey/bmdbus.h
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef BM_DBUS_H_
+#define BM_DBUS_H_
+
+#include <QObject>
+
+class BMDBus : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(Connection)
+
+public:
+
+ enum Connection{
+ System,
+ Session
+ };
+
+ BMDBus(QObject * parent = nullptr);
+
+public Q_SLOTS:
+
+ QObject* createInterface(const QString & service, const QString & path, const QString & interface, Connection bus);
+
+ bool exportObject(const QString & path, const QString & interface, Connection bus, QObject *obj);
+
+private: ///methods:
+
+
+};
+
+
+#endif
diff --git a/plugins/bluemonkey/config.js b/plugins/bluemonkey/config.js
new file mode 100644
index 00000000..131247e8
--- /dev/null
+++ b/plugins/bluemonkey/config.js
@@ -0,0 +1,279 @@
+var Zone = {
+ None: 0,
+ Front: 1,
+ Middle : 1 << 1,
+ Right : 1 << 2,
+ Left : 1 << 3,
+ Rear : 1 << 4,
+ Center : 1 << 5,
+ LeftSide : 1 << 6,
+ RightSide : 1 << 7,
+ FrontSide : 1 << 8,
+ BackSide : 1 << 9
+};
+
+Zone.Driver = Zone.Front | Zone.Left;
+
+bluemonkey.createCustomProperty("BluemonkeySuperProperty", "It's true!");
+bluemonkey.createCustomProperty("AnswerToTheUniverse", 42);
+
+dbusConnected = bluemonkey.subscribeTo("DBusConnected");
+
+dbusConnected.changed.connect(function () {
+ if(dbusConnected.value !== true)
+ return;
+
+ bluemonkey.exportInterface("Bluemonkey",[{'BluemonkeySuperProperty' : 'SuperProperty'},
+ {'AnswerToTheUniverse' : 'AnswerToTheUniverse'}]);
+});
+
+bluemonkey.loadModule("@PLUGIN_INSTALL_PATH@/bluemonkeyDBusModule.so");
+
+if(dbus)
+{
+ var dbusIface = dbus.createInterface("org.freedesktop.DBus", "/", "org.freedesktop.DBus", dbus.Session);
+
+ var reply = dbusIface.GetId();
+
+ bluemonkey.log("org.freedesktop.DBus.GetId() response: " + reply);
+}
+
+bluemonkey.createCustomProperty("VehicleSpeed", 10);
+bluemonkey.createCustomProperty("EngineSpeed", 5000);
+bluemonkey.createCustomProperty("PowertrainTorque", 324);
+bluemonkey.createCustomProperty("AcceleratorPedalPosition", 50);
+bluemonkey.createCustomProperty("ThrottlePosition", 50);
+bluemonkey.createCustomProperty("TransmissionModeW3C", "park");
+bluemonkey.createCustomProperty("TransmissionGearPosition", 1);
+bluemonkey.createCustomProperty("CruiseControlActive", false);
+bluemonkey.createCustomProperty("CruiseControlSpeed", 10);
+
+///LightStatus:
+bluemonkey.createCustomProperty("LightHead", false);
+bluemonkey.createCustomProperty("LightRightTurn", false);
+bluemonkey.createCustomProperty("LightLeftTurn", false);
+bluemonkey.createCustomProperty("LightBrake", false);
+bluemonkey.createCustomProperty("LightFog", true);
+bluemonkey.createCustomProperty("LightHazard", false);
+bluemonkey.createCustomProperty("LightParking", false);
+bluemonkey.createCustomProperty("LightHighBeam", false);
+bluemonkey.createCustomProperty("LightAutomatic", true);
+bluemonkey.createCustomProperty("LightDynamicHighBeam", false);
+
+bluemonkey.createCustomProperty("Horn", false);
+bluemonkey.createCustomProperty("Chime", false);
+
+///Fuel:
+bluemonkey.createCustomProperty("FuelLevel", 90);
+bluemonkey.createCustomProperty("FuelRange", 100);
+bluemonkey.createCustomProperty("FuelConsumption", 10);
+bluemonkey.createCustomProperty("FuelEconomy", 10);
+bluemonkey.createCustomProperty("FuelAverageEconomy", 10);
+bluemonkey.createCustomProperty("FuelAverageConsumption", 10);
+bluemonkey.createCustomProperty("FuelConsumptionSinceRestart", 10);
+bluemonkey.createCustomProperty("LightHighBeam", false);
+bluemonkey.createCustomProperty("LightAutomatic", true);
+bluemonkey.createCustomProperty("FuelTimeSinceRestart", 10000);
+
+///EngineOil:
+bluemonkey.createCustomProperty("EngineOilTemperature", 60);
+bluemonkey.createCustomProperty("EngineOilPressure", 60);
+bluemonkey.createCustomProperty("EngineOilChangeIndicator", false);
+bluemonkey.createCustomProperty("EngineOilLifeRemaining", 30);
+
+bluemonkey.createCustomProperty("AccelerationX", 0);
+bluemonkey.createCustomProperty("AccelerationY", 0);
+bluemonkey.createCustomProperty("AccelerationZ", 10);
+
+bluemonkey.createCustomProperty("SteeringWheelAngleW3C", 10);
+bluemonkey.createCustomProperty("WheelTick", 1000);
+
+bluemonkey.createCustomProperty("EngineCoolantLevel", 100);
+bluemonkey.createCustomProperty("EngineCoolantTemperature", 60);
+
+bluemonkey.createCustomProperty("IgnitionTimeOn", 5000);
+bluemonkey.createCustomProperty("IgnitionTimeOff", 5000);
+
+bluemonkey.createCustomProperty("YawRate", 128);
+bluemonkey.createCustomProperty("WheelBrake", false);
+
+bluemonkey.createCustomProperty("BrakesWorn", false, Zone.Front | Zone.Right)
+bluemonkey.createCustomProperty("BrakeFluidLevel", 100, Zone.Front | Zone.Right)
+bluemonkey.createCustomProperty("BrakeFluidLevelLow", false, Zone.Front | Zone.Right)
+bluemonkey.createCustomProperty("BrakePadWear", 0, Zone.Front | Zone.Right)
+
+bluemonkey.createCustomProperty("WasherFluidLevel", 100);
+bluemonkey.createCustomProperty("WasherFluidLevelLow", false);
+
+bluemonkey.createCustomProperty("MalfunctionIndicatorOn", false);
+
+bluemonkey.createCustomProperty("AccumulatedEngineRuntime", 0);
+bluemonkey.createCustomProperty("DistanceWithMILOn", 0);
+bluemonkey.createCustomProperty("DistanceSinceCodeCleared", 0);
+bluemonkey.createCustomProperty("TimeRunMILOn", 0);
+bluemonkey.createCustomProperty("TimeTroubleCodeClear", 0);
+
+bluemonkey.createCustomProperty("BatteryVoltage", 13);
+bluemonkey.createCustomProperty("BatteryCurrent", 1);
+bluemonkey.createCustomProperty("BatteryChargeLevel", 100);
+
+bluemonkey.createCustomProperty("TirePressure", 200, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("TirePressureLow", false, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("TireTemperature", 20, Zone.Front | Zone.Right);
+
+bluemonkey.createCustomProperty("TirePressure", 200, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("TirePressureLow", false, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("TireTemperature", 20, Zone.Front | Zone.Left);
+
+bluemonkey.createCustomProperty("TirePressure", 200, Zone.Rear| Zone.Right);
+bluemonkey.createCustomProperty("TirePressureLow", false, Zone.Rear | Zone.Right);
+bluemonkey.createCustomProperty("TireTemperature", 20, Zone.Rear | Zone.Right);
+
+bluemonkey.createCustomProperty("TirePressure", 200, Zone.Rear | Zone.Left);
+bluemonkey.createCustomProperty("TirePressureLow", false, Zone.Rear | Zone.Left);
+bluemonkey.createCustomProperty("TireTemperature", 20, Zone.Rear | Zone.Left);
+
+bluemonkey.createCustomProperty("ActiveNoiseControlMode", false);
+bluemonkey.createCustomProperty("AvailableSounds", ["LightSpeed", "v8"]);
+bluemonkey.createCustomProperty("EngineSoundEnhancementMode", "");
+
+bluemonkey.createCustomProperty("SeatPositionBackCushion", 0, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("SeatPositionRecline", 0, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("SeatPositionSlide", 0, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("SeatPositionCushionHeight", 0, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("SeatPositionHeadrest", 0, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("SeatPositionSideCushion", 0, Zone.Front | Zone.Right);
+
+bluemonkey.createCustomProperty("SeatPositionBackCushion", 0, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("SeatPositionRecline", 0, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("SeatPositionSlide", 0, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("SeatPositionCushionHeight", 0, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("SeatPositionHeadrest", 0, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("SeatPositionSideCushion", 0, Zone.Front | Zone.Left);
+
+bluemonkey.createCustomProperty("VehicleDriveMode", "auto");
+
+bluemonkey.createCustomProperty("MirrorSettingPan", 0, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("MirrorSettingTilt", 0, Zone.Front | Zone.Left);
+
+bluemonkey.createCustomProperty("MirrorSettingPan", 0, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("MirrorSettingTilt", 0, Zone.Front | Zone.Right);
+
+bluemonkey.createCustomProperty("DashboardIllumination", 5);
+
+bluemonkey.createCustomProperty("AntilockBreakingSystem", false);
+bluemonkey.createCustomProperty("AntilockBreakingSystemEnabled", true);
+
+bluemonkey.createCustomProperty("TractionControlSystem", true);
+bluemonkey.createCustomProperty("TractionControlSystemEnabled", true);
+
+bluemonkey.createCustomProperty("ElectronicStabilityControlEnabled", true);
+bluemonkey.createCustomProperty("ElectronicStabilityControlEngaged", true);
+
+bluemonkey.createCustomProperty("VehicleTopSpeedLimit", 150);
+
+bluemonkey.createCustomProperty("AirbagActivated", true, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("AirbagDeployed", false, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("AirbagActivated", true, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("AirbagDeployed", false, Zone.Front | Zone.Right);
+
+bluemonkey.createCustomProperty("ChildSafetyLock", false, Zone.Rear | Zone.Left);
+bluemonkey.createCustomProperty("ChildSafetyLock", true, Zone.Rear | Zone.Right);
+
+bluemonkey.createCustomProperty("AntilockBrakingSystem", false);
+bluemonkey.createCustomProperty("AntilockBrakingSystemEnabled", true);
+
+bluemonkey.createCustomProperty("DoorStatusW3C", "closed", Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("DoorStatusW3C", "closed", Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("DoorStatusW3C", "closed", Zone.Rear | Zone.Right);
+bluemonkey.createCustomProperty("DoorStatusW3C", "closed", Zone.Rear | Zone.Left);
+bluemonkey.createCustomProperty("DoorLockStatus", true, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("DoorLockStatus", true, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("DoorLockStatus", true, Zone.Rear | Zone.Right);
+bluemonkey.createCustomProperty("DoorLockStatus", true, Zone.Rear | Zone.Left);
+
+bluemonkey.createCustomProperty("OccupantStatusW3C", "adult", Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("OccupantStatusW3C", "adult", Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("OccupantStatusW3C", "child", Zone.Rear | Zone.Right);
+bluemonkey.createCustomProperty("OccupantStatusW3C", "child", Zone.Rear | Zone.Left);
+bluemonkey.createCustomProperty("SeatBeltStatus", true, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("SeatBeltStatus", true, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("SeatBeltStatus", true, Zone.Rear | Zone.Right);
+bluemonkey.createCustomProperty("SeatBeltStatus", true, Zone.Rear | Zone.Left);
+bluemonkey.createCustomProperty("OccupantName", "Kevron", Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("OccupantName", "Irene", Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("OccupantName", "Miggie", Zone.Rear | Zone.Right);
+bluemonkey.createCustomProperty("OccupantName", "Emma", Zone.Rear | Zone.Left);
+bluemonkey.createCustomProperty("OccupantIdentificationType", "camera", Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("OccupantIdentificationType", "Bluetooth", Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("OccupantIdentificationType", "pin", Zone.Rear | Zone.Right);
+bluemonkey.createCustomProperty("OccupantIdentificationType", "pin", Zone.Rear | Zone.Left);
+
+bluemonkey.createCustomProperty("TargetTemperature", 20);
+bluemonkey.createCustomProperty("FanSpeed", 1);
+bluemonkey.createCustomProperty("AirConditioning", false);
+bluemonkey.createCustomProperty("Heater", false);
+bluemonkey.createCustomProperty("AirflowDirection", 0);
+bluemonkey.createCustomProperty("AirRecirculation", false);
+
+bluemonkey.createCustomProperty("TargetTemperature", 20, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("AirRecirculation", false, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("SteeringWheelHeater", 0, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("SeatHeater", 0, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("SeatCooler", 0, Zone.Front | Zone.Left);
+
+bluemonkey.createCustomProperty("AirflowDirection", 0, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("TargetTemperature", 25, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("SeatHeater", 0, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("SeatCooler", 0, Zone.Front | Zone.Right);
+
+bluemonkey.createCustomProperty("ExteriorTemperature", 30.0);
+bluemonkey.createCustomProperty("InteriorTemperature", 23.0);
+
+bluemonkey.createCustomProperty("DefrostWindow", false, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("DefrostMirrors", false, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("DefrostWindow", false, Zone.Front | Zone.Left);
+bluemonkey.createCustomProperty("DefrostMirrors", false, Zone.Front | Zone.Left);
+
+bluemonkey.createCustomProperty("RainSensor", 0);
+
+bluemonkey.createCustomProperty("WindsheildWiperSpeed", "off");
+bluemonkey.createCustomProperty("WindsheildWiperSetting", "auto");
+
+bluemonkey.createCustomProperty("ConvertableRoof", false);
+bluemonkey.createCustomProperty("ConvertableRoofStatus", "closed");
+
+bluemonkey.createCustomProperty("Sunroof", 0);
+bluemonkey.createCustomProperty("SunroofTilt", 0);
+
+bluemonkey.createCustomProperty("WindowStatus", 100, Zone.Driver);
+bluemonkey.createCustomProperty("WindowLockStatus", false, Zone.Driver);
+bluemonkey.createCustomProperty("WindowStatus", 100, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("WindowLockStatus", false, Zone.Front | Zone.Right);
+bluemonkey.createCustomProperty("WindowStatus", 100, Zone.Rear| Zone.Right);
+bluemonkey.createCustomProperty("WindowLockStatus", true, Zone.Rear | Zone.Right);
+bluemonkey.createCustomProperty("WindowStatus", 100, Zone.Rear| Zone.Left);
+bluemonkey.createCustomProperty("WindowLockStatus", true, Zone.Rear | Zone.Left);
+
+bluemonkey.createCustomProperty("AtmosphericPressure", 1013);
+
+bluemonkey.createCustomProperty("LaneDepartureStatus", "running");
+bluemonkey.createCustomProperty("AlarmStatus", "prearmed");
+bluemonkey.createCustomProperty("ParkingBrakeStatusW3C", "inactive");
+
+bluemonkey.createCustomProperty("Altitude", 200);
+bluemonkey.createCustomProperty("Latitude", 45.541174);
+bluemonkey.createCustomProperty("Longitude", -122.958967);
+
+
+var speedProperty = bluemonkey.subscribeTo("VehicleSpeed");
+
+var testTimer = bluemonkey.createTimer();
+ testTimer.interval = 3000;
+ testTimer.singleShot = false;
+ testTimer.timeout.connect(function() {
+ //VehicleSpeed
+ speedProperty.value = Math.floor((Math.random() * 100) + 1);
+ });
+
+//testTimer.start();
diff --git a/plugins/bluemonkey/customPrograms.js b/plugins/bluemonkey/customPrograms.js
new file mode 100644
index 00000000..6bbb5e9c
--- /dev/null
+++ b/plugins/bluemonkey/customPrograms.js
@@ -0,0 +1,2 @@
+var averageSpeed=0; var speedTicks=0; var totalSpeed=0; speedProperty.changed.connect(function(value) { totalSpeed += value; speedTicks++; averageSpeed = totalSpeed / speedTicks;});
+var todo = new Array();
diff --git a/plugins/bluemonkey/db.cpp b/plugins/bluemonkey/db.cpp
new file mode 100644
index 00000000..609e7314
--- /dev/null
+++ b/plugins/bluemonkey/db.cpp
@@ -0,0 +1,108 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "db.h"
+
+#include <debugout.h>
+
+#include <QObject>
+#include <QSqlError>
+#include <QSqlRecord>
+#include <QtQml>
+
+extern "C" std::map<std::string, QObject*> create(std::map<std::string, std::string> config, QObject* parent)
+{
+ std::map<std::string, QObject*> moduleInstances;
+ moduleInstances["database"] = new BluemonkeyDatabaseModule(parent);
+ return moduleInstances;
+}
+
+bool Database::open(QString connectionName, QString filename)
+{
+ db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
+ db.setDatabaseName(filename);
+ return db.open();
+}
+
+void Database::close()
+{
+ if(db.isOpen())
+ {
+ db.close();
+ }
+}
+
+QObject *Database::exec(QString query)
+{
+ return new Query(db.exec(query), this);
+}
+
+QString Database::lastError()
+{
+ return db.lastError().text();
+}
+
+
+Query::Query(QSqlQuery q, QObject* parent)
+ :QObject(parent)
+{
+ query = q;
+}
+
+Query::Query(QString connectionName)
+{
+ setConnectionName(connectionName);
+}
+
+void Query::setConnectionName(QString connectionName)
+{
+ mConnectionName = connectionName;
+ db = QSqlDatabase::database(connectionName);
+ query = QSqlQuery(db);
+}
+
+bool Query::exec(QString queryStr)
+{
+ query.setNumericalPrecisionPolicy(QSql::HighPrecision);
+ return query.exec(queryStr);
+}
+
+QVariantList Query::results()
+{
+ QVariantList results;
+
+ QSqlRecord r = query.record();
+
+ while(query.next())
+ {
+
+ QVariantMap prop;
+ ///iterate on the properties:
+ for(int i=0; i< r.count(); i++)
+ {
+ QString name = r.fieldName(i);
+
+ QVariant val = query.value(i);
+ prop[name] = val;
+ }
+
+ results << prop;
+ }
+
+ return results;
+}
diff --git a/plugins/bluemonkey/db.h b/plugins/bluemonkey/db.h
new file mode 100644
index 00000000..33298bdc
--- /dev/null
+++ b/plugins/bluemonkey/db.h
@@ -0,0 +1,87 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <QObject>
+#include <QSqlDatabase>
+#include <QSqlQuery>
+#include <QVariant>
+#include <QVariantList>
+
+class Database;
+class Query;
+
+class Database: public QObject
+{
+ Q_OBJECT
+public:
+ Database(QObject* parent = nullptr):QObject(parent){ }
+ ~Database() { close(); }
+
+ QSqlDatabase database() { return db; }
+
+public Q_SLOTS:
+
+ bool open(QString connectionName, QString filename);
+ void close();
+
+ QObject* exec(QString query);
+
+ QString lastError();
+
+private:
+ QSqlDatabase db;
+};
+
+class Query: public QObject
+{
+ Q_OBJECT
+public:
+ Query(QObject* parent = nullptr):QObject(parent){}
+ Query(QSqlQuery q, QObject* parent = nullptr);
+ Q_INVOKABLE Query(QString connectionName);
+public Q_SLOTS:
+ void setConnectionName(QString connectionName);
+
+ bool exec(QString queryStr);
+
+ QVariantList results();
+
+private:
+ QSqlQuery query;
+ QString mConnectionName;
+ QSqlDatabase db;
+};
+
+
+class BluemonkeyDatabaseModule : public QObject
+{
+ Q_OBJECT
+public:
+ BluemonkeyDatabaseModule(QObject* parent = nullptr): QObject(parent) { }
+
+public Q_SLOTS:
+ QObject* createNewDatabase()
+ {
+ return new Database(this);
+ }
+
+ QObject* createNewQuery()
+ {
+ return new Query(this);
+ }
+};
diff --git a/plugins/bluemonkey/ircSettings.js b/plugins/bluemonkey/ircSettings.js
new file mode 100644
index 00000000..06439d30
--- /dev/null
+++ b/plugins/bluemonkey/ircSettings.js
@@ -0,0 +1,26 @@
+var address = "chat.freenode.com"
+var port = 8001
+var proxy = ""
+var username = ""
+var nick = ""
+var pass = ""
+
+
+function ircConnecting() {
+ print("connecting to irc");
+}
+
+function ircConnected() {
+ print("connected");
+ for(var i=0;i<irc.channels.length;i++)
+ {
+ irc.join(irc.channels[i]);
+ }
+}
+
+
+irc.channels = ["#bluemonkey","#linuxice"]
+irc.connected.connect(ircConnected);
+irc.connecting.connect(ircConnecting);
+
+irc.connect(address,port,proxy,username,nick,pass);
diff --git a/plugins/bluemonkey/irccoms.cpp b/plugins/bluemonkey/irccoms.cpp
new file mode 100644
index 00000000..02beffd7
--- /dev/null
+++ b/plugins/bluemonkey/irccoms.cpp
@@ -0,0 +1,217 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "irccoms.h"
+#include <QtDebug>
+#include <IrcCommand>
+#include <IrcMessage>
+#include <QSslSocket>
+#include <QSslError>
+#include <QFile>
+#include <QNetworkProxy>
+#include <QTimer>
+#include <QJSEngine>
+#include <debugout.h>
+
+extern "C" std::map<std::string, QObject*> create(std::map<std::string, std::string> config, QObject* parent)
+{
+ std::map<std::string, QObject*> moduleInstances;
+
+ moduleInstances["irc"] = new IrcCommunication(config, parent);
+
+ return moduleInstances;
+}
+
+#define foreach Q_FOREACH
+
+IrcCommunication::IrcCommunication(std::map<std::string, std::string> config, QObject* parent)
+ :IrcSession(parent)
+{
+
+ QObject::connect(this, &IrcCommunication::connected, [this](){
+ announceDequeue();
+ connectedChanged(true);
+ });
+
+ QObject::connect(this, &IrcCommunication::disconnected, [this](){
+ connectedChanged(false);
+ reconnect();
+ });
+
+ QObject::connect(this,SIGNAL(socketError(QAbstractSocket::SocketError)),this,SLOT(socketError(QAbstractSocket::SocketError)));
+ QObject::connect(this,SIGNAL(messageReceived(IrcMessage*)),this,SLOT(onMessageReceived(IrcMessage*)));
+
+ QJSEngine *engine = new QJSEngine(this);
+
+ QJSValue eventEngineValue = engine->newQObject(this);
+ engine->globalObject().setProperty("irc", eventEngineValue);
+
+ QString str = config["ircSettings"].c_str();
+
+ QFile file(str);
+ if(!file.open(QIODevice::ReadOnly))
+ {
+ DebugOut(DebugOut::Error)<<"failed to open irc config file: "<<str.toStdString()<<endl;
+ return;
+ }
+
+ QString script = file.readAll();
+
+ file.close();
+
+ QJSValue response = engine->evaluate(script);
+
+ DebugOut()<<response.toString().toStdString()<<endl;
+
+}
+
+void IrcCommunication::announceDequeue()
+{
+ foreach(QString s, announceQueue)
+ {
+ announce(s);
+ }
+ announceQueue.clear();
+}
+
+void IrcCommunication::announce(QString s)
+{
+ if(!isConnected())
+ {
+ announceQueue.append(s);
+ return;
+ }
+
+ qDebug()<<"channels: "<<mChannels;
+ foreach(QString channel, mChannels)
+ {
+ qDebug()<<"sending "<<s<<" to channel: "<<channel;
+ IrcCommand command;
+ command.setType(IrcCommand::Message);
+ command.setParameters(QStringList()<<channel<<s);
+ sendCommand(&command);
+ }
+}
+
+void IrcCommunication::respond(QString target, QString s)
+{
+ IrcCommand *command = IrcCommand::createMessage(target,s);
+ sendCommand(command);
+
+ delete command;
+
+}
+
+void IrcCommunication::onMessageReceived(IrcMessage *msg)
+{
+ qDebug()<<"message received "<<msg->type()<<" prefix: "<<msg->sender().prefix()<<" params:"<<msg->parameters();
+
+ if(msg->type() == IrcMessage::Private)
+ {
+ if(msg->parameters().count() > 1)
+ {
+ QString sender = msg->parameters().at(0);
+ QString m = msg->parameters().at(1);
+
+ message(sender, msg->sender().prefix(), m);
+ }
+
+ }
+}
+
+void IrcCommunication::connect(QString host, int port, QString proxy, QString user, QString nick, QString pass)
+{
+ setHost(host);
+ setPort(port);
+ setUserName(user);
+ setNickName(nick);
+ setRealName(nick);
+
+ if(!proxy.isEmpty())
+ {
+ if(!proxy.contains(":"))
+ {
+ qDebug("proxy format must be 'address:port'");
+ return;
+ }
+ QString host = proxy.split(":").at(0);
+ int port = proxy.split(":").at(1).toInt();
+
+ QNetworkProxy netproxy;
+ netproxy.setType(QNetworkProxy::Socks5Proxy);
+ netproxy.setHostName(host);
+ netproxy.setPort(port);
+
+ QNetworkProxy::setApplicationProxy(netproxy);
+ }
+
+ qDebug()<<"opening irc session";
+ open();
+}
+
+void IrcCommunication::setSsl(bool use)
+{
+ if(use)
+ {
+ setSecure(true);
+ }
+}
+
+void IrcCommunication::join(QString channel)
+{
+ if(!mChannels.contains(channel))
+ mChannels.append(channel);
+
+ IrcCommand command;
+ command.setType(IrcCommand::Join);
+ command.setParameters(QStringList()<<channel);
+ sendCommand(&command);
+}
+
+void IrcCommunication::reconnect()
+{
+ if(socket()->state() == QAbstractSocket::ConnectedState)
+ return;
+
+ if(socket()->state() == QAbstractSocket::ConnectingState && socket()->state() != QAbstractSocket::ConnectedState)
+ QTimer::singleShot(5000,this,SLOT(reconnect()));
+ else
+ QTimer::singleShot(5000,this,SLOT(open()));
+}
+
+void IrcCommunication::sslError(QList<QSslError> )
+{
+ qDebug()<<"some ssl errors!! trying to ignore them";
+ QSslSocket* sock = qobject_cast<QSslSocket*>(socket());
+ if(sock)
+ {
+ sock->ignoreSslErrors();
+ }
+}
+
+void IrcCommunication::socketError(QAbstractSocket::SocketError error)
+{
+ qDebug()<<"Socket error. attempting to reconnect..."<<error;
+ reconnect();
+}
+
+void IrcCommunication::setIgnoreInvalidCert(bool ignore)
+{
+ if(ignore)
+ QObject::connect(socket(),SIGNAL(sslErrors(QList<QSslError>)),this,SLOT(sslError(QList<QSslError>)));
+}
diff --git a/plugins/bluemonkey/irccoms.h b/plugins/bluemonkey/irccoms.h
new file mode 100644
index 00000000..dacfd6a4
--- /dev/null
+++ b/plugins/bluemonkey/irccoms.h
@@ -0,0 +1,70 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef COMMUNICATION_H
+#define COMMUNICATION_H
+#include <QObject>
+#include <QVariant>
+#include <QStringList>
+#include <QSslError>
+#include <map>
+#include <QAbstractSocket>
+
+#include <IrcSession>
+#include <IrcMessage>
+
+class IrcCommunication: public IrcSession
+{
+ Q_OBJECT
+ Q_PROPERTY(QStringList channels READ channels WRITE setChannels)
+ Q_PROPERTY(bool ssl READ ssl WRITE setSsl)
+public:
+ IrcCommunication(std::map<std::string, std::string> config, QObject* parent=0);
+ QStringList channels() { return mChannels; }
+ void setChannels(QStringList c) { mChannels = c; }
+
+ void announceDequeue();
+
+ bool ssl() { return isSecure(); }
+
+public Q_SLOTS:
+ void respond(QString target, QString msg);
+ void announce(QString);
+ void connect(QString host,int port, QString proxy, QString user, QString nick, QString pass);
+ void setSsl(bool use);
+ void setIgnoreInvalidCert(bool ignore);
+ void join(QString channel);
+
+ void debugMessage(QString v) { qDebug()<<v; }
+
+ void reconnect();
+
+private Q_SLOTS:
+ void onMessageReceived(IrcMessage*);
+ void sslError(QList<QSslError>);
+ void socketError(QAbstractSocket::SocketError);
+
+Q_SIGNALS:
+ void message(QString sender, QString prefix, QString codes);
+
+private:
+ QStringList announceQueue;
+ QStringList mChannels;
+};
+
+#endif // COMMUNICATION_H
diff --git a/plugins/bluetooth/CMakeLists.txt b/plugins/bluetooth/CMakeLists.txt
new file mode 100644
index 00000000..af9f7c38
--- /dev/null
+++ b/plugins/bluetooth/CMakeLists.txt
@@ -0,0 +1,39 @@
+if(bluetooth_plugin)
+
+add_definitions(-Dbluetooth_plugin)
+
+set(bluetooth_headers bluetoothplugin.h)
+set(bluetooth_sources bluetoothplugin.cpp )
+
+find_package(Qt5Core REQUIRED)
+find_package(Qt5DBus REQUIRED)
+find_package(Qt5Network REQUIRED)
+
+message(STATUS ${Qt5DBus_INCLUDE_DIRS})
+
+set(QT_INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS})
+set(QT_LIBRARIES ${Qt5Core_LIBRARIES} ${Qt5DBus_LIBRARIES} ${Qt5Network_LIBRARIES})
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
+add_definitions(${Qt5Core_DEFINITIONS})
+
+set(CMAKE_AUTOMOC ON)
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${gio_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/plugins/common ${QT_INCLUDE_DIRS})
+
+add_library(bluetoothplugin MODULE ${bluetooth_sources})
+set_target_properties(bluetoothplugin PROPERTIES PREFIX "")
+target_link_libraries(bluetoothplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common ${link_libraries} ${gio_LIBRARIES} ${QT_LIBRARIES})
+
+install(TARGETS bluetoothplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ambbt.conf DESTINATION /etc/dbus-1/system.d )
+
+add_executable(testAmbBt testAmbBt.cpp bluetoothplugin.cpp)
+target_link_libraries(testAmbBt ${link_libraries} amb -L${CMAKE_CURRENT_BINARY_DIR}/lib amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common ${QT_LIBRARIES})
+
+install (TARGETS testAmbBt RUNTIME DESTINATION bin)
+
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/bluetooth.in.json ${CMAKE_CURRENT_BINARY_DIR}/bluetooth @ONLY)
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/bluetooth DESTINATION ${PLUGIN_SEGMENT_INSTALL_PATH})
+
+endif(bluetooth_plugin)
diff --git a/plugins/bluetooth/ambbt.conf b/plugins/bluetooth/ambbt.conf
new file mode 100644
index 00000000..eeaa2c75
--- /dev/null
+++ b/plugins/bluetooth/ambbt.conf
@@ -0,0 +1,15 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+ <policy context="default">
+ <allow own="org.automotive.message.broker.bluetooth"/>
+ <allow send_destination="org.automotive.message.broker.bluetooth"/>
+
+
+ <allow send_interface="org.bluez.Profile1"
+ send_path="/org/bluez/spp" />
+
+ </policy>
+
+</busconfig>
diff --git a/plugins/bluetooth/bluetooth.in.json b/plugins/bluetooth/bluetooth.in.json
new file mode 100644
index 00000000..b6e8b86e
--- /dev/null
+++ b/plugins/bluetooth/bluetooth.in.json
@@ -0,0 +1,5 @@
+{
+ "name" : "Bluetooth",
+ "path" : "@PLUGIN_INSTALL_PATH@/bluetoothplugin.so",
+ "enabled" : false
+}
diff --git a/plugins/bluetooth/bluetoothplugin.cpp b/plugins/bluetooth/bluetoothplugin.cpp
new file mode 100644
index 00000000..6e9fbe5f
--- /dev/null
+++ b/plugins/bluetooth/bluetoothplugin.cpp
@@ -0,0 +1,207 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "bluetoothplugin.h"
+
+#include <timestamp.h>
+#include <listplusplus.h>
+#include <bluetooth5.h>
+
+#include <iostream>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <glib.h>
+
+#include <QDBusConnection>
+#include <QDBusInterface>
+#include <QDBusReply>
+#include <QSocketNotifier>
+
+using namespace std;
+
+#include "debugout.h"
+
+bool readCallback(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+// DebugOut(5) << "Polling..." << condition << endl;
+
+ if(condition & G_IO_ERR)
+ {
+ DebugOut(DebugOut::Error)<<"GpsNmeaSource polling error."<<endl;
+ }
+
+ if (condition & G_IO_HUP)
+ {
+ //Hang up. Returning false closes out the GIOChannel.
+ //printf("Callback on G_IO_HUP\n");
+ DebugOut(DebugOut::Warning)<<"socket hangup event..."<<endl;
+ return false;
+ }
+
+ AbstractBluetoothSerialProfile* p = static_cast<AbstractBluetoothSerialProfile*>(data);
+
+ p->canHasData();
+
+ return true;
+}
+
+BluetoothSinkPlugin::BluetoothSinkPlugin(AbstractRoutingEngine* re, map<string, string> config)
+:AbstractSink(re, config)
+{
+
+}
+
+extern "C" void create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ new BluetoothSinkPlugin(routingengine, config);
+}
+
+const string BluetoothSinkPlugin::uuid()
+{
+ return "47ec4ed0-dc45-11e3-9c1a-0800200c9a66";
+}
+
+void BluetoothSinkPlugin::propertyChanged(AbstractPropertyType *value)
+{
+
+}
+
+void BluetoothSinkPlugin::dataReceived(QByteArray data)
+{
+
+}
+
+AbstractBluetoothSerialProfile::AbstractBluetoothSerialProfile(QString r)
+ :role(r)
+{
+ new BtProfileAdaptor(this);
+
+ if(!QDBusConnection::systemBus().registerService("org.automotive.message.broker.bluetooth"))
+ DebugOut(DebugOut::Error)<<"Failed to register DBus service name: "<<QDBusConnection::systemBus().lastError().message().toStdString()<<endl;
+
+ if(!QDBusConnection::systemBus().registerObject("/org/bluez/spp", this))
+ DebugOut(DebugOut::Error)<<"Failed to register DBus object"<<endl;
+
+ QDBusInterface profileManagerIface("org.bluez", "/org/bluez", "org.bluez.ProfileManager1", QDBusConnection::systemBus());
+
+ QVariantMap options;
+ options["Name"] = "AMB spp";
+ options["Role"] = role;
+ options["Channel"] = qVariantFromValue(uint16_t(23));
+ options["AutoConnect"] = true;
+
+ QDBusReply<void> reply = profileManagerIface.call("RegisterProfile", qVariantFromValue(QDBusObjectPath("/org/bluez/spp")), "00001101-0000-1000-8000-00805F9B34FB", options);
+
+ if(!reply.isValid())
+ {
+ DebugOut(DebugOut::Error)<<"RegisterProfile call failed: "<<reply.error().message().toStdString()<<endl;
+ }
+
+}
+
+void AbstractBluetoothSerialProfile::connect(string hwaddy)
+{
+ std::string device = findDevice(hwaddy);
+
+ if(device.empty())
+ {
+ DebugOut(DebugOut::Error) << "could not find device with address: " << hwaddy << endl;
+ return;
+ }
+
+ QDBusInterface deviceManager("org.bluez", device.c_str(), "org.bluez.Device1", QDBusConnection::systemBus());
+
+ if(!deviceManager.isValid())
+ {
+ DebugOut(DebugOut::Error) << "could not create DBus interface for device with address '"
+ << hwaddy <<"' " << deviceManager.lastError().message().toStdString() << endl;
+ return;
+ }
+
+ QDBusPendingCall reply = deviceManager.asyncCall("Connect");
+
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
+
+ QObject::connect(watcher, &QDBusPendingCallWatcher::finished, [](QDBusPendingCallWatcher* call)
+ {
+ QDBusPendingReply<void> reply = *call;
+ if(reply.isError())
+ {
+ DebugOut(DebugOut::Error) << "Connecting: " << reply.error().message().toStdString() << endl;
+ }
+ });
+
+}
+
+void AbstractBluetoothSerialProfile::release()
+{
+ DebugOut()<<"release called."<<endl;
+}
+
+void AbstractBluetoothSerialProfile::newConnection(string path, QDBusUnixFileDescriptor fd, QVariantMap props)
+{
+ DebugOut()<<"new Connection! Path: "<<path<<" fd: "<<fd.fileDescriptor()<<endl;
+
+ socket.setDescriptor(fd.fileDescriptor());
+
+ GIOChannel *chan = g_io_channel_unix_new(socket.fileDescriptor());
+ g_io_add_watch(chan, GIOCondition(G_IO_IN | G_IO_HUP | G_IO_ERR),(GIOFunc)readCallback, this);
+ g_io_channel_set_close_on_unref(chan, true);
+ g_io_channel_unref(chan);
+}
+
+void AbstractBluetoothSerialProfile::requestDisconnection(string path)
+{
+ DebugOut()<<"requestDisconnection called. Path: "<<path<<endl;
+ socket.close();
+}
+
+void AbstractBluetoothSerialProfile::canHasData()
+{
+ QByteArray data = socket.read().c_str();
+
+ DebugOut()<<"data read: "<<data.constData()<<endl;
+
+ dataReceived(data);
+}
+
+void AbstractBluetoothSerialProfile::write(const std::string & data)
+{
+ socket.write(data);
+}
+
+BtProfileAdaptor::BtProfileAdaptor(AbstractBluetoothSerialProfile *parent)
+ :QDBusAbstractAdaptor(parent), mParent(parent)
+{
+
+}
+
+void BtProfileAdaptor::Release()
+{
+ mParent->release();
+}
+
+void BtProfileAdaptor::NewConnection(QDBusObjectPath device, QDBusUnixFileDescriptor fd, QVariantMap fd_properties)
+{
+ mParent->newConnection(device.path().toStdString(), fd, fd_properties);
+}
+
+void BtProfileAdaptor::RequestDisconnection(QDBusObjectPath device)
+{
+ mParent->requestDisconnection(device.path().toStdString());
+}
diff --git a/plugins/bluetooth/bluetoothplugin.h b/plugins/bluetooth/bluetoothplugin.h
new file mode 100644
index 00000000..e7d42a71
--- /dev/null
+++ b/plugins/bluetooth/bluetoothplugin.h
@@ -0,0 +1,106 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef BT_PLUGIN_H_
+#define BT_PLUGIN_H_
+
+#include <abstractsink.h>
+#include <serialport.hpp>
+#include <string>
+
+#include <QDBusAbstractAdaptor>
+#include <QDBusObjectPath>
+#include <QVariantMap>
+#include <QTcpSocket>
+#include <QDBusUnixFileDescriptor>
+
+class AbstractBluetoothSerialProfile;
+
+class BtProfileAdaptor : public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.bluez.Profile1")
+
+public:
+
+ BtProfileAdaptor(AbstractBluetoothSerialProfile* parent);
+
+public Q_SLOTS:
+
+ void Release();
+
+ void NewConnection(QDBusObjectPath device, QDBusUnixFileDescriptor fd, QVariantMap fd_properties);
+
+ void RequestDisconnection(QDBusObjectPath device);
+
+private:
+
+ AbstractBluetoothSerialProfile* mParent;
+
+};
+
+class AbstractBluetoothSerialProfile: public QObject
+{
+ Q_OBJECT
+
+public:
+ AbstractBluetoothSerialProfile(QString role = "server");
+
+ virtual void connect(std::string hwaddy);
+
+ virtual void release();
+
+ virtual void newConnection(std::string path, QDBusUnixFileDescriptor fd, QVariantMap props);
+
+ virtual void requestDisconnection(std::string path);
+
+ virtual void canHasData();
+
+ void write(const string & data);
+
+protected:
+ virtual void connected() {}
+ virtual void disconnected() {}
+ virtual void dataReceived(QByteArray data) {}
+ SerialPort socket;
+
+private:
+ QString role;
+};
+
+class BluetoothSinkPlugin: public AbstractBluetoothSerialProfile, public AbstractSink
+{
+ Q_OBJECT
+
+public:
+ BluetoothSinkPlugin(AbstractRoutingEngine* re, map<string, string> config);
+
+ const string uuid();
+
+ void supportedChanged(const PropertyList &) {}
+
+ void propertyChanged(AbstractPropertyType* value);
+
+protected:
+ virtual void dataReceived(QByteArray data);
+
+};
+
+
+
+#endif // EXAMPLEPLUGIN_H
diff --git a/plugins/bluetooth/testAmbBt.cpp b/plugins/bluetooth/testAmbBt.cpp
new file mode 100644
index 00000000..296edbce
--- /dev/null
+++ b/plugins/bluetooth/testAmbBt.cpp
@@ -0,0 +1,48 @@
+#include <bluetooth5.h>
+#include <debugout.h>
+#include <QCoreApplication>
+#include <QJsonDocument>
+#include <QStringList>
+#include <QDebug>
+
+#include "bluetoothplugin.h"
+
+class BluetoothSerialClient: public AbstractBluetoothSerialProfile
+{
+public:
+ BluetoothSerialClient(): AbstractBluetoothSerialProfile("client") {}
+
+ void connected()
+ {
+
+ }
+
+ void disconnected()
+ {
+
+ }
+
+ void dataReceived(QByteArray d)
+ {
+ qDebug()<<"data: "<< d;
+ }
+};
+
+int main(int argc, char** argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QString addy = app.arguments().at(1);
+
+ DebugOut::setDebugThreshhold(6);
+
+ qDebug()<<"connecting to: "<<addy;
+
+ BluetoothSerialClient client;
+
+ client.connect(addy.toStdString());
+
+ app.exec();
+
+ return 1;
+}
diff --git a/plugins/cangenplugin/CMakeLists.txt b/plugins/cangenplugin/CMakeLists.txt
new file mode 100644
index 00000000..a954a00f
--- /dev/null
+++ b/plugins/cangenplugin/CMakeLists.txt
@@ -0,0 +1,20 @@
+if(cangen_plugin)
+############################################################################################################################################
+
+pkg_check_modules(websockets REQUIRED libwebsockets)
+pkg_check_modules(json REQUIRED json)
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${gio_INCLUDE_DIRS} ${gio-unix_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/plugins/common ${Boost_INCLUDE_DIRS} ${json_INCLUDE_DIRS})
+
+set(cangenplugin_headers cangenplugin.h websockets.h)
+set(cangenplugin_sources cangenplugin.cpp websockets.cpp)
+
+add_library(cangenplugin MODULE ${cangenplugin_sources} ${cangenplugin_headers})
+set_target_properties(cangenplugin PROPERTIES PREFIX "")
+target_link_libraries(cangenplugin amb amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common ${link_libraries} ${websockets_LIBRARIES} -lrt ${json_LIBRARIES})
+
+install(TARGETS cangenplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+
+############################################################################################################################################
+
+endif(cangen_plugin)
diff --git a/plugins/cangenplugin/cangenplugin.cpp b/plugins/cangenplugin/cangenplugin.cpp
new file mode 100644
index 00000000..73d32538
--- /dev/null
+++ b/plugins/cangenplugin/cangenplugin.cpp
@@ -0,0 +1,466 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <boost/assert.hpp>
+#include <glib.h>
+#include <deque>
+
+#include <vehicleproperty.h>
+#include <listplusplus.h>
+
+#include <logger.h>
+#include <ambplugin.h>
+
+#include "cangenplugin.h"
+
+//----------------------------------------------------------------------------
+// CANGenPlugin
+//----------------------------------------------------------------------------
+
+// library exported function for plugin loader
+extern "C" void create(AbstractRoutingEngine* routingengine, std::map<std::string, std::string> config)
+{
+#ifndef UNIT_TESTS
+ DEBUG_CONF("cangenplugin",
+ CUtil::Logger::file_off | CUtil::Logger::screen_on,
+ CUtil::Logger::EInfo, CUtil::Logger::EInfo
+ );
+#endif
+
+ AmbPlugin<CANGenPlugin> * plugin = new AmbPlugin<CANGenPlugin>(routingengine, config);
+ plugin->init();
+}
+
+//----------------------------------------------------------------------------
+// CANGenPlugin
+//----------------------------------------------------------------------------
+
+CANGenPlugin::CANGenPlugin(AbstractRoutingEngine* re, const map<string, string>& config, AbstractSource& parent) :
+ AmbPluginImpl(re, config, parent),
+ ws(new WebSockets(*this))
+{
+ addPropertySupport(Zone::None,[]()
+ {
+ return new SimCommand();
+ });
+}
+
+CANGenPlugin::~CANGenPlugin()
+{
+ for(auto it = interfaces.begin(); it != interfaces.end(); ++it){
+ it->second->stop();
+ }
+}
+
+void CANGenPlugin::init()
+{
+ routingEngine->subscribeToProperty("MappingTable", &source);
+}
+
+void CANGenPlugin::propertyChanged(AbstractPropertyType* value)
+{
+ if(!value)
+ return;
+ if(!value->name.compare("MappingTable")) {
+ parseMappingTable(value->toString());
+ }
+}
+
+AsyncPropertyReply *CANGenPlugin::setProperty(const AsyncSetPropertyRequest &request)
+{
+ if(request.property == "SimCommand")
+ {
+ std::string v = request.value->toString();
+
+ dataReceived(nullptr, v.c_str(), v.length());
+ }
+
+ return AmbPluginImpl::setProperty(request);
+}
+
+void CANGenPlugin::parseMappingTable(const std::string& table)
+{
+ scoped_lock<interprocess_recursive_mutex> lock(mutex);
+
+ std::string json(table);
+ std::replace(json.begin(), json.end(), '\'', '"');// replace all ' to "
+ std::unique_ptr<json_object, decltype(&json_object_put)> rootobject(json_tokener_parse(json.c_str()), &json_object_put);
+ if(!rootobject)
+ {
+ LOG_ERROR("Failed to parse json: " << json);
+ return;
+ }
+
+ // Success, use json_obj here.
+ mappingTable.clear();
+ json_object *sources = json_object_object_get(rootobject.get(),"sources");
+ if(!sources)
+ return;
+ array_list* arraySources = json_object_get_array(sources);
+ if(!arraySources)
+ return;
+ for(int i=0; i < array_list_length(arraySources); ++i)
+ {
+ json_object *rootsource = static_cast<json_object*>(array_list_get_idx(arraySources,i));
+ if(!rootsource)
+ continue;
+ json_object* source = json_object_object_get(rootsource, "source");
+ if(!source)
+ continue;
+ json_object* guid = json_object_object_get(source, "guid");
+ const std::string guidstr(guid ? json_object_get_string(guid) : "");
+ json_object* signals = json_object_object_get(rootsource, "signals");
+ if(!signals)
+ continue;
+ array_list* arraySignals = json_object_get_array(signals);
+ for(int j = 0; j < array_list_length(arraySignals); ++j)
+ {
+ json_object *signal = static_cast<json_object*>(array_list_get_idx(arraySignals,j));
+ if(!signal)
+ continue;
+ mappingTable.addProperty(guidstr, signal);
+ }// signals array loop
+ }// sources array loop
+}
+
+// from CANObserver
+void CANGenPlugin::errorOccured(CANObserver::CANError error)
+{
+ (void) error;
+ LOG_INFO( "CANPlugin::errorOccured() not implemented "<< std::endl );
+}
+
+void CANGenPlugin::standardFrameReceived(const can_frame& frame)
+{
+ (void) frame;
+ LOG_INFO( "CANPlugin::standardFrameReceived() not implemented "<< std::endl );
+}
+
+void CANGenPlugin::extendedFrameReceived(const can_frame& frame)
+{
+ LOG_INFO("CANPlugin::extendedFrameReceived()");
+ printFrame(frame);
+}
+
+void CANGenPlugin::errorFrameReceived(const can_frame& frame)
+{
+ LOG_INFO("CANPlugin::errorFrameReceived()");
+ printFrame(frame);
+}
+
+void CANGenPlugin::remoteTransmissionRequest(const can_frame& frame)
+{
+ (void) frame;
+ LOG_INFO( "CANPlugin::remoteTransmissionRequest() not implemented "<< std::endl );
+}
+
+void CANGenPlugin::printFrame(const can_frame& frame) const
+{
+ LOG_INFO( "CANPlugin::printFrame can_id: " << std::hex << frame.can_id << std::dec << endl );
+ LOG_INFO( "CANPlugin::printFrame can_dlc: " << int(frame.can_dlc) << endl );
+
+ std::stringstream ss;
+ for(int i=0; i<frame.can_dlc; ++i){
+ ss << " " << std::hex << (int)(frame.data[i]);
+ }
+ ss << std::dec;
+
+ LOG_INFO( "CANPlugin::printFrame can data" << ss.str() << endl );
+}
+
+bool CANGenPlugin::sendValue(const std::string& interface, AbstractPropertyType* value)
+{
+ scoped_lock<interprocess_recursive_mutex> lock(mutex);
+
+ if(!value)
+ return false;
+ int can_id = mappingTable.getCanId(value->sourceUuid, value->zone, value->name);
+ if(can_id == 0)
+ return false;
+
+ can_frame frame;
+ frame.can_id = can_id;
+ std::unique_ptr<GVariant, decltype(&g_variant_unref)> v(value->toVariant(), &g_variant_unref);
+ gsize vs = g_variant_get_size(v.get());
+ assert(vs <= sizeof(frame.data));// Has to be <= 8
+ frame.can_dlc = vs > sizeof(frame.data) ? sizeof(frame.data) : vs;
+ memcpy(frame.data, g_variant_get_data(v.get()), frame.can_dlc);
+
+ auto& canBus = interfaces[interface];
+ if(!canBus){
+ canBus = std::shared_ptr<CANBus>(new CANBus(*static_cast<CANObserver*>(this)));
+ bool started(canBus->start(interface.c_str()));
+ if(!started)
+ return false;
+ }
+ return canBus->sendExtendedFrame(frame);
+}
+
+void CANGenPlugin::getValue(libwebsocket* socket, const std::string& property, int zone, const std::string& id)
+{
+ AsyncPropertyRequest request;
+ PropertyList foo = VehicleProperty::capabilities();
+ if(contains(foo, property))
+ {
+ request.property = property;
+ }
+ else
+ {
+ DebugOut(0)<<"websocketsink: Invalid property requested: "<<property;
+ return;
+ }
+
+ request.zoneFilter = zone;
+ request.completed = [socket,id,property](AsyncPropertyReply* reply)
+ {
+ DebugOut()<<"Got property: "<<reply->property.c_str()<<endl;
+ if(!reply->value){
+ DebugOut()<<"Property value is null"<<endl;
+ delete reply;
+ return;
+ }
+
+ stringstream s;
+ s.precision(15);
+
+ s << "{\"type\":\"methodReply\",\"name\":\"get\",\"data\":{";
+ s << "\"property\":\"" << property << "\",\"zone\":\"" << reply->value->zone << "\",\"value\":\"" << reply->value->toString() << "\",\"timestamp\":\""<<reply->value->timestamp<<"\",";
+ s <<"\"sequence\": \""<<reply->value->sequence<<"\"}";
+ s << ",\"transactionid\":\"" << id << "\"}";
+
+ string replystr = s.str();
+ //printf("Reply: %s\n",replystr.c_str());
+ LOG_MESSAGE("Reply:" << replystr << endl);
+
+ //if(replystr.length() > 4096){
+ // WebSockets::Write(socket, replystr.substr(0,4096));
+ // WebSockets::Write(socket, replystr.substr(4096, 4096));
+ //}
+ //else WebSockets::Write(socket, replystr);
+ WebSockets::Write(socket, replystr);
+
+ delete reply;
+ };
+
+ routingEngine->getPropertyAsync(request);
+}
+
+void CANGenPlugin::setValue(libwebsocket* socket, const std::string& property, const std::string& value, int zone, const std::string& interface, const std::string& transactionId)
+{
+ LOG_MESSAGE( "CANGenPlugin::setValue called with arguments:" << property << ", " << value << endl);
+
+ bool sent(false);
+ std::unique_ptr<AbstractPropertyType> type(VehicleProperty::getPropertyTypeForPropertyNameValue(property,value));
+ if(type) {
+ type->zone = zone;
+ type->sourceUuid = CANSimPluginUUID;
+
+ sent = sendValue(interface, type.get());
+ }
+
+ stringstream ss;
+ ss << "{\"type\":\"methodReply\",\"name\":\"set\",\"data\":[{\"property\":\"" << property << "\"}],\"transactionid\":\"" << transactionId << "\"";
+ if(!sent)
+ ss << ",\"error\":\"method call failed\"";
+ ss << "}";
+
+ string replystr = ss.str();
+ LOG_MESSAGE( "Reply:" << replystr << endl);
+
+ WebSockets::Write(socket, replystr);
+}
+
+void CANGenPlugin::dataReceived(libwebsocket* socket, const char* data, size_t len)
+{
+ if(!data || len == 0)
+ return;
+
+ //TODO: refactor ? copied from websocketsink
+ std::unique_ptr<json_object, decltype(&json_object_put)> rootobject(nullptr, &json_object_put);
+ std::unique_ptr<json_tokener, decltype(&json_tokener_free)> tokener(json_tokener_new(), &json_tokener_free);
+ enum json_tokener_error err;
+ do
+ { std::unique_ptr<json_object, decltype(&json_object_put)> tmpobject(json_tokener_parse_ex(tokener.get(), data, len), &json_object_put);
+ rootobject.swap(tmpobject);
+ } while ((err = json_tokener_get_error(tokener.get())) == json_tokener_continue);
+ if (err != json_tokener_success)
+ {
+ LOG_ERROR("Error: " << json_tokener_error_desc(err) << std::endl);
+ return;
+ }
+ if(!rootobject)
+ {
+ LOG_ERROR("Failed to parse json: " << data << std::endl);
+ return;
+ }
+
+ if (tokener->char_offset < len) // XXX shouldn't access internal fields
+ {
+ // Handle extra characters after parsed object as desired.
+ // e.g. issue an error, parse another object from that point, etc...
+ }
+ // Success, use jobj here.
+ json_object *typeobject = json_object_object_get(rootobject.get(),"type");
+ json_object *nameobject = json_object_object_get(rootobject.get(),"name");
+ json_object *transidobject = json_object_object_get(rootobject.get(),"transactionid");
+
+ if(!typeobject || !nameobject || !transidobject)
+ {
+ DebugOut(DebugOut::Warning)<<"Malformed json. aborting"<<endl;
+ return;
+ }
+
+ string type = string(json_object_get_string(typeobject));
+ string name = string(json_object_get_string(nameobject));
+ string id;
+ if (json_object_get_type(transidobject) == json_type_string)
+ {
+ id = string(json_object_get_string(transidobject));
+ }
+ else
+ {
+ stringstream strstr;
+ strstr << json_object_get_int(transidobject);
+ id = strstr.str();
+ }
+ if (type == "method") {
+
+ vector<string> propertyNames;
+ list< std::tuple<string, string, string, Zone::Type, string> > propertyData;
+
+ json_object *dataobject = json_object_object_get(rootobject.get(),"data");
+ if (json_object_get_type(dataobject) == json_type_array)
+ {
+ array_list *arraylist = json_object_get_array(dataobject);
+ for (int i=0;i<array_list_length(arraylist);i++)
+ {
+ json_object *arrayobject = (json_object*)array_list_get_idx(arraylist,i);
+ if (json_object_get_type(arrayobject) == json_type_object)
+ {
+ json_object *interfaceobject = json_object_object_get(arrayobject,"interface");
+ json_object *propobject = json_object_object_get(arrayobject,"property");
+ json_object *valueobject = json_object_object_get(arrayobject,"value");
+ json_object *zoneobject = json_object_object_get(arrayobject,"zone");
+ json_object *sourceobject = json_object_object_get(arrayobject,"source");
+ string interfacestr = string(interfaceobject ? json_object_get_string(interfaceobject) : "vcan0");
+ string keystr = string(propobject ? json_object_get_string(propobject) : "");
+ string valuestr = string(valueobject ? json_object_get_string(valueobject): "");
+ string sourcestr = string(sourceobject ? json_object_get_string(sourceobject): "");
+ Zone::Type z(Zone::None);
+ if(zoneobject){
+ try {
+ z = static_cast<Zone::Type>(boost::lexical_cast<int,std::string>(json_object_get_string(zoneobject)));
+ } catch (...) { }
+ }
+ propertyData.push_back(make_tuple(interfacestr, keystr, valuestr, z, sourcestr));
+ }
+ else if (json_object_get_type(arrayobject) == json_type_string)
+ {
+ string propertyName = string(json_object_get_string(arrayobject));
+ propertyNames.push_back(propertyName);
+ }
+ }
+ //array_list_free(arraylist);
+ }
+ else
+ {
+ string path = json_object_get_string(dataobject);
+ if (path != "")
+ {
+ propertyNames.push_back(path);
+ }
+ }
+ if (type == "method")
+ {
+ if (name == "get")
+ {
+ if (!propertyNames.empty())
+ {
+ //GetProperty is going to be a singleshot sink.
+ getValue(socket,propertyNames.front(),Zone::None,id);
+ }
+ else if (!propertyData.empty())
+ {
+ //GetProperty is going to be a singleshot sink.
+ auto prop = propertyData.front();
+ getValue(socket,std::get<1>(prop),std::get<3>(prop),id);
+ }
+ else
+ {
+ LOG_WARNING(" \"get\" method called with no data! Transaction ID:" << id);
+ }
+ }
+ else if (name == "set")
+ {
+ LOG_MESSAGE("set called");
+ if (!propertyNames.empty())
+ {
+ //Should not happen
+ }
+ else if (!propertyData.empty())
+ {
+ for (auto prop = propertyData.begin(); prop != propertyData.end(); ++prop)
+ {
+ LOG_MESSAGE("websocketsinkmanager setting " << std::get<1>(*prop) << " to " << std::get<2>(*prop) << " in zone " << std::get<3>(*prop));
+ setValue(socket,std::get<1>(*prop),std::get<2>(*prop),std::get<3>(*prop),std::get<0>(*prop), id);
+ }
+ }
+ }
+ else if (name == "getSupportedEventTypes")
+ {
+ //If data.front() dosen't contain a property name, return a list of properties supported.
+ //if it does, then return the event types that particular property supports.
+ string typessupported = "";
+ if (propertyNames.empty())
+ {
+ //Send what properties we support
+ PropertyList foo(routingEngine->supported());
+ PropertyList::const_iterator i=foo.cbegin();
+ while (i != foo.cend())
+ {
+ if(i==foo.cbegin())
+ typessupported.append("\"").append((*i)).append("\"");
+ else
+ typessupported.append(",\"").append((*i)).append("\"");
+ ++i;
+ }
+ }
+ else
+ {
+ //Send what events a particular property supports
+ PropertyList foo(routingEngine->supported());
+ if (contains(foo,propertyNames.front()))
+ {
+ //sinkManager->addSingleShotSink(wsi,data.front(),id);
+ typessupported = "\"get\",\"getSupportedEventTypes\"";
+ }
+ }
+ stringstream s;
+ string s2;
+ s << "{\"type\":\"methodReply\",\"name\":\"getSupportedEventTypes\",\"data\":[" << typessupported << "],\"transactionid\":\"" << id << "\"}";
+ string replystr = s.str();
+ LOG_INFO(" JSON Reply: " << replystr);
+ WebSockets::Write(socket, replystr);
+ }
+ else
+ {
+ DebugOut(0)<<"Unknown method called."<<endl;
+ }
+ }
+ }
+}
diff --git a/plugins/cangenplugin/cangenplugin.h b/plugins/cangenplugin/cangenplugin.h
new file mode 100644
index 00000000..09e9c4e5
--- /dev/null
+++ b/plugins/cangenplugin/cangenplugin.h
@@ -0,0 +1,314 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _CANGENPLUGINIMPL_H_
+#define _CANGENPLUGINIMPL_H_
+
+#include <map>
+#include <memory>
+#include <tgmath.h>
+#include <libwebsockets.h>
+#include <json.h>
+
+#include <canbus.h>
+#include <canobserver.h>
+
+#include <ambpluginimpl.h>
+#include "websockets.h"
+
+/*!
+ * \defgroup cangenplugin cangenplugin shared library.
+ *
+ * \brief CANGenPlugin generates CAN frames for CANSimPlugin based on WebSocket Simulator API requests.
+ *
+ * CANGenPlugin is a source plug-in for Automotive message broker(AMB). \n
+ * For the AMB library API please visit <a href="https://github.com/otcshare/automotive-message-broker">Automotive message broker web page</a>.\n
+ *
+ * To load this plugin at AMB starup, insert following rows into AMB configuration file:
+ * \code
+ * {
+ * "name" : "CANGenPlugin",
+ * "path":"/usr/lib/automotive-message-broker/cangenplugin.so"
+ * }
+ * \endcode
+ *
+ * It supports following Simulator API commands:
+ * \li Simulator.get() - Get property request - JSON in the form:
+ * \code {"type":"method","name":"get","transactionid":"862bb93d-a302-9a58-baa9-d90265ac843c","data":[{"property":"VehicleSpeed","zone":"0"}]} \endcode
+ * CANGenPlugin replies to this command with actual value, timestamp and sequence number of the requested property with the JSON in the form:\n
+ * \code {"type":"methodReply","name":"get","data":{"property":"VehicleSpeed","zone":"0","value":"35","timestamp":"1388656508.34255","sequence": "2"},"transactionid":"862bb93d-a302-9a58-baa9-d90265ac843c"} \endcode
+ * \li Simulator.set() - Set property request(simulation of the property new value) - JSON in the form:\n
+ * \code {"type":"method","name":"set","transactionid":"d5935c94-7b05-fd67-56bc-31c320185035","data":[{"interface":"vcan0","property":"VehicleSpeed","value":"33","zone":"0"}]} \endcode
+ * Based on property name and zone CANGenPlugin finds corresponding CAN Id of the requested property, builds CAN frame and sends it via specified CAN interface in the host OS.\n
+ * I replies back to the Simulator with the operation error code on failure or without error code on success:\n
+ * \code {"type":"methodReply","name":"set","data":[{"property":"VehicleSpeed"}],"transactionid":"d5935c94-7b05-fd67-56bc-31c320185035","error":"method call failed"} \endcode
+ * \code {"type":"methodReply","name":"set","data":[{"property":"VehicleSpeed"}],"transactionid":"d5935c94-7b05-fd67-56bc-31c320185035"}\endcode
+ *
+ * @{
+ */
+
+/*!
+ * \brief CAN frames generator plug-in for the AMB CAN Simulator.
+ *
+ * On startup it subscribe and reads 'MappingTable' property from CANSimPlugin, parses it and build
+ * own mapping table(AMB property to CAN Id map) of all properties from CANSimPlugin that can be simulated.\n
+ * In parallel to building mapping table of the AMB properties and their corresponding CAN Ids it starts listening for javascrip Simulator API commands on WebSocket port \p \b 23001. \n
+ *
+ * \see \ref libcanbus
+ * \class CANGenPlugin
+ */
+
+static const char* CANSimPluginUUID = "3f43e231-11ec-4782-9b5a-3dbcc5221eeb";
+
+class CANGenPlugin: public AmbPluginImpl, public CANObserver, public WebSocketsObserver {
+
+public:
+
+ /*!
+ * \param re AbstractRoutingEngine
+ * \param config Map of the configuration string values loaded on startup from AMB configuration file
+ * \param parent AmbPlugin instance
+ */
+ CANGenPlugin(AbstractRoutingEngine* re, const std::map<std::string, std::string>& config, AbstractSource &parent);
+ virtual ~CANGenPlugin(); // has to be virtual because of unit tests
+
+ // from AbstractSink
+public:
+
+ /*! uuid() is a unique identifier of the plugin
+ * @return a guid-style unique identifier
+ */
+ const std::string uuid() const { return "becbbef9-6cc8-4b9e-8cd7-2fbe37b9b52a"; }
+
+ /*! propertyChanged is called when a subscribed to property changes.
+ * @see AbstractRoutingEngine::subscribeToPropertyChanges()
+ * \param value value of the property that changed. this is a temporary pointer that will be destroyed.
+ * Do not destroy it. If you need to store the value use value.anyValue(), value.value<T>() or
+ * value->copy() to copy.
+ */
+ void propertyChanged(AbstractPropertyType* value);
+
+ AsyncPropertyReply* setProperty(const AsyncSetPropertyRequest &request);
+
+ // from CANObserver
+public:
+ /*!
+ * Called when error occurred on the bus.
+ * \fn errorOccured
+ * \param error \link CANObserver#CANError Bus error code \endlink
+ */
+ virtual void errorOccured(CANObserver::CANError error);/* socket error */
+ /*!
+ * Called when standard frame was is received from the bus.
+ * \fn standardFrameReceived
+ * \param frame Received frame
+ */
+ virtual void standardFrameReceived(const can_frame& frame);/* SFF was present */
+ /*!
+ * Called when extended frame was is received from the bus.
+ * \fn extendedFrameReceived
+ * \param frame Received frame
+ */
+ virtual void extendedFrameReceived(const can_frame& frame);/* EFF was present */
+ /*!
+ * Called when error frame was received from the bus.
+ * \fn errorFrameReceived
+ * \param frame Error frame
+ */
+ virtual void errorFrameReceived(const can_frame& frame);/* error frame */
+ /*!
+ * Called when remote transmission frame was received from the bus.
+ * \fn remoteTransmissionRequest
+ * \param frame RTR frame
+ */
+ virtual void remoteTransmissionRequest(const can_frame& frame);/* remote transmission request (SFF/EFF is still present)*/
+
+ /*!
+ * Second phase of the plugin initialization.
+ * \fn init
+ */
+ virtual void init();
+
+ // from WebSocketsObserver
+
+ /*!
+ * Called when data received from libwebsockets
+ * \fn dataReceived
+ * \param socket libwebsocket* to be used to send any reply.
+ * \param data Received data pointer.
+ * \param len Length of the data.
+ * \return None
+ */
+ void dataReceived(libwebsocket* socket, const char* data, size_t len);
+
+//
+// Internal methods:
+//
+private:
+
+ /*!
+ * \brief Prints received CAN frame
+ * \param frame Received CAN frame.
+ * \internal
+ * \private
+ */
+ void printFrame(const can_frame& frame) const;
+
+ /*!
+ * Parses 'MappingTable' property from CANSimPlugin.
+ * Result is stored in internal MappingTable class(AMB property and Zone to CAN Id map) which contains all properties that can be simulated.
+ * \param json Content of the 'MappingTable' property in JSON format.
+ */
+ void parseMappingTable(const std::string& json);
+
+ /*!
+ * \brief Simulator.get request handler function.
+ * Builds and sends reply with the property value, timestamp and sequence number in JSON format.
+ * \param socket libwebsocket handle to be used to send reply.
+ * \param property Name of the property.
+ * \param zone Property's zone.
+ * \param uuid Request's transaction id.
+ * \private
+ */
+ void getValue(libwebsocket* socket, const std::string& property, int zone, const std::string& uuid);
+
+ /*!
+ * \brief Simulator.set request handler function.
+ * Formats property's value as a AMB's AbstractPropertyValue and passes it to sendValue. Reply to the Simulator with reply string in JSON format.
+ * \param socket libwebsocket handle to be used to send reply.
+ * \param property Name of the property.
+ * \param value Property's new value to be simulated.
+ * \param zone Property's zone.
+ * \param interface CAN interface to be used to send CAN frame.
+ * \param transactionId Request's transaction id.
+ * \private
+ */
+ void setValue(libwebsocket* socket, const std::string& property, const std::string& value, int zone, const std::string& interface, const std::string& transactionId);
+
+ /*!
+ * \brief Build and sends CAN frame to CANSimPlugin.
+ * Finds CAN Id using mappingTable for requested property name and zone, builds CAN frame with the property's new value and tries to send it via requested CAN interface.
+ * \param interface CAN interface to be used to send CAN frame.
+ * \param value AMB's AbstractPropertyValue which encapsulates property name, zone and value.
+ * \return true if CAN frame was successfully sent, otherwise false.
+ * \private
+ */
+ bool sendValue(const std::string& interface, AbstractPropertyType* value);
+
+ /*!
+ * Internal helper class
+ * AMB property and property's zone to CAN Id map
+ * \class MappingTable
+ * \private
+ * \internal
+ *
+ */
+ class MappingTable{
+ public:
+ MappingTable()
+ {
+ }
+
+ MappingTable(const MappingTable& other) = delete;
+ MappingTable& operator=(const MappingTable& other) = delete;
+ MappingTable(MappingTable&& other) = default;
+ MappingTable& operator=(MappingTable&& other) = default;
+
+ void addProperty(const std::string& source, json_object* signal)
+ {
+ json_object* canIdObj = json_object_object_get(signal, "can_id");
+ json_object* nameObj = json_object_object_get(signal, "name");
+ if(!canIdObj || !nameObj) // mandatory
+ return;
+ Zone::Type zone(Zone::None);
+ json_object* zoneObj = json_object_object_get(signal, "zone");
+ if(zoneObj)
+ zone = json_object_get_int(zoneObj);
+
+ auto& zp = mapping[source];
+ auto& prop = zp[Zone::Type(zone)];
+ std::string name(json_object_get_string(nameObj));
+ int can_id = json_object_get_int(canIdObj);
+ prop[name] = can_id; // update an existing value
+ }
+
+ int getCanId(const std::string& source, const Zone::Type& zone, const VehicleProperty::Property& name) const
+ {
+ //return mapping[source][zone][name]; // caution! this will insert if not found. I don't want it.
+ auto sourceIt = mapping.find(source);
+ if(sourceIt == mapping.end())
+ return 0;
+ auto zoneIt = sourceIt->second.find(zone);
+ if(zoneIt == sourceIt->second.end())
+ return 0;
+ auto propIt = zoneIt->second.find(name);
+ if(propIt == zoneIt->second.end())
+ return 0;
+ else
+ return propIt->second;
+ }
+
+ void clear()
+ {
+ mapping.clear();
+ }
+
+ private:
+ typedef std::map< Zone::Type, std::map<VehicleProperty::Property, canid_t> > ZonedProperty;
+ std::map<std::string, ZonedProperty> mapping;
+ };
+
+//
+// data:
+//
+
+ /*!
+ * AMB property and property's zone to CAN Id map
+ * \private
+ */
+ MappingTable mappingTable;
+
+ /*!
+ * Opened CAN interfaces used to send CAN frames
+ * \private
+ */
+ std::map<std::string, std::shared_ptr<CANBus> > interfaces;
+
+ /*!
+ * Encapsulated libwebsocket library
+ * \private
+ */
+ std::unique_ptr<WebSockets> ws;
+
+ /*!
+ * Mutex to protect mappingTable container during property 'MappingTable' parsing on change notification
+ * \private
+ */
+ interprocess_recursive_mutex mutex;
+};
+
+class SimCommand: public StringPropertyType
+{
+public:
+ SimCommand(): StringPropertyType("SimCommand") { }
+ SimCommand(std::string val) : StringPropertyType("SimCommand",val) { }
+};
+
+#endif // _CANGENPLUGINIMPL_H_
+
+/** @} */
diff --git a/plugins/cangenplugin/test/CMakeLists.txt b/plugins/cangenplugin/test/CMakeLists.txt
new file mode 100644
index 00000000..76348e7e
--- /dev/null
+++ b/plugins/cangenplugin/test/CMakeLists.txt
@@ -0,0 +1,48 @@
+
+set(include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/lib ${CMAKE_SOURCE_DIR}/lib ../ ../../../tests)
+
+find_library(libtool_LIBRARY ltdl DOC "Libtool libraries")
+find_path(libtool_INCLUDE_DIR ltdl.h DOC "Libtool headers")
+
+pkg_check_modules(glib REQUIRED glib-2.0)
+pkg_check_modules(json REQUIRED json)
+pkg_check_modules(websockets REQUIRED libwebsockets)
+
+#find libcanbus.a library:
+find_library(canbus_LIBRARY canbus PATHS $ENV{IVIPOC_HOME}/native/lib DOC "canbus library")
+if(canbus_LIBRARY)
+ message(STATUS "canbus library found")
+else(canbus_LIBRARY)
+ message(FATAL_ERROR "canbus library is missing. please install or build canbus")
+endif(canbus_LIBRARY)
+
+#find libivipoc-common.a library:
+find_library(ivipoc-common_LIBRARY ivipoc-common PATHS $ENV{IVIPOC_HOME}/native/lib DOC "ivipoc-common library")
+if(ivipoc-common_LIBRARY)
+ message(STATUS "ivipoc-common library found")
+else(ivipoc-common_LIBRARY)
+ message(FATAL_ERROR "ivipoc-common library is missing. please install or build canbus")
+endif(ivipoc-common_LIBRARY)
+
+#find canbus headers:
+find_path(canbus_INCLUDE_DIR canbus.h canobserver.h logger.h mutex.h thread.h
+ PATHS $ENV{IVIPOC_HOME}/native/include
+ DOC "canbus headers")
+
+if(canbus_INCLUDE_DIR)
+ message(STATUS "canbus headers found.")
+else(canbus_INCLUDE_DIR)
+ message(FATAL_ERROR "no canbus headers found")
+endif(canbus_INCLUDE_DIR)
+
+set(ut_cangenplugin_headers cangenplugin.h websockets.h mockabstractroutingengine.h)
+set(ut_cangenplugin_sources main.cpp ut_cangenplugin.cpp ../cangenplugin.cpp ../websockets.cpp)
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
+add_definitions(-fPIC -g)
+
+add_executable(ut_cangenplugin ${ut_cangenplugin_sources})
+
+include_directories(${include_dirs} ../ivipocbase ${libtool_INCLUDE_DIR} ${canbus_INCLUDE_DIR} ${glib_INCLUDE_DIRS} ${gio_INCLUDE_DIRS})
+target_link_libraries(ut_cangenplugin ${link_libraries} ivipocbase -L${CMAKE_CURRENT_BINARY_DIR}/../../../ivipocbase/build ${libtool_LIBRARY} ${glib_LIBRARIES} ${json_LIBRARIES} amb ${websockets_LIBRARIES} ${canbus_LIBRARY} ${ivipoc-common_LIBRARY} -lgobject-2.0 -lpthread)
+
diff --git a/plugins/cangenplugin/test/main.cpp b/plugins/cangenplugin/test/main.cpp
new file mode 100644
index 00000000..8e870abc
--- /dev/null
+++ b/plugins/cangenplugin/test/main.cpp
@@ -0,0 +1,73 @@
+/*****************************************************************
+ * INTEL CONFIDENTIAL
+ * Copyright 2011 - 2013 Intel Corporation All Rights Reserved.
+ *
+ * The source code contained or described herein and all documents related to the
+ * source code("Material") are owned by Intel Corporation or its suppliers or
+ * licensors.Title to the Material remains with Intel Corporation or its
+ * suppliers and licensors.The Material may contain trade secrets and proprietary
+ * and confidential information of Intel Corporation and its suppliers and
+ * licensors, and is protected by worldwide copyright and trade secret laws and
+ * treaty provisions.No part of the Material may be used, copied, reproduced,
+ * modified, published, uploaded, posted, transmitted, distributed, or disclosed
+ * in any way without Intels prior express written permission.
+ * No license under any patent, copyright, trade secret or other intellectual
+ * property right is granted to or conferred upon you by disclosure or delivery
+ * of the Materials, either expressly, by implication, inducement, estoppel or
+ * otherwise.Any license under such intellectual property rights must be
+ * express and approved by Intel in writing.
+ *
+ * Unless otherwise agreed by Intel in writing, you may not remove or alter this
+ * notice or any other notice embedded in Materials by Intel or Intels suppliers
+ * or licensors in any way.
+ *****************************************************************/
+
+#include <glib-object.h>
+#include <CppUTest/CommandLineTestRunner.h>
+#include "logger.h"
+
+struct ThreadData{
+ int argc;
+ char** argv;
+ int testResult;
+ GMainLoop* mainLoop;
+};
+
+static void* tests_thread(void *data)
+{
+ ThreadData* td = static_cast<ThreadData*>(data);
+ if(td){
+ td->testResult = CommandLineTestRunner::RunAllTests(td->argc, td->argv);
+ g_main_loop_quit(td->mainLoop);
+ }
+ return td;
+}
+
+int main(int ac, char **av)
+{
+ ThreadData td;
+ td.argc = ac;
+ td.argv = av;
+ td.testResult = 0;
+
+ DEBUG_CONF("ut_cangenplugin",
+#ifdef _DEBUG
+ CUtil::Logger::file_on|CUtil::Logger::screen_on,
+#else
+ CUtil::Logger::file_on|CUtil::Logger::screen_off,
+#endif
+ CUtil::Logger::EInfo, CUtil::Logger::EWarning);
+
+ td.mainLoop = g_main_loop_new(NULL, FALSE);
+
+ // Run the mainloop and the tests thread
+ GThread* testThread = g_thread_new("tests thread", &tests_thread, &td);
+
+ g_main_loop_run(td.mainLoop);
+ g_thread_join(testThread);
+
+ g_main_loop_unref(td.mainLoop);
+
+
+ return td.testResult;
+}
diff --git a/plugins/cangenplugin/test/ut_cangenplugin.cpp b/plugins/cangenplugin/test/ut_cangenplugin.cpp
new file mode 100644
index 00000000..76c211c9
--- /dev/null
+++ b/plugins/cangenplugin/test/ut_cangenplugin.cpp
@@ -0,0 +1,345 @@
+/*****************************************************************
+ * INTEL CONFIDENTIAL
+ * Copyright 2011 - 2013 Intel Corporation All Rights Reserved.
+ *
+ * The source code contained or described herein and all documents related to the
+ * source code("Material") are owned by Intel Corporation or its suppliers or
+ * licensors.Title to the Material remains with Intel Corporation or its
+ * suppliers and licensors.The Material may contain trade secrets and proprietary
+ * and confidential information of Intel Corporation and its suppliers and
+ * licensors, and is protected by worldwide copyright and trade secret laws and
+ * treaty provisions.No part of the Material may be used, copied, reproduced,
+ * modified, published, uploaded, posted, transmitted, distributed, or disclosed
+ * in any way without Intels prior express written permission.
+ * No license under any patent, copyright, trade secret or other intellectual
+ * property right is granted to or conferred upon you by disclosure or delivery
+ * of the Materials, either expressly, by implication, inducement, estoppel or
+ * otherwise.Any license under such intellectual property rights must be
+ * express and approved by Intel in writing.
+ *
+ * Unless otherwise agreed by Intel in writing, you may not remove or alter this
+ * notice or any other notice embedded in Materials by Intel or Intels suppliers
+ * or licensors in any way.
+ *****************************************************************/
+
+#include "logger.h"
+
+#include <ltdl.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+
+#include <listplusplus.h>
+#define private protected
+#include "cangenplugin.h"
+#undef private
+#include "mockabstractroutingengine.h"
+#include "mockcanbus.h"
+
+typedef void* create_t(AbstractRoutingEngine*, std::map<std::string, std::string>);
+
+class Loader{
+public:
+ Loader()
+ {
+ if(lt_dlinit())
+ {
+ cerr<<"error initializing libtool: "<<__FILE__<<" - "<<__FUNCTION__<<":"<<__LINE__<<" "<<lt_dlerror()<<endl;
+ throw std::runtime_error("Error initializing libtool. aborting");
+ }
+ }
+
+ ~Loader()
+ {
+ auto handle = openHandles.begin();
+ while(handle != openHandles.end())
+ lt_dlclose(*handle++);
+ lt_dlexit();
+ }
+
+ template<class T>
+ T loadPlugin(std::string pluginName, AbstractRoutingEngine* routingEngine, std::map<std::string, std::string> config)
+ {
+ DebugOut()<<"Loading plugin: "<<pluginName<<endl;
+
+ lt_dlhandle handle = lt_dlopenext(pluginName.c_str());
+
+ if(!handle)
+ {
+ cerr<<"error opening plugin: "<<pluginName<<" in "<<__FILE__<<" - "<<__FUNCTION__<<":"<<__LINE__<<" "<<lt_dlerror()<<endl;
+ return nullptr;
+ }
+
+ openHandles.push_back(handle);
+ create_t* f_create = (create_t *)lt_dlsym(handle, "create");
+
+ //mErrorString = lt_dlerror();
+
+ if(f_create)
+ {
+ void* obj = f_create(routingEngine, config);
+ return static_cast<T>( obj );
+ }
+
+ return nullptr;
+ }
+private:
+ std::vector<lt_dlhandle> openHandles;
+};
+
+class TestCANGenPluginImpl : public CANGenPlugin
+{
+public:
+ TestCANGenPluginImpl(AbstractRoutingEngine* re, map<string, string> config, AbstractSource& parent) :
+ CANGenPlugin(re, config, parent)
+ {
+ mock().actualCall("CANGenPlugin::CANGenPlugin");
+ }
+
+ virtual ~TestCANGenPluginImpl()
+ {
+ mock().actualCall("CANGenPlugin::~CANGenPlugin");
+ }
+
+ void TestAddPropertyToMappingTable(const char* source, const int can_id, const char* name, const Zone::Type& zone)
+ {
+ std::unique_ptr<json_object, decltype(&json_object_put)> prop(json_object_new_object(), &json_object_put);
+ json_object_object_add(prop.get(), "can_id", json_object_new_int(can_id));
+ json_object_object_add(prop.get(), "name", json_object_new_string(name));
+ json_object_object_add(prop.get(), "zone", json_object_new_int(static_cast<int>(zone)));
+ mappingTable.addProperty(source, prop.get());
+ }
+
+ inline bool TestSendValue(const string& interface, AbstractPropertyType* value){ return sendValue(interface, value); }
+ inline void TestSetCanBusInterface(const string& interface){
+ interfaces[interface] = std::shared_ptr<CANBus>(new MockCANBus(*this));
+ }
+ inline int getCanId(const std::string& source, const Zone::Type& zone, const VehicleProperty::Property& name){
+ return mappingTable.getCanId(source, zone, name);
+ }
+ inline bool TestSetAndGetValue(const std::string& property, const std::string& value, int zone, const std::string& interface, const std::string& transactionId)
+ {
+ setValue(nullptr, property, value, zone, interface, transactionId);
+
+ getValue(nullptr, property, zone, transactionId);
+ }
+};
+
+class TestCANGenPlugin : public AmbPlugin<TestCANGenPluginImpl>
+{
+public:
+ TestCANGenPlugin(AbstractRoutingEngine* re, map<string, string> config) :
+ AmbPlugin<TestCANGenPluginImpl>(re, config)
+ {
+ mock().actualCall("AmbPlugin::AmbPlugin");
+ }
+
+ virtual ~TestCANGenPlugin()
+ {
+ mock().actualCall("AmbPlugin::~AmbPlugin");
+ }
+
+ inline TestCANGenPluginImpl* getImplementation() { return dynamic_cast<TestCANGenPluginImpl*>(d.get()); }
+};
+
+TEST_GROUP(CANGenPlugin)
+{
+ MockAbstractRoutingEngine *routingEngine;
+ std::map<std::string, std::string> config;
+ TestCANGenPlugin *plugin;
+
+ void setup()
+ {
+ DebugOut::setDebugThreshhold(0);
+ VehicleProperty::factory();
+ routingEngine = new MockAbstractRoutingEngine();
+ plugin = nullptr;
+ mock().expectOneCall("AmbPlugin::AmbPlugin");
+ mock().expectOneCall("CANGenPlugin::CANGenPlugin");
+ //mock().expectOneCall("CANBus::start").andReturnValue(1);
+ mock().expectOneCall("AbstractRoutingEngine::setSupported");
+ plugin = new TestCANGenPlugin(routingEngine, config);
+ }
+ void teardown()
+ {
+ //mock().expectOneCall("CANBus::stop");
+ mock().expectOneCall("CANGenPlugin::~CANGenPlugin");
+ mock().expectOneCall("AmbPlugin::~AmbPlugin");
+ if(plugin != nullptr) {
+ delete plugin;
+ plugin = nullptr;
+ }
+ VehicleProperty::shutdown();
+
+ delete routingEngine;
+ routingEngine = nullptr;
+
+ mock().checkExpectations();
+ mock().clear();
+ }
+};
+
+TEST(CANGenPlugin, create)
+{
+
+ //mock().expectOneCall("CANSimPlugin::CANSimPlugin");
+ Loader ldr;
+
+ mock().expectOneCall("AbstractRoutingEngine::setSupported");
+ AbstractSource* myplugin = ldr.loadPlugin<AbstractSource*>("./build/cangenplugin.so", routingEngine, config);
+ CHECK( myplugin != nullptr);
+ delete myplugin;
+}
+
+TEST(CANGenPlugin, uuid)
+{
+ std::string uuid = plugin->uuid();
+ //CHECK_EQUAL_C_STRING("3f43e231-11ec-4782-9b5a-3dbcc5221eeb", uuid.c_str());
+ CHECK(uuid.length() > 0);
+}
+
+TEST(CANGenPlugin, propertyChanged)
+{
+ plugin->propertyChanged(nullptr);
+
+ std::unique_ptr<AbstractPropertyType> value(VehicleProperty::getPropertyTypeForPropertyNameValue(VehicleProperty::VehicleSpeed, "55"));
+ value->zone = Zone::None;
+ value->sourceUuid = plugin->uuid();
+
+ plugin->propertyChanged(value.get());
+
+ value = std::unique_ptr<AbstractPropertyType>(new StringPropertyType("MappingTable", "{}"));
+ plugin->propertyChanged(value.get());
+
+}
+
+TEST(CANGenPlugin, parseMappingTable)
+{
+ std::unique_ptr<AbstractPropertyType> value(new StringPropertyType("MappingTable", "{"));
+ plugin->propertyChanged(value.get());
+
+ value = std::unique_ptr<AbstractPropertyType>(new StringPropertyType("MappingTable", "{ "
+ "'sources': [ { 'source': { 'guid': '3f43e231-11ec-4782-9b5a-3dbcc5221eeb' }, "
+ "'signals': [ "
+ "{ 'can_id': 10, 'name': 'SeatHeater', 'zone': 0 }, "
+ "{ 'can_id': 11, 'name': 'SeatHeater', 'zone': 2 }, "
+ "{ 'can_id': 12, 'name': 'SeatHeater', 'zone': 4 }, "
+ "{ 'can_id': 13, 'name': 'SeatHeater', 'zone': 8 }, "
+ "{ 'can_id': 14, 'name': 'SeatHeater', 'zone': 16 }, "
+ "{ 'can_id': 15, 'name': 'SeatHeater', 'zone': 32 }, "
+ "{ 'can_id': 16, 'name': 'SeatHeater', 'zone': 64 }, "
+ "{ 'can_id': 17, 'name': 'SeatHeater', 'zone': 128 }, "
+ "{ 'can_id': 18, 'name': 'SeatHeater', 'zone': 256 }, "
+ "{ 'can_id': 19, 'name': 'SeatHeater', 'zone': 512 }, "
+ "{ 'can_id': 20, 'name': 'SeatHeater', 'zone': 5 }, "
+ "{ 'can_id': 21, 'name': 'SeatHeater', 'zone': 9 }, "
+ "{ 'can_id': 22, 'name': 'SeatHeater', 'zone': 6 }, "
+ "{ 'can_id': 23, 'name': 'SeatHeater', 'zone': 10 }, "
+ "{ 'can_id': 24, 'name': 'SeatHeater', 'zone': 20 }, "
+ "{ 'can_id': 25, 'name': 'SeatHeater', 'zone': 24 }"
+ " ] } ] }"));
+ plugin->propertyChanged(value.get());
+ CHECK(20 == plugin->getImplementation()->getCanId(
+ std::string("3f43e231-11ec-4782-9b5a-3dbcc5221eeb"),
+ Zone::Type(5), VehicleProperty::Property("SeatHeater")));
+
+ value = std::unique_ptr<AbstractPropertyType>(new StringPropertyType("MappingTable", "{ "
+ "'signals': [ "
+ "{ 'can_id': 10, 'name': 'SeatHeater', 'zone': 0 }, "
+ "{ 'can_id': 11, 'name': 'SeatHeater', 'zone': 2 }, "
+ "{ 'can_id': 12, 'name': 'SeatHeater', 'zone': 4 }, "
+ "{ 'can_id': 13, 'name': 'SeatHeater', 'zone': 8 }, "
+ "{ 'can_id': 14, 'name': 'SeatHeater', 'zone': 16 }, "
+ "{ 'can_id': 15, 'name': 'SeatHeater', 'zone': 32 }, "
+ "{ 'can_id': 16, 'name': 'SeatHeater', 'zone': 64 }, "
+ "{ 'can_id': 17, 'name': 'SeatHeater', 'zone': 128 }, "
+ "{ 'can_id': 18, 'name': 'SeatHeater', 'zone': 256 }, "
+ "{ 'can_id': 19, 'name': 'SeatHeater', 'zone': 512 }, "
+ "{ 'can_id': 20, 'name': 'SeatHeater', 'zone': 5 }, "
+ "{ 'can_id': 21, 'name': 'SeatHeater', 'zone': 9 }, "
+ "{ 'can_id': 22, 'name': 'SeatHeater', 'zone': 6 }, "
+ "{ 'can_id': 23, 'name': 'SeatHeater', 'zone': 10 }, "
+ "{ 'can_id': 24, 'name': 'SeatHeater', 'zone': 20 }, "
+ "{ 'can_id': 25, 'name': 'SeatHeater', 'zone': 24 }"
+ " ] } ] }"));
+ plugin->propertyChanged(value.get());
+ CHECK(20 != plugin->getImplementation()->getCanId(
+ std::string("3f43e231-11ec-4782-9b5a-3dbcc5221eeb"),
+ Zone::Type(5), VehicleProperty::Property("SeatHeater"))
+ );
+}
+
+TEST(CANGenPlugin, errorOccured)
+{
+ plugin->getImplementation()->errorOccured(static_cast<CANObserver::CANError>(-1));
+
+ CANObserver::CANError error(CANObserver::GENERAL_ERROR);
+ plugin->getImplementation()->errorOccured(error);
+}
+
+TEST(CANGenPlugin, standardFrameReceived)
+{
+ can_frame frame;
+ memset(&frame, 0, sizeof(frame));
+ frame.can_id = 0x00a;
+ plugin->getImplementation()->standardFrameReceived(frame);
+}
+
+TEST(CANGenPlugin, extendedFrameReceived)
+{
+ can_frame frame;
+ memset(&frame, 0, sizeof(frame));
+ plugin->getImplementation()->extendedFrameReceived(frame);
+}
+
+TEST(CANGenPlugin, errorFrameReceived)
+{
+ can_frame frame;
+ memset(&frame, 0, sizeof(frame));
+ plugin->getImplementation()->errorFrameReceived(frame);
+}
+
+TEST(CANGenPlugin, remoteTransmissionRequest)
+{
+ can_frame frame;
+ memset(&frame, 0, sizeof(frame));
+ plugin->getImplementation()->remoteTransmissionRequest(frame);
+}
+
+TEST(CANGenPlugin, sendValue)
+{
+ plugin->getImplementation()->TestSetCanBusInterface("vcan98");
+ CHECK(plugin->getImplementation()->TestSendValue("vcan98", nullptr) == false);
+
+ std::unique_ptr<AbstractPropertyType> value(VehicleProperty::getPropertyTypeForPropertyNameValue(VehicleProperty::DoorsPerRow, "[2,2]"));
+ CHECK(plugin->getImplementation()->TestSendValue("vcan98", value.get()) == false);
+
+ plugin->getImplementation()->TestAddPropertyToMappingTable(plugin->uuid().c_str(), 0xA, VehicleProperty::VehicleSpeed.c_str(), Zone::None);
+ value = std::unique_ptr<AbstractPropertyType>(VehicleProperty::getPropertyTypeForPropertyNameValue(VehicleProperty::VehicleSpeed, "55"));
+ value->zone = Zone::None;
+ value->sourceUuid = plugin->uuid();
+ plugin->getImplementation()->TestSetCanBusInterface("vcan98");
+ mock().expectOneCall("CANBus::sendExtendedFrame").andReturnValue(0);
+ CHECK(plugin->getImplementation()->TestSendValue("vcan98", value.get()) == false);
+
+ plugin->getImplementation()->TestSetCanBusInterface("vcan99");
+ mock().expectOneCall("CANBus::sendExtendedFrame").andReturnValue(1);
+ CHECK(plugin->getImplementation()->TestSendValue("vcan99", value.get()) == true);
+ mock().expectNCalls(2,"CANBus::stop");
+}
+
+TEST(CANGenPlugin, SetAndGetValue)
+{
+ plugin->getImplementation()->TestSetCanBusInterface("vcan0");
+ mock().expectOneCall("CANBus::sendExtendedFrame").andReturnValue(1);
+ plugin->getImplementation()->TestAddPropertyToMappingTable(CANSimPluginUUID, 0xA, VehicleProperty::VehicleSpeed.c_str(), Zone::None);
+ plugin->getImplementation()->TestSetAndGetValue(VehicleProperty::VehicleSpeed, "33", 0, "vcan0", "trans1");
+ mock().expectOneCall("CANBus::stop");
+}
+
+TEST(CANGenPlugin, dataReceived)
+{
+ const char *get = R"({"type":"method","name":"get","transactionid":"862bb93d-a302-9a58-baa9-d90265ac843c","data":[{"property":"VehicleSpeed","zone":"0"}]})";
+ plugin->getImplementation()->dataReceived(nullptr, get, strlen(get));
+ const char *set = R"({"type":"method","name":"set","transactionid":"d5935c94-7b05-fd67-56bc-31c320185035","data":[{"interface":"vcan0","property":"VehicleSpeed","value":"33","zone":"0"}]})";
+ plugin->getImplementation()->dataReceived(nullptr, set, strlen(set));
+}
diff --git a/plugins/cangenplugin/websockets.cpp b/plugins/cangenplugin/websockets.cpp
new file mode 100644
index 00000000..bafbe16d
--- /dev/null
+++ b/plugins/cangenplugin/websockets.cpp
@@ -0,0 +1,251 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "websockets.h"
+#include <json/json.h>
+#include <json/json_object.h>
+#include <json/json_tokener.h>
+#include <vehicleproperty.h>
+#include <listplusplus.h>
+
+#define __SMALLFILE__ std::string(__FILE__).substr(std::string(__FILE__).rfind("/")+1)
+
+static int websocket_callback(
+ libwebsocket_context *context, libwebsocket *wsi, libwebsocket_callback_reasons reason, void *user,void *in, size_t len)
+{
+ WebSockets *ws = static_cast<WebSockets*>(libwebsocket_context_user (context));
+ WebSocketsObserver* observer = &ws->getObserver();
+ DebugOut(5) << __SMALLFILE__ << ":" << __LINE__ <<
+ "websocket_callback:" << reason << " ,user:" << reinterpret_cast<uint64_t>(user) << endl;
+ if(!observer)
+ return 0;
+
+ switch (reason)
+ {
+ case LWS_CALLBACK_CLIENT_WRITEABLE:
+ {
+ //Connection has been established.
+ //printf("Connection established\n");
+ break;
+ }
+ case LWS_CALLBACK_CLOSED:
+ {
+ //Connection is closed, we need to remove all related sinks
+ //sinkManager->disconnectAll(wsi);
+ break;
+ }
+ case LWS_CALLBACK_CLIENT_RECEIVE:
+ {
+ //printf("Client writable\n");
+ break;
+ }
+ case LWS_CALLBACK_SERVER_WRITEABLE:
+ {
+ //printf("Server writable\n");
+ break;
+ }
+
+ case LWS_CALLBACK_RECEIVE:
+ {
+ //printf("Data Received: %s\n",(char*)in);
+ //The lack of a break; here is intentional.
+ }
+ case LWS_CALLBACK_HTTP:
+ {
+ //TODO: Verify that ALL requests get sent via LWS_CALLBACK_HTTP, so we can use that instead of LWS_CALLBACK_RECIEVE
+ const char *data = static_cast<const char*>(in);
+ DebugOut() << __SMALLFILE__ << ":" << __LINE__ << " Requested: " << data << "\n";
+ observer->dataReceived(wsi, data, len);
+ break;
+ }
+ case LWS_CALLBACK_ADD_POLL_FD:
+ {
+ //printf("Adding poll %i\n",sinkManager);
+ DebugOut(5) << __SMALLFILE__ <<":"<< __LINE__ << "Adding poll" << endl;
+ ws->addPoll(libwebsocket_get_socket_fd(wsi));
+ break;
+ }
+ case LWS_CALLBACK_DEL_POLL_FD:
+ {
+ ws->removePoll(libwebsocket_get_socket_fd(wsi));
+ break;
+ }
+ case LWS_CALLBACK_SET_MODE_POLL_FD:
+ {
+ //Set the poll mode
+ break;
+ }
+ case LWS_CALLBACK_CLEAR_MODE_POLL_FD:
+ {
+ //Don't handle this yet.
+ break;
+ }
+ default:
+ {
+ //printf("Unhandled callback: %i\n",reason);
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Unhandled callback:" << reason << "\n";
+ break;
+ }
+ }
+ return 0;
+}
+
+static bool gioPollingFunc(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+ //DebugOut(5) << "Polling..." << condition << endl;
+ WebSockets* ws = static_cast<WebSockets*>(data);
+
+ if(condition & G_IO_ERR)
+ {
+ DebugOut(0)<< __SMALLFILE__ <<":"<< __LINE__ <<" websocketsink polling error."<<endl;
+ }
+
+ if (condition & G_IO_HUP)
+ {
+ //Hang up. Returning false closes out the GIOChannel.
+ //printf("Callback on G_IO_HUP\n");
+ DebugOut(0)<<"socket hangup event..."<<endl;
+ if(ws)
+ ws->removePoll(g_io_channel_unix_get_fd(source));
+ return false;
+ }
+
+ //This is the polling function. If it return false, glib will stop polling this FD.
+ //printf("Polling...%i\n",condition);
+
+ lws_tokens token;
+ struct pollfd pollstruct;
+ int newfd = g_io_channel_unix_get_fd(source);
+ pollstruct.fd = newfd;
+ pollstruct.events = condition;
+ pollstruct.revents = condition;
+ //libwebsocket_context* context = sinkManager->lwscontext();
+ libwebsocket_service_fd(static_cast<WebSockets*>(data)->getContext(),&pollstruct);
+
+ if(pollstruct.revents & G_IO_ERR)
+ {
+ DebugOut(0)<< __SMALLFILE__ <<":"<< __LINE__ <<" websocketsink polling error."<<endl;
+ }
+
+ if (pollstruct.revents & G_IO_HUP)
+ {
+ //Hang up. Returning false closes out the GIOChannel.
+ //printf("Callback on G_IO_HUP\n");
+ DebugOut(0)<<"socket hangup event..."<<endl;
+ if(ws)
+ ws->removePoll(g_io_channel_unix_get_fd(source));
+ return false;
+ }
+ return true;
+}
+
+WebSockets::WebSockets(WebSocketsObserver& observer, Type t, int port, string ip) :
+ observer(observer),
+ protocollist({ { "http-only", websocket_callback, 0 }, { NULL, NULL, 0 } }),
+ context(nullptr, &libwebsocket_context_destroy)
+{
+ //Protocol list for libwebsockets.
+ //protocollist[0] = { "http-only", websocket_callback, 0 };
+ //protocollist[1] = { NULL, NULL, 0 };
+
+ struct lws_context_creation_info info;
+ memset(&info, 0, sizeof info);
+ info.iface = "any";
+ info.protocols = protocollist;
+ info.extensions = libwebsocket_get_internal_extensions();
+ info.gid = -1;
+ info.uid = -1;
+ info.options = 0;
+ info.port = port;
+ info.user = this;
+ //context = libwebsocket_create_context(&info);
+ context = lwsContextPtr(libwebsocket_create_context(&info), &libwebsocket_context_destroy);
+
+ if(t == WebSockets::Client)
+ {
+ libwebsocket_client_connect(context.get(), ip.c_str(), port, false, "/", "localhost", "websocket", protocollist[0].name, -1);
+ }
+}
+
+WebSockets::~WebSockets()
+{
+ scoped_lock<interprocess_recursive_mutex> lock(mutex);
+ context.reset();
+ for (auto it = m_ioChannelMap.begin(); it != m_ioChannelMap.end(); ++it)
+ {
+ int fd = g_io_channel_unix_get_fd(it->second);
+ g_io_channel_shutdown(it->second, false, 0);
+ auto sourceIt = m_ioSourceMap.find(fd);
+ if( sourceIt != m_ioSourceMap.end() ) {
+ g_source_remove(sourceIt->second); //Since the watch owns the GIOChannel, this should unref it enough to dissapear.
+ m_ioSourceMap.erase(sourceIt);
+ }
+ }
+ m_ioChannelMap.clear();
+ assert(m_ioSourceMap.empty() == true);
+}
+
+int WebSockets::Write(struct libwebsocket *lws, const std::string& strToWrite)
+{
+ std::unique_ptr<char[]> buffer(new char[LWS_SEND_BUFFER_PRE_PADDING + strToWrite.length() + LWS_SEND_BUFFER_POST_PADDING]);
+
+ char *buf = buffer.get() + LWS_SEND_BUFFER_PRE_PADDING;
+ strcpy(buf, strToWrite.c_str());
+
+ //NOTE: delete[] on buffer is not needed since std::unique_ptr<char[]> is used
+ return lws ? libwebsocket_write(lws, (unsigned char*)buf, strToWrite.length(), LWS_WRITE_TEXT) : 0;
+}
+
+void WebSockets::addPoll(int fd)
+{
+ scoped_lock<interprocess_recursive_mutex> lock(mutex);
+ GIOChannel *chan = g_io_channel_unix_new(fd);
+ stringstream ss;
+ ss << chan;
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Adding chanel" << ss.str() << endl;
+ guint sourceid = g_io_add_watch(chan, GIOCondition(G_IO_IN | G_IO_HUP | G_IO_ERR),(GIOFunc)gioPollingFunc, this);
+ ss.str(std::string());
+ ss << sourceid;
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Source is" << ss.str() << endl;
+ g_io_channel_set_close_on_unref(chan,true);
+ g_io_channel_unref(chan); //Pass ownership of the GIOChannel to the watch.
+ m_ioChannelMap[fd] = chan;
+ m_ioSourceMap[fd] = sourceid;
+}
+
+void WebSockets::removePoll(int fd)
+{
+ scoped_lock<interprocess_recursive_mutex> lock(mutex);
+ auto channelIt = m_ioChannelMap.find(fd);
+ if( channelIt != m_ioChannelMap.end() ) {
+ stringstream ss;
+ ss << channelIt->second;
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Erasing channel" << ss.str() << endl;
+ g_io_channel_shutdown(channelIt->second,false,0);
+ m_ioChannelMap.erase(channelIt);
+
+ }
+ auto sourceIt = m_ioSourceMap.find(fd);
+ if( sourceIt != m_ioSourceMap.end() ) {
+ stringstream ss;
+ ss << sourceIt->second;
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Erasing source" << ss.str() << endl;
+ g_source_remove(sourceIt->second); //Since the watch owns the GIOChannel, this should unref it enough to dissapear.
+ m_ioSourceMap.erase(sourceIt);
+ }
+}
diff --git a/plugins/cangenplugin/websockets.h b/plugins/cangenplugin/websockets.h
new file mode 100644
index 00000000..add00bc9
--- /dev/null
+++ b/plugins/cangenplugin/websockets.h
@@ -0,0 +1,194 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _WEBSOCKETS_H_
+#define _WEBSOCKETS_H_
+
+#include <map>
+#include <memory>
+#include <libwebsockets.h>
+#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include "abstractpropertytype.h"
+
+using namespace boost::interprocess;
+
+/*! \addtogroup cangenplugin
+ * @{
+ */
+
+/*!
+ * \brief WebSockets observer interface.
+ *
+ * dataReceived callback is called when any data are received.
+ * \class WebSocketsObserver
+ */
+class WebSocketsObserver{
+public:
+ virtual ~WebSocketsObserver() { } /*LCOV_EXCL_LINE*/
+
+ /*!
+ * WebSocketsObserver getter
+ * \fn dataReceived
+ * \param socket Pointer to raw libwebsocket pointer to be used in reply if needed
+ * \param data pointer to buffer where input data are stored
+ * \param len length in bytes of the input data in buffer
+ */
+ virtual void dataReceived(libwebsocket* socket, const char* data, size_t len) = 0;
+};
+
+/*!
+ * \brief Encapsulation of the libwebsockets library.
+ *
+ * Listens on \p \b 23001 port. Calls WebSocketsObserver::dataReceived callback when any data are received.
+ * \sa <a href="http://libwebsockets.org/trac/libwebsockets">libwebsockets</a>
+ *
+ * \class WebSockets
+ */
+class WebSockets {
+public:
+ enum Type {
+ Server,
+ Client
+ };
+
+ /*!
+ * \param observer \link #WebSocketsObserver Observer \endlink to be called when any data are received.
+ */
+ WebSockets(WebSocketsObserver& observer, Type t=Server, int port = 23001, std::string ip="");
+
+ /*!
+ * Copy constructor
+ * @internal
+ */
+ WebSockets(const WebSockets&) = delete;
+ /*!
+ * Copy assignment
+ * @return Reference to WebSockets
+ * @internal
+ */
+ WebSockets& operator=(const WebSockets&) = delete;
+ /*!
+ * Move constructor
+ * @internal
+ */
+ WebSockets(WebSockets&&) = delete;
+ /*!
+ * Move assignment
+ * @return Reference to WebSockets
+ * @internal
+ */
+ WebSockets& operator=(WebSockets&&) = delete;
+
+ ~WebSockets();
+
+ /*!
+ * libwebsocket_write helper function
+ * \fn Write
+ * \param lws libwebsocket *
+ * \param strToWrite Data to be written.
+ * \return Number of the data bytes written.
+ */
+ static int Write(libwebsocket *lws, const std::string& strToWrite);
+
+ /*!
+ * libwebsocket helper function, called on LWS_CALLBACK_ADD_POLL_FD
+ * \fn addPoll
+ * \param fd libwebsocket raw file descriptor
+ * \internal
+ */
+ void addPoll(int fd);
+
+ /*!
+ * libwebsocket helper function, called on LWS_CALLBACK_DEL_POLL_FD
+ * \fn removePoll
+ * \param fd libwebsocket raw file descriptor
+ * \internal
+ */
+ void removePoll(int fd);
+
+ /*!
+ * WebSocketsObserver getter
+ * \fn getObserver
+ * \return \link #WebSocketsObserver Observer \endlink to be called when any data are received
+ * \internal
+ */
+ inline WebSocketsObserver& getObserver() { return observer; }
+
+ /*!
+ * libwebsocket_context getter
+ * \fn getContext
+ * \return Pointer to libwebsocket_context
+ * \internal
+ */
+ inline libwebsocket_context* getContext() { return context.get(); }
+
+private:
+
+ /*!
+ * \link #WebSocketsObserver Observer \endlink to be called when any data are received.
+ * \private
+ */
+ WebSocketsObserver& observer;
+
+
+ /*!
+ * Supported libwebsocket protocols
+ * \var protocollist;
+ * \private
+ */
+ struct libwebsocket_protocols protocollist[2];
+
+ /*!
+ * libwebsocket_context pointer encapsulated in std::unique_ptr
+ * \private
+ */
+ typedef std::unique_ptr<libwebsocket_context, decltype(&libwebsocket_context_destroy)> lwsContextPtr;
+
+ /*!
+ * Pointer to libwebsocket_context
+ * \var context
+ * \private
+ */
+ lwsContextPtr context;
+
+ /*!
+ * libwebsocket raw file descriptor to GIOChannel pointer map.
+ * \var m_ioChannelMap
+ * \private
+ */
+ std::map<int,GIOChannel*> m_ioChannelMap;
+
+ /*!
+ * libwebsocket raw file descriptor to glib source object id map.
+ * \var m_ioSourceMap
+ * \private
+ */
+ std::map<int,guint> m_ioSourceMap;
+
+ /*!
+ * Mutex to protect m_ioChannelMap and m_ioSourceMap containers during callbacks from libwebsockets
+ * \var mutex
+ * \private
+ */
+ interprocess_recursive_mutex mutex;
+};
+
+#endif // _WEBSOCKETS_H_
+
+/** @} */
diff --git a/plugins/cansimplugin/CMakeLists.txt b/plugins/cansimplugin/CMakeLists.txt
new file mode 100644
index 00000000..e29c0de8
--- /dev/null
+++ b/plugins/cansimplugin/CMakeLists.txt
@@ -0,0 +1,20 @@
+if(cansim_plugin)
+############################################################################################################################################
+
+pkg_check_modules(json REQUIRED json)
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${gio_INCLUDE_DIRS} ${gio-unix_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/plugins/common ${Boost_INCLUDE_DIRS} ${json_INCLUDE_DIRS})
+
+set(cansimplugin_headers cansimplugin.h)
+set(cansimplugin_sources cansimplugin.cpp)
+
+add_library(cansimplugin MODULE ${cansimplugin_sources} ${cansimplugin_headers})
+set_target_properties(cansimplugin PROPERTIES PREFIX "")
+target_link_libraries(cansimplugin amb amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common ${link_libraries} -lrt ${json_LIBRARIES})
+
+install(TARGETS cansimplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+
+############################################################################################################################################
+
+endif(cansim_plugin)
+
diff --git a/plugins/cansimplugin/cansimplugin.cpp b/plugins/cansimplugin/cansimplugin.cpp
new file mode 100644
index 00000000..b609b3f9
--- /dev/null
+++ b/plugins/cansimplugin/cansimplugin.cpp
@@ -0,0 +1,389 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <boost/assert.hpp>
+#include <glib.h>
+#include <deque>
+#include <json.h>
+
+#include <vehicleproperty.h>
+#include <listplusplus.h>
+#include <ambplugin.h>
+
+#include <logger.h>
+
+#include "cansimplugin.h"
+
+static const char* DEFAULT_CAN_IF_NAME = "vcan0";
+
+//----------------------------------------------------------------------------
+// CANSimPlugin
+//----------------------------------------------------------------------------
+
+// library exported function for plugin loader
+extern "C" void create(AbstractRoutingEngine* routingengine, std::map<std::string, std::string> config)
+{
+#ifndef UNIT_TESTS
+ DEBUG_CONF("cansimplugin",
+ CUtil::Logger::file_off|CUtil::Logger::screen_on,
+ CUtil::Logger::EInfo, CUtil::Logger::EInfo
+ );
+#endif
+ AmbPlugin<CANSimPlugin> * plugin = new AmbPlugin<CANSimPlugin>(routingengine, config);
+ plugin->init();
+}
+
+//----------------------------------------------------------------------------
+// CANSimPlugin
+//----------------------------------------------------------------------------
+
+const VehicleProperty::Property MappingTable = "MappingTable";
+
+//
+// IVIPOC signals
+//
+const VehicleProperty::Property BatteryStatus = "BatteryStatus";
+PROPERTYTYPEBASIC(BatteryStatus, uint16_t)
+const VehicleProperty::Property FullBatteryRange = "FullBatteryRange";
+PROPERTYTYPEBASIC(FullBatteryRange, uint16_t)
+const VehicleProperty::Property Weather = "Weather";
+PROPERTYTYPEBASIC(Weather, uint16_t)
+const VehicleProperty::Property AvgKW = "AvgKW";
+PROPERTYTYPEBASIC(AvgKW, double)
+
+#define ADDPROPERTY(property, default_value, zone_value) \
+ addPropertySupport(zone_value, [](){ \
+ return new property ## Type(default_value); \
+ })
+
+CANSimPlugin::CANSimPlugin(AbstractRoutingEngine* re, const map<string, string>& config, AbstractSource& parent) :
+ AmbPluginImpl(re, config, parent)
+{
+ auto it = config.find("interfaces");
+ if(it != config.end() && it->second.length()){
+ std::unique_ptr<json_object, decltype(&json_object_put)> rootobject(json_tokener_parse(it->second.c_str()), &json_object_put);
+ if(rootobject){
+ g_assert(json_object_get_type(rootobject.get())==json_type_array);
+ array_list *ifacelist = json_object_get_array(rootobject.get());
+ if (ifacelist) {
+ for(int i=0; i < array_list_length(ifacelist); ++i)
+ {
+ json_object* obj = (json_object*)array_list_get_idx(ifacelist,i);
+ const char* str = obj ? json_object_get_string(obj) : nullptr;
+ if(str){
+ interfaces[str] = std::shared_ptr<CANBus>(new CANBus(*static_cast<CANObserver*>(this)));
+ }
+ }
+ }
+ }
+ }
+ // Default interface if none has been configured.
+ if(interfaces.empty()){
+ interfaces[DEFAULT_CAN_IF_NAME] = std::shared_ptr<CANBus>(new CANBus(*static_cast<CANObserver*>(this)));
+ }
+
+ addPropertySupport(
+ Zone::None,
+ [](){
+ StringPropertyType *s = new StringPropertyType(MappingTable, "");
+ s->zone = Zone::None;
+ return s;
+ }
+ );
+
+ //
+ // IVIPOC signals
+ //
+ ADDPROPERTY(VehicleProperty::ChildLockStatus, false, Zone::None);
+ ADDPROPERTY(VehicleProperty::LightHead, false, Zone::None);
+ ADDPROPERTY(VehicleProperty::LightParking, false, Zone::None);
+ ADDPROPERTY(VehicleProperty::AirConditioning, false, Zone::None);
+ ADDPROPERTY(BatteryStatus, 58, Zone::None);
+ ADDPROPERTY(FullBatteryRange, 350, Zone::None);
+ ADDPROPERTY(VehicleProperty::ExteriorTemperature, 74, Zone::None);
+ ADDPROPERTY(VehicleProperty::InteriorTemperature, 68, Zone::None);
+ ADDPROPERTY(VehicleProperty::FrontWheelRadius, 0, Zone::None);
+ ADDPROPERTY(Weather, 1, Zone::None);
+ ADDPROPERTY(AvgKW, 28, Zone::None);
+ ADDPROPERTY(VehicleProperty::VehicleSpeed, 65, Zone::None);
+ ADDPROPERTY(VehicleProperty::Odometer, 75126, Zone::None);
+ ADDPROPERTY(VehicleProperty::TransmissionShiftPosition, Transmission::Drive, Zone::None);
+ ADDPROPERTY(VehicleProperty::NightMode, false, Zone::None);
+ ADDPROPERTY(VehicleProperty::ExteriorBrightness, 1000, Zone::None);
+ // HVAC
+ ADDPROPERTY(VehicleProperty::LightHazard, false, Zone::None);
+ ADDPROPERTY(VehicleProperty::SeatHeater, 0, Zone::FrontLeft);
+ ADDPROPERTY(VehicleProperty::SeatHeater, 0, Zone::FrontRight);
+ ADDPROPERTY(VehicleProperty::AirRecirculation, false, Zone::None);
+ ADDPROPERTY(VehicleProperty::AirflowDirection, HVAC::Front, Zone::None);
+ ADDPROPERTY(VehicleProperty::FanSpeed, 200, Zone::None);
+ ADDPROPERTY(VehicleProperty::TargetTemperature, 68, Zone::Left);
+ ADDPROPERTY(VehicleProperty::TargetTemperature, 68, Zone::Right);
+
+ ADDPROPERTY(VehicleProperty::Defrost, false, Zone::Front);
+ ADDPROPERTY(VehicleProperty::Defrost, false, Zone::Rear);
+
+ ADDPROPERTY(VehicleProperty::VehiclePowerMode, Power::Run, Zone::None);
+ // TirePresure
+ ADDPROPERTY(VehicleProperty::TirePressure, 2.3, Zone::FrontLeft);
+ ADDPROPERTY(VehicleProperty::TirePressure, 2.3, Zone::FrontRight);
+ ADDPROPERTY(VehicleProperty::TirePressure, 2.4, Zone::RearLeft);
+ ADDPROPERTY(VehicleProperty::TirePressure, 2.4, Zone::RearRight);
+}
+
+CANSimPlugin::~CANSimPlugin()
+{
+ for(auto it = interfaces.begin(); it != interfaces.end(); ++it){
+ it->second->stop();
+ }
+}
+
+void CANSimPlugin::init()
+{
+ AmbPluginImpl::init();
+ for(auto it = interfaces.begin(); it != interfaces.end(); ++it){
+ it->second->start(it->first.c_str());
+ }
+}
+
+void CANSimPlugin::supportedChanged(const PropertyList& supportedProperties)
+{
+ PropertyList s = const_cast<PropertyList&>(supportedProperties);
+ removeOne(&s, MappingTable);// CANSimPlugin has own copy of the PropertyList from AmbPlugin
+ createMappingTable(supportedProperties);
+}
+
+int CANSimPlugin::supportedOperations() const
+{
+ return AbstractSource::Get | AbstractSource::Set;
+}
+
+void CANSimPlugin::createMappingTable(const PropertyList& /*supported*/)
+{
+ //
+ // Local helper classes
+ //
+ class JsonObject : public std::unique_ptr<json_object, decltype(&json_object_put)>
+ {
+ public:
+ JsonObject(json_object* object) : std::unique_ptr<json_object, decltype(&json_object_put)>(object, &json_object_put) {}
+ };
+
+ class PROPERTY{
+ public:
+ PROPERTY(const VehicleProperty::Property& propertyName, const Zone::Type& z, int canId) :
+ name(propertyName),
+ zone(z),
+ can_id(canId)
+ {
+ }
+ PROPERTY(const PROPERTY& other) = delete;
+ PROPERTY& operator=(const PROPERTY& other) = delete;
+ PROPERTY(PROPERTY&& other) = default;
+ PROPERTY& operator=(PROPERTY&& other) = default;
+ JsonObject toJson()
+ {
+ JsonObject prop(json_object_new_object());
+ json_object_object_add(prop.get(), "can_id", json_object_new_int(can_id));
+ json_object_object_add(prop.get(), "name", json_object_new_string(name.c_str()));
+ json_object_object_add(prop.get(), "zone", json_object_new_int(static_cast<int>(zone)));
+ return prop;
+ }
+ private:
+ std::string name;
+ Zone::Type zone;
+ int can_id;
+ };
+
+ //
+ PropertyList allProperties(VehicleProperty::capabilities());
+
+ removeOne(&allProperties, MappingTable);
+
+ //
+ // Create mapping table in JSON format
+ //
+ map< std::string, std::deque<PROPERTY> > table;
+ PropertyList addedProperties;
+ PropertyList removedProperties;
+ std::map< canid_t, std::tuple< std::string, VehicleProperty::Property, Zone::Type> > newMappingTable;
+ int can_id = 10; // Let's have a space for a special messages. Just in case .... in the future.
+ for(PropertyList::const_iterator propIt = allProperties.begin(); propIt != allProperties.end(); ++propIt)
+ {
+ VehicleProperty::Property propertyName(*propIt);
+
+ std::vector<std::string> sources(routingEngine->sourcesForProperty(propertyName));
+ size_t size = sources.size();
+
+ bool IAmTheSource = contains(sources, uuid());
+
+ if(size == 0 || size == 1 && IAmTheSource) {
+ if( size == 0 ){
+ // I'm the source from now
+ ZonePropertyType& zonePropType = properties[propertyName];
+ std::shared_ptr<AbstractPropertyType> value(VehicleProperty::getPropertyTypeForPropertyNameValue(propertyName));
+ if(value){
+ value->zone = Zone::None;
+ zonePropType.insert(make_pair(Zone::None, value));
+ addedProperties.push_back(propertyName);
+ }
+ else{
+ properties.erase(propertyName);
+ }
+ }
+ std::string source(uuid());
+ //PropertyInfo info(routingEngine->getPropertyInfo(propertyName,source));
+ //Zone::ZoneList zones(info.zones());
+ //if(zones.empty())
+ Zone::ZoneList zones;
+ {
+ for(int i = 0; i< 10; ++i){
+ Zone::Type zone(Zone::None);
+ if(i)
+ zone = static_cast<Zone::Type>(1 << i);
+ zones.push_back(zone);
+ }
+ zones.push_back(Zone::FrontRight);
+ zones.push_back(Zone::FrontLeft);
+ zones.push_back(Zone::MiddleRight);
+ zones.push_back(Zone::MiddleLeft);
+ zones.push_back(Zone::RearRight);
+ zones.push_back(Zone::RearLeft);
+ }
+ for( auto z=zones.begin(); z != zones.end(); ++z ){
+ table[source].push_back(PROPERTY(propertyName, *z, can_id));
+ newMappingTable[can_id++] = make_tuple(source, propertyName, *z);
+ }
+ }
+ else if(IAmTheSource){
+ // I'm the source, and there is another source
+ properties.erase(propertyName);// I don't need to simulate it anymore
+ removedProperties.push_back(propertyName);
+ }
+ }
+
+ if(addedProperties.size() || removedProperties.size()) {
+ JsonObject sources(json_object_new_array());
+ for(auto it = table.begin(); it != table.end(); ++it) {
+ // one source object:
+ JsonObject source(json_object_new_object());
+ JsonObject description(json_object_new_object());
+ json_object_object_add(description.get(), "guid", json_object_new_string(it->first.c_str()));
+ json_object_object_add(source.get(), "source", description.release());
+ // signals:
+ JsonObject sigs(json_object_new_array());
+ for(auto signalIt = it->second.begin(); signalIt != it->second.end(); ++signalIt) {
+ json_object_array_add(sigs.get(), signalIt->toJson().release());
+ }
+ // add signals into source
+ json_object_object_add(source.get(), "signals", sigs.release());
+ // add one source into sources array
+ json_object_array_add(sources.get(), source.release());
+ }
+ // result json:
+ JsonObject result(json_object_new_object());
+ json_object_object_add(result.get(), "sources", sources.release());
+
+ std::string mappingTableValue(json_object_to_json_string(result.get()));
+
+ std::replace(mappingTableValue.begin(), mappingTableValue.end(), '"', '\'');// replace all " to '
+ auto tableProperty = properties[MappingTable][Zone::None];
+ if(tableProperty){
+ // we have a new MappingTable
+ mappingTable.swap(newMappingTable);
+ tableProperty->setValue(mappingTableValue);
+ routingEngine->updateProperty(tableProperty.get(), uuid());
+ }
+
+ routingEngine->updateSupported(addedProperties, removedProperties, &source);
+ }
+}
+
+// from CANObserver
+void CANSimPlugin::errorOccured(CANObserver::CANError error)
+{
+ (void) error;
+ LOG_INFO( "CANSimPlugin::errorOccured() not implemented "<< std::endl );
+}
+
+void CANSimPlugin::standardFrameReceived(const can_frame& frame)
+{
+ (void) frame;
+ LOG_INFO( "CANSimPlugin::standardFrameReceived() not implemented "<< std::endl );
+}
+
+void CANSimPlugin::extendedFrameReceived(const can_frame& frame)
+{
+ LOG_INFO("CANSimPlugin::extendedFrameReceived()");
+ printFrame(frame);
+
+ auto it = mappingTable.find(frame.can_id);
+ if( it == mappingTable.end()){
+ LOG_WARNING("can_id not found");
+ return;
+ }
+
+ std::string source(std::get<0>(it->second));
+ VehicleProperty::Property name(std::get<1>(it->second));
+ Zone::Type zone(std::get<2>(it->second));
+ AbstractPropertyType* value = findPropertyType(name, zone);
+ if(!value)
+ return;
+
+ std::unique_ptr<GVariant, decltype(&g_variant_unref)> v(value->toVariant(), &g_variant_unref);
+ std::unique_ptr<GVariant, decltype(&g_variant_unref)> v_untrusted(
+ g_variant_new_from_data( g_variant_get_type(v.release()), frame.data, frame.can_dlc, FALSE, nullptr, nullptr),
+ &g_variant_unref
+ );
+ std::unique_ptr<GVariant, decltype(&g_variant_unref)> v_normal(g_variant_get_normal_form(v_untrusted.release()), &g_variant_unref);
+ if(g_variant_is_normal_form(v_normal.get())) {
+ value->fromVariant(v_normal.get());
+ routingEngine->updateProperty(value, source);
+ }
+ else{
+ LOG_ERROR("Can't convert value from CAN to GVariant");
+ }
+}
+
+void CANSimPlugin::errorFrameReceived(const can_frame& frame)
+{
+ LOG_INFO("CANSimPlugin::errorFrameReceived()");
+ printFrame(frame);
+}
+
+void CANSimPlugin::remoteTransmissionRequest(const can_frame& frame)
+{
+ (void) frame;
+ LOG_INFO( "CANSimPlugin::remoteTransmissionRequest() not implemented "<< std::endl );
+}
+
+void CANSimPlugin::printFrame(const can_frame& frame) const
+{
+ LOG_INFO( "CANSimPlugin::printFrame can_id: " << std::hex << frame.can_id << std::dec << endl );
+ LOG_INFO( "CANSimPlugin::printFrame can_dlc: " << int(frame.can_dlc) << endl );
+
+ std::stringstream ss;
+ for(int i=0; i<frame.can_dlc; ++i){
+ ss << " " << std::hex << (int)(frame.data[i]);
+ }
+ ss << std::dec;
+
+ LOG_INFO( "CANSimPlugin::printFrame can data" << ss.str() << endl );
+}
+
+
diff --git a/plugins/cansimplugin/cansimplugin.h b/plugins/cansimplugin/cansimplugin.h
new file mode 100644
index 00000000..40b55d51
--- /dev/null
+++ b/plugins/cansimplugin/cansimplugin.h
@@ -0,0 +1,174 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _CANSIMPLUGINIMPL_H_
+#define _CANSIMPLUGINIMPL_H_
+
+#include <map>
+#include <memory>
+#include <tgmath.h>
+
+#include <canbus.h>
+#include <canobserver.h>
+
+#include "ambpluginimpl.h"
+
+/*!
+ * \defgroup cansimplugin cansimplugin shared library
+ * \brief CANSimPlugin listens on configured CAN interfaces(e.g. vcan0, vcan1, ...) for CAN frames from CANGenPlugin and translates them into AMB property changes.
+ *
+ * CANSimPlugin is a source plug-in for Automotive message broker(AMB). \n
+ * For the AMB library API please visit <a href="https://github.com/otcshare/automotive-message-broker">Automotive message broker web page</a>.\n
+ *
+ * To load this plugin at AMB starup, insert following rows into AMB configuration file:
+ * \code
+ * {
+ * "name" : "CANSimPlugin",
+ * "path":"/usr/lib/automotive-message-broker/cansimplugin.so",
+ * "interfaces" : ["vcan0", "vcan1"]
+ * }
+ * \endcode
+ *
+ * \note CANSimPlugin has to be the last source plug-in listed in AMB configuration file. Otherwise it can accidentally unregister or try to simulate some AMB properties supported from other sources.
+ *
+ * @{
+ */
+
+/*!
+ * \brief CAN frames listener plug-in for the AMB CAN Simulator.
+ *
+ * Listens on AMB notification for changes in supported properties using supportedChanged() callback. \n
+ * On startup it registers property called 'MappingTable' and all properties needed for simulation in html5UI.Dashboard and html5UI.HVAC applications. \n
+ * Immediately after it registers own properties it will get first notification supportedChanged().\n
+ * On every notification from supportedChanged() CANSimPlugin goes through all supported properties in AMB, exclude those properties for which there are known sources in the AMB,\n
+ * assigns to each single property and zone some unique CAN Id(builds 'mapping table') and this 'mapping table' stores as JSON string and updates it as a 'MappingTable' property in AMB.\n
+ * When 'MappingTable' is built and ready it starts to listen on all required CAN interfaces in AMB configuration file.\n
+ * On any received CAN frame it goes through the mappingTable, finds property name and zone based on received CAN Id, reads new value from CAN frame and updates it in the AMB.
+ *
+ * \see \ref libcanbus
+ *
+ * \class CANSimPlugin
+ */
+class CANSimPlugin : public AmbPluginImpl, public CANObserver {
+
+public:
+ /*!
+ * \param re AbstractRoutingEngine
+ * \param config Map of the configuration string values loaded on startup from AMB configuration file
+ * \param parent AmbPlugin instance
+ */
+ CANSimPlugin(AbstractRoutingEngine* re, const std::map<std::string, std::string>& config, AbstractSource& parent);
+ virtual ~CANSimPlugin(); // has to be virtual because of unit tests
+
+ // from AbstractSink
+public:
+
+ /*! uuid() is a unique identifier
+ * \return a guid-style unique identifier
+ */
+ const std::string uuid() const { return "3f43e231-11ec-4782-9b5a-3dbcc5221eeb"; }
+
+ /*! Called when the supported properties changes
+ * \param supportedProperties the new list of supported properties.
+ */
+ void supportedChanged(const PropertyList& supportedProperties);
+
+ /*!
+ * \brief supportedOperations
+ * \return returns the supported operations.
+ */
+ int supportedOperations() const;
+
+ // from CANObserver
+public:
+ /*!
+ * Called when error occurred on the bus.
+ * \fn errorOccured
+ * \param error @link CANObserver#CANError Bus error code @endlink
+ */
+ virtual void errorOccured(CANObserver::CANError error);/* socket error */
+ /*!
+ * Called when standard frame was is received from the bus.
+ * \fn standardFrameReceived
+ * \param frame Received frame
+ */
+ virtual void standardFrameReceived(const can_frame& frame);/* SFF was present */
+ /*!
+ * Called when extended frame was is received from the bus.
+ * \fn extendedFrameReceived
+ * \param frame Received frame
+ */
+ virtual void extendedFrameReceived(const can_frame& frame);/* EFF was present */
+ /*!
+ * Called when error frame was received from the bus.
+ * \fn errorFrameReceived
+ * \param frame Error frame
+ */
+ virtual void errorFrameReceived(const can_frame& frame);/* error frame */
+ /*!
+ * Called when remote transmission frame was received from the bus.
+ * \fn remoteTransmissionRequest
+ * \param frame RTR frame
+ */
+ virtual void remoteTransmissionRequest(const can_frame& frame);/* remote transmission request (SFF/EFF is still present)*/
+
+ /*!
+ * Second phase of the plugin initialization.
+ * \fn init
+ */
+ virtual void init();
+
+private:
+
+ /*!
+ * \brief Prints received CAN frame
+ * \param frame Received CAN frame.
+ * \internal
+ * \private
+ */
+ void printFrame(const can_frame& frame) const;
+
+ /*!
+ * \brief Creates string in JSON format which contains all supported AMB properties that can be used for simulation.
+ * \param supported All supported AMB properties.
+ * \see Automotive message broker's \b AsyncRangePropertyReply
+ * \private
+ */
+ void createMappingTable(const PropertyList& supported);
+
+//
+// data:
+//
+
+ /*!
+ * Map of the can_id and corresponding AMB properties in tuple<property_source_id, property_name, zone>
+ * \property mappingTable
+ * \private
+ */
+ std::map< canid_t, std::tuple<std::string, VehicleProperty::Property, Zone::Type> > mappingTable;
+
+ /**
+ * Map of the CAN interfaces used in simulator. Contains libcanbus#CANBus class instances.
+ * \property interfaces
+ * \private
+ */
+ std::map<std::string, std::shared_ptr<CANBus> > interfaces;
+};
+#endif // _CANSIMPLUGINIMPL_H_
+
+/** @} */
diff --git a/plugins/cansimplugin/test/CMakeLists.txt b/plugins/cansimplugin/test/CMakeLists.txt
new file mode 100644
index 00000000..ecd348b5
--- /dev/null
+++ b/plugins/cansimplugin/test/CMakeLists.txt
@@ -0,0 +1,20 @@
+
+set(include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/lib ${CMAKE_SOURCE_DIR}/lib ../ ../../../tests)
+
+find_library(libtool_LIBRARY ltdl DOC "Libtool libraries")
+find_path(libtool_INCLUDE_DIR ltdl.h DOC "Libtool headers")
+
+pkg_check_modules(glib REQUIRED glib-2.0)
+pkg_check_modules(json REQUIRED json)
+
+set(ut_cansimplugin_headers cansimplugin.h cansimpluginimpl.h mockabstractroutingengine.h)
+set(ut_cansimplugin_sources main.cpp ut_cansimplugin.cpp ../cansimplugin.cpp)
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
+add_definitions(-fPIC -g)
+
+add_executable(ut_cansimplugin ${ut_cansimplugin_sources})
+
+include_directories(${include_dirs} ${libtool_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/plugins/common ${glib_INCLUDE_DIRS} ${gio_INCLUDE_DIRS})
+target_link_libraries(ut_cansimplugin ${link_libraries} amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common ${libtool_LIBRARY} ${glib_LIBRARIES} ${json_LIBRARIES} amb -lrt -lgobject-2.0 -lpthread)
+
diff --git a/plugins/cansimplugin/test/main.cpp b/plugins/cansimplugin/test/main.cpp
new file mode 100644
index 00000000..40fa9677
--- /dev/null
+++ b/plugins/cansimplugin/test/main.cpp
@@ -0,0 +1,67 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <glib-object.h>
+#include <CppUTest/CommandLineTestRunner.h>
+#include "logger.h"
+
+struct ThreadData{
+ int argc;
+ char** argv;
+ int testResult;
+ GMainLoop* mainLoop;
+};
+
+static void* tests_thread(void *data)
+{
+ ThreadData* td = static_cast<ThreadData*>(data);
+ if(td){
+ td->testResult = CommandLineTestRunner::RunAllTests(td->argc, td->argv);
+ g_main_loop_quit(td->mainLoop);
+ }
+ return td;
+}
+
+int main(int ac, char **av)
+{
+ ThreadData td;
+ td.argc = ac;
+ td.argv = av;
+ td.testResult = 0;
+
+ DEBUG_CONF("ut_cansimplugin",
+#ifdef _DEBUG
+ CUtil::Logger::file_on|CUtil::Logger::screen_on,
+#else
+ CUtil::Logger::file_on|CUtil::Logger::screen_off,
+#endif
+ CUtil::Logger::EInfo, CUtil::Logger::EWarning);
+
+ td.mainLoop = g_main_loop_new(NULL, FALSE);
+
+ // Run the mainloop and the tests thread
+ GThread* testThread = g_thread_new("tests thread", &tests_thread, &td);
+
+ g_main_loop_run(td.mainLoop);
+ g_thread_join(testThread);
+
+ g_main_loop_unref(td.mainLoop);
+
+
+ return td.testResult;
+}
diff --git a/plugins/cansimplugin/test/ut_cansimplugin.cpp b/plugins/cansimplugin/test/ut_cansimplugin.cpp
new file mode 100644
index 00000000..6da51826
--- /dev/null
+++ b/plugins/cansimplugin/test/ut_cansimplugin.cpp
@@ -0,0 +1,475 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "logger.h"
+
+#include <ltdl.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+
+#include <listplusplus.h>
+#define private protected
+#include "cansimplugin.h"
+#undef private
+#include "mockabstractroutingengine.h"
+#include "mockcanbus.h"
+
+const char* mappingTable = "MappingTable";
+
+typedef void* create_t(AbstractRoutingEngine*, std::map<std::string, std::string>);
+
+class Loader{
+public:
+ Loader()
+ {
+ if(lt_dlinit())
+ {
+ cerr<<"error initializing libtool: "<<__FILE__<<" - "<<__FUNCTION__<<":"<<__LINE__<<" "<<lt_dlerror()<<endl;
+ throw std::runtime_error("Error initializing libtool. aborting");
+ }
+ }
+
+ ~Loader()
+ {
+ auto handle = openHandles.begin();
+ while(handle != openHandles.end())
+ lt_dlclose(*handle++);
+ lt_dlexit();
+ }
+
+ template<class T>
+ T loadPlugin(std::string pluginName, AbstractRoutingEngine* routingEngine, std::map<std::string, std::string> config)
+ {
+ DebugOut()<<"Loading plugin: "<<pluginName<<endl;
+
+ lt_dlhandle handle = lt_dlopenext(pluginName.c_str());
+
+ if(!handle)
+ {
+ cerr<<"error opening plugin: "<<pluginName<<" in "<<__FILE__<<" - "<<__FUNCTION__<<":"<<__LINE__<<" "<<lt_dlerror()<<endl;
+ return nullptr;
+ }
+
+ openHandles.push_back(handle);
+ create_t* f_create = (create_t *)lt_dlsym(handle, "create");
+
+ //mErrorString = lt_dlerror();
+
+ if(f_create)
+ {
+ void* obj = f_create(routingEngine, config);
+ return static_cast<T>( obj );
+ }
+
+ return nullptr;
+ }
+private:
+ std::vector<lt_dlhandle> openHandles;
+};
+
+class TestCANSimPluginImpl : public CANSimPlugin
+{
+public:
+ TestCANSimPluginImpl(AbstractRoutingEngine* re, map<string, string> config, AbstractSource& parent) :
+ CANSimPlugin(re, config, parent)
+ {
+ mock().actualCall("CANSimPlugin::CANSimPlugin");
+
+ for(auto it=interfaces.begin(); it != interfaces.end(); ++it){
+ interfaces[it->first] = std::shared_ptr<CANBus>(new MockCANBus(*this));
+ }
+ }
+
+ virtual ~TestCANSimPluginImpl()
+ {
+ mock().actualCall("CANSimPlugin::~CANSimPlugin");
+ }
+
+ std::string TestCreateMappingTable(const PropertyList& supported) {
+ supportedChanged(supported);
+ AbstractPropertyType* value = findPropertyType("MappingTable", Zone::None);
+ if(!value)
+ return "";
+ return value->toString();
+ }
+
+ inline void TestAddPropertyToMappingTable(const int id, const char* source, const char* propertyName, const Zone::Type& z)
+ {
+ mappingTable[id] = make_tuple(source, propertyName, z);
+ ZonePropertyType& zonePropType = properties[propertyName];
+ std::shared_ptr<AbstractPropertyType> value(VehicleProperty::getPropertyTypeForPropertyNameValue(propertyName));
+ if(value){
+ value->zone = z;
+ zonePropType.insert(make_pair(z, value));
+ }
+ else{
+ properties.erase(propertyName);
+ }
+ }
+};
+
+class TestCANSimPlugin : public AmbPlugin<TestCANSimPluginImpl>
+{
+public:
+ TestCANSimPlugin(AbstractRoutingEngine* re, map<string, string> config) :
+ AmbPlugin<TestCANSimPluginImpl>(re, config)
+ {
+ mock().actualCall("AmbPlugin::AmbPlugin");
+ }
+
+ virtual ~TestCANSimPlugin()
+ {
+ mock().actualCall("AmbPlugin::~AmbPlugin");
+ }
+
+ inline TestCANSimPluginImpl* getImplementation() { return dynamic_cast<TestCANSimPluginImpl*>(d.get()); }
+};
+
+TEST_GROUP(CANSimPlugin)
+{
+ MockAbstractRoutingEngine *routingEngine;
+ std::map<std::string, std::string> config;
+ TestCANSimPlugin *plugin;
+
+ void setup()
+ {
+ DebugOut::setDebugThreshhold(0);
+ VehicleProperty::factory();
+ routingEngine = new MockAbstractRoutingEngine();
+ plugin = nullptr;
+ mock().expectOneCall("AmbPlugin::AmbPlugin");
+ mock().expectOneCall("CANSimPlugin::CANSimPlugin");
+ mock().expectOneCall("CANBus::stop"); // because of the interfaces[it->first] = std::shared_ptr<CANBus>(new MockCANBus(*this)); in TestCANSimPluginImpl
+ mock().expectOneCall("AbstractRoutingEngine::setSupported");
+ mock().expectNCalls(27, "AbstractRoutingEngine::supported"); // 27 well-known properties in AMB API
+ config["interfaces"] = "[\"vcan999\"]";
+ plugin = new TestCANSimPlugin(routingEngine, config);
+ }
+ void teardown()
+ {
+ //mock().expectOneCall("CANBus::stop");
+ mock().expectOneCall("AmbPlugin::~AmbPlugin");
+ mock().expectOneCall("CANSimPlugin::~CANSimPlugin");
+ if(plugin != nullptr) {
+ delete plugin;
+ plugin = nullptr;
+ }
+ VehicleProperty::shutdown();
+
+ delete routingEngine;
+ routingEngine = nullptr;
+
+ mock().checkExpectations();
+ mock().clear();
+ }
+};
+
+TEST(CANSimPlugin, create)
+{
+
+ //mock().expectOneCall("CANSimPlugin::CANSimPlugin");
+ Loader ldr;
+ config.clear();// create plugin with emtpy interfaces list at least once.
+ mock().expectOneCall("AbstractRoutingEngine::setSupported");
+ mock().expectNCalls(32, "AbstractRoutingEngine::supported"); // we are calling 32 times addPropertySupport in AMB API
+ AbstractSource* myplugin = ldr.loadPlugin<AbstractSource*>("./build/cansimplugin.so", routingEngine, config);
+ CHECK( myplugin != nullptr);
+ delete myplugin;
+}
+
+TEST(CANSimPlugin, getPropertyAsync)
+{
+ bool replySuccess(false);
+ int replyError(-1);
+ int replyZone(-1);
+ std::string replySignalName("");
+
+ // NULL pointer test
+ plugin->getPropertyAsync(nullptr);
+
+ // Invalid request test
+ AsyncPropertyRequest requestInvalid;
+ requestInvalid.timeout = 0;
+ AsyncPropertyReply* reply = new AsyncPropertyReply(requestInvalid);
+ plugin->getPropertyAsync(reply);
+ delete reply; reply = nullptr;
+
+ requestInvalid.property = "NotExists";
+ requestInvalid.completed = [&](AsyncPropertyReply* reply)
+ {
+ replySuccess = reply->success;
+ replyError = reply->error;
+ if(reply->value) {
+ LOG_TRACE("getPropertyAsync completed, value is: " << reply->value->toString());
+ replyZone = reply->value->zone;
+ replySignalName = reply->value->name;
+ }
+ delete reply;
+ };
+
+ reply = new AsyncPropertyReply(requestInvalid);
+ plugin->getPropertyAsync(reply);
+
+ CHECK(replySuccess == false);
+ CHECK(replyError == AsyncPropertyReply::InvalidOperation);
+
+ plugin->getImplementation()->TestAddPropertyToMappingTable(0xa, plugin->uuid().c_str(), VehicleProperty::SeatHeater.c_str(), Zone::FrontLeft);
+ AsyncPropertyRequest request;
+ request.timeout = 0;
+ request.property = VehicleProperty::SeatHeater;
+ request.zoneFilter = Zone::FrontLeft;
+ request.completed = requestInvalid.completed;
+
+ reply = new AsyncPropertyReply(request);
+ plugin->getPropertyAsync(reply);
+
+ CHECK(replySuccess == true);
+ CHECK_EQUAL_C_STRING(request.property.c_str(), replySignalName.c_str());
+ CHECK_EQUAL_C_INT(request.zoneFilter, replyZone);
+
+}
+
+TEST(CANSimPlugin, getRangePropertyAsync)
+{
+ bool replySuccess(false);
+ int replyError(-1);
+
+ plugin->getRangePropertyAsync(nullptr);
+
+ AsyncRangePropertyRequest requestInvalid;
+ AsyncRangePropertyReply* reply = new AsyncRangePropertyReply(requestInvalid);
+ plugin->getRangePropertyAsync(reply);
+ delete reply; reply = nullptr;
+
+ AsyncRangePropertyRequest request;
+ request.properties.push_back(VehicleProperty::SeatHeater);
+ request.completed = [&](AsyncRangePropertyReply* reply)
+ {
+ replySuccess = reply->success;
+ replyError = reply->error;
+ delete reply;
+ };
+
+ reply = new AsyncRangePropertyReply(request);
+ plugin->getRangePropertyAsync(reply);
+
+ CHECK(replySuccess == false);
+ CHECK(replyError == AsyncPropertyReply::InvalidOperation);
+}
+
+TEST(CANSimPlugin, setProperty)
+{
+ bool replySuccess(false);
+ int replyError(-1);
+ std::string replySignalName("");
+
+ // Invalid request test
+ AsyncSetPropertyRequest requestInvalid;
+ requestInvalid.timeout = 0;
+ AsyncPropertyReply* reply = plugin->setProperty(requestInvalid);
+ delete reply; reply = nullptr;
+
+ requestInvalid.property = "NotExists";
+ requestInvalid.completed = [&](AsyncPropertyReply* reply)
+ {
+ replySuccess = reply->success;
+ replyError = reply->error;
+ delete reply;
+ };
+
+ reply = plugin->setProperty(requestInvalid);
+
+ CHECK(replySuccess == false);
+ CHECK(replyError == AsyncPropertyReply::InvalidOperation);
+
+ plugin->getImplementation()->TestAddPropertyToMappingTable(0xa, plugin->uuid().c_str(), VehicleProperty::SeatHeater.c_str(), Zone::FrontLeft);
+ mock().expectOneCall("AbstractRoutingEngine::updateProperty");
+ AsyncSetPropertyRequest request;
+ request.timeout = 0;
+ request.property = VehicleProperty::SeatHeater;
+ request.zoneFilter = Zone::FrontLeft;
+ request.value = VehicleProperty::getPropertyTypeForPropertyNameValue(request.property, "1");
+ request.completed = requestInvalid.completed;
+
+ reply = plugin->setProperty(request);
+ delete request.value;
+ request.value = nullptr;
+
+ CHECK(replySuccess == true);
+ CHECK(replyError == AsyncPropertyReply::NoError);
+}
+
+TEST(CANSimPlugin, subscribeUnsubscribeToPropertyChanges)
+{
+ plugin->subscribeToPropertyChanges("");
+
+ // AbstractRoutingEngine::updateProperty is called so many times as many zones signal has
+ mock().expectNCalls(1, "AbstractRoutingEngine::updateProperty");
+ plugin->subscribeToPropertyChanges(VehicleProperty::VehicleSpeed);// only Zone::None
+
+ // empty implemnetation, does nothing
+ plugin->unsubscribeToPropertyChanges("");
+ plugin->unsubscribeToPropertyChanges(VehicleProperty::VehicleSpeed);
+
+}
+
+TEST(CANSimPlugin, supported)
+{
+ PropertyList supported = plugin->supported();
+ CHECK_EQUAL_C_INT(29, supported.size());
+}
+
+TEST(CANSimPlugin, supportedOperations)
+{
+ int supported = plugin->supportedOperations();
+ CHECK_EQUAL_C_INT(AbstractSource::Get | AbstractSource::Set, supported);
+}
+
+TEST(CANSimPlugin, getPropertyInfo)
+{
+ PropertyInfo pi = plugin->getPropertyInfo(VehicleProperty::EngineSpeed);
+ CHECK(!pi.isValid());
+ std::list<Zone::Type> zones = pi.zones();
+ CHECK(zones.empty());
+ pi = plugin->getPropertyInfo(mappingTable);
+ CHECK(pi.isValid());
+ zones = pi.zones();
+ CHECK(ListPlusPlus<Zone::Type>(&zones).contains(Zone::None));
+}
+
+TEST(CANSimPlugin, uuid)
+{
+ std::string uuid = plugin->uuid();
+ //CHECK_EQUAL_C_STRING("3f43e231-11ec-4782-9b5a-3dbcc5221eeb", uuid.c_str());
+ CHECK(uuid.length() > 0);
+}
+
+TEST(CANSimPlugin, BasicPropertyType_fromString_and_toString)
+{
+
+ //VehicleProperty::DefrostType *defrost = new VehicleProperty::DefrostType();
+ //defrost->append(Window::SideMirrorLeft, true);
+ //defrost->append(Window::SideMirrorRight, false);
+ //defrost->fromString(defrost->toString());
+ //CHECK_EQUAL_C_STRING("{'6':'1', '7':'0'}", defrost->toString().c_str());
+ //delete defrost;
+
+ BasicPropertyType<bool> boolean(true);
+ boolean.fromString(boolean.toString());
+ CHECK_EQUAL_C_STRING("1", boolean.toString().c_str());
+
+}
+
+TEST(CANSimPlugin, createMappingTable)
+{
+ const char* expected = "{ "
+ "'sources': [ { 'source': { 'guid': '3f43e231-11ec-4782-9b5a-3dbcc5221eeb' }, "
+ "'signals': [ "
+ "{ 'can_id': 10, 'name': 'SeatHeater', 'zone': 0 }, "
+ "{ 'can_id': 11, 'name': 'SeatHeater', 'zone': 2 }, "
+ "{ 'can_id': 12, 'name': 'SeatHeater', 'zone': 4 }, "
+ "{ 'can_id': 13, 'name': 'SeatHeater', 'zone': 8 }, "
+ "{ 'can_id': 14, 'name': 'SeatHeater', 'zone': 16 }, "
+ "{ 'can_id': 15, 'name': 'SeatHeater', 'zone': 32 }, "
+ "{ 'can_id': 16, 'name': 'SeatHeater', 'zone': 64 }, "
+ "{ 'can_id': 17, 'name': 'SeatHeater', 'zone': 128 }, "
+ "{ 'can_id': 18, 'name': 'SeatHeater', 'zone': 256 }, "
+ "{ 'can_id': 19, 'name': 'SeatHeater', 'zone': 512 }, "
+ "{ 'can_id': 20, 'name': 'SeatHeater', 'zone': 5 }, "
+ "{ 'can_id': 21, 'name': 'SeatHeater', 'zone': 9 }, "
+ "{ 'can_id': 22, 'name': 'SeatHeater', 'zone': 6 }, "
+ "{ 'can_id': 23, 'name': 'SeatHeater', 'zone': 10 }, "
+ "{ 'can_id': 24, 'name': 'SeatHeater', 'zone': 20 }, "
+ "{ 'can_id': 25, 'name': 'SeatHeater', 'zone': 24 }"
+ " ] } ] }";
+
+ std::list<std::string> supportedProps(VehicleProperty::capabilities());
+ supportedProps.remove(VehicleProperty::SeatHeater);
+ mock().setData("properties", &supportedProps);
+ std::list<std::string> sources({"3f43e231-11ec-4782-9b5a-3dbcc5221eeb", "another-source"});
+ mock().setData("sources", &sources);
+ PropertyInfo pi(1, {Zone::FrontLeft, Zone::FrontRight});
+ mock().setData("PropertyInfo", &pi);
+ mock().expectNCalls(supportedProps.size(), "AbstractRoutingEngine::sourcesForProperty");
+ //mock().expectNCalls(supportedProps.size()*(sources.size()-1), "AbstractRoutingEngine::getPropertyInfo");
+ mock().expectOneCall("AbstractRoutingEngine::supported");
+ mock().expectOneCall("AbstractRoutingEngine::updateProperty");
+ //mock().expectOneCall("AbstractRoutingEngine::setSupported");
+
+ const std::string& mappingTable = plugin->getImplementation()->TestCreateMappingTable(routingEngine->supported());
+ LOG_ERROR("json: " << mappingTable);
+
+ CHECK(mappingTable.length() > 0);
+ json_object* mp = json_tokener_parse(mappingTable.c_str());
+ json_object_put(mp);
+ CHECK(mp != nullptr);
+ CHECK_EQUAL_C_STRING(expected, mappingTable.c_str());
+
+}
+
+TEST(CANSimPlugin, errorOccured)
+{
+ plugin->getImplementation()->errorOccured(static_cast<CANObserver::CANError>(-1));
+
+ CANObserver::CANError error(CANObserver::GENERAL_ERROR);
+ plugin->getImplementation()->errorOccured(error);
+}
+
+TEST(CANSimPlugin, standardFrameReceived)
+{
+ can_frame frame;
+ memset(&frame, 0, sizeof(frame));
+ frame.can_id = 0x00a;
+ plugin->getImplementation()->standardFrameReceived(frame);
+}
+
+TEST(CANSimPlugin, extendedFrameReceived)
+{
+ can_frame frame;
+ memset(&frame, 0, sizeof(frame));
+ frame.can_id = 0xFFFFFFFF;// not existing
+ mock().expectNCalls(0,"AbstractRoutingEngine::updateProperty");// no prop. with this can_id
+ plugin->getImplementation()->extendedFrameReceived(frame);
+
+ plugin->getImplementation()->TestAddPropertyToMappingTable(0xb, plugin->uuid().c_str(), "NotExisttingProperty", Zone::None);
+ frame.can_id = 0xb;
+ frame.can_dlc = 8;
+ mock().expectNCalls(0,"AbstractRoutingEngine::updateProperty");// no prop. with this can_id
+ plugin->getImplementation()->extendedFrameReceived(frame);
+
+ // existing property VehicleSpeed
+ plugin->getImplementation()->TestAddPropertyToMappingTable(0xa, plugin->uuid().c_str(), VehicleProperty::VehicleSpeed.c_str(), Zone::None);
+ frame.can_id = 0xa;
+ mock().expectOneCall("AbstractRoutingEngine::updateProperty");
+ plugin->getImplementation()->extendedFrameReceived(frame);
+
+}
+
+TEST(CANSimPlugin, errorFrameReceived)
+{
+ can_frame frame;
+ memset(&frame, 0, sizeof(frame));
+ plugin->getImplementation()->errorFrameReceived(frame);
+}
+
+TEST(CANSimPlugin, remoteTransmissionRequest)
+{
+ can_frame frame;
+ memset(&frame, 0, sizeof(frame));
+ plugin->getImplementation()->remoteTransmissionRequest(frame);
+}
diff --git a/plugins/chrony/CMakeLists.txt b/plugins/chrony/CMakeLists.txt
new file mode 100644
index 00000000..5a666284
--- /dev/null
+++ b/plugins/chrony/CMakeLists.txt
@@ -0,0 +1,19 @@
+if(chrony_plugin)
+
+set(chrony_headers chrony.h)
+set(chrony_sources chrony.cpp )
+
+add_library(chrony MODULE ${chrony_sources})
+set_target_properties(chrony PROPERTIES PREFIX "")
+target_link_libraries(chrony amb -L${CMAKE_CURRENT_BINARY_DIR}/lib amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common ${link_libraries} ${gio_LIBRARIES})
+
+install(TARGETS chrony LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_BINARY_DIR}/chrony.README @ONLY)
+
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/chrony.README DESTINATION ${DOC_INSTALL_DIR}/plugins)
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/chrony.in.json ${CMAKE_CURRENT_BINARY_DIR}/chrony @ONLY)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/chrony DESTINATION ${PLUGIN_SEGMENT_INSTALL_PATH})
+
+endif(chrony_plugin)
diff --git a/plugins/chrony/README b/plugins/chrony/README
new file mode 100644
index 00000000..a9f28c24
--- /dev/null
+++ b/plugins/chrony/README
@@ -0,0 +1,24 @@
+CHRONY plugin
+Version: @PROJECT_VERSION@
+
+This plugin will forward the GpsTime property to the CHRONYD daemon.
+
+To enable the CHRONY plugin, run cmake and enable the chrony_plugin option:
+
+cmake -Dchrony_plugin=On ..
+
+To use this plugin, add the following to the "sinks" array in /etc/ambd/config:
+
+{
+ "name" : "chrony",
+ "path" : "@PLUGIN_INSTALL_PATH@/chrony.so",
+}
+
+Configuration Key Definitions:
+
+"name"
+name of plugin. This key is not used by the plugin at this moment.
+
+"path"
+path to plugin on the filesystem.
+
diff --git a/plugins/chrony/chrony.cpp b/plugins/chrony/chrony.cpp
new file mode 100644
index 00000000..aa7737c9
--- /dev/null
+++ b/plugins/chrony/chrony.cpp
@@ -0,0 +1,81 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+ Copyright (C) 2015 AWTC Europe
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "chrony.h"
+#include "ambplugin.h"
+#include "abstractroutingengine.h"
+#include "debugout.h"
+#include "listplusplus.h"
+
+#include <glib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <math.h>
+
+extern "C" void create(AbstractRoutingEngine* routingEngine, map<string, string> config)
+{
+ auto plugin = new AmbPlugin<ChronySink>(routingEngine, config);
+ plugin->init();
+}
+
+ChronySink::ChronySink(AbstractRoutingEngine* re, const std::map<std::string, std::string>& config, AbstractSource& parent)
+ :AmbPluginImpl(re, config, parent)
+{
+}
+
+void ChronySink::init()
+{
+ routingEngine->subscribeToProperty("GpsTime", &source);
+}
+
+PropertyList ChronySink::subscriptions()
+{
+}
+
+void ChronySink::propertyChanged(AbstractPropertyType *value)
+{
+ int sockfd;
+ struct sockaddr_un s;
+ struct chrony_sock_sample chronydata;
+
+ sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (sockfd < 0) return;
+
+ s.sun_family = AF_UNIX;
+ strcpy(s.sun_path, CHRONYD_SOCKET );
+
+ if(connect(sockfd, (struct sockaddr *)&s, sizeof(s)) == -1)
+ {
+ return;
+ }
+
+ gettimeofday(&(chronydata.tv), NULL);
+ chronydata.offset = (value->value<double>() - chronydata.tv.tv_sec) - (chronydata.tv.tv_usec / 1000000.0);
+ chronydata.offset -= (amb::currentTime()-value->timestamp);
+ chronydata.pulse = 0;
+ chronydata.leap = 0;
+ chronydata.magic = 0x534f434b;
+ send(sockfd,&chronydata,sizeof(chronydata),0);
+
+ close(sockfd);
+}
+
diff --git a/plugins/chrony/chrony.h b/plugins/chrony/chrony.h
new file mode 100644
index 00000000..f694c5a0
--- /dev/null
+++ b/plugins/chrony/chrony.h
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+ Copyright (C) 2015 AWTC Europe
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef CHRONYSINK_H
+#define CHRONYSINK_H
+
+#include "ambpluginimpl.h"
+
+#define CHRONYD_SOCKET "/tmp/chrony.gps.sock"
+
+struct chrony_sock_sample {
+ struct timeval tv;
+ double offset;
+ int pulse;
+ int leap;
+ int _pad;
+ int magic;
+};
+
+class ChronySink : public AmbPluginImpl
+{
+
+public:
+ ChronySink(AbstractRoutingEngine* re, const std::map<std::string, std::string>& config, AbstractSource& parent);
+ ~ChronySink() { };
+ const std::string uuid() const { return "35324592-db72-11e4-b432-0022684a4a24"; }
+ virtual void init();
+ virtual PropertyList subscriptions();
+ virtual void propertyChanged( AbstractPropertyType* value);
+
+};
+
+#endif // CHRONYSINK_H
diff --git a/plugins/chrony/chrony.in.json b/plugins/chrony/chrony.in.json
new file mode 100644
index 00000000..8bd53518
--- /dev/null
+++ b/plugins/chrony/chrony.in.json
@@ -0,0 +1,5 @@
+{
+ "name" : "Chrony plugin",
+ "path" : "@PLUGIN_INSTALL_PATH@/chrony.so",
+ "enabled" : true
+}
diff --git a/plugins/common/CMakeLists.txt b/plugins/common/CMakeLists.txt
new file mode 100644
index 00000000..c57c8b3c
--- /dev/null
+++ b/plugins/common/CMakeLists.txt
@@ -0,0 +1,24 @@
+set(plugins_common_sources abstractio.hpp serialport.hpp bluetoothadapterproxy.c bluetooth.hpp bluetoothmanagerproxy.c bluetoothserialproxy.c bluetooth5.cpp
+ canadapter.cpp cansocket.cpp cansocketreader.cpp canbusimpl.cpp cansocketadapter.cpp logger.cpp mutex.cpp thread.cpp dbusexport.cpp dbusplugin.cpp
+ abstractdbusinterface.cpp dbussignaller.cpp varianttype.cpp)
+set(plugins_common_headers_install abstractio.hpp serialport.hpp bluetooth.hpp bluetoothadapterproxy.h bluetoothmanagerproxy.h bluetoothserialproxy.h
+ bluetooth5.h canbus.h canadapter.h cansocket.h cansocketreader.h canbusimpl.h cansocketadapter.h canobserver.h logger.h mutex.h thread.h
+ dbusexport.h dbusplugin.h abstractdbusinterface.h dbussignaller.h varianttype.h)
+
+add_library(amb-plugins-common SHARED ${plugins_common_sources})
+
+pkg_check_modules(gio-unix REQUIRED gio-unix-2.0)
+
+include_directories( ${include_dirs} ${gio-unix_INCLUDE_DIRS} )
+
+target_link_libraries(amb-plugins-common ${libtool_LIBRARY} ${glib_LIBRARIES} ${gio_LIBRARIES} ${gio-unix_LIBRARIES})
+
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/amb-plugins-common.pc.in ${CMAKE_CURRENT_BINARY_DIR}/amb-plugins-common.pc @ONLY)
+
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/amb-plugins-common.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+
+install (FILES ${plugins_common_headers_install} DESTINATION ${INCLUDE_INSTALL_DIR}/amb COMPONENT Devel)
+
+install (TARGETS amb-plugins-common LIBRARY DESTINATION ${LIB_INSTALL_DIR} RUNTIME DESTINATION bin ARCHIVE DESTINATION ${LIB_INSTALL_DIR})
+
+
diff --git a/plugins/common/abstractdbusinterface.cpp b/plugins/common/abstractdbusinterface.cpp
new file mode 100644
index 00000000..85940a04
--- /dev/null
+++ b/plugins/common/abstractdbusinterface.cpp
@@ -0,0 +1,616 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "abstractdbusinterface.h"
+
+#include <abstractroutingengine.h>
+#include <debugout.h>
+#include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <gio/gio.h>
+#include <listplusplus.h>
+
+#include "varianttype.h"
+#include "dbussignaller.h"
+
+static DBusSignaller* signaller = nullptr;
+
+unordered_map<string, AbstractDBusInterface*> AbstractDBusInterface::objectMap;
+PropertyList AbstractDBusInterface::mimplementedProperties;
+
+const uint getPid(const char *owner)
+{
+ GError* error = nullptr;
+ GDBusProxy* dbus = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL,
+ "org.freedesktop.DBus",
+ "/",
+ "org.freedesktop.DBus",
+ NULL,
+ &error);
+
+ if(error)
+ {
+ throw std::runtime_error(error->message);
+ }
+
+ error = nullptr;
+
+ GVariant* pid = g_dbus_proxy_call_sync(dbus, "GetConnectionUnixProcessID", g_variant_new("(s)", owner), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+
+ if(error)
+ {
+ DebugOut(DebugOut::Error)<< error->message << endl;
+ }
+
+ uint thePid=0;
+
+ g_variant_get(pid,"(u)",&thePid);
+
+ return thePid;
+}
+
+void AbstractDBusInterface::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)
+{
+
+ std::string method = method_name;
+ AbstractDBusInterface* iface = static_cast<AbstractDBusInterface*>(user_data);
+
+ if(DebugOut::getDebugThreshhold() >= 6)
+ {
+ DebugOut(6)<<"DBus method call from: "<<sender<< " pid: " <<getPid(sender)<< " interface: "<<interface_name<<" method: "<<method<<endl;
+ DebugOut(6)<<"DBus method call path: "<<object_path<<endl;
+ }
+
+ g_assert(iface);
+
+ 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 = 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));
+ 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());
+ }
+ });
+ return;
+ }
+ }
+ else if(method == "GetHistory")
+ {
+ double beginTime = 0;
+ double endTime = 0;
+
+ g_variant_get(parameters, "(dd)", &beginTime, &endTime);
+
+ auto propertyMap = iface->getProperties();
+
+ PropertyList propertyList;
+
+ for(auto itr = propertyMap.begin(); itr != propertyMap.end(); itr++)
+ {
+ VariantType* prop = (*itr).second;
+
+ if(!contains(propertyList, prop->ambPropertyName()))
+ propertyList.push_back(prop->ambPropertyName());
+ }
+
+ std::string ifaceName = iface->interfaceName();
+
+ AsyncRangePropertyRequest request;
+
+ request.properties = propertyList;
+ request.timeBegin = beginTime;
+ request.timeEnd = endTime;
+ request.zone = iface->zone();
+ //request.sourceUuid = iface->source();
+
+ request.completed = [&invocation,&ifaceName](AsyncRangePropertyReply* r)
+ {
+ auto reply = amb::make_unique(r);
+ if(!reply->success)
+ {
+ stringstream str;
+ str<<"Error during request: "<<AsyncPropertyReply::errorToStr(reply->error);
+ ifaceName += ".Error";
+ g_dbus_method_invocation_return_dbus_error(invocation, ifaceName.c_str(), str.str().c_str());
+ return;
+ }
+
+ if(!reply->values.size())
+ {
+ ifaceName += ".Error";
+ g_dbus_method_invocation_return_dbus_error(invocation, ifaceName.c_str(), "No results");
+ return;
+ }
+
+ GVariantBuilder builder;
+ 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_dbus_method_invocation_return_value(invocation,g_variant_new("(a{svd})",&builder));
+ };
+
+ iface->re->getRangePropertyAsync(request);
+
+ return;
+ }
+
+ ///TODO: Deprecated in 0.15
+ else if(boost::algorithm::starts_with(method, "Get"))
+ {
+ amb::deprecateMethod(method, "0.15");
+ std::string propertyName = method.substr(3);
+ auto propertyMap = iface->getProperties();
+ if(propertyMap.find(propertyName) == propertyMap.end())
+ {
+ g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Unknown method.");
+ return;
+ }
+
+ VariantType * property = propertyMap[propertyName];
+
+ GError *error = NULL;
+
+ GVariant **params = g_new(GVariant*,4);
+ GVariant *val = g_variant_ref(property->value()->toVariant());
+ params[0] = g_variant_new("v", val);
+ params[1] = g_variant_new("d",property->timestamp());
+ params[2] = g_variant_new("i",property->value()->sequence);
+ params[3] = g_variant_new("i",property->updateFrequency());
+
+ GVariant *tuple_variant = g_variant_new_tuple(params,4);
+
+ g_dbus_method_invocation_return_value(invocation, tuple_variant);
+
+ g_free(params);
+ g_variant_unref(val);
+
+ if(error)
+ {
+ DebugOut(DebugOut::Error)<<error->message<<endl;
+ g_error_free(error);
+ }
+ return;
+ }
+
+ g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR,G_DBUS_ERROR_UNKNOWN_METHOD, "Unknown method.");
+}
+
+AbstractDBusInterface::AbstractDBusInterface(string interfaceName, string objectName,
+ GDBusConnection* connection)
+ : mInterfaceName(interfaceName), mConnection(connection), mPropertyName(objectName), supported(false), zoneFilter(Zone::None), mTime(0), regId(0)
+{
+ startRegistration();
+
+ mObjectPath = "/" + objectName;
+}
+
+AbstractDBusInterface::~AbstractDBusInterface()
+{
+ unregisterObject();
+
+ PropertyList impl = implementedProperties();
+
+ for(auto itr = impl.begin(); itr != impl.end(); itr++)
+ {
+ if(properties.find(*itr) != properties.end())
+ {
+ // Deleted in ~DBusSink()
+ //delete properties[*itr];
+ properties.erase(*itr);
+ }
+ }
+
+ objectMap.erase(mObjectPath);
+}
+
+void AbstractDBusInterface::addProperty(VariantType * property)
+{
+ string nameToLower = property->name();
+ boost::algorithm::to_lower<string>(nameToLower);
+
+ string access;
+
+ if(property->access() == VariantType::Read)
+ access = "read";
+ else if(property->access() == VariantType::Write)
+ access = "write";
+ else if(property->access() == VariantType::ReadWrite)
+ access = "readwrite";
+ else throw -1; //FIXME: don't throw
+
+ std::string pn = property->name();
+
+ ///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>"
+ "<property type='i' name='" + pn + "Sequence' access='read' />";
+
+ properties[pn] = property;
+
+ if(!contains(mimplementedProperties, property->ambPropertyName()))
+ {
+ std::string pname = property->ambPropertyName();
+ mimplementedProperties.push_back(pname);
+ }
+}
+
+void AbstractDBusInterface::registerObject()
+{
+ if(!mConnection)
+ {
+ throw std::runtime_error("forgot to call setDBusConnection on AbstractDBusInterface");
+ }
+
+ if(introspectionXml.empty())
+ {
+ cerr<<"no interface to export: "<<mInterfaceName<<endl;
+ throw -1;
+ }
+
+ if(!boost::algorithm::ends_with(introspectionXml,"</node>"))
+ {
+ introspectionXml += "</interface>"
+ "</node>";
+ }
+
+ GError* error=NULL;
+
+ GDBusNodeInfo* introspection = g_dbus_node_info_new_for_xml(introspectionXml.c_str(), &error);
+
+ if(!introspection || error)
+ {
+
+ DebugOut(DebugOut::Error)<<"Error in "<<__FILE__<<" - "<<__FUNCTION__<<":"<<__LINE__<<endl;
+ DebugOut(DebugOut::Error)<<error->message<<endl;
+ DebugOut(DebugOut::Error)<<"probably bad xml:"<<endl;
+ DebugOut(DebugOut::Error)<<introspectionXml<<endl;
+
+ g_error_free(error);
+
+ return;
+ }
+
+ GDBusInterfaceInfo* mInterfaceInfo = g_dbus_node_info_lookup_interface(introspection, mInterfaceName.c_str());
+
+
+ const GDBusInterfaceVTable vtable = { handleMyMethodCall, nullptr, nullptr };
+
+ GError* error2=NULL;
+
+ DebugOut()<<"registering DBus path: "<<mObjectPath<<endl;
+
+ regId = g_dbus_connection_register_object(mConnection, mObjectPath.c_str(), mInterfaceInfo, &vtable, this, NULL, &error2);
+ g_dbus_node_info_unref(introspection);
+ if(error2)
+ {
+ DebugOut(DebugOut::Error)<<error2->message<<endl;
+ g_error_free(error2);
+ }
+
+ if(regId == 0)
+ {
+ DebugOut(DebugOut::Error)<<"We failed to register on DBus"<<endl;
+ }
+}
+
+void AbstractDBusInterface::unregisterObject()
+{
+ if(regId)
+ {
+ DebugOut()<<__FUNCTION__<<endl;
+ g_dbus_connection_unregister_object(mConnection, regId);
+ }
+
+ regId=0;
+}
+
+void AbstractDBusInterface::updateValue(VariantType *property)
+{
+ if(mConnection == nullptr)
+ {
+ return;
+ }
+
+ if(isRegistered())
+ signaller->fireSignal(mConnection, mObjectPath, mInterfaceName, "PropertiesChanged", property);
+}
+
+std::list<AbstractDBusInterface *> AbstractDBusInterface::getObjectsForProperty(string object)
+{
+ std::list<AbstractDBusInterface *> l;
+ for(auto itr = objectMap.begin(); itr != objectMap.end(); itr++)
+ {
+ AbstractDBusInterface * interface = (*itr).second;
+ if(interface->objectName() == object)
+ l.push_back(interface);
+ }
+
+ return l;
+}
+list<AbstractDBusInterface *> AbstractDBusInterface::interfaces()
+{
+ std::list<AbstractDBusInterface*> ifaces;
+
+ for(auto itr = objectMap.begin(); itr != objectMap.end(); itr++)
+ {
+ ifaces.push_back((*itr).second);
+ }
+
+ return ifaces;
+}
+
+std::vector<std::string> AbstractDBusInterface::supportedInterfaces()
+{
+ std::vector<std::string> ifaces;
+
+ for(auto itr : objectMap)
+ {
+ if(itr.second->isSupported())
+ ifaces.push_back(itr.second->objectName());
+ }
+
+ return ifaces;
+}
+
+bool AbstractDBusInterface::implementsProperty(string property)
+{
+ for(auto itr = properties.begin(); itr != properties.end(); itr++)
+ {
+ if((*itr).first == property)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+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' />"
+ "<method name='GetHistory'>"
+ " <arg type='d' direction='in' name='beginTimestamp' />"
+ " <arg type='d' direction='in' name='endTimestamp' />"
+ " <arg type='a(svd)' direction='out' name='result' />"
+ "</method>";
+}
+
+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)
+ {
+ DebugOut(6)<<"DBus GetProperty call from: "<<sender<< " pid: " <<getPid(sender)<< " interface: "<<interfaceName<<" property: "<<propertyName<<endl;
+ DebugOut(6)<<"DBus GetProperty call path: "<<objectPath<<endl;
+ }
+
+ std::string pn = propertyName;
+ if(pn == "Time")
+ {
+ if(objectMap.find(objectPath) == objectMap.end())
+ {
+ DebugOut(DebugOut::Error)<<objectPath<<" is not a valid object path."<<endl;
+ return nullptr;
+ }
+ double time = objectMap[objectPath]->time();
+
+ GVariant* value = g_variant_new("d", time);
+ return value;
+ }
+
+ if(boost::ends_with(pn, "Sequence"))
+ {
+ AbstractDBusInterface* t = static_cast<AbstractDBusInterface*>(userData);
+
+ int pos = pn.find("Sequence");
+
+ std::string p = pn.substr(0,pos);
+
+ VariantType * theProperty = t->property(p);
+
+ if(!theProperty)
+ {
+ DebugOut(DebugOut::Error)<<"Invalid Sequence property: "<<p<<endl;
+ return nullptr;
+ }
+
+ int sequence = theProperty->sequence();
+
+ GVariant* value = g_variant_new("i", sequence);
+ return value;
+ }
+
+ if(pn == "Zone")
+ {
+ if(objectMap.find(objectPath) == objectMap.end())
+ {
+ DebugOut(DebugOut::Error)<<objectPath<<" is not a valid object path."<<endl;
+ return nullptr;
+ }
+
+ Zone::Type zone = objectMap[objectPath]->zone();
+
+ GVariant* value = g_variant_new("i",(int)zone);
+ return value;
+ }
+
+ if(objectMap.count(objectPath))
+ {
+ GVariant* value = objectMap[objectPath]->getProperty(propertyName);
+
+ DebugOut(6) << "Returning value for: " << propertyName << endl;
+ return value;
+ }
+
+
+ DebugOut(DebugOut::Error)<<"No interface for" << interfaceName <<endl;
+ 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,
+ std::function<void (bool, AsyncPropertyReply::Error)> callback)
+{
+ if(DebugOut::getDebugThreshhold() >= 6)
+ {
+ DebugOut(6)<<"DBus SetProperty call from: "<<sender<< " pid: " <<getPid(sender)<< " interface: "<<interfaceName<<" property: "<<propertyName<<endl;
+ DebugOut(6)<<"DBus SetProperty call path: "<<objectPath<<endl;
+ }
+
+ if(objectMap.count(objectPath))
+ {
+ objectMap[objectPath]->setProperty(propertyName, value, callback);
+ return true;
+ }
+
+ return false;
+}
+
+void AbstractDBusInterface::setProperty(string propertyName, GVariant *value, std::function<void (bool, AsyncPropertyReply::Error)> callback)
+{
+ if(properties.count(propertyName))
+ {
+ properties[propertyName]->fromVariant(value, callback);
+ }
+ else if(callback)
+ {
+ callback(false, AsyncPropertyReply::InvalidOperation);
+ }
+}
+
+GVariant *AbstractDBusInterface::getProperty(string propertyName)
+{
+ if(properties.count(propertyName))
+ return properties[propertyName]->toVariant();
+
+ return nullptr;
+}
+
+void AbstractDBusInterface::setTimeout(int timeout)
+{
+ if(!signaller)
+ signaller = DBusSignaller::factory(timeout);
+}
+
diff --git a/plugins/common/abstractdbusinterface.h b/plugins/common/abstractdbusinterface.h
new file mode 100644
index 00000000..9bff3da9
--- /dev/null
+++ b/plugins/common/abstractdbusinterface.h
@@ -0,0 +1,168 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef ABSTRACTDBUSINTERFACE_H
+#define ABSTRACTDBUSINTERFACE_H
+
+#include <string>
+#include <functional>
+#include <unordered_map>
+#include <list>
+#include <gio/gio.h>
+#include <boost/any.hpp>
+#include <nullptr.h>
+#include "abstractpropertytype.h"
+#include <abstractroutingengine.h>
+#include "varianttype.h"
+
+const uint getPid(const char *owner);
+
+typedef std::vector<VariantType*> PropertyDBusMap;
+
+class AbstractDBusInterface
+{
+
+public:
+ AbstractDBusInterface(std::string interfaceName, std::string objectName, GDBusConnection* connection);
+
+ virtual ~AbstractDBusInterface();
+
+ void setDBusConnection(GDBusConnection* connection)
+ {
+ mConnection = connection;
+ }
+
+ void registerObject();
+ void unregisterObject();
+
+ void addProperty(VariantType* property);
+ virtual void updateValue(VariantType* property);
+
+ static PropertyList implementedProperties() { return mimplementedProperties; }
+
+ static std::list<AbstractDBusInterface *> getObjectsForProperty(std::string property);
+
+ static list<AbstractDBusInterface*> interfaces();
+
+ static std::vector<string> supportedInterfaces();
+
+ std::string interfaceName() { return mInterfaceName; }
+ void setInterfaceName(const std::string & ifaceName)
+ {
+ mInterfaceName = ifaceName;
+ }
+
+ bool implementsProperty(std::string property);
+
+ /*!
+ * \brief hasPropertyDBus
+ * \param attributeName, name of DBus property
+ * \return true if attributeName is supported by this interface
+ */
+ bool hasPropertyDBus(std::string attributeName)
+ {
+
+ for(auto i : propertyDBusMap)
+ {
+ if(i->name() == attributeName)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ std::string objectPath() { return mObjectPath; }
+
+ bool isSupported() { return supported; }
+
+ double time() { return mTime; }
+
+ VariantType* property(std::string propertyName)
+ {
+ if(properties.find(propertyName) != properties.end())
+ return properties[propertyName];
+ return nullptr;
+ }
+
+ AbstractRoutingEngine* re;
+
+ void setObjectPath(std::string op)
+ {
+ if(objectMap.find(op) != objectMap.end())
+ objectMap.erase(op);
+
+ mObjectPath = op;
+ objectMap[mObjectPath] = this;
+ }
+
+ std::string objectName() { return mPropertyName; }
+
+ Zone::Type zone() { return zoneFilter; }
+
+ std::string source() { return mSourceFilter; }
+
+ std::unordered_map<std::string, VariantType*> getProperties() { return properties; }
+
+ bool isRegistered() { return regId > 0; }
+
+protected:
+
+ void startRegistration();
+
+ static GVariant *getProperty(GDBusConnection * connection, const gchar * sender, const gchar *objectPath,
+ const gchar *interfaceName, const gchar * propertyName, GError** error,
+ 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, std::function<void (bool, AsyncPropertyReply::Error)> callback);
+
+ 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);
+
+ std::unordered_map<std::string, VariantType*> properties;
+
+ Zone::Type zoneFilter;
+
+ PropertyDBusMap propertyDBusMap;
+
+ bool supported;
+ double mTime;
+ std::string mSourceFilter;
+
+private:
+ std::string mInterfaceName;
+ std::string mObjectPath;
+ std::string mPropertyName;
+ std::string introspectionXml;
+ GDBusConnection * mConnection;
+ static std::unordered_map<std::string, AbstractDBusInterface*> objectMap;
+ static PropertyList mimplementedProperties;
+ guint regId;
+ int mTimeout;
+
+};
+
+#endif // ABSTRACTDBUSINTERFACE_H
diff --git a/plugins/common/abstractio.hpp b/plugins/common/abstractio.hpp
new file mode 100644
index 00000000..3e0aa676
--- /dev/null
+++ b/plugins/common/abstractio.hpp
@@ -0,0 +1,19 @@
+#ifndef _ABSTRACTIO_H_
+#define _ABSTRACTIO_H_
+
+#include <string>
+
+class AbstractIo
+{
+public:
+
+ virtual bool open() = 0;
+ virtual bool close() = 0;
+ virtual bool isOpen() =0;
+ virtual std::string read() = 0;
+ virtual void write(std::string data) = 0;
+
+ virtual int fileDescriptor() = 0;
+};
+
+#endif
diff --git a/plugins/common/amb-plugins-common.pc.in b/plugins/common/amb-plugins-common.pc.in
new file mode 100644
index 00000000..8871c5ed
--- /dev/null
+++ b/plugins/common/amb-plugins-common.pc.in
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDE_INSTALL_DIR@/amb
+
+Name: amb-plugins-common
+Description:
+Version: @PROJECT_VERSION@
+Requires: gio-2.0 glib-2.0 automotive-message-broker
+Libs: -L${libdir} -lamb -luuid -lamb-plugins-common
+Cflags: -I${includedir}
diff --git a/plugins/common/bluetooth.hpp b/plugins/common/bluetooth.hpp
new file mode 100644
index 00000000..a5799b56
--- /dev/null
+++ b/plugins/common/bluetooth.hpp
@@ -0,0 +1,191 @@
+#ifndef BLUETOOTHWRAPPER
+#define BLUETOOTHWRAPPER
+
+#include <string>
+#include <debugout.h>
+
+#include "bluetoothmanagerproxy.h"
+#include "bluetoothadapterproxy.h"
+#include "bluetoothserialproxy.h"
+
+
+class BluetoothDevice
+{
+public:
+
+ std::string getDeviceForAddress(std::string address, std::string adapterAddy = "")
+ {
+ GError* error = NULL;
+ OrgBluezManager* manager = org_bluez_manager_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.bluez","/",NULL, &error);
+
+ if(!manager)
+ {
+ DebugOut(DebugOut::Warning)<<"Error getting bluetooth manager proxy: "<<error->message<<endl;
+ g_error_free(error);
+ return "";
+ }
+
+ error = NULL;
+
+ gchar* adapterPath;
+
+ if(adapterAddy != "")
+ {
+ if(!org_bluez_manager_call_find_adapter_sync(manager,adapterAddy.c_str(), &adapterPath, NULL, &error))
+ {
+ DebugOut(DebugOut::Warning)<<"Error getting bluetooth adapter ("<<adapterAddy<<"): "<<error->message<<endl;
+ g_error_free(error);
+ return "";
+ }
+
+ error = NULL;
+ }
+
+ else
+ {
+ if(!org_bluez_manager_call_default_adapter_sync(manager,&adapterPath, NULL, &error))
+ {
+ DebugOut(DebugOut::Warning)<<"Error getting bluetooth default adapter: "<<error->message<<endl;
+ g_error_free(error);
+ return "";
+ }
+
+ error = NULL;
+ }
+
+ OrgBluezAdapter* adapter = org_bluez_adapter_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.bluez",adapterPath,NULL,&error);
+ if(!adapter)
+ {
+ DebugOut(DebugOut::Warning)<<"Error getting bluetooth adapter proxy: "<<error->message<<endl;
+ g_error_free(error);
+ return "";
+ }
+
+ error = NULL;
+
+ gchar* devicePath;
+ if(!org_bluez_adapter_call_find_device_sync(adapter,address.c_str(),&devicePath,NULL,&error) ||
+ std::string(devicePath) == "")
+ {
+ DebugOut(DebugOut::Warning)<<"Error finding bluetooth device: "<<address<<error->message<<endl;
+ g_error_free(error);
+ return "";
+ }
+
+ error = NULL;
+
+ OrgBluezSerial* serialDevice = org_bluez_serial_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.bluez",devicePath,NULL,&error);
+
+ if(!serialDevice)
+ {
+ DebugOut(DebugOut::Warning)<<"Error getting bluetooth serial device proxy: "<<error->message<<endl;
+ g_error_free(error);
+ return "";
+ }
+
+ gchar* serialDeviceName;
+ if(!org_bluez_serial_call_connect_sync(serialDevice,"spp",&serialDeviceName,NULL,&error))
+ {
+ DebugOut(DebugOut::Warning)<<"Error connecting bluetooth serial device: "<<address<<" - "<<error->message<<endl;
+ g_error_free(error);
+ return "";
+ }
+
+ return serialDeviceName;
+ }
+
+ void disconnect(std::string address, std::string adapterAddy = "")
+ {
+ GError* error = NULL;
+ OrgBluezManager* manager = org_bluez_manager_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.bluez","/",NULL, &error);
+
+ if(!manager)
+ {
+ DebugOut(DebugOut::Warning)<<"Error getting bluetooth manager proxy: "<<error->message<<endl;
+ g_error_free(error);
+ return ;
+ }
+
+ error = NULL;
+
+ gchar* adapterPath;
+
+ if(adapterAddy != "")
+ {
+ if(!org_bluez_manager_call_find_adapter_sync(manager,adapterAddy.c_str(), &adapterPath, NULL, &error))
+ {
+ DebugOut(DebugOut::Warning)<<"Error getting bluetooth adapter ("<<adapterAddy<<"): "<<error->message<<endl;
+ g_error_free(error);
+ return ;
+ }
+
+ error = NULL;
+ }
+
+ else
+ {
+ if(!org_bluez_manager_call_default_adapter_sync(manager,&adapterPath, NULL, &error))
+ {
+ DebugOut(DebugOut::Warning)<<"Error getting bluetooth default adapter: "<<error->message<<endl;
+ g_error_free(error);
+ return ;
+ }
+
+ error = NULL;
+ }
+
+ OrgBluezAdapter* adapter = org_bluez_adapter_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.bluez",adapterPath,NULL,&error);
+ if(!adapter)
+ {
+ DebugOut(DebugOut::Warning)<<"Error getting bluetooth adapter proxy: "<<error->message<<endl;
+ g_error_free(error);
+ return ;
+ }
+
+ error = NULL;
+
+ gchar* devicePath;
+ if(!org_bluez_adapter_call_find_device_sync(adapter,address.c_str(),&devicePath,NULL,&error) ||
+ std::string(devicePath) == "")
+ {
+ DebugOut(DebugOut::Warning)<<"Error finding bluetooth device: "<<address<<error->message<<endl;
+ g_error_free(error);
+ return ;
+ }
+
+ error = NULL;
+
+ OrgBluezSerial* serialDevice = org_bluez_serial_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ "org.bluez",devicePath,NULL,&error);
+
+ if(!serialDevice)
+ {
+ DebugOut(DebugOut::Warning)<<"Error getting bluetooth serial device proxy: "<<error->message<<endl;
+ g_error_free(error);
+ return ;
+ }
+
+ gchar* serialDeviceName;
+ if(!org_bluez_serial_call_disconnect_sync(serialDevice,"spp",NULL,&error))
+ {
+ DebugOut(DebugOut::Warning)<<"Error disconnecting bluetooth serial device: "<<address<<" - "<<error->message<<endl;
+ g_error_free(error);
+ return ;
+ }
+ }
+
+};
+
+
+#endif
diff --git a/plugins/common/bluetooth5.cpp b/plugins/common/bluetooth5.cpp
new file mode 100644
index 00000000..c2c63275
--- /dev/null
+++ b/plugins/common/bluetooth5.cpp
@@ -0,0 +1,368 @@
+#include "bluetooth5.h"
+#include "superptr.hpp"
+
+#include "debugout.h"
+#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
+#include <string>
+
+static const gchar introspection_xml[] =
+ "<node>"
+ " <interface name='org.bluez.Profile1'>"
+ " <method name='Release'>"
+ " </method>"
+ " <method name='NewConnection'>"
+ " <arg type='o' name='device' direction='in'/>"
+ " <arg type='h' name='fd' direction='in'/>"
+ " <arg type='a{sv}' name='fd_properties' direction='in'/>"
+ " </method>"
+ " <method name='RequestDisconnection'>"
+ " <arg type='o' name='device' direction='in'/>"
+ " </method>"
+ " </interface>"
+ "</node>";
+
+static void handleMethodCall(GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+
+ Bluetooth5* manager = static_cast<Bluetooth5*>(user_data);
+
+ std::string method = method_name;
+
+ if(method == "Release")
+ {
+
+ }
+ else if(method == "NewConnection")
+ {
+ DebugOut()<<"NewConnection() called"<<endl;
+
+ gchar* device;
+ gint32 fd;
+ GVariantIter* iter;
+
+ DebugOut() << "parameters signature: " << g_variant_get_type_string(parameters) << endl;
+
+ g_variant_get(parameters,"(oha{sv})", &device, &fd, &iter);
+
+ DebugOut() << "device: " << device << endl;
+
+ auto message = g_dbus_method_invocation_get_message(invocation);
+
+ auto fdList = g_dbus_message_get_unix_fd_list(message);
+
+ GError* error = nullptr;
+
+ fd = g_unix_fd_list_get(fdList, 0, &error);
+
+ auto errorPtr = amb::make_super(error);
+
+ if(errorPtr)
+ {
+ DebugOut(DebugOut::Error) << "Error trying to get fd: " << errorPtr->message << endl;
+ return;
+ }
+
+ char* propertyName;
+ GVariant* value;
+
+ DebugOut() << "trying to see what properties we got with this call" << endl;
+
+ while(g_variant_iter_next(iter,"{sv}", &propertyName, &value))
+ {
+ auto keyPtr = amb::make_super(propertyName);
+ auto valuePtr = amb::make_super(value);
+ DebugOut() << "key " << keyPtr.get() << "value signature: " << g_variant_get_type_string(valuePtr.get()) << endl;
+ }
+
+ manager->connected_(fd);
+ }
+ else if(method == "RequestDisconnection")
+ {
+ DebugOut()<<"disconnection."<<endl;
+ }
+ else
+ {
+ g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Unknown method.");
+ }
+
+ /// return nothing:
+ g_dbus_method_invocation_return_value(invocation, nullptr);
+}
+
+static GVariant* getProperty(GDBusConnection* connection, const gchar* sender, const gchar* objectPath, const gchar* interfaceName, const gchar* propertyName, GError** error, gpointer userData)
+{
+ return NULL;
+}
+
+static gboolean setProperty(GDBusConnection * connection, const gchar * sender, const gchar *objectPath,
+ const gchar *interfaceName, const gchar * propertyName, GVariant *value,
+ GError** error, gpointer userData)
+{
+ return false;
+}
+
+static const GDBusInterfaceVTable interfaceVTable =
+{
+ handleMethodCall,
+ getProperty,
+ setProperty
+};
+
+std::string findDevice(std::string address, std::string adapterPath)
+{
+ std::string objectPath;
+
+ GError * proxyError = nullptr;
+ auto managerProxy = amb::make_super(g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL,
+ "org.bluez",
+ "/",
+ "org.freedesktop.DBus.ObjectManager",
+ nullptr, &proxyError));
+
+ auto proxyErrorPtr = amb::make_super(proxyError);
+ if(proxyErrorPtr)
+ {
+ DebugOut(DebugOut::Error)<<"Could not create ObjectManager proxy for Bluez: "<<proxyErrorPtr->message<<endl;
+ return "";
+ }
+
+ GError * getManagerObjectError = nullptr;
+
+ auto objectMap = amb::make_super(g_dbus_proxy_call_sync(managerProxy.get(), "GetManagedObjects",nullptr, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &getManagerObjectError));
+
+ auto getManagerObjectErrorPtr = amb::make_super(getManagerObjectError);
+
+ if(getManagerObjectErrorPtr)
+ {
+ DebugOut(DebugOut::Error)<<"Failed call to GetManagedObjects: "<<getManagerObjectErrorPtr->message<<endl;
+ return "";
+ }
+
+ GVariantIter* iter;
+ char* objPath;
+ GVariantIter* level2Dict;
+
+ g_variant_get(objectMap.get(), "(a{oa{sa{sv}}})",&iter);
+
+ auto iterPtr = amb::make_super(iter);
+
+
+ while(g_variant_iter_next(iter, "{oa{sa{sv}}}",&objPath, &level2Dict))
+ {
+ auto level2DictPtr = amb::make_super(level2Dict);
+ auto objPathPtr = amb::make_super(objPath);
+
+ char * interfaceName;
+ GVariantIter* innerDict;
+ while(g_variant_iter_next(level2DictPtr.get(), "{sa{sv}}", &interfaceName, &innerDict))
+ {
+ auto interfaceNamePtr = amb::make_super(interfaceName);
+ auto innerDictPtr = amb::make_super(innerDict);
+ if(std::string(interfaceNamePtr.get()) == "org.bluez.Device1")
+ {
+ char* propertyName;
+ GVariant* value;
+
+ while(objectPath == "" && g_variant_iter_next(innerDictPtr.get(),"{sv}", &propertyName, &value))
+ {
+ auto propertyNamePtr = amb::make_super(propertyName);
+ auto valuePtr = amb::make_super(value);
+
+ if(std::string(propertyNamePtr.get()) == "Address")
+ {
+ char* addy;
+ g_variant_get(valuePtr.get(),"s",&addy);
+
+ auto addyPtr = amb::make_super(addy);
+
+ if(addyPtr && std::string(addyPtr.get()) == address)
+ {
+ objectPath = objPathPtr.get();
+ }
+ }
+ ///TODO: filter only devices that have the specified adapter
+ }
+ }
+ }
+ }
+
+ return objectPath;
+}
+
+Bluetooth5::Bluetooth5()
+{
+ GError* errorIntrospection = NULL;
+
+ GDBusNodeInfo* introspection = g_dbus_node_info_new_for_xml(introspection_xml, &errorIntrospection);
+
+ auto errorIntrospectionPtr = amb::make_super(errorIntrospection);
+
+ if(errorIntrospectionPtr)
+ {
+ DebugOut(DebugOut::Error)<<"in instrospection xml: "<<errorIntrospectionPtr->message<<endl;
+ return;
+ }
+
+ GError* errorBus = nullptr;
+
+ GDBusInterfaceInfo* mInterfaceInfo = g_dbus_node_info_lookup_interface(introspection, "org.bluez.Profile1");
+
+ mConnection = amb::make_super(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &errorBus));
+
+ auto errorBusPtr = amb::make_super(errorBus);
+
+ if(errorBusPtr)
+ {
+ DebugOut(DebugOut::Error)<<"getting system bus: "<<errorBusPtr->message<<endl;
+ return;
+ }
+
+ GError* errorRegister = nullptr;
+
+ int regId = g_dbus_connection_register_object(mConnection.get(), "/org/bluez/spp", mInterfaceInfo, &interfaceVTable, this, NULL, &errorRegister);
+
+ auto errorRegisterPtr = amb::make_super(errorRegister);
+
+ if(errorRegisterPtr)
+ {
+
+ DebugOut(DebugOut::Error)<<"Registering org.bluez.Profile1 Interface: "<<errorRegisterPtr->message<<endl;
+ return;
+ }
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_DICTIONARY);
+
+ g_variant_builder_add(&builder, "{sv}", "Name", g_variant_new("s","AMB spp client"));
+ g_variant_builder_add(&builder, "{sv}", "Role", g_variant_new("s","client"));
+ g_variant_builder_add(&builder, "{sv}", "AutoConnect", g_variant_new("b",true));
+
+ GError* errorRegisterCall = nullptr;
+
+ g_dbus_connection_call_sync(mConnection.get(),
+ "org.bluez",
+ "/org/bluez",
+ "org.bluez.ProfileManager1",
+ "RegisterProfile",
+ g_variant_new("(osa{sv})", "/org/bluez/spp", "00001101-0000-1000-8000-00805F9B34FB", &builder),
+ nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &errorRegisterCall);
+
+ auto errorRegisterCallPtr = amb::make_super(errorRegisterCall);
+
+ if(errorRegisterCallPtr)
+ {
+ DebugOut(DebugOut::Error)<<"RegisterProfile failed: "<<errorRegisterCallPtr->message<<endl;
+ return;
+ }
+}
+
+bool Bluetooth5::setDevice(string address)
+{
+ mPath = findDevice(address);
+
+
+ if(mPath == "")
+ {
+ DebugOut(DebugOut::Error) << "device path not found. Not paired? " << endl;
+ return false;
+ }
+
+ return true;
+}
+
+void Bluetooth5::getDeviceForAddress(std::string address, ConnectedCallback connectedCallback)
+{
+ mConnected = connectedCallback;
+
+ if(!setDevice(address))
+ return;
+
+ DebugOut() << "Bluetooth device path: " << mPath << endl;
+
+ connect(connectedCallback);
+}
+
+void Bluetooth5::connected_(int fd)
+{
+ try
+ {
+ mConnected(fd);
+ }
+ catch(...)
+ {
+ DebugOut(DebugOut::Error) << "Error calling connected callback" << endl;
+ }
+}
+
+void Bluetooth5::connect(ConnectedCallback onconnectedCallback)
+{
+ mConnected = onconnectedCallback;
+
+ GError* error = nullptr;
+
+ auto deviceProxyPtr = amb::make_super(g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,G_DBUS_PROXY_FLAGS_NONE,NULL,
+ "org.bluez", mPath.c_str(), "org.bluez.Device1", nullptr, &error));
+
+ auto errorPtr = amb::make_super(error);
+
+ if(errorPtr)
+ {
+ DebugOut(DebugOut::Error) << "Error getting bluetooth device proxy " << errorPtr->message <<endl;
+ return;
+ }
+
+ g_dbus_proxy_call(deviceProxyPtr.get(), "Connect", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr,
+ [](GObject *source_object, GAsyncResult *res, gpointer user_data)
+ {
+
+ GError* error = nullptr;
+
+ g_dbus_proxy_call_finish(G_DBUS_PROXY (source_object), res, &error);
+
+ auto errorPtr = amb::make_super(error);
+
+ if(errorPtr)
+ {
+ DebugOut(DebugOut::Warning) << "error trying to connect profile: " << errorPtr->message << endl;
+ }
+ },
+ this);
+}
+
+void Bluetooth5::disconnect()
+{
+ GError* error = nullptr;
+
+ auto deviceProxyPtr = amb::make_super(g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,G_DBUS_PROXY_FLAGS_NONE,NULL,
+ "org.bluez", mPath.c_str(), "org.bluez.Device1", nullptr, &error));
+
+ auto errorPtr = amb::make_super(error);
+
+ if(errorPtr)
+ {
+ DebugOut(DebugOut::Error) << "Error getting bluetooth device proxy " << errorPtr->message <<endl;
+ return;
+ }
+
+ g_dbus_proxy_call(deviceProxyPtr.get(), "Disconnect", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr,[](GObject *source_object,
+ GAsyncResult *res, gpointer user_data){
+ GError* error = nullptr;
+
+ g_dbus_proxy_call_finish(G_DBUS_PROXY (source_object), res, &error);
+
+ auto errorPtr = amb::make_super(error);
+
+ if(errorPtr)
+ {
+ DebugOut(DebugOut::Error) << "error trying to disconnect: " << errorPtr->message << endl;
+ }
+ }, nullptr);
+}
diff --git a/plugins/common/bluetooth5.h b/plugins/common/bluetooth5.h
new file mode 100644
index 00000000..4dd698e4
--- /dev/null
+++ b/plugins/common/bluetooth5.h
@@ -0,0 +1,32 @@
+#ifndef BLUETOOTH_5_H_
+#define BLUETOOOTH_5_H_
+
+#include <string>
+#include <functional>
+#include <superptr.hpp>
+
+typedef std::function<void(int)> ConnectedCallback;
+
+std::string findDevice(std::string address, std::string adapterPath="");
+
+class Bluetooth5
+{
+public:
+ Bluetooth5();
+
+ bool setDevice(std::string address);
+ void getDeviceForAddress(std::string address, ConnectedCallback onnectedCallback);
+
+ void connected_(int fd);
+
+ void connect(ConnectedCallback onconnectedCallback);
+ void disconnect();
+
+
+private:
+ ConnectedCallback mConnected;
+ amb::super_ptr<GDBusConnection> mConnection;
+ std::string mPath;
+};
+
+#endif
diff --git a/plugins/common/bluetoothadapterproxy.c b/plugins/common/bluetoothadapterproxy.c
new file mode 100644
index 00000000..a4725c7b
--- /dev/null
+++ b/plugins/common/bluetoothadapterproxy.c
@@ -0,0 +1,3801 @@
+/*
+ * Generated by gdbus-codegen 2.32.1. DO NOT EDIT.
+ *
+ * The license of this code is the same as for the source it was derived from.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "bluetoothadapterproxy.h"
+
+#ifdef G_OS_UNIX
+# include <gio/gunixfdlist.h>
+#endif
+
+typedef struct
+{
+ GDBusArgInfo parent_struct;
+ gboolean use_gvariant;
+} _ExtendedGDBusArgInfo;
+
+typedef struct
+{
+ GDBusMethodInfo parent_struct;
+ const gchar *signal_name;
+ gboolean pass_fdlist;
+} _ExtendedGDBusMethodInfo;
+
+typedef struct
+{
+ GDBusSignalInfo parent_struct;
+ const gchar *signal_name;
+} _ExtendedGDBusSignalInfo;
+
+typedef struct
+{
+ GDBusPropertyInfo parent_struct;
+ const gchar *hyphen_name;
+ gboolean use_gvariant;
+} _ExtendedGDBusPropertyInfo;
+
+typedef struct
+{
+ GDBusInterfaceInfo parent_struct;
+ const gchar *hyphen_name;
+} _ExtendedGDBusInterfaceInfo;
+
+typedef struct
+{
+ const _ExtendedGDBusPropertyInfo *info;
+ guint prop_id;
+ GValue orig_value; /* the value before the change */
+} ChangedProperty;
+
+static void
+_changed_property_free (ChangedProperty *data)
+{
+ g_value_unset (&data->orig_value);
+ g_free (data);
+}
+
+static gboolean
+_g_strv_equal0 (gchar **a, gchar **b)
+{
+ gboolean ret = FALSE;
+ guint n;
+ if (a == NULL && b == NULL)
+ {
+ ret = TRUE;
+ goto out;
+ }
+ if (a == NULL || b == NULL)
+ goto out;
+ if (g_strv_length (a) != g_strv_length (b))
+ goto out;
+ for (n = 0; a[n] != NULL; n++)
+ if (g_strcmp0 (a[n], b[n]) != 0)
+ goto out;
+ ret = TRUE;
+out:
+ return ret;
+}
+
+static gboolean
+_g_variant_equal0 (GVariant *a, GVariant *b)
+{
+ gboolean ret = FALSE;
+ if (a == NULL && b == NULL)
+ {
+ ret = TRUE;
+ goto out;
+ }
+ if (a == NULL || b == NULL)
+ goto out;
+ ret = g_variant_equal (a, b);
+out:
+ return ret;
+}
+
+G_GNUC_UNUSED static gboolean
+_g_value_equal (const GValue *a, const GValue *b)
+{
+ gboolean ret = FALSE;
+ g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));
+ switch (G_VALUE_TYPE (a))
+ {
+ case G_TYPE_BOOLEAN:
+ ret = (g_value_get_boolean (a) == g_value_get_boolean (b));
+ break;
+ case G_TYPE_UCHAR:
+ ret = (g_value_get_uchar (a) == g_value_get_uchar (b));
+ break;
+ case G_TYPE_INT:
+ ret = (g_value_get_int (a) == g_value_get_int (b));
+ break;
+ case G_TYPE_UINT:
+ ret = (g_value_get_uint (a) == g_value_get_uint (b));
+ break;
+ case G_TYPE_INT64:
+ ret = (g_value_get_int64 (a) == g_value_get_int64 (b));
+ break;
+ case G_TYPE_UINT64:
+ ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));
+ break;
+ case G_TYPE_DOUBLE:
+ ret = (g_value_get_double (a) == g_value_get_double (b));
+ break;
+ case G_TYPE_STRING:
+ ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);
+ break;
+ case G_TYPE_VARIANT:
+ ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b));
+ break;
+ default:
+ if (G_VALUE_TYPE (a) == G_TYPE_STRV)
+ ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b));
+ else
+ g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a)));
+ break;
+ }
+ return ret;
+}
+
+/* ------------------------------------------------------------------------
+ * Code for interface org.bluez.Adapter
+ * ------------------------------------------------------------------------
+ */
+
+/**
+ * SECTION:OrgBluezAdapter
+ * @title: OrgBluezAdapter
+ * @short_description: Generated C code for the org.bluez.Adapter D-Bus interface
+ *
+ * This section contains code for working with the <link linkend="gdbus-interface-org-bluez-Adapter.top_of_page">org.bluez.Adapter</link> D-Bus interface in C.
+ */
+
+/* ---- Introspection data for org.bluez.Adapter ---- */
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_get_properties_OUT_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "a{sv}",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_method_info_get_properties_OUT_ARG_pointers[] =
+{
+ &_org_bluez_adapter_method_info_get_properties_OUT_ARG_unnamed_arg0,
+ NULL
+};
+
+static const GDBusAnnotationInfo _org_bluez_adapter_method_get_properties_annotation_info_0 =
+{
+ -1,
+ "com.trolltech.QtDBus.QtTypeName.Out0",
+ "QVariantMap",
+ NULL
+};
+
+static const GDBusAnnotationInfo * const _org_bluez_adapter_method_get_properties_annotation_info_pointers[] =
+{
+ &_org_bluez_adapter_method_get_properties_annotation_info_0,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_get_properties =
+{
+ {
+ -1,
+ "GetProperties",
+ NULL,
+ (GDBusArgInfo **) &_org_bluez_adapter_method_info_get_properties_OUT_ARG_pointers,
+ (GDBusAnnotationInfo **) &_org_bluez_adapter_method_get_properties_annotation_info_pointers
+ },
+ "handle-get-properties",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_set_property_IN_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_set_property_IN_ARG_unnamed_arg1 =
+{
+ {
+ -1,
+ "unnamed_arg1",
+ "v",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_method_info_set_property_IN_ARG_pointers[] =
+{
+ &_org_bluez_adapter_method_info_set_property_IN_ARG_unnamed_arg0,
+ &_org_bluez_adapter_method_info_set_property_IN_ARG_unnamed_arg1,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_set_property =
+{
+ {
+ -1,
+ "SetProperty",
+ (GDBusArgInfo **) &_org_bluez_adapter_method_info_set_property_IN_ARG_pointers,
+ NULL,
+ NULL
+ },
+ "handle-set-property",
+ FALSE
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_request_session =
+{
+ {
+ -1,
+ "RequestSession",
+ NULL,
+ NULL,
+ NULL
+ },
+ "handle-request-session",
+ FALSE
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_release_session =
+{
+ {
+ -1,
+ "ReleaseSession",
+ NULL,
+ NULL,
+ NULL
+ },
+ "handle-release-session",
+ FALSE
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_start_discovery =
+{
+ {
+ -1,
+ "StartDiscovery",
+ NULL,
+ NULL,
+ NULL
+ },
+ "handle-start-discovery",
+ FALSE
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_stop_discovery =
+{
+ {
+ -1,
+ "StopDiscovery",
+ NULL,
+ NULL,
+ NULL
+ },
+ "handle-stop-discovery",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_list_devices_OUT_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "ao",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_method_info_list_devices_OUT_ARG_pointers[] =
+{
+ &_org_bluez_adapter_method_info_list_devices_OUT_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_list_devices =
+{
+ {
+ -1,
+ "ListDevices",
+ NULL,
+ (GDBusArgInfo **) &_org_bluez_adapter_method_info_list_devices_OUT_ARG_pointers,
+ NULL
+ },
+ "handle-list-devices",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_create_device_IN_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_method_info_create_device_IN_ARG_pointers[] =
+{
+ &_org_bluez_adapter_method_info_create_device_IN_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_create_device_OUT_ARG_unnamed_arg1 =
+{
+ {
+ -1,
+ "unnamed_arg1",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_method_info_create_device_OUT_ARG_pointers[] =
+{
+ &_org_bluez_adapter_method_info_create_device_OUT_ARG_unnamed_arg1,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_create_device =
+{
+ {
+ -1,
+ "CreateDevice",
+ (GDBusArgInfo **) &_org_bluez_adapter_method_info_create_device_IN_ARG_pointers,
+ (GDBusArgInfo **) &_org_bluez_adapter_method_info_create_device_OUT_ARG_pointers,
+ NULL
+ },
+ "handle-create-device",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_create_paired_device_IN_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_create_paired_device_IN_ARG_unnamed_arg1 =
+{
+ {
+ -1,
+ "unnamed_arg1",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_create_paired_device_IN_ARG_unnamed_arg2 =
+{
+ {
+ -1,
+ "unnamed_arg2",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_method_info_create_paired_device_IN_ARG_pointers[] =
+{
+ &_org_bluez_adapter_method_info_create_paired_device_IN_ARG_unnamed_arg0,
+ &_org_bluez_adapter_method_info_create_paired_device_IN_ARG_unnamed_arg1,
+ &_org_bluez_adapter_method_info_create_paired_device_IN_ARG_unnamed_arg2,
+ NULL
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_create_paired_device_OUT_ARG_unnamed_arg3 =
+{
+ {
+ -1,
+ "unnamed_arg3",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_method_info_create_paired_device_OUT_ARG_pointers[] =
+{
+ &_org_bluez_adapter_method_info_create_paired_device_OUT_ARG_unnamed_arg3,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_create_paired_device =
+{
+ {
+ -1,
+ "CreatePairedDevice",
+ (GDBusArgInfo **) &_org_bluez_adapter_method_info_create_paired_device_IN_ARG_pointers,
+ (GDBusArgInfo **) &_org_bluez_adapter_method_info_create_paired_device_OUT_ARG_pointers,
+ NULL
+ },
+ "handle-create-paired-device",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_cancel_device_creation_IN_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_method_info_cancel_device_creation_IN_ARG_pointers[] =
+{
+ &_org_bluez_adapter_method_info_cancel_device_creation_IN_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_cancel_device_creation =
+{
+ {
+ -1,
+ "CancelDeviceCreation",
+ (GDBusArgInfo **) &_org_bluez_adapter_method_info_cancel_device_creation_IN_ARG_pointers,
+ NULL,
+ NULL
+ },
+ "handle-cancel-device-creation",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_remove_device_IN_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_method_info_remove_device_IN_ARG_pointers[] =
+{
+ &_org_bluez_adapter_method_info_remove_device_IN_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_remove_device =
+{
+ {
+ -1,
+ "RemoveDevice",
+ (GDBusArgInfo **) &_org_bluez_adapter_method_info_remove_device_IN_ARG_pointers,
+ NULL,
+ NULL
+ },
+ "handle-remove-device",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_find_device_IN_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_method_info_find_device_IN_ARG_pointers[] =
+{
+ &_org_bluez_adapter_method_info_find_device_IN_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_find_device_OUT_ARG_unnamed_arg1 =
+{
+ {
+ -1,
+ "unnamed_arg1",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_method_info_find_device_OUT_ARG_pointers[] =
+{
+ &_org_bluez_adapter_method_info_find_device_OUT_ARG_unnamed_arg1,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_find_device =
+{
+ {
+ -1,
+ "FindDevice",
+ (GDBusArgInfo **) &_org_bluez_adapter_method_info_find_device_IN_ARG_pointers,
+ (GDBusArgInfo **) &_org_bluez_adapter_method_info_find_device_OUT_ARG_pointers,
+ NULL
+ },
+ "handle-find-device",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_register_agent_IN_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_register_agent_IN_ARG_unnamed_arg1 =
+{
+ {
+ -1,
+ "unnamed_arg1",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_method_info_register_agent_IN_ARG_pointers[] =
+{
+ &_org_bluez_adapter_method_info_register_agent_IN_ARG_unnamed_arg0,
+ &_org_bluez_adapter_method_info_register_agent_IN_ARG_unnamed_arg1,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_register_agent =
+{
+ {
+ -1,
+ "RegisterAgent",
+ (GDBusArgInfo **) &_org_bluez_adapter_method_info_register_agent_IN_ARG_pointers,
+ NULL,
+ NULL
+ },
+ "handle-register-agent",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_method_info_unregister_agent_IN_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_method_info_unregister_agent_IN_ARG_pointers[] =
+{
+ &_org_bluez_adapter_method_info_unregister_agent_IN_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_adapter_method_info_unregister_agent =
+{
+ {
+ -1,
+ "UnregisterAgent",
+ (GDBusArgInfo **) &_org_bluez_adapter_method_info_unregister_agent_IN_ARG_pointers,
+ NULL,
+ NULL
+ },
+ "handle-unregister-agent",
+ FALSE
+};
+
+static const _ExtendedGDBusMethodInfo * const _org_bluez_adapter_method_info_pointers[] =
+{
+ &_org_bluez_adapter_method_info_get_properties,
+ &_org_bluez_adapter_method_info_set_property,
+ &_org_bluez_adapter_method_info_request_session,
+ &_org_bluez_adapter_method_info_release_session,
+ &_org_bluez_adapter_method_info_start_discovery,
+ &_org_bluez_adapter_method_info_stop_discovery,
+ &_org_bluez_adapter_method_info_list_devices,
+ &_org_bluez_adapter_method_info_create_device,
+ &_org_bluez_adapter_method_info_create_paired_device,
+ &_org_bluez_adapter_method_info_cancel_device_creation,
+ &_org_bluez_adapter_method_info_remove_device,
+ &_org_bluez_adapter_method_info_find_device,
+ &_org_bluez_adapter_method_info_register_agent,
+ &_org_bluez_adapter_method_info_unregister_agent,
+ NULL
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_signal_info_property_changed_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_signal_info_property_changed_ARG_unnamed_arg1 =
+{
+ {
+ -1,
+ "unnamed_arg1",
+ "v",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_signal_info_property_changed_ARG_pointers[] =
+{
+ &_org_bluez_adapter_signal_info_property_changed_ARG_unnamed_arg0,
+ &_org_bluez_adapter_signal_info_property_changed_ARG_unnamed_arg1,
+ NULL
+};
+
+static const _ExtendedGDBusSignalInfo _org_bluez_adapter_signal_info_property_changed =
+{
+ {
+ -1,
+ "PropertyChanged",
+ (GDBusArgInfo **) &_org_bluez_adapter_signal_info_property_changed_ARG_pointers,
+ NULL
+ },
+ "property-changed"
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_signal_info_device_created_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_signal_info_device_created_ARG_pointers[] =
+{
+ &_org_bluez_adapter_signal_info_device_created_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusSignalInfo _org_bluez_adapter_signal_info_device_created =
+{
+ {
+ -1,
+ "DeviceCreated",
+ (GDBusArgInfo **) &_org_bluez_adapter_signal_info_device_created_ARG_pointers,
+ NULL
+ },
+ "device-created"
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_signal_info_device_removed_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_signal_info_device_removed_ARG_pointers[] =
+{
+ &_org_bluez_adapter_signal_info_device_removed_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusSignalInfo _org_bluez_adapter_signal_info_device_removed =
+{
+ {
+ -1,
+ "DeviceRemoved",
+ (GDBusArgInfo **) &_org_bluez_adapter_signal_info_device_removed_ARG_pointers,
+ NULL
+ },
+ "device-removed"
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_signal_info_device_found_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_signal_info_device_found_ARG_unnamed_arg1 =
+{
+ {
+ -1,
+ "unnamed_arg1",
+ "a{sv}",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_signal_info_device_found_ARG_pointers[] =
+{
+ &_org_bluez_adapter_signal_info_device_found_ARG_unnamed_arg0,
+ &_org_bluez_adapter_signal_info_device_found_ARG_unnamed_arg1,
+ NULL
+};
+
+static const GDBusAnnotationInfo _org_bluez_adapter_signal_device_found_annotation_info_0 =
+{
+ -1,
+ "com.trolltech.QtDBus.QtTypeName.In1",
+ "QVariantMap",
+ NULL
+};
+
+static const GDBusAnnotationInfo * const _org_bluez_adapter_signal_device_found_annotation_info_pointers[] =
+{
+ &_org_bluez_adapter_signal_device_found_annotation_info_0,
+ NULL
+};
+
+static const _ExtendedGDBusSignalInfo _org_bluez_adapter_signal_info_device_found =
+{
+ {
+ -1,
+ "DeviceFound",
+ (GDBusArgInfo **) &_org_bluez_adapter_signal_info_device_found_ARG_pointers,
+ (GDBusAnnotationInfo **) &_org_bluez_adapter_signal_device_found_annotation_info_pointers
+ },
+ "device-found"
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_adapter_signal_info_device_disappeared_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_adapter_signal_info_device_disappeared_ARG_pointers[] =
+{
+ &_org_bluez_adapter_signal_info_device_disappeared_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusSignalInfo _org_bluez_adapter_signal_info_device_disappeared =
+{
+ {
+ -1,
+ "DeviceDisappeared",
+ (GDBusArgInfo **) &_org_bluez_adapter_signal_info_device_disappeared_ARG_pointers,
+ NULL
+ },
+ "device-disappeared"
+};
+
+static const _ExtendedGDBusSignalInfo * const _org_bluez_adapter_signal_info_pointers[] =
+{
+ &_org_bluez_adapter_signal_info_property_changed,
+ &_org_bluez_adapter_signal_info_device_created,
+ &_org_bluez_adapter_signal_info_device_removed,
+ &_org_bluez_adapter_signal_info_device_found,
+ &_org_bluez_adapter_signal_info_device_disappeared,
+ NULL
+};
+
+static const _ExtendedGDBusInterfaceInfo _org_bluez_adapter_interface_info =
+{
+ {
+ -1,
+ "org.bluez.Adapter",
+ (GDBusMethodInfo **) &_org_bluez_adapter_method_info_pointers,
+ (GDBusSignalInfo **) &_org_bluez_adapter_signal_info_pointers,
+ NULL,
+ NULL
+ },
+ "org-bluez-adapter",
+};
+
+
+/**
+ * org_bluez_adapter_interface_info:
+ *
+ * Gets a machine-readable description of the <link linkend="gdbus-interface-org-bluez-Adapter.top_of_page">org.bluez.Adapter</link> D-Bus interface.
+ *
+ * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free.
+ */
+GDBusInterfaceInfo *
+org_bluez_adapter_interface_info (void)
+{
+ return (GDBusInterfaceInfo *) &_org_bluez_adapter_interface_info;
+}
+
+/**
+ * org_bluez_adapter_override_properties:
+ * @klass: The class structure for a #GObject<!-- -->-derived class.
+ * @property_id_begin: The property id to assign to the first overridden property.
+ *
+ * Overrides all #GObject properties in the #OrgBluezAdapter interface for a concrete class.
+ * The properties are overridden in the order they are defined.
+ *
+ * Returns: The last property id.
+ */
+guint
+org_bluez_adapter_override_properties (GObjectClass *klass, guint property_id_begin)
+{
+ return property_id_begin - 1;
+}
+
+
+
+/**
+ * OrgBluezAdapter:
+ *
+ * Abstract interface type for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Adapter.top_of_page">org.bluez.Adapter</link>.
+ */
+
+/**
+ * OrgBluezAdapterIface:
+ * @parent_iface: The parent interface.
+ * @handle_cancel_device_creation: Handler for the #OrgBluezAdapter::handle-cancel-device-creation signal.
+ * @handle_create_device: Handler for the #OrgBluezAdapter::handle-create-device signal.
+ * @handle_create_paired_device: Handler for the #OrgBluezAdapter::handle-create-paired-device signal.
+ * @handle_find_device: Handler for the #OrgBluezAdapter::handle-find-device signal.
+ * @handle_get_properties: Handler for the #OrgBluezAdapter::handle-get-properties signal.
+ * @handle_list_devices: Handler for the #OrgBluezAdapter::handle-list-devices signal.
+ * @handle_register_agent: Handler for the #OrgBluezAdapter::handle-register-agent signal.
+ * @handle_release_session: Handler for the #OrgBluezAdapter::handle-release-session signal.
+ * @handle_remove_device: Handler for the #OrgBluezAdapter::handle-remove-device signal.
+ * @handle_request_session: Handler for the #OrgBluezAdapter::handle-request-session signal.
+ * @handle_set_property: Handler for the #OrgBluezAdapter::handle-set-property signal.
+ * @handle_start_discovery: Handler for the #OrgBluezAdapter::handle-start-discovery signal.
+ * @handle_stop_discovery: Handler for the #OrgBluezAdapter::handle-stop-discovery signal.
+ * @handle_unregister_agent: Handler for the #OrgBluezAdapter::handle-unregister-agent signal.
+ * @device_created: Handler for the #OrgBluezAdapter::device-created signal.
+ * @device_disappeared: Handler for the #OrgBluezAdapter::device-disappeared signal.
+ * @device_found: Handler for the #OrgBluezAdapter::device-found signal.
+ * @device_removed: Handler for the #OrgBluezAdapter::device-removed signal.
+ * @property_changed: Handler for the #OrgBluezAdapter::property-changed signal.
+ *
+ * Virtual table for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Adapter.top_of_page">org.bluez.Adapter</link>.
+ */
+
+static void
+org_bluez_adapter_default_init (OrgBluezAdapterIface *iface)
+{
+ /* GObject signals for incoming D-Bus method calls: */
+ /**
+ * OrgBluezAdapter::handle-get-properties:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.GetProperties">GetProperties()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_get_properties() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-get-properties",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_get_properties),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_DBUS_METHOD_INVOCATION);
+
+ /**
+ * OrgBluezAdapter::handle-set-property:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_unnamed_arg0: Argument passed by remote caller.
+ * @arg_unnamed_arg1: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.SetProperty">SetProperty()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_set_property() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-set-property",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_set_property),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 3,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_VARIANT);
+
+ /**
+ * OrgBluezAdapter::handle-request-session:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.RequestSession">RequestSession()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_request_session() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-request-session",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_request_session),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_DBUS_METHOD_INVOCATION);
+
+ /**
+ * OrgBluezAdapter::handle-release-session:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.ReleaseSession">ReleaseSession()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_release_session() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-release-session",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_release_session),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_DBUS_METHOD_INVOCATION);
+
+ /**
+ * OrgBluezAdapter::handle-start-discovery:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.StartDiscovery">StartDiscovery()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_start_discovery() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-start-discovery",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_start_discovery),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_DBUS_METHOD_INVOCATION);
+
+ /**
+ * OrgBluezAdapter::handle-stop-discovery:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.StopDiscovery">StopDiscovery()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_stop_discovery() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-stop-discovery",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_stop_discovery),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_DBUS_METHOD_INVOCATION);
+
+ /**
+ * OrgBluezAdapter::handle-list-devices:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.ListDevices">ListDevices()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_list_devices() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-list-devices",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_list_devices),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_DBUS_METHOD_INVOCATION);
+
+ /**
+ * OrgBluezAdapter::handle-create-device:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_unnamed_arg0: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.CreateDevice">CreateDevice()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_create_device() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-create-device",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_create_device),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 2,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING);
+
+ /**
+ * OrgBluezAdapter::handle-create-paired-device:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_unnamed_arg0: Argument passed by remote caller.
+ * @arg_unnamed_arg1: Argument passed by remote caller.
+ * @arg_unnamed_arg2: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.CreatePairedDevice">CreatePairedDevice()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_create_paired_device() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-create-paired-device",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_create_paired_device),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 4,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+ /**
+ * OrgBluezAdapter::handle-cancel-device-creation:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_unnamed_arg0: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.CancelDeviceCreation">CancelDeviceCreation()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_cancel_device_creation() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-cancel-device-creation",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_cancel_device_creation),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 2,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING);
+
+ /**
+ * OrgBluezAdapter::handle-remove-device:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_unnamed_arg0: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.RemoveDevice">RemoveDevice()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_remove_device() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-remove-device",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_remove_device),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 2,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING);
+
+ /**
+ * OrgBluezAdapter::handle-find-device:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_unnamed_arg0: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.FindDevice">FindDevice()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_find_device() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-find-device",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_find_device),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 2,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING);
+
+ /**
+ * OrgBluezAdapter::handle-register-agent:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_unnamed_arg0: Argument passed by remote caller.
+ * @arg_unnamed_arg1: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.RegisterAgent">RegisterAgent()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_register_agent() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-register-agent",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_register_agent),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 3,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_STRING);
+
+ /**
+ * OrgBluezAdapter::handle-unregister-agent:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_unnamed_arg0: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Adapter.UnregisterAgent">UnregisterAgent()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_adapter_complete_unregister_agent() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-unregister-agent",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, handle_unregister_agent),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 2,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING);
+
+ /* GObject signals for received D-Bus signals: */
+ /**
+ * OrgBluezAdapter::property-changed:
+ * @object: A #OrgBluezAdapter.
+ * @arg_unnamed_arg0: Argument.
+ * @arg_unnamed_arg1: Argument.
+ *
+ * On the client-side, this signal is emitted whenever the D-Bus signal <link linkend="gdbus-signal-org-bluez-Adapter.PropertyChanged">"PropertyChanged"</link> is received.
+ *
+ * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.
+ */
+ g_signal_new ("property-changed",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, property_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 2, G_TYPE_STRING, G_TYPE_VARIANT);
+
+ /**
+ * OrgBluezAdapter::device-created:
+ * @object: A #OrgBluezAdapter.
+ * @arg_unnamed_arg0: Argument.
+ *
+ * On the client-side, this signal is emitted whenever the D-Bus signal <link linkend="gdbus-signal-org-bluez-Adapter.DeviceCreated">"DeviceCreated"</link> is received.
+ *
+ * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.
+ */
+ g_signal_new ("device-created",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, device_created),
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+
+ /**
+ * OrgBluezAdapter::device-removed:
+ * @object: A #OrgBluezAdapter.
+ * @arg_unnamed_arg0: Argument.
+ *
+ * On the client-side, this signal is emitted whenever the D-Bus signal <link linkend="gdbus-signal-org-bluez-Adapter.DeviceRemoved">"DeviceRemoved"</link> is received.
+ *
+ * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.
+ */
+ g_signal_new ("device-removed",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, device_removed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+
+ /**
+ * OrgBluezAdapter::device-found:
+ * @object: A #OrgBluezAdapter.
+ * @arg_unnamed_arg0: Argument.
+ * @arg_unnamed_arg1: Argument.
+ *
+ * On the client-side, this signal is emitted whenever the D-Bus signal <link linkend="gdbus-signal-org-bluez-Adapter.DeviceFound">"DeviceFound"</link> is received.
+ *
+ * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.
+ */
+ g_signal_new ("device-found",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, device_found),
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 2, G_TYPE_STRING, G_TYPE_VARIANT);
+
+ /**
+ * OrgBluezAdapter::device-disappeared:
+ * @object: A #OrgBluezAdapter.
+ * @arg_unnamed_arg0: Argument.
+ *
+ * On the client-side, this signal is emitted whenever the D-Bus signal <link linkend="gdbus-signal-org-bluez-Adapter.DeviceDisappeared">"DeviceDisappeared"</link> is received.
+ *
+ * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.
+ */
+ g_signal_new ("device-disappeared",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezAdapterIface, device_disappeared),
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+
+}
+
+typedef OrgBluezAdapterIface OrgBluezAdapterInterface;
+G_DEFINE_INTERFACE (OrgBluezAdapter, org_bluez_adapter, G_TYPE_OBJECT);
+
+/**
+ * org_bluez_adapter_emit_property_changed:
+ * @object: A #OrgBluezAdapter.
+ * @arg_unnamed_arg0: Argument to pass with the signal.
+ * @arg_unnamed_arg1: Argument to pass with the signal.
+ *
+ * Emits the <link linkend="gdbus-signal-org-bluez-Adapter.PropertyChanged">"PropertyChanged"</link> D-Bus signal.
+ */
+void
+org_bluez_adapter_emit_property_changed (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1)
+{
+ g_signal_emit_by_name (object, "property-changed", arg_unnamed_arg0, arg_unnamed_arg1);
+}
+
+/**
+ * org_bluez_adapter_emit_device_created:
+ * @object: A #OrgBluezAdapter.
+ * @arg_unnamed_arg0: Argument to pass with the signal.
+ *
+ * Emits the <link linkend="gdbus-signal-org-bluez-Adapter.DeviceCreated">"DeviceCreated"</link> D-Bus signal.
+ */
+void
+org_bluez_adapter_emit_device_created (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0)
+{
+ g_signal_emit_by_name (object, "device-created", arg_unnamed_arg0);
+}
+
+/**
+ * org_bluez_adapter_emit_device_removed:
+ * @object: A #OrgBluezAdapter.
+ * @arg_unnamed_arg0: Argument to pass with the signal.
+ *
+ * Emits the <link linkend="gdbus-signal-org-bluez-Adapter.DeviceRemoved">"DeviceRemoved"</link> D-Bus signal.
+ */
+void
+org_bluez_adapter_emit_device_removed (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0)
+{
+ g_signal_emit_by_name (object, "device-removed", arg_unnamed_arg0);
+}
+
+/**
+ * org_bluez_adapter_emit_device_found:
+ * @object: A #OrgBluezAdapter.
+ * @arg_unnamed_arg0: Argument to pass with the signal.
+ * @arg_unnamed_arg1: Argument to pass with the signal.
+ *
+ * Emits the <link linkend="gdbus-signal-org-bluez-Adapter.DeviceFound">"DeviceFound"</link> D-Bus signal.
+ */
+void
+org_bluez_adapter_emit_device_found (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1)
+{
+ g_signal_emit_by_name (object, "device-found", arg_unnamed_arg0, arg_unnamed_arg1);
+}
+
+/**
+ * org_bluez_adapter_emit_device_disappeared:
+ * @object: A #OrgBluezAdapter.
+ * @arg_unnamed_arg0: Argument to pass with the signal.
+ *
+ * Emits the <link linkend="gdbus-signal-org-bluez-Adapter.DeviceDisappeared">"DeviceDisappeared"</link> D-Bus signal.
+ */
+void
+org_bluez_adapter_emit_device_disappeared (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0)
+{
+ g_signal_emit_by_name (object, "device-disappeared", arg_unnamed_arg0);
+}
+
+/**
+ * org_bluez_adapter_call_get_properties:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.GetProperties">GetProperties()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_get_properties_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_get_properties_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_get_properties (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "GetProperties",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_get_properties_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @out_unnamed_arg0: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_get_properties().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_get_properties().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_get_properties_finish (
+ OrgBluezAdapter *proxy,
+ GVariant **out_unnamed_arg0,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(@a{sv})",
+ out_unnamed_arg0);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_get_properties_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @out_unnamed_arg0: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.GetProperties">GetProperties()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_get_properties() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_get_properties_sync (
+ OrgBluezAdapter *proxy,
+ GVariant **out_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "GetProperties",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(@a{sv})",
+ out_unnamed_arg0);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_set_property:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @arg_unnamed_arg1: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.SetProperty">SetProperty()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_set_property_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_set_property_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_set_property (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "SetProperty",
+ g_variant_new ("(s@v)",
+ arg_unnamed_arg0,
+ arg_unnamed_arg1),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_set_property_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_set_property().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_set_property().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_set_property_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_set_property_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @arg_unnamed_arg1: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.SetProperty">SetProperty()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_set_property() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_set_property_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "SetProperty",
+ g_variant_new ("(s@v)",
+ arg_unnamed_arg0,
+ arg_unnamed_arg1),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_request_session:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.RequestSession">RequestSession()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_request_session_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_request_session_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_request_session (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "RequestSession",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_request_session_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_request_session().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_request_session().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_request_session_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_request_session_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.RequestSession">RequestSession()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_request_session() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_request_session_sync (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "RequestSession",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_release_session:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.ReleaseSession">ReleaseSession()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_release_session_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_release_session_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_release_session (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "ReleaseSession",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_release_session_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_release_session().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_release_session().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_release_session_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_release_session_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.ReleaseSession">ReleaseSession()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_release_session() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_release_session_sync (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "ReleaseSession",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_start_discovery:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.StartDiscovery">StartDiscovery()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_start_discovery_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_start_discovery_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_start_discovery (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "StartDiscovery",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_start_discovery_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_start_discovery().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_start_discovery().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_start_discovery_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_start_discovery_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.StartDiscovery">StartDiscovery()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_start_discovery() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_start_discovery_sync (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "StartDiscovery",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_stop_discovery:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.StopDiscovery">StopDiscovery()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_stop_discovery_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_stop_discovery_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_stop_discovery (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "StopDiscovery",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_stop_discovery_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_stop_discovery().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_stop_discovery().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_stop_discovery_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_stop_discovery_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.StopDiscovery">StopDiscovery()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_stop_discovery() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_stop_discovery_sync (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "StopDiscovery",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_list_devices:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.ListDevices">ListDevices()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_list_devices_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_list_devices_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_list_devices (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "ListDevices",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_list_devices_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @out_unnamed_arg0: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_list_devices().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_list_devices().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_list_devices_finish (
+ OrgBluezAdapter *proxy,
+ gchar ***out_unnamed_arg0,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(^ao)",
+ out_unnamed_arg0);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_list_devices_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @out_unnamed_arg0: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.ListDevices">ListDevices()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_list_devices() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_list_devices_sync (
+ OrgBluezAdapter *proxy,
+ gchar ***out_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "ListDevices",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(^ao)",
+ out_unnamed_arg0);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_create_device:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.CreateDevice">CreateDevice()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_create_device_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_create_device_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_create_device (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "CreateDevice",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_create_device_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @out_unnamed_arg1: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_create_device().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_create_device().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_create_device_finish (
+ OrgBluezAdapter *proxy,
+ gchar **out_unnamed_arg1,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(o)",
+ out_unnamed_arg1);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_create_device_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @out_unnamed_arg1: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.CreateDevice">CreateDevice()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_create_device() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_create_device_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ gchar **out_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "CreateDevice",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(o)",
+ out_unnamed_arg1);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_create_paired_device:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @arg_unnamed_arg1: Argument to pass with the method invocation.
+ * @arg_unnamed_arg2: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.CreatePairedDevice">CreatePairedDevice()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_create_paired_device_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_create_paired_device_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_create_paired_device (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ const gchar *arg_unnamed_arg1,
+ const gchar *arg_unnamed_arg2,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "CreatePairedDevice",
+ g_variant_new ("(sos)",
+ arg_unnamed_arg0,
+ arg_unnamed_arg1,
+ arg_unnamed_arg2),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_create_paired_device_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @out_unnamed_arg3: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_create_paired_device().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_create_paired_device().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_create_paired_device_finish (
+ OrgBluezAdapter *proxy,
+ gchar **out_unnamed_arg3,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(o)",
+ out_unnamed_arg3);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_create_paired_device_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @arg_unnamed_arg1: Argument to pass with the method invocation.
+ * @arg_unnamed_arg2: Argument to pass with the method invocation.
+ * @out_unnamed_arg3: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.CreatePairedDevice">CreatePairedDevice()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_create_paired_device() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_create_paired_device_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ const gchar *arg_unnamed_arg1,
+ const gchar *arg_unnamed_arg2,
+ gchar **out_unnamed_arg3,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "CreatePairedDevice",
+ g_variant_new ("(sos)",
+ arg_unnamed_arg0,
+ arg_unnamed_arg1,
+ arg_unnamed_arg2),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(o)",
+ out_unnamed_arg3);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_cancel_device_creation:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.CancelDeviceCreation">CancelDeviceCreation()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_cancel_device_creation_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_cancel_device_creation_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_cancel_device_creation (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "CancelDeviceCreation",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_cancel_device_creation_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_cancel_device_creation().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_cancel_device_creation().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_cancel_device_creation_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_cancel_device_creation_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.CancelDeviceCreation">CancelDeviceCreation()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_cancel_device_creation() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_cancel_device_creation_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "CancelDeviceCreation",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_remove_device:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.RemoveDevice">RemoveDevice()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_remove_device_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_remove_device_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_remove_device (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "RemoveDevice",
+ g_variant_new ("(o)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_remove_device_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_remove_device().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_remove_device().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_remove_device_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_remove_device_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.RemoveDevice">RemoveDevice()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_remove_device() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_remove_device_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "RemoveDevice",
+ g_variant_new ("(o)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_find_device:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.FindDevice">FindDevice()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_find_device_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_find_device_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_find_device (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "FindDevice",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_find_device_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @out_unnamed_arg1: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_find_device().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_find_device().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_find_device_finish (
+ OrgBluezAdapter *proxy,
+ gchar **out_unnamed_arg1,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(o)",
+ out_unnamed_arg1);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_find_device_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @out_unnamed_arg1: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.FindDevice">FindDevice()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_find_device() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_find_device_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ gchar **out_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "FindDevice",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(o)",
+ out_unnamed_arg1);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_register_agent:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @arg_unnamed_arg1: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.RegisterAgent">RegisterAgent()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_register_agent_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_register_agent_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_register_agent (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ const gchar *arg_unnamed_arg1,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "RegisterAgent",
+ g_variant_new ("(os)",
+ arg_unnamed_arg0,
+ arg_unnamed_arg1),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_register_agent_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_register_agent().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_register_agent().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_register_agent_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_register_agent_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @arg_unnamed_arg1: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.RegisterAgent">RegisterAgent()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_register_agent() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_register_agent_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ const gchar *arg_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "RegisterAgent",
+ g_variant_new ("(os)",
+ arg_unnamed_arg0,
+ arg_unnamed_arg1),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_unregister_agent:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.UnregisterAgent">UnregisterAgent()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_call_unregister_agent_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_call_unregister_agent_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_adapter_call_unregister_agent (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "UnregisterAgent",
+ g_variant_new ("(o)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_adapter_call_unregister_agent_finish:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_call_unregister_agent().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_adapter_call_unregister_agent().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_unregister_agent_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_call_unregister_agent_sync:
+ * @proxy: A #OrgBluezAdapterProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Adapter.UnregisterAgent">UnregisterAgent()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_call_unregister_agent() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_adapter_call_unregister_agent_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "UnregisterAgent",
+ g_variant_new ("(o)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_adapter_complete_get_properties:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @unnamed_arg0: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.GetProperties">GetProperties()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_get_properties (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ GVariant *unnamed_arg0)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(@a{sv})",
+ unnamed_arg0));
+}
+
+/**
+ * org_bluez_adapter_complete_set_property:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.SetProperty">SetProperty()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_set_property (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/**
+ * org_bluez_adapter_complete_request_session:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.RequestSession">RequestSession()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_request_session (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/**
+ * org_bluez_adapter_complete_release_session:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.ReleaseSession">ReleaseSession()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_release_session (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/**
+ * org_bluez_adapter_complete_start_discovery:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.StartDiscovery">StartDiscovery()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_start_discovery (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/**
+ * org_bluez_adapter_complete_stop_discovery:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.StopDiscovery">StopDiscovery()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_stop_discovery (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/**
+ * org_bluez_adapter_complete_list_devices:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @unnamed_arg0: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.ListDevices">ListDevices()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_list_devices (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *const *unnamed_arg0)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(^ao)",
+ unnamed_arg0));
+}
+
+/**
+ * org_bluez_adapter_complete_create_device:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @unnamed_arg1: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.CreateDevice">CreateDevice()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_create_device (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *unnamed_arg1)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(o)",
+ unnamed_arg1));
+}
+
+/**
+ * org_bluez_adapter_complete_create_paired_device:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @unnamed_arg3: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.CreatePairedDevice">CreatePairedDevice()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_create_paired_device (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *unnamed_arg3)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(o)",
+ unnamed_arg3));
+}
+
+/**
+ * org_bluez_adapter_complete_cancel_device_creation:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.CancelDeviceCreation">CancelDeviceCreation()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_cancel_device_creation (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/**
+ * org_bluez_adapter_complete_remove_device:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.RemoveDevice">RemoveDevice()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_remove_device (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/**
+ * org_bluez_adapter_complete_find_device:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @unnamed_arg1: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.FindDevice">FindDevice()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_find_device (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *unnamed_arg1)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(o)",
+ unnamed_arg1));
+}
+
+/**
+ * org_bluez_adapter_complete_register_agent:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.RegisterAgent">RegisterAgent()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_register_agent (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/**
+ * org_bluez_adapter_complete_unregister_agent:
+ * @object: A #OrgBluezAdapter.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Adapter.UnregisterAgent">UnregisterAgent()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_adapter_complete_unregister_agent (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/* ------------------------------------------------------------------------ */
+
+/**
+ * OrgBluezAdapterProxy:
+ *
+ * The #OrgBluezAdapterProxy structure contains only private data and should only be accessed using the provided API.
+ */
+
+/**
+ * OrgBluezAdapterProxyClass:
+ * @parent_class: The parent class.
+ *
+ * Class structure for #OrgBluezAdapterProxy.
+ */
+
+struct _OrgBluezAdapterProxyPrivate
+{
+ GData *qdata;
+};
+
+static void org_bluez_adapter_proxy_iface_init (OrgBluezAdapterIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (OrgBluezAdapterProxy, org_bluez_adapter_proxy, G_TYPE_DBUS_PROXY,
+ G_IMPLEMENT_INTERFACE (TYPE_ORG_BLUEZ_ADAPTER, org_bluez_adapter_proxy_iface_init));
+
+static void
+org_bluez_adapter_proxy_finalize (GObject *object)
+{
+ OrgBluezAdapterProxy *proxy = ORG_BLUEZ_ADAPTER_PROXY (object);
+ g_datalist_clear (&proxy->priv->qdata);
+ G_OBJECT_CLASS (org_bluez_adapter_proxy_parent_class)->finalize (object);
+}
+
+static void
+org_bluez_adapter_proxy_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+}
+
+static void
+org_bluez_adapter_proxy_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+}
+
+static void
+org_bluez_adapter_proxy_g_signal (GDBusProxy *proxy,
+ const gchar *sender_name,
+ const gchar *signal_name,
+ GVariant *parameters)
+{
+ _ExtendedGDBusSignalInfo *info;
+ GVariantIter iter;
+ GVariant *child;
+ GValue *paramv;
+ guint num_params;
+ guint n;
+ guint signal_id;
+ info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_org_bluez_adapter_interface_info, signal_name);
+ if (info == NULL)
+ return;
+ num_params = g_variant_n_children (parameters);
+ paramv = g_new0 (GValue, num_params + 1);
+ g_value_init (&paramv[0], TYPE_ORG_BLUEZ_ADAPTER);
+ g_value_set_object (&paramv[0], proxy);
+ g_variant_iter_init (&iter, parameters);
+ n = 1;
+ while ((child = g_variant_iter_next_value (&iter)) != NULL)
+ {
+ _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1];
+ if (arg_info->use_gvariant)
+ {
+ g_value_init (&paramv[n], G_TYPE_VARIANT);
+ g_value_set_variant (&paramv[n], child);
+ n++;
+ }
+ else
+ g_dbus_gvariant_to_gvalue (child, &paramv[n++]);
+ g_variant_unref (child);
+ }
+ signal_id = g_signal_lookup (info->signal_name, TYPE_ORG_BLUEZ_ADAPTER);
+ g_signal_emitv (paramv, signal_id, 0, NULL);
+ for (n = 0; n < num_params + 1; n++)
+ g_value_unset (&paramv[n]);
+ g_free (paramv);
+}
+
+static void
+org_bluez_adapter_proxy_g_properties_changed (GDBusProxy *_proxy,
+ GVariant *changed_properties,
+ const gchar *const *invalidated_properties)
+{
+ OrgBluezAdapterProxy *proxy = ORG_BLUEZ_ADAPTER_PROXY (_proxy);
+ guint n;
+ const gchar *key;
+ GVariantIter *iter;
+ _ExtendedGDBusPropertyInfo *info;
+ g_variant_get (changed_properties, "a{sv}", &iter);
+ while (g_variant_iter_next (iter, "{&sv}", &key, NULL))
+ {
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_org_bluez_adapter_interface_info, key);
+ g_datalist_remove_data (&proxy->priv->qdata, key);
+ if (info != NULL)
+ g_object_notify (G_OBJECT (proxy), info->hyphen_name);
+ }
+ g_variant_iter_free (iter);
+ for (n = 0; invalidated_properties[n] != NULL; n++)
+ {
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_org_bluez_adapter_interface_info, invalidated_properties[n]);
+ g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]);
+ if (info != NULL)
+ g_object_notify (G_OBJECT (proxy), info->hyphen_name);
+ }
+}
+
+static void
+org_bluez_adapter_proxy_init (OrgBluezAdapterProxy *proxy)
+{
+ proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, TYPE_ORG_BLUEZ_ADAPTER_PROXY, OrgBluezAdapterProxyPrivate);
+ g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), org_bluez_adapter_interface_info ());
+}
+
+static void
+org_bluez_adapter_proxy_class_init (OrgBluezAdapterProxyClass *klass)
+{
+ GObjectClass *gobject_class;
+ GDBusProxyClass *proxy_class;
+
+ g_type_class_add_private (klass, sizeof (OrgBluezAdapterProxyPrivate));
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = org_bluez_adapter_proxy_finalize;
+ gobject_class->get_property = org_bluez_adapter_proxy_get_property;
+ gobject_class->set_property = org_bluez_adapter_proxy_set_property;
+
+ proxy_class = G_DBUS_PROXY_CLASS (klass);
+ proxy_class->g_signal = org_bluez_adapter_proxy_g_signal;
+ proxy_class->g_properties_changed = org_bluez_adapter_proxy_g_properties_changed;
+
+}
+
+static void
+org_bluez_adapter_proxy_iface_init (OrgBluezAdapterIface *iface)
+{
+}
+
+/**
+ * org_bluez_adapter_proxy_new:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: (allow-none): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously creates a proxy for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Adapter.top_of_page">org.bluez.Adapter</link>. See g_dbus_proxy_new() for more details.
+ *
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_proxy_new_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_proxy_new_sync() for the synchronous, blocking version of this constructor.
+ */
+void
+org_bluez_adapter_proxy_new (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_async_initable_new_async (TYPE_ORG_BLUEZ_ADAPTER_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.bluez.Adapter", NULL);
+}
+
+/**
+ * org_bluez_adapter_proxy_new_finish:
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_proxy_new().
+ * @error: Return location for error or %NULL
+ *
+ * Finishes an operation started with org_bluez_adapter_proxy_new().
+ *
+ * Returns: (transfer full) (type OrgBluezAdapterProxy): The constructed proxy object or %NULL if @error is set.
+ */
+OrgBluezAdapter *
+org_bluez_adapter_proxy_new_finish (
+ GAsyncResult *res,
+ GError **error)
+{
+ GObject *ret;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (res);
+ ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
+ g_object_unref (source_object);
+ if (ret != NULL)
+ return ORG_BLUEZ_ADAPTER (ret);
+ else
+ return NULL;
+}
+
+/**
+ * org_bluez_adapter_proxy_new_sync:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: (allow-none): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL
+ *
+ * Synchronously creates a proxy for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Adapter.top_of_page">org.bluez.Adapter</link>. See g_dbus_proxy_new_sync() for more details.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_proxy_new() for the asynchronous version of this constructor.
+ *
+ * Returns: (transfer full) (type OrgBluezAdapterProxy): The constructed proxy object or %NULL if @error is set.
+ */
+OrgBluezAdapter *
+org_bluez_adapter_proxy_new_sync (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GInitable *ret;
+ ret = g_initable_new (TYPE_ORG_BLUEZ_ADAPTER_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.bluez.Adapter", NULL);
+ if (ret != NULL)
+ return ORG_BLUEZ_ADAPTER (ret);
+ else
+ return NULL;
+}
+
+
+/**
+ * org_bluez_adapter_proxy_new_for_bus:
+ * @bus_type: A #GBusType.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like org_bluez_adapter_proxy_new() but takes a #GBusType instead of a #GDBusConnection.
+ *
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_adapter_proxy_new_for_bus_finish() to get the result of the operation.
+ *
+ * See org_bluez_adapter_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor.
+ */
+void
+org_bluez_adapter_proxy_new_for_bus (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_async_initable_new_async (TYPE_ORG_BLUEZ_ADAPTER_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.bluez.Adapter", NULL);
+}
+
+/**
+ * org_bluez_adapter_proxy_new_for_bus_finish:
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_adapter_proxy_new_for_bus().
+ * @error: Return location for error or %NULL
+ *
+ * Finishes an operation started with org_bluez_adapter_proxy_new_for_bus().
+ *
+ * Returns: (transfer full) (type OrgBluezAdapterProxy): The constructed proxy object or %NULL if @error is set.
+ */
+OrgBluezAdapter *
+org_bluez_adapter_proxy_new_for_bus_finish (
+ GAsyncResult *res,
+ GError **error)
+{
+ GObject *ret;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (res);
+ ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
+ g_object_unref (source_object);
+ if (ret != NULL)
+ return ORG_BLUEZ_ADAPTER (ret);
+ else
+ return NULL;
+}
+
+/**
+ * org_bluez_adapter_proxy_new_for_bus_sync:
+ * @bus_type: A #GBusType.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL
+ *
+ * Like org_bluez_adapter_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_adapter_proxy_new_for_bus() for the asynchronous version of this constructor.
+ *
+ * Returns: (transfer full) (type OrgBluezAdapterProxy): The constructed proxy object or %NULL if @error is set.
+ */
+OrgBluezAdapter *
+org_bluez_adapter_proxy_new_for_bus_sync (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GInitable *ret;
+ ret = g_initable_new (TYPE_ORG_BLUEZ_ADAPTER_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.bluez.Adapter", NULL);
+ if (ret != NULL)
+ return ORG_BLUEZ_ADAPTER (ret);
+ else
+ return NULL;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+/**
+ * OrgBluezAdapterSkeleton:
+ *
+ * The #OrgBluezAdapterSkeleton structure contains only private data and should only be accessed using the provided API.
+ */
+
+/**
+ * OrgBluezAdapterSkeletonClass:
+ * @parent_class: The parent class.
+ *
+ * Class structure for #OrgBluezAdapterSkeleton.
+ */
+
+struct _OrgBluezAdapterSkeletonPrivate
+{
+ GValue *properties;
+ GList *changed_properties;
+ GSource *changed_properties_idle_source;
+ GMainContext *context;
+ GMutex lock;
+};
+
+static void
+_org_bluez_adapter_skeleton_handle_method_call (
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ OrgBluezAdapterSkeleton *skeleton = ORG_BLUEZ_ADAPTER_SKELETON (user_data);
+ _ExtendedGDBusMethodInfo *info;
+ GVariantIter iter;
+ GVariant *child;
+ GValue *paramv;
+ guint num_params;
+ guint num_extra;
+ guint n;
+ guint signal_id;
+ GValue return_value = G_VALUE_INIT;
+ info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation);
+ g_assert (info != NULL);
+ num_params = g_variant_n_children (parameters);
+ num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra);
+ n = 0;
+ g_value_init (&paramv[n], TYPE_ORG_BLUEZ_ADAPTER);
+ g_value_set_object (&paramv[n++], skeleton);
+ g_value_init (&paramv[n], G_TYPE_DBUS_METHOD_INVOCATION);
+ g_value_set_object (&paramv[n++], invocation);
+ if (info->pass_fdlist)
+ {
+#ifdef G_OS_UNIX
+ g_value_init (&paramv[n], G_TYPE_UNIX_FD_LIST);
+ g_value_set_object (&paramv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation)));
+#else
+ g_assert_not_reached ();
+#endif
+ }
+ g_variant_iter_init (&iter, parameters);
+ while ((child = g_variant_iter_next_value (&iter)) != NULL)
+ {
+ _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra];
+ if (arg_info->use_gvariant)
+ {
+ g_value_init (&paramv[n], G_TYPE_VARIANT);
+ g_value_set_variant (&paramv[n], child);
+ n++;
+ }
+ else
+ g_dbus_gvariant_to_gvalue (child, &paramv[n++]);
+ g_variant_unref (child);
+ }
+ signal_id = g_signal_lookup (info->signal_name, TYPE_ORG_BLUEZ_ADAPTER);
+ g_value_init (&return_value, G_TYPE_BOOLEAN);
+ g_signal_emitv (paramv, signal_id, 0, &return_value);
+ if (!g_value_get_boolean (&return_value))
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name);
+ g_value_unset (&return_value);
+ for (n = 0; n < num_params + num_extra; n++)
+ g_value_unset (&paramv[n]);
+ g_free (paramv);
+}
+
+static GVariant *
+_org_bluez_adapter_skeleton_handle_get_property (
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GError **error,
+ gpointer user_data)
+{
+ OrgBluezAdapterSkeleton *skeleton = ORG_BLUEZ_ADAPTER_SKELETON (user_data);
+ GValue value = G_VALUE_INIT;
+ GParamSpec *pspec;
+ _ExtendedGDBusPropertyInfo *info;
+ GVariant *ret;
+ ret = NULL;
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_org_bluez_adapter_interface_info, property_name);
+ g_assert (info != NULL);
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
+ if (pspec == NULL)
+ {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
+ }
+ else
+ {
+ g_value_init (&value, pspec->value_type);
+ g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value);
+ ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature));
+ g_value_unset (&value);
+ }
+ return ret;
+}
+
+static gboolean
+_org_bluez_adapter_skeleton_handle_set_property (
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GVariant *variant,
+ GError **error,
+ gpointer user_data)
+{
+ OrgBluezAdapterSkeleton *skeleton = ORG_BLUEZ_ADAPTER_SKELETON (user_data);
+ GValue value = G_VALUE_INIT;
+ GParamSpec *pspec;
+ _ExtendedGDBusPropertyInfo *info;
+ gboolean ret;
+ ret = FALSE;
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_org_bluez_adapter_interface_info, property_name);
+ g_assert (info != NULL);
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
+ if (pspec == NULL)
+ {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
+ }
+ else
+ {
+ if (info->use_gvariant)
+ g_value_set_variant (&value, variant);
+ else
+ g_dbus_gvariant_to_gvalue (variant, &value);
+ g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value);
+ g_value_unset (&value);
+ ret = TRUE;
+ }
+ return ret;
+}
+
+static const GDBusInterfaceVTable _org_bluez_adapter_skeleton_vtable =
+{
+ _org_bluez_adapter_skeleton_handle_method_call,
+ _org_bluez_adapter_skeleton_handle_get_property,
+ _org_bluez_adapter_skeleton_handle_set_property
+};
+
+static GDBusInterfaceInfo *
+org_bluez_adapter_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton)
+{
+ return org_bluez_adapter_interface_info ();
+}
+
+static GDBusInterfaceVTable *
+org_bluez_adapter_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton)
+{
+ return (GDBusInterfaceVTable *) &_org_bluez_adapter_skeleton_vtable;
+}
+
+static GVariant *
+org_bluez_adapter_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton)
+{
+ OrgBluezAdapterSkeleton *skeleton = ORG_BLUEZ_ADAPTER_SKELETON (_skeleton);
+
+ GVariantBuilder builder;
+ guint n;
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ if (_org_bluez_adapter_interface_info.parent_struct.properties == NULL)
+ goto out;
+ for (n = 0; _org_bluez_adapter_interface_info.parent_struct.properties[n] != NULL; n++)
+ {
+ GDBusPropertyInfo *info = _org_bluez_adapter_interface_info.parent_struct.properties[n];
+ if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
+ {
+ GVariant *value;
+ value = _org_bluez_adapter_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.bluez.Adapter", info->name, NULL, skeleton);
+ if (value != NULL)
+ {
+ g_variant_take_ref (value);
+ g_variant_builder_add (&builder, "{sv}", info->name, value);
+ g_variant_unref (value);
+ }
+ }
+ }
+out:
+ return g_variant_builder_end (&builder);
+}
+
+static void
+org_bluez_adapter_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton)
+{
+}
+
+static void
+_org_bluez_adapter_on_signal_property_changed (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1)
+{
+ OrgBluezAdapterSkeleton *skeleton = ORG_BLUEZ_ADAPTER_SKELETON (object);
+
+ GList *connections, *l;
+ GVariant *signal_variant;
+ connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
+
+ signal_variant = g_variant_ref_sink (g_variant_new ("(s@v)",
+ arg_unnamed_arg0,
+ arg_unnamed_arg1));
+ for (l = connections; l != NULL; l = l->next)
+ {
+ GDBusConnection *connection = l->data;
+ g_dbus_connection_emit_signal (connection,
+ NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.bluez.Adapter", "PropertyChanged",
+ signal_variant, NULL);
+ }
+ g_variant_unref (signal_variant);
+ g_list_free_full (connections, g_object_unref);
+}
+
+static void
+_org_bluez_adapter_on_signal_device_created (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0)
+{
+ OrgBluezAdapterSkeleton *skeleton = ORG_BLUEZ_ADAPTER_SKELETON (object);
+
+ GList *connections, *l;
+ GVariant *signal_variant;
+ connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
+
+ signal_variant = g_variant_ref_sink (g_variant_new ("(o)",
+ arg_unnamed_arg0));
+ for (l = connections; l != NULL; l = l->next)
+ {
+ GDBusConnection *connection = l->data;
+ g_dbus_connection_emit_signal (connection,
+ NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.bluez.Adapter", "DeviceCreated",
+ signal_variant, NULL);
+ }
+ g_variant_unref (signal_variant);
+ g_list_free_full (connections, g_object_unref);
+}
+
+static void
+_org_bluez_adapter_on_signal_device_removed (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0)
+{
+ OrgBluezAdapterSkeleton *skeleton = ORG_BLUEZ_ADAPTER_SKELETON (object);
+
+ GList *connections, *l;
+ GVariant *signal_variant;
+ connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
+
+ signal_variant = g_variant_ref_sink (g_variant_new ("(o)",
+ arg_unnamed_arg0));
+ for (l = connections; l != NULL; l = l->next)
+ {
+ GDBusConnection *connection = l->data;
+ g_dbus_connection_emit_signal (connection,
+ NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.bluez.Adapter", "DeviceRemoved",
+ signal_variant, NULL);
+ }
+ g_variant_unref (signal_variant);
+ g_list_free_full (connections, g_object_unref);
+}
+
+static void
+_org_bluez_adapter_on_signal_device_found (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1)
+{
+ OrgBluezAdapterSkeleton *skeleton = ORG_BLUEZ_ADAPTER_SKELETON (object);
+
+ GList *connections, *l;
+ GVariant *signal_variant;
+ connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
+
+ signal_variant = g_variant_ref_sink (g_variant_new ("(s@a{sv})",
+ arg_unnamed_arg0,
+ arg_unnamed_arg1));
+ for (l = connections; l != NULL; l = l->next)
+ {
+ GDBusConnection *connection = l->data;
+ g_dbus_connection_emit_signal (connection,
+ NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.bluez.Adapter", "DeviceFound",
+ signal_variant, NULL);
+ }
+ g_variant_unref (signal_variant);
+ g_list_free_full (connections, g_object_unref);
+}
+
+static void
+_org_bluez_adapter_on_signal_device_disappeared (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0)
+{
+ OrgBluezAdapterSkeleton *skeleton = ORG_BLUEZ_ADAPTER_SKELETON (object);
+
+ GList *connections, *l;
+ GVariant *signal_variant;
+ connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
+
+ signal_variant = g_variant_ref_sink (g_variant_new ("(s)",
+ arg_unnamed_arg0));
+ for (l = connections; l != NULL; l = l->next)
+ {
+ GDBusConnection *connection = l->data;
+ g_dbus_connection_emit_signal (connection,
+ NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.bluez.Adapter", "DeviceDisappeared",
+ signal_variant, NULL);
+ }
+ g_variant_unref (signal_variant);
+ g_list_free_full (connections, g_object_unref);
+}
+
+static void org_bluez_adapter_skeleton_iface_init (OrgBluezAdapterIface *iface);
+G_DEFINE_TYPE_WITH_CODE (OrgBluezAdapterSkeleton, org_bluez_adapter_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,
+ G_IMPLEMENT_INTERFACE (TYPE_ORG_BLUEZ_ADAPTER, org_bluez_adapter_skeleton_iface_init));
+
+static void
+org_bluez_adapter_skeleton_finalize (GObject *object)
+{
+ OrgBluezAdapterSkeleton *skeleton = ORG_BLUEZ_ADAPTER_SKELETON (object);
+ g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);
+ if (skeleton->priv->changed_properties_idle_source != NULL)
+ g_source_destroy (skeleton->priv->changed_properties_idle_source);
+ g_main_context_unref (skeleton->priv->context);
+ g_mutex_clear (&skeleton->priv->lock);
+ G_OBJECT_CLASS (org_bluez_adapter_skeleton_parent_class)->finalize (object);
+}
+
+static void
+org_bluez_adapter_skeleton_init (OrgBluezAdapterSkeleton *skeleton)
+{
+ skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, TYPE_ORG_BLUEZ_ADAPTER_SKELETON, OrgBluezAdapterSkeletonPrivate);
+ g_mutex_init (&skeleton->priv->lock);
+ skeleton->priv->context = g_main_context_ref_thread_default ();
+}
+
+static void
+org_bluez_adapter_skeleton_class_init (OrgBluezAdapterSkeletonClass *klass)
+{
+ GObjectClass *gobject_class;
+ GDBusInterfaceSkeletonClass *skeleton_class;
+
+ g_type_class_add_private (klass, sizeof (OrgBluezAdapterSkeletonPrivate));
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = org_bluez_adapter_skeleton_finalize;
+
+ skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
+ skeleton_class->get_info = org_bluez_adapter_skeleton_dbus_interface_get_info;
+ skeleton_class->get_properties = org_bluez_adapter_skeleton_dbus_interface_get_properties;
+ skeleton_class->flush = org_bluez_adapter_skeleton_dbus_interface_flush;
+ skeleton_class->get_vtable = org_bluez_adapter_skeleton_dbus_interface_get_vtable;
+}
+
+static void
+org_bluez_adapter_skeleton_iface_init (OrgBluezAdapterIface *iface)
+{
+ iface->property_changed = _org_bluez_adapter_on_signal_property_changed;
+ iface->device_created = _org_bluez_adapter_on_signal_device_created;
+ iface->device_removed = _org_bluez_adapter_on_signal_device_removed;
+ iface->device_found = _org_bluez_adapter_on_signal_device_found;
+ iface->device_disappeared = _org_bluez_adapter_on_signal_device_disappeared;
+}
+
+/**
+ * org_bluez_adapter_skeleton_new:
+ *
+ * Creates a skeleton object for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Adapter.top_of_page">org.bluez.Adapter</link>.
+ *
+ * Returns: (transfer full) (type OrgBluezAdapterSkeleton): The skeleton object.
+ */
+OrgBluezAdapter *
+org_bluez_adapter_skeleton_new (void)
+{
+ return ORG_BLUEZ_ADAPTER (g_object_new (TYPE_ORG_BLUEZ_ADAPTER_SKELETON, NULL));
+}
+
diff --git a/plugins/common/bluetoothadapterproxy.h b/plugins/common/bluetoothadapterproxy.h
new file mode 100644
index 00000000..9d431d1f
--- /dev/null
+++ b/plugins/common/bluetoothadapterproxy.h
@@ -0,0 +1,578 @@
+/*
+ * Generated by gdbus-codegen 2.32.1. DO NOT EDIT.
+ *
+ * The license of this code is the same as for the source it was derived from.
+ */
+
+#ifndef __BLUETOOTHADAPTERPROXY_H__
+#define __BLUETOOTHADAPTERPROXY_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+
+/* ------------------------------------------------------------------------ */
+/* Declarations for org.bluez.Adapter */
+
+#define TYPE_ORG_BLUEZ_ADAPTER (org_bluez_adapter_get_type ())
+#define ORG_BLUEZ_ADAPTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_ORG_BLUEZ_ADAPTER, OrgBluezAdapter))
+#define IS_ORG_BLUEZ_ADAPTER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_ORG_BLUEZ_ADAPTER))
+#define ORG_BLUEZ_ADAPTER_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), TYPE_ORG_BLUEZ_ADAPTER, OrgBluezAdapterIface))
+
+struct _OrgBluezAdapter;
+typedef struct _OrgBluezAdapter OrgBluezAdapter;
+typedef struct _OrgBluezAdapterIface OrgBluezAdapterIface;
+
+struct _OrgBluezAdapterIface
+{
+ GTypeInterface parent_iface;
+
+
+ gboolean (*handle_cancel_device_creation) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_unnamed_arg0);
+
+ gboolean (*handle_create_device) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_unnamed_arg0);
+
+ gboolean (*handle_create_paired_device) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_unnamed_arg0,
+ const gchar *arg_unnamed_arg1,
+ const gchar *arg_unnamed_arg2);
+
+ gboolean (*handle_find_device) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_unnamed_arg0);
+
+ gboolean (*handle_get_properties) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+ gboolean (*handle_list_devices) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+ gboolean (*handle_register_agent) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_unnamed_arg0,
+ const gchar *arg_unnamed_arg1);
+
+ gboolean (*handle_release_session) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+ gboolean (*handle_remove_device) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_unnamed_arg0);
+
+ gboolean (*handle_request_session) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+ gboolean (*handle_set_property) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1);
+
+ gboolean (*handle_start_discovery) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+ gboolean (*handle_stop_discovery) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+ gboolean (*handle_unregister_agent) (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_unnamed_arg0);
+
+ void (*device_created) (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0);
+
+ void (*device_disappeared) (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0);
+
+ void (*device_found) (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1);
+
+ void (*device_removed) (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0);
+
+ void (*property_changed) (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1);
+
+};
+
+GType org_bluez_adapter_get_type (void) G_GNUC_CONST;
+
+GDBusInterfaceInfo *org_bluez_adapter_interface_info (void);
+guint org_bluez_adapter_override_properties (GObjectClass *klass, guint property_id_begin);
+
+
+/* D-Bus method call completion functions: */
+void org_bluez_adapter_complete_get_properties (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ GVariant *unnamed_arg0);
+
+void org_bluez_adapter_complete_set_property (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+void org_bluez_adapter_complete_request_session (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+void org_bluez_adapter_complete_release_session (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+void org_bluez_adapter_complete_start_discovery (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+void org_bluez_adapter_complete_stop_discovery (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+void org_bluez_adapter_complete_list_devices (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *const *unnamed_arg0);
+
+void org_bluez_adapter_complete_create_device (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *unnamed_arg1);
+
+void org_bluez_adapter_complete_create_paired_device (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *unnamed_arg3);
+
+void org_bluez_adapter_complete_cancel_device_creation (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+void org_bluez_adapter_complete_remove_device (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+void org_bluez_adapter_complete_find_device (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *unnamed_arg1);
+
+void org_bluez_adapter_complete_register_agent (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+void org_bluez_adapter_complete_unregister_agent (
+ OrgBluezAdapter *object,
+ GDBusMethodInvocation *invocation);
+
+
+
+/* D-Bus signal emissions functions: */
+void org_bluez_adapter_emit_property_changed (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1);
+
+void org_bluez_adapter_emit_device_created (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0);
+
+void org_bluez_adapter_emit_device_removed (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0);
+
+void org_bluez_adapter_emit_device_found (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1);
+
+void org_bluez_adapter_emit_device_disappeared (
+ OrgBluezAdapter *object,
+ const gchar *arg_unnamed_arg0);
+
+
+
+/* D-Bus method calls: */
+void org_bluez_adapter_call_get_properties (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_get_properties_finish (
+ OrgBluezAdapter *proxy,
+ GVariant **out_unnamed_arg0,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_get_properties_sync (
+ OrgBluezAdapter *proxy,
+ GVariant **out_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_call_set_property (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_set_property_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_set_property_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_call_request_session (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_request_session_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_request_session_sync (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_call_release_session (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_release_session_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_release_session_sync (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_call_start_discovery (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_start_discovery_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_start_discovery_sync (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_call_stop_discovery (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_stop_discovery_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_stop_discovery_sync (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_call_list_devices (
+ OrgBluezAdapter *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_list_devices_finish (
+ OrgBluezAdapter *proxy,
+ gchar ***out_unnamed_arg0,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_list_devices_sync (
+ OrgBluezAdapter *proxy,
+ gchar ***out_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_call_create_device (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_create_device_finish (
+ OrgBluezAdapter *proxy,
+ gchar **out_unnamed_arg1,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_create_device_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ gchar **out_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_call_create_paired_device (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ const gchar *arg_unnamed_arg1,
+ const gchar *arg_unnamed_arg2,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_create_paired_device_finish (
+ OrgBluezAdapter *proxy,
+ gchar **out_unnamed_arg3,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_create_paired_device_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ const gchar *arg_unnamed_arg1,
+ const gchar *arg_unnamed_arg2,
+ gchar **out_unnamed_arg3,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_call_cancel_device_creation (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_cancel_device_creation_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_cancel_device_creation_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_call_remove_device (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_remove_device_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_remove_device_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_call_find_device (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_find_device_finish (
+ OrgBluezAdapter *proxy,
+ gchar **out_unnamed_arg1,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_find_device_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ gchar **out_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_call_register_agent (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ const gchar *arg_unnamed_arg1,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_register_agent_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_register_agent_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ const gchar *arg_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_call_unregister_agent (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_adapter_call_unregister_agent_finish (
+ OrgBluezAdapter *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_adapter_call_unregister_agent_sync (
+ OrgBluezAdapter *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error);
+
+
+
+/* ---- */
+
+#define TYPE_ORG_BLUEZ_ADAPTER_PROXY (org_bluez_adapter_proxy_get_type ())
+#define ORG_BLUEZ_ADAPTER_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_ORG_BLUEZ_ADAPTER_PROXY, OrgBluezAdapterProxy))
+#define ORG_BLUEZ_ADAPTER_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TYPE_ORG_BLUEZ_ADAPTER_PROXY, OrgBluezAdapterProxyClass))
+#define ORG_BLUEZ_ADAPTER_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_ORG_BLUEZ_ADAPTER_PROXY, OrgBluezAdapterProxyClass))
+#define IS_ORG_BLUEZ_ADAPTER_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_ORG_BLUEZ_ADAPTER_PROXY))
+#define IS_ORG_BLUEZ_ADAPTER_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_ORG_BLUEZ_ADAPTER_PROXY))
+
+typedef struct _OrgBluezAdapterProxy OrgBluezAdapterProxy;
+typedef struct _OrgBluezAdapterProxyClass OrgBluezAdapterProxyClass;
+typedef struct _OrgBluezAdapterProxyPrivate OrgBluezAdapterProxyPrivate;
+
+struct _OrgBluezAdapterProxy
+{
+ /*< private >*/
+ GDBusProxy parent_instance;
+ OrgBluezAdapterProxyPrivate *priv;
+};
+
+struct _OrgBluezAdapterProxyClass
+{
+ GDBusProxyClass parent_class;
+};
+
+GType org_bluez_adapter_proxy_get_type (void) G_GNUC_CONST;
+
+void org_bluez_adapter_proxy_new (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+OrgBluezAdapter *org_bluez_adapter_proxy_new_finish (
+ GAsyncResult *res,
+ GError **error);
+OrgBluezAdapter *org_bluez_adapter_proxy_new_sync (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_adapter_proxy_new_for_bus (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+OrgBluezAdapter *org_bluez_adapter_proxy_new_for_bus_finish (
+ GAsyncResult *res,
+ GError **error);
+OrgBluezAdapter *org_bluez_adapter_proxy_new_for_bus_sync (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error);
+
+
+/* ---- */
+
+#define TYPE_ORG_BLUEZ_ADAPTER_SKELETON (org_bluez_adapter_skeleton_get_type ())
+#define ORG_BLUEZ_ADAPTER_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_ORG_BLUEZ_ADAPTER_SKELETON, OrgBluezAdapterSkeleton))
+#define ORG_BLUEZ_ADAPTER_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TYPE_ORG_BLUEZ_ADAPTER_SKELETON, OrgBluezAdapterSkeletonClass))
+#define ORG_BLUEZ_ADAPTER_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_ORG_BLUEZ_ADAPTER_SKELETON, OrgBluezAdapterSkeletonClass))
+#define IS_ORG_BLUEZ_ADAPTER_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_ORG_BLUEZ_ADAPTER_SKELETON))
+#define IS_ORG_BLUEZ_ADAPTER_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_ORG_BLUEZ_ADAPTER_SKELETON))
+
+typedef struct _OrgBluezAdapterSkeleton OrgBluezAdapterSkeleton;
+typedef struct _OrgBluezAdapterSkeletonClass OrgBluezAdapterSkeletonClass;
+typedef struct _OrgBluezAdapterSkeletonPrivate OrgBluezAdapterSkeletonPrivate;
+
+struct _OrgBluezAdapterSkeleton
+{
+ /*< private >*/
+ GDBusInterfaceSkeleton parent_instance;
+ OrgBluezAdapterSkeletonPrivate *priv;
+};
+
+struct _OrgBluezAdapterSkeletonClass
+{
+ GDBusInterfaceSkeletonClass parent_class;
+};
+
+GType org_bluez_adapter_skeleton_get_type (void) G_GNUC_CONST;
+
+OrgBluezAdapter *org_bluez_adapter_skeleton_new (void);
+
+
+G_END_DECLS
+
+#endif /* __BLUETOOTHADAPTERPROXY_H__ */
diff --git a/plugins/common/bluetoothmanagerproxy.c b/plugins/common/bluetoothmanagerproxy.c
new file mode 100644
index 00000000..f4f0d147
--- /dev/null
+++ b/plugins/common/bluetoothmanagerproxy.c
@@ -0,0 +1,1941 @@
+/*
+ * Generated by gdbus-codegen 2.32.1. DO NOT EDIT.
+ *
+ * The license of this code is the same as for the source it was derived from.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "bluetoothmanagerproxy.h"
+
+#ifdef G_OS_UNIX
+# include <gio/gunixfdlist.h>
+#endif
+
+typedef struct
+{
+ GDBusArgInfo parent_struct;
+ gboolean use_gvariant;
+} _ExtendedGDBusArgInfo;
+
+typedef struct
+{
+ GDBusMethodInfo parent_struct;
+ const gchar *signal_name;
+ gboolean pass_fdlist;
+} _ExtendedGDBusMethodInfo;
+
+typedef struct
+{
+ GDBusSignalInfo parent_struct;
+ const gchar *signal_name;
+} _ExtendedGDBusSignalInfo;
+
+typedef struct
+{
+ GDBusPropertyInfo parent_struct;
+ const gchar *hyphen_name;
+ gboolean use_gvariant;
+} _ExtendedGDBusPropertyInfo;
+
+typedef struct
+{
+ GDBusInterfaceInfo parent_struct;
+ const gchar *hyphen_name;
+} _ExtendedGDBusInterfaceInfo;
+
+typedef struct
+{
+ const _ExtendedGDBusPropertyInfo *info;
+ guint prop_id;
+ GValue orig_value; /* the value before the change */
+} ChangedProperty;
+
+static void
+_changed_property_free (ChangedProperty *data)
+{
+ g_value_unset (&data->orig_value);
+ g_free (data);
+}
+
+static gboolean
+_g_strv_equal0 (gchar **a, gchar **b)
+{
+ gboolean ret = FALSE;
+ guint n;
+ if (a == NULL && b == NULL)
+ {
+ ret = TRUE;
+ goto out;
+ }
+ if (a == NULL || b == NULL)
+ goto out;
+ if (g_strv_length (a) != g_strv_length (b))
+ goto out;
+ for (n = 0; a[n] != NULL; n++)
+ if (g_strcmp0 (a[n], b[n]) != 0)
+ goto out;
+ ret = TRUE;
+out:
+ return ret;
+}
+
+static gboolean
+_g_variant_equal0 (GVariant *a, GVariant *b)
+{
+ gboolean ret = FALSE;
+ if (a == NULL && b == NULL)
+ {
+ ret = TRUE;
+ goto out;
+ }
+ if (a == NULL || b == NULL)
+ goto out;
+ ret = g_variant_equal (a, b);
+out:
+ return ret;
+}
+
+G_GNUC_UNUSED static gboolean
+_g_value_equal (const GValue *a, const GValue *b)
+{
+ gboolean ret = FALSE;
+ g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));
+ switch (G_VALUE_TYPE (a))
+ {
+ case G_TYPE_BOOLEAN:
+ ret = (g_value_get_boolean (a) == g_value_get_boolean (b));
+ break;
+ case G_TYPE_UCHAR:
+ ret = (g_value_get_uchar (a) == g_value_get_uchar (b));
+ break;
+ case G_TYPE_INT:
+ ret = (g_value_get_int (a) == g_value_get_int (b));
+ break;
+ case G_TYPE_UINT:
+ ret = (g_value_get_uint (a) == g_value_get_uint (b));
+ break;
+ case G_TYPE_INT64:
+ ret = (g_value_get_int64 (a) == g_value_get_int64 (b));
+ break;
+ case G_TYPE_UINT64:
+ ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));
+ break;
+ case G_TYPE_DOUBLE:
+ ret = (g_value_get_double (a) == g_value_get_double (b));
+ break;
+ case G_TYPE_STRING:
+ ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);
+ break;
+ case G_TYPE_VARIANT:
+ ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b));
+ break;
+ default:
+ if (G_VALUE_TYPE (a) == G_TYPE_STRV)
+ ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b));
+ else
+ g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a)));
+ break;
+ }
+ return ret;
+}
+
+/* ------------------------------------------------------------------------
+ * Code for interface org.bluez.Manager
+ * ------------------------------------------------------------------------
+ */
+
+/**
+ * SECTION:OrgBluezManager
+ * @title: OrgBluezManager
+ * @short_description: Generated C code for the org.bluez.Manager D-Bus interface
+ *
+ * This section contains code for working with the <link linkend="gdbus-interface-org-bluez-Manager.top_of_page">org.bluez.Manager</link> D-Bus interface in C.
+ */
+
+/* ---- Introspection data for org.bluez.Manager ---- */
+
+static const _ExtendedGDBusArgInfo _org_bluez_manager_method_info_get_properties_OUT_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "a{sv}",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_manager_method_info_get_properties_OUT_ARG_pointers[] =
+{
+ &_org_bluez_manager_method_info_get_properties_OUT_ARG_unnamed_arg0,
+ NULL
+};
+
+static const GDBusAnnotationInfo _org_bluez_manager_method_get_properties_annotation_info_0 =
+{
+ -1,
+ "com.trolltech.QtDBus.QtTypeName.Out0",
+ "QVariantMap",
+ NULL
+};
+
+static const GDBusAnnotationInfo * const _org_bluez_manager_method_get_properties_annotation_info_pointers[] =
+{
+ &_org_bluez_manager_method_get_properties_annotation_info_0,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_manager_method_info_get_properties =
+{
+ {
+ -1,
+ "GetProperties",
+ NULL,
+ (GDBusArgInfo **) &_org_bluez_manager_method_info_get_properties_OUT_ARG_pointers,
+ (GDBusAnnotationInfo **) &_org_bluez_manager_method_get_properties_annotation_info_pointers
+ },
+ "handle-get-properties",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_manager_method_info_default_adapter_OUT_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_manager_method_info_default_adapter_OUT_ARG_pointers[] =
+{
+ &_org_bluez_manager_method_info_default_adapter_OUT_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_manager_method_info_default_adapter =
+{
+ {
+ -1,
+ "DefaultAdapter",
+ NULL,
+ (GDBusArgInfo **) &_org_bluez_manager_method_info_default_adapter_OUT_ARG_pointers,
+ NULL
+ },
+ "handle-default-adapter",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_manager_method_info_find_adapter_IN_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_manager_method_info_find_adapter_IN_ARG_pointers[] =
+{
+ &_org_bluez_manager_method_info_find_adapter_IN_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_manager_method_info_find_adapter_OUT_ARG_unnamed_arg1 =
+{
+ {
+ -1,
+ "unnamed_arg1",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_manager_method_info_find_adapter_OUT_ARG_pointers[] =
+{
+ &_org_bluez_manager_method_info_find_adapter_OUT_ARG_unnamed_arg1,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_manager_method_info_find_adapter =
+{
+ {
+ -1,
+ "FindAdapter",
+ (GDBusArgInfo **) &_org_bluez_manager_method_info_find_adapter_IN_ARG_pointers,
+ (GDBusArgInfo **) &_org_bluez_manager_method_info_find_adapter_OUT_ARG_pointers,
+ NULL
+ },
+ "handle-find-adapter",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_manager_method_info_list_adapters_OUT_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "ao",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_manager_method_info_list_adapters_OUT_ARG_pointers[] =
+{
+ &_org_bluez_manager_method_info_list_adapters_OUT_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_manager_method_info_list_adapters =
+{
+ {
+ -1,
+ "ListAdapters",
+ NULL,
+ (GDBusArgInfo **) &_org_bluez_manager_method_info_list_adapters_OUT_ARG_pointers,
+ NULL
+ },
+ "handle-list-adapters",
+ FALSE
+};
+
+static const _ExtendedGDBusMethodInfo * const _org_bluez_manager_method_info_pointers[] =
+{
+ &_org_bluez_manager_method_info_get_properties,
+ &_org_bluez_manager_method_info_default_adapter,
+ &_org_bluez_manager_method_info_find_adapter,
+ &_org_bluez_manager_method_info_list_adapters,
+ NULL
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_manager_signal_info_property_changed_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_manager_signal_info_property_changed_ARG_unnamed_arg1 =
+{
+ {
+ -1,
+ "unnamed_arg1",
+ "v",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_manager_signal_info_property_changed_ARG_pointers[] =
+{
+ &_org_bluez_manager_signal_info_property_changed_ARG_unnamed_arg0,
+ &_org_bluez_manager_signal_info_property_changed_ARG_unnamed_arg1,
+ NULL
+};
+
+static const _ExtendedGDBusSignalInfo _org_bluez_manager_signal_info_property_changed =
+{
+ {
+ -1,
+ "PropertyChanged",
+ (GDBusArgInfo **) &_org_bluez_manager_signal_info_property_changed_ARG_pointers,
+ NULL
+ },
+ "property-changed"
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_manager_signal_info_adapter_added_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_manager_signal_info_adapter_added_ARG_pointers[] =
+{
+ &_org_bluez_manager_signal_info_adapter_added_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusSignalInfo _org_bluez_manager_signal_info_adapter_added =
+{
+ {
+ -1,
+ "AdapterAdded",
+ (GDBusArgInfo **) &_org_bluez_manager_signal_info_adapter_added_ARG_pointers,
+ NULL
+ },
+ "adapter-added"
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_manager_signal_info_adapter_removed_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_manager_signal_info_adapter_removed_ARG_pointers[] =
+{
+ &_org_bluez_manager_signal_info_adapter_removed_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusSignalInfo _org_bluez_manager_signal_info_adapter_removed =
+{
+ {
+ -1,
+ "AdapterRemoved",
+ (GDBusArgInfo **) &_org_bluez_manager_signal_info_adapter_removed_ARG_pointers,
+ NULL
+ },
+ "adapter-removed"
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_manager_signal_info_default_adapter_changed_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "o",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_manager_signal_info_default_adapter_changed_ARG_pointers[] =
+{
+ &_org_bluez_manager_signal_info_default_adapter_changed_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusSignalInfo _org_bluez_manager_signal_info_default_adapter_changed =
+{
+ {
+ -1,
+ "DefaultAdapterChanged",
+ (GDBusArgInfo **) &_org_bluez_manager_signal_info_default_adapter_changed_ARG_pointers,
+ NULL
+ },
+ "default-adapter-changed"
+};
+
+static const _ExtendedGDBusSignalInfo * const _org_bluez_manager_signal_info_pointers[] =
+{
+ &_org_bluez_manager_signal_info_property_changed,
+ &_org_bluez_manager_signal_info_adapter_added,
+ &_org_bluez_manager_signal_info_adapter_removed,
+ &_org_bluez_manager_signal_info_default_adapter_changed,
+ NULL
+};
+
+static const _ExtendedGDBusInterfaceInfo _org_bluez_manager_interface_info =
+{
+ {
+ -1,
+ "org.bluez.Manager",
+ (GDBusMethodInfo **) &_org_bluez_manager_method_info_pointers,
+ (GDBusSignalInfo **) &_org_bluez_manager_signal_info_pointers,
+ NULL,
+ NULL
+ },
+ "org-bluez-manager",
+};
+
+
+/**
+ * org_bluez_manager_interface_info:
+ *
+ * Gets a machine-readable description of the <link linkend="gdbus-interface-org-bluez-Manager.top_of_page">org.bluez.Manager</link> D-Bus interface.
+ *
+ * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free.
+ */
+GDBusInterfaceInfo *
+org_bluez_manager_interface_info (void)
+{
+ return (GDBusInterfaceInfo *) &_org_bluez_manager_interface_info;
+}
+
+/**
+ * org_bluez_manager_override_properties:
+ * @klass: The class structure for a #GObject<!-- -->-derived class.
+ * @property_id_begin: The property id to assign to the first overridden property.
+ *
+ * Overrides all #GObject properties in the #OrgBluezManager interface for a concrete class.
+ * The properties are overridden in the order they are defined.
+ *
+ * Returns: The last property id.
+ */
+guint
+org_bluez_manager_override_properties (GObjectClass *klass, guint property_id_begin)
+{
+ return property_id_begin - 1;
+}
+
+
+
+/**
+ * OrgBluezManager:
+ *
+ * Abstract interface type for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Manager.top_of_page">org.bluez.Manager</link>.
+ */
+
+/**
+ * OrgBluezManagerIface:
+ * @parent_iface: The parent interface.
+ * @handle_default_adapter: Handler for the #OrgBluezManager::handle-default-adapter signal.
+ * @handle_find_adapter: Handler for the #OrgBluezManager::handle-find-adapter signal.
+ * @handle_get_properties: Handler for the #OrgBluezManager::handle-get-properties signal.
+ * @handle_list_adapters: Handler for the #OrgBluezManager::handle-list-adapters signal.
+ * @adapter_added: Handler for the #OrgBluezManager::adapter-added signal.
+ * @adapter_removed: Handler for the #OrgBluezManager::adapter-removed signal.
+ * @default_adapter_changed: Handler for the #OrgBluezManager::default-adapter-changed signal.
+ * @property_changed: Handler for the #OrgBluezManager::property-changed signal.
+ *
+ * Virtual table for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Manager.top_of_page">org.bluez.Manager</link>.
+ */
+
+static void
+org_bluez_manager_default_init (OrgBluezManagerIface *iface)
+{
+ /* GObject signals for incoming D-Bus method calls: */
+ /**
+ * OrgBluezManager::handle-get-properties:
+ * @object: A #OrgBluezManager.
+ * @invocation: A #GDBusMethodInvocation.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Manager.GetProperties">GetProperties()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_manager_complete_get_properties() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-get-properties",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezManagerIface, handle_get_properties),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_DBUS_METHOD_INVOCATION);
+
+ /**
+ * OrgBluezManager::handle-default-adapter:
+ * @object: A #OrgBluezManager.
+ * @invocation: A #GDBusMethodInvocation.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Manager.DefaultAdapter">DefaultAdapter()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_manager_complete_default_adapter() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-default-adapter",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezManagerIface, handle_default_adapter),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_DBUS_METHOD_INVOCATION);
+
+ /**
+ * OrgBluezManager::handle-find-adapter:
+ * @object: A #OrgBluezManager.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_unnamed_arg0: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Manager.FindAdapter">FindAdapter()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_manager_complete_find_adapter() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-find-adapter",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezManagerIface, handle_find_adapter),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 2,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING);
+
+ /**
+ * OrgBluezManager::handle-list-adapters:
+ * @object: A #OrgBluezManager.
+ * @invocation: A #GDBusMethodInvocation.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Manager.ListAdapters">ListAdapters()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_manager_complete_list_adapters() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-list-adapters",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezManagerIface, handle_list_adapters),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_DBUS_METHOD_INVOCATION);
+
+ /* GObject signals for received D-Bus signals: */
+ /**
+ * OrgBluezManager::property-changed:
+ * @object: A #OrgBluezManager.
+ * @arg_unnamed_arg0: Argument.
+ * @arg_unnamed_arg1: Argument.
+ *
+ * On the client-side, this signal is emitted whenever the D-Bus signal <link linkend="gdbus-signal-org-bluez-Manager.PropertyChanged">"PropertyChanged"</link> is received.
+ *
+ * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.
+ */
+ g_signal_new ("property-changed",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezManagerIface, property_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 2, G_TYPE_STRING, G_TYPE_VARIANT);
+
+ /**
+ * OrgBluezManager::adapter-added:
+ * @object: A #OrgBluezManager.
+ * @arg_unnamed_arg0: Argument.
+ *
+ * On the client-side, this signal is emitted whenever the D-Bus signal <link linkend="gdbus-signal-org-bluez-Manager.AdapterAdded">"AdapterAdded"</link> is received.
+ *
+ * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.
+ */
+ g_signal_new ("adapter-added",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezManagerIface, adapter_added),
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+
+ /**
+ * OrgBluezManager::adapter-removed:
+ * @object: A #OrgBluezManager.
+ * @arg_unnamed_arg0: Argument.
+ *
+ * On the client-side, this signal is emitted whenever the D-Bus signal <link linkend="gdbus-signal-org-bluez-Manager.AdapterRemoved">"AdapterRemoved"</link> is received.
+ *
+ * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.
+ */
+ g_signal_new ("adapter-removed",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezManagerIface, adapter_removed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+
+ /**
+ * OrgBluezManager::default-adapter-changed:
+ * @object: A #OrgBluezManager.
+ * @arg_unnamed_arg0: Argument.
+ *
+ * On the client-side, this signal is emitted whenever the D-Bus signal <link linkend="gdbus-signal-org-bluez-Manager.DefaultAdapterChanged">"DefaultAdapterChanged"</link> is received.
+ *
+ * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.
+ */
+ g_signal_new ("default-adapter-changed",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezManagerIface, default_adapter_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+
+}
+
+typedef OrgBluezManagerIface OrgBluezManagerInterface;
+G_DEFINE_INTERFACE (OrgBluezManager, org_bluez_manager, G_TYPE_OBJECT);
+
+/**
+ * org_bluez_manager_emit_property_changed:
+ * @object: A #OrgBluezManager.
+ * @arg_unnamed_arg0: Argument to pass with the signal.
+ * @arg_unnamed_arg1: Argument to pass with the signal.
+ *
+ * Emits the <link linkend="gdbus-signal-org-bluez-Manager.PropertyChanged">"PropertyChanged"</link> D-Bus signal.
+ */
+void
+org_bluez_manager_emit_property_changed (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1)
+{
+ g_signal_emit_by_name (object, "property-changed", arg_unnamed_arg0, arg_unnamed_arg1);
+}
+
+/**
+ * org_bluez_manager_emit_adapter_added:
+ * @object: A #OrgBluezManager.
+ * @arg_unnamed_arg0: Argument to pass with the signal.
+ *
+ * Emits the <link linkend="gdbus-signal-org-bluez-Manager.AdapterAdded">"AdapterAdded"</link> D-Bus signal.
+ */
+void
+org_bluez_manager_emit_adapter_added (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0)
+{
+ g_signal_emit_by_name (object, "adapter-added", arg_unnamed_arg0);
+}
+
+/**
+ * org_bluez_manager_emit_adapter_removed:
+ * @object: A #OrgBluezManager.
+ * @arg_unnamed_arg0: Argument to pass with the signal.
+ *
+ * Emits the <link linkend="gdbus-signal-org-bluez-Manager.AdapterRemoved">"AdapterRemoved"</link> D-Bus signal.
+ */
+void
+org_bluez_manager_emit_adapter_removed (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0)
+{
+ g_signal_emit_by_name (object, "adapter-removed", arg_unnamed_arg0);
+}
+
+/**
+ * org_bluez_manager_emit_default_adapter_changed:
+ * @object: A #OrgBluezManager.
+ * @arg_unnamed_arg0: Argument to pass with the signal.
+ *
+ * Emits the <link linkend="gdbus-signal-org-bluez-Manager.DefaultAdapterChanged">"DefaultAdapterChanged"</link> D-Bus signal.
+ */
+void
+org_bluez_manager_emit_default_adapter_changed (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0)
+{
+ g_signal_emit_by_name (object, "default-adapter-changed", arg_unnamed_arg0);
+}
+
+/**
+ * org_bluez_manager_call_get_properties:
+ * @proxy: A #OrgBluezManagerProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Manager.GetProperties">GetProperties()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_manager_call_get_properties_finish() to get the result of the operation.
+ *
+ * See org_bluez_manager_call_get_properties_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_manager_call_get_properties (
+ OrgBluezManager *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "GetProperties",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_manager_call_get_properties_finish:
+ * @proxy: A #OrgBluezManagerProxy.
+ * @out_unnamed_arg0: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_manager_call_get_properties().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_manager_call_get_properties().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_manager_call_get_properties_finish (
+ OrgBluezManager *proxy,
+ GVariant **out_unnamed_arg0,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(@a{sv})",
+ out_unnamed_arg0);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_manager_call_get_properties_sync:
+ * @proxy: A #OrgBluezManagerProxy.
+ * @out_unnamed_arg0: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Manager.GetProperties">GetProperties()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_manager_call_get_properties() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_manager_call_get_properties_sync (
+ OrgBluezManager *proxy,
+ GVariant **out_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "GetProperties",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(@a{sv})",
+ out_unnamed_arg0);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_manager_call_default_adapter:
+ * @proxy: A #OrgBluezManagerProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Manager.DefaultAdapter">DefaultAdapter()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_manager_call_default_adapter_finish() to get the result of the operation.
+ *
+ * See org_bluez_manager_call_default_adapter_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_manager_call_default_adapter (
+ OrgBluezManager *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "DefaultAdapter",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_manager_call_default_adapter_finish:
+ * @proxy: A #OrgBluezManagerProxy.
+ * @out_unnamed_arg0: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_manager_call_default_adapter().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_manager_call_default_adapter().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_manager_call_default_adapter_finish (
+ OrgBluezManager *proxy,
+ gchar **out_unnamed_arg0,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(o)",
+ out_unnamed_arg0);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_manager_call_default_adapter_sync:
+ * @proxy: A #OrgBluezManagerProxy.
+ * @out_unnamed_arg0: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Manager.DefaultAdapter">DefaultAdapter()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_manager_call_default_adapter() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_manager_call_default_adapter_sync (
+ OrgBluezManager *proxy,
+ gchar **out_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "DefaultAdapter",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(o)",
+ out_unnamed_arg0);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_manager_call_find_adapter:
+ * @proxy: A #OrgBluezManagerProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Manager.FindAdapter">FindAdapter()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_manager_call_find_adapter_finish() to get the result of the operation.
+ *
+ * See org_bluez_manager_call_find_adapter_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_manager_call_find_adapter (
+ OrgBluezManager *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "FindAdapter",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_manager_call_find_adapter_finish:
+ * @proxy: A #OrgBluezManagerProxy.
+ * @out_unnamed_arg1: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_manager_call_find_adapter().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_manager_call_find_adapter().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_manager_call_find_adapter_finish (
+ OrgBluezManager *proxy,
+ gchar **out_unnamed_arg1,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(o)",
+ out_unnamed_arg1);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_manager_call_find_adapter_sync:
+ * @proxy: A #OrgBluezManagerProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @out_unnamed_arg1: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Manager.FindAdapter">FindAdapter()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_manager_call_find_adapter() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_manager_call_find_adapter_sync (
+ OrgBluezManager *proxy,
+ const gchar *arg_unnamed_arg0,
+ gchar **out_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "FindAdapter",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(o)",
+ out_unnamed_arg1);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_manager_call_list_adapters:
+ * @proxy: A #OrgBluezManagerProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Manager.ListAdapters">ListAdapters()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_manager_call_list_adapters_finish() to get the result of the operation.
+ *
+ * See org_bluez_manager_call_list_adapters_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_manager_call_list_adapters (
+ OrgBluezManager *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "ListAdapters",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_manager_call_list_adapters_finish:
+ * @proxy: A #OrgBluezManagerProxy.
+ * @out_unnamed_arg0: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_manager_call_list_adapters().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_manager_call_list_adapters().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_manager_call_list_adapters_finish (
+ OrgBluezManager *proxy,
+ gchar ***out_unnamed_arg0,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(^ao)",
+ out_unnamed_arg0);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_manager_call_list_adapters_sync:
+ * @proxy: A #OrgBluezManagerProxy.
+ * @out_unnamed_arg0: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Manager.ListAdapters">ListAdapters()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_manager_call_list_adapters() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_manager_call_list_adapters_sync (
+ OrgBluezManager *proxy,
+ gchar ***out_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "ListAdapters",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(^ao)",
+ out_unnamed_arg0);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_manager_complete_get_properties:
+ * @object: A #OrgBluezManager.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @unnamed_arg0: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Manager.GetProperties">GetProperties()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_manager_complete_get_properties (
+ OrgBluezManager *object,
+ GDBusMethodInvocation *invocation,
+ GVariant *unnamed_arg0)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(@a{sv})",
+ unnamed_arg0));
+}
+
+/**
+ * org_bluez_manager_complete_default_adapter:
+ * @object: A #OrgBluezManager.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @unnamed_arg0: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Manager.DefaultAdapter">DefaultAdapter()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_manager_complete_default_adapter (
+ OrgBluezManager *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *unnamed_arg0)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(o)",
+ unnamed_arg0));
+}
+
+/**
+ * org_bluez_manager_complete_find_adapter:
+ * @object: A #OrgBluezManager.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @unnamed_arg1: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Manager.FindAdapter">FindAdapter()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_manager_complete_find_adapter (
+ OrgBluezManager *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *unnamed_arg1)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(o)",
+ unnamed_arg1));
+}
+
+/**
+ * org_bluez_manager_complete_list_adapters:
+ * @object: A #OrgBluezManager.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @unnamed_arg0: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Manager.ListAdapters">ListAdapters()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_manager_complete_list_adapters (
+ OrgBluezManager *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *const *unnamed_arg0)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(^ao)",
+ unnamed_arg0));
+}
+
+/* ------------------------------------------------------------------------ */
+
+/**
+ * OrgBluezManagerProxy:
+ *
+ * The #OrgBluezManagerProxy structure contains only private data and should only be accessed using the provided API.
+ */
+
+/**
+ * OrgBluezManagerProxyClass:
+ * @parent_class: The parent class.
+ *
+ * Class structure for #OrgBluezManagerProxy.
+ */
+
+struct _OrgBluezManagerProxyPrivate
+{
+ GData *qdata;
+};
+
+static void org_bluez_manager_proxy_iface_init (OrgBluezManagerIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (OrgBluezManagerProxy, org_bluez_manager_proxy, G_TYPE_DBUS_PROXY,
+ G_IMPLEMENT_INTERFACE (TYPE_ORG_BLUEZ_MANAGER, org_bluez_manager_proxy_iface_init));
+
+static void
+org_bluez_manager_proxy_finalize (GObject *object)
+{
+ OrgBluezManagerProxy *proxy = ORG_BLUEZ_MANAGER_PROXY (object);
+ g_datalist_clear (&proxy->priv->qdata);
+ G_OBJECT_CLASS (org_bluez_manager_proxy_parent_class)->finalize (object);
+}
+
+static void
+org_bluez_manager_proxy_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+}
+
+static void
+org_bluez_manager_proxy_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+}
+
+static void
+org_bluez_manager_proxy_g_signal (GDBusProxy *proxy,
+ const gchar *sender_name,
+ const gchar *signal_name,
+ GVariant *parameters)
+{
+ _ExtendedGDBusSignalInfo *info;
+ GVariantIter iter;
+ GVariant *child;
+ GValue *paramv;
+ guint num_params;
+ guint n;
+ guint signal_id;
+ info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_org_bluez_manager_interface_info, signal_name);
+ if (info == NULL)
+ return;
+ num_params = g_variant_n_children (parameters);
+ paramv = g_new0 (GValue, num_params + 1);
+ g_value_init (&paramv[0], TYPE_ORG_BLUEZ_MANAGER);
+ g_value_set_object (&paramv[0], proxy);
+ g_variant_iter_init (&iter, parameters);
+ n = 1;
+ while ((child = g_variant_iter_next_value (&iter)) != NULL)
+ {
+ _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1];
+ if (arg_info->use_gvariant)
+ {
+ g_value_init (&paramv[n], G_TYPE_VARIANT);
+ g_value_set_variant (&paramv[n], child);
+ n++;
+ }
+ else
+ g_dbus_gvariant_to_gvalue (child, &paramv[n++]);
+ g_variant_unref (child);
+ }
+ signal_id = g_signal_lookup (info->signal_name, TYPE_ORG_BLUEZ_MANAGER);
+ g_signal_emitv (paramv, signal_id, 0, NULL);
+ for (n = 0; n < num_params + 1; n++)
+ g_value_unset (&paramv[n]);
+ g_free (paramv);
+}
+
+static void
+org_bluez_manager_proxy_g_properties_changed (GDBusProxy *_proxy,
+ GVariant *changed_properties,
+ const gchar *const *invalidated_properties)
+{
+ OrgBluezManagerProxy *proxy = ORG_BLUEZ_MANAGER_PROXY (_proxy);
+ guint n;
+ const gchar *key;
+ GVariantIter *iter;
+ _ExtendedGDBusPropertyInfo *info;
+ g_variant_get (changed_properties, "a{sv}", &iter);
+ while (g_variant_iter_next (iter, "{&sv}", &key, NULL))
+ {
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_org_bluez_manager_interface_info, key);
+ g_datalist_remove_data (&proxy->priv->qdata, key);
+ if (info != NULL)
+ g_object_notify (G_OBJECT (proxy), info->hyphen_name);
+ }
+ g_variant_iter_free (iter);
+ for (n = 0; invalidated_properties[n] != NULL; n++)
+ {
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_org_bluez_manager_interface_info, invalidated_properties[n]);
+ g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]);
+ if (info != NULL)
+ g_object_notify (G_OBJECT (proxy), info->hyphen_name);
+ }
+}
+
+static void
+org_bluez_manager_proxy_init (OrgBluezManagerProxy *proxy)
+{
+ proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, TYPE_ORG_BLUEZ_MANAGER_PROXY, OrgBluezManagerProxyPrivate);
+ g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), org_bluez_manager_interface_info ());
+}
+
+static void
+org_bluez_manager_proxy_class_init (OrgBluezManagerProxyClass *klass)
+{
+ GObjectClass *gobject_class;
+ GDBusProxyClass *proxy_class;
+
+ g_type_class_add_private (klass, sizeof (OrgBluezManagerProxyPrivate));
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = org_bluez_manager_proxy_finalize;
+ gobject_class->get_property = org_bluez_manager_proxy_get_property;
+ gobject_class->set_property = org_bluez_manager_proxy_set_property;
+
+ proxy_class = G_DBUS_PROXY_CLASS (klass);
+ proxy_class->g_signal = org_bluez_manager_proxy_g_signal;
+ proxy_class->g_properties_changed = org_bluez_manager_proxy_g_properties_changed;
+
+}
+
+static void
+org_bluez_manager_proxy_iface_init (OrgBluezManagerIface *iface)
+{
+}
+
+/**
+ * org_bluez_manager_proxy_new:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: (allow-none): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously creates a proxy for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Manager.top_of_page">org.bluez.Manager</link>. See g_dbus_proxy_new() for more details.
+ *
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_manager_proxy_new_finish() to get the result of the operation.
+ *
+ * See org_bluez_manager_proxy_new_sync() for the synchronous, blocking version of this constructor.
+ */
+void
+org_bluez_manager_proxy_new (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_async_initable_new_async (TYPE_ORG_BLUEZ_MANAGER_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.bluez.Manager", NULL);
+}
+
+/**
+ * org_bluez_manager_proxy_new_finish:
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_manager_proxy_new().
+ * @error: Return location for error or %NULL
+ *
+ * Finishes an operation started with org_bluez_manager_proxy_new().
+ *
+ * Returns: (transfer full) (type OrgBluezManagerProxy): The constructed proxy object or %NULL if @error is set.
+ */
+OrgBluezManager *
+org_bluez_manager_proxy_new_finish (
+ GAsyncResult *res,
+ GError **error)
+{
+ GObject *ret;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (res);
+ ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
+ g_object_unref (source_object);
+ if (ret != NULL)
+ return ORG_BLUEZ_MANAGER (ret);
+ else
+ return NULL;
+}
+
+/**
+ * org_bluez_manager_proxy_new_sync:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: (allow-none): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL
+ *
+ * Synchronously creates a proxy for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Manager.top_of_page">org.bluez.Manager</link>. See g_dbus_proxy_new_sync() for more details.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_manager_proxy_new() for the asynchronous version of this constructor.
+ *
+ * Returns: (transfer full) (type OrgBluezManagerProxy): The constructed proxy object or %NULL if @error is set.
+ */
+OrgBluezManager *
+org_bluez_manager_proxy_new_sync (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GInitable *ret;
+ ret = g_initable_new (TYPE_ORG_BLUEZ_MANAGER_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.bluez.Manager", NULL);
+ if (ret != NULL)
+ return ORG_BLUEZ_MANAGER (ret);
+ else
+ return NULL;
+}
+
+
+/**
+ * org_bluez_manager_proxy_new_for_bus:
+ * @bus_type: A #GBusType.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like org_bluez_manager_proxy_new() but takes a #GBusType instead of a #GDBusConnection.
+ *
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_manager_proxy_new_for_bus_finish() to get the result of the operation.
+ *
+ * See org_bluez_manager_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor.
+ */
+void
+org_bluez_manager_proxy_new_for_bus (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_async_initable_new_async (TYPE_ORG_BLUEZ_MANAGER_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.bluez.Manager", NULL);
+}
+
+/**
+ * org_bluez_manager_proxy_new_for_bus_finish:
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_manager_proxy_new_for_bus().
+ * @error: Return location for error or %NULL
+ *
+ * Finishes an operation started with org_bluez_manager_proxy_new_for_bus().
+ *
+ * Returns: (transfer full) (type OrgBluezManagerProxy): The constructed proxy object or %NULL if @error is set.
+ */
+OrgBluezManager *
+org_bluez_manager_proxy_new_for_bus_finish (
+ GAsyncResult *res,
+ GError **error)
+{
+ GObject *ret;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (res);
+ ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
+ g_object_unref (source_object);
+ if (ret != NULL)
+ return ORG_BLUEZ_MANAGER (ret);
+ else
+ return NULL;
+}
+
+/**
+ * org_bluez_manager_proxy_new_for_bus_sync:
+ * @bus_type: A #GBusType.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL
+ *
+ * Like org_bluez_manager_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_manager_proxy_new_for_bus() for the asynchronous version of this constructor.
+ *
+ * Returns: (transfer full) (type OrgBluezManagerProxy): The constructed proxy object or %NULL if @error is set.
+ */
+OrgBluezManager *
+org_bluez_manager_proxy_new_for_bus_sync (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GInitable *ret;
+ ret = g_initable_new (TYPE_ORG_BLUEZ_MANAGER_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.bluez.Manager", NULL);
+ if (ret != NULL)
+ return ORG_BLUEZ_MANAGER (ret);
+ else
+ return NULL;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+/**
+ * OrgBluezManagerSkeleton:
+ *
+ * The #OrgBluezManagerSkeleton structure contains only private data and should only be accessed using the provided API.
+ */
+
+/**
+ * OrgBluezManagerSkeletonClass:
+ * @parent_class: The parent class.
+ *
+ * Class structure for #OrgBluezManagerSkeleton.
+ */
+
+struct _OrgBluezManagerSkeletonPrivate
+{
+ GValue *properties;
+ GList *changed_properties;
+ GSource *changed_properties_idle_source;
+ GMainContext *context;
+ GMutex lock;
+};
+
+static void
+_org_bluez_manager_skeleton_handle_method_call (
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ OrgBluezManagerSkeleton *skeleton = ORG_BLUEZ_MANAGER_SKELETON (user_data);
+ _ExtendedGDBusMethodInfo *info;
+ GVariantIter iter;
+ GVariant *child;
+ GValue *paramv;
+ guint num_params;
+ guint num_extra;
+ guint n;
+ guint signal_id;
+ GValue return_value = G_VALUE_INIT;
+ info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation);
+ g_assert (info != NULL);
+ num_params = g_variant_n_children (parameters);
+ num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra);
+ n = 0;
+ g_value_init (&paramv[n], TYPE_ORG_BLUEZ_MANAGER);
+ g_value_set_object (&paramv[n++], skeleton);
+ g_value_init (&paramv[n], G_TYPE_DBUS_METHOD_INVOCATION);
+ g_value_set_object (&paramv[n++], invocation);
+ if (info->pass_fdlist)
+ {
+#ifdef G_OS_UNIX
+ g_value_init (&paramv[n], G_TYPE_UNIX_FD_LIST);
+ g_value_set_object (&paramv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation)));
+#else
+ g_assert_not_reached ();
+#endif
+ }
+ g_variant_iter_init (&iter, parameters);
+ while ((child = g_variant_iter_next_value (&iter)) != NULL)
+ {
+ _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra];
+ if (arg_info->use_gvariant)
+ {
+ g_value_init (&paramv[n], G_TYPE_VARIANT);
+ g_value_set_variant (&paramv[n], child);
+ n++;
+ }
+ else
+ g_dbus_gvariant_to_gvalue (child, &paramv[n++]);
+ g_variant_unref (child);
+ }
+ signal_id = g_signal_lookup (info->signal_name, TYPE_ORG_BLUEZ_MANAGER);
+ g_value_init (&return_value, G_TYPE_BOOLEAN);
+ g_signal_emitv (paramv, signal_id, 0, &return_value);
+ if (!g_value_get_boolean (&return_value))
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name);
+ g_value_unset (&return_value);
+ for (n = 0; n < num_params + num_extra; n++)
+ g_value_unset (&paramv[n]);
+ g_free (paramv);
+}
+
+static GVariant *
+_org_bluez_manager_skeleton_handle_get_property (
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GError **error,
+ gpointer user_data)
+{
+ OrgBluezManagerSkeleton *skeleton = ORG_BLUEZ_MANAGER_SKELETON (user_data);
+ GValue value = G_VALUE_INIT;
+ GParamSpec *pspec;
+ _ExtendedGDBusPropertyInfo *info;
+ GVariant *ret;
+ ret = NULL;
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_org_bluez_manager_interface_info, property_name);
+ g_assert (info != NULL);
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
+ if (pspec == NULL)
+ {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
+ }
+ else
+ {
+ g_value_init (&value, pspec->value_type);
+ g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value);
+ ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature));
+ g_value_unset (&value);
+ }
+ return ret;
+}
+
+static gboolean
+_org_bluez_manager_skeleton_handle_set_property (
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GVariant *variant,
+ GError **error,
+ gpointer user_data)
+{
+ OrgBluezManagerSkeleton *skeleton = ORG_BLUEZ_MANAGER_SKELETON (user_data);
+ GValue value = G_VALUE_INIT;
+ GParamSpec *pspec;
+ _ExtendedGDBusPropertyInfo *info;
+ gboolean ret;
+ ret = FALSE;
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_org_bluez_manager_interface_info, property_name);
+ g_assert (info != NULL);
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
+ if (pspec == NULL)
+ {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
+ }
+ else
+ {
+ if (info->use_gvariant)
+ g_value_set_variant (&value, variant);
+ else
+ g_dbus_gvariant_to_gvalue (variant, &value);
+ g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value);
+ g_value_unset (&value);
+ ret = TRUE;
+ }
+ return ret;
+}
+
+static const GDBusInterfaceVTable _org_bluez_manager_skeleton_vtable =
+{
+ _org_bluez_manager_skeleton_handle_method_call,
+ _org_bluez_manager_skeleton_handle_get_property,
+ _org_bluez_manager_skeleton_handle_set_property
+};
+
+static GDBusInterfaceInfo *
+org_bluez_manager_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton)
+{
+ return org_bluez_manager_interface_info ();
+}
+
+static GDBusInterfaceVTable *
+org_bluez_manager_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton)
+{
+ return (GDBusInterfaceVTable *) &_org_bluez_manager_skeleton_vtable;
+}
+
+static GVariant *
+org_bluez_manager_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton)
+{
+ OrgBluezManagerSkeleton *skeleton = ORG_BLUEZ_MANAGER_SKELETON (_skeleton);
+
+ GVariantBuilder builder;
+ guint n;
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ if (_org_bluez_manager_interface_info.parent_struct.properties == NULL)
+ goto out;
+ for (n = 0; _org_bluez_manager_interface_info.parent_struct.properties[n] != NULL; n++)
+ {
+ GDBusPropertyInfo *info = _org_bluez_manager_interface_info.parent_struct.properties[n];
+ if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
+ {
+ GVariant *value;
+ value = _org_bluez_manager_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.bluez.Manager", info->name, NULL, skeleton);
+ if (value != NULL)
+ {
+ g_variant_take_ref (value);
+ g_variant_builder_add (&builder, "{sv}", info->name, value);
+ g_variant_unref (value);
+ }
+ }
+ }
+out:
+ return g_variant_builder_end (&builder);
+}
+
+static void
+org_bluez_manager_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton)
+{
+}
+
+static void
+_org_bluez_manager_on_signal_property_changed (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1)
+{
+ OrgBluezManagerSkeleton *skeleton = ORG_BLUEZ_MANAGER_SKELETON (object);
+
+ GList *connections, *l;
+ GVariant *signal_variant;
+ connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
+
+ signal_variant = g_variant_ref_sink (g_variant_new ("(s@v)",
+ arg_unnamed_arg0,
+ arg_unnamed_arg1));
+ for (l = connections; l != NULL; l = l->next)
+ {
+ GDBusConnection *connection = l->data;
+ g_dbus_connection_emit_signal (connection,
+ NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.bluez.Manager", "PropertyChanged",
+ signal_variant, NULL);
+ }
+ g_variant_unref (signal_variant);
+ g_list_free_full (connections, g_object_unref);
+}
+
+static void
+_org_bluez_manager_on_signal_adapter_added (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0)
+{
+ OrgBluezManagerSkeleton *skeleton = ORG_BLUEZ_MANAGER_SKELETON (object);
+
+ GList *connections, *l;
+ GVariant *signal_variant;
+ connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
+
+ signal_variant = g_variant_ref_sink (g_variant_new ("(o)",
+ arg_unnamed_arg0));
+ for (l = connections; l != NULL; l = l->next)
+ {
+ GDBusConnection *connection = l->data;
+ g_dbus_connection_emit_signal (connection,
+ NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.bluez.Manager", "AdapterAdded",
+ signal_variant, NULL);
+ }
+ g_variant_unref (signal_variant);
+ g_list_free_full (connections, g_object_unref);
+}
+
+static void
+_org_bluez_manager_on_signal_adapter_removed (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0)
+{
+ OrgBluezManagerSkeleton *skeleton = ORG_BLUEZ_MANAGER_SKELETON (object);
+
+ GList *connections, *l;
+ GVariant *signal_variant;
+ connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
+
+ signal_variant = g_variant_ref_sink (g_variant_new ("(o)",
+ arg_unnamed_arg0));
+ for (l = connections; l != NULL; l = l->next)
+ {
+ GDBusConnection *connection = l->data;
+ g_dbus_connection_emit_signal (connection,
+ NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.bluez.Manager", "AdapterRemoved",
+ signal_variant, NULL);
+ }
+ g_variant_unref (signal_variant);
+ g_list_free_full (connections, g_object_unref);
+}
+
+static void
+_org_bluez_manager_on_signal_default_adapter_changed (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0)
+{
+ OrgBluezManagerSkeleton *skeleton = ORG_BLUEZ_MANAGER_SKELETON (object);
+
+ GList *connections, *l;
+ GVariant *signal_variant;
+ connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
+
+ signal_variant = g_variant_ref_sink (g_variant_new ("(o)",
+ arg_unnamed_arg0));
+ for (l = connections; l != NULL; l = l->next)
+ {
+ GDBusConnection *connection = l->data;
+ g_dbus_connection_emit_signal (connection,
+ NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.bluez.Manager", "DefaultAdapterChanged",
+ signal_variant, NULL);
+ }
+ g_variant_unref (signal_variant);
+ g_list_free_full (connections, g_object_unref);
+}
+
+static void org_bluez_manager_skeleton_iface_init (OrgBluezManagerIface *iface);
+G_DEFINE_TYPE_WITH_CODE (OrgBluezManagerSkeleton, org_bluez_manager_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,
+ G_IMPLEMENT_INTERFACE (TYPE_ORG_BLUEZ_MANAGER, org_bluez_manager_skeleton_iface_init));
+
+static void
+org_bluez_manager_skeleton_finalize (GObject *object)
+{
+ OrgBluezManagerSkeleton *skeleton = ORG_BLUEZ_MANAGER_SKELETON (object);
+ g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);
+ if (skeleton->priv->changed_properties_idle_source != NULL)
+ g_source_destroy (skeleton->priv->changed_properties_idle_source);
+ g_main_context_unref (skeleton->priv->context);
+ g_mutex_clear (&skeleton->priv->lock);
+ G_OBJECT_CLASS (org_bluez_manager_skeleton_parent_class)->finalize (object);
+}
+
+static void
+org_bluez_manager_skeleton_init (OrgBluezManagerSkeleton *skeleton)
+{
+ skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, TYPE_ORG_BLUEZ_MANAGER_SKELETON, OrgBluezManagerSkeletonPrivate);
+ g_mutex_init (&skeleton->priv->lock);
+ skeleton->priv->context = g_main_context_ref_thread_default ();
+}
+
+static void
+org_bluez_manager_skeleton_class_init (OrgBluezManagerSkeletonClass *klass)
+{
+ GObjectClass *gobject_class;
+ GDBusInterfaceSkeletonClass *skeleton_class;
+
+ g_type_class_add_private (klass, sizeof (OrgBluezManagerSkeletonPrivate));
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = org_bluez_manager_skeleton_finalize;
+
+ skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
+ skeleton_class->get_info = org_bluez_manager_skeleton_dbus_interface_get_info;
+ skeleton_class->get_properties = org_bluez_manager_skeleton_dbus_interface_get_properties;
+ skeleton_class->flush = org_bluez_manager_skeleton_dbus_interface_flush;
+ skeleton_class->get_vtable = org_bluez_manager_skeleton_dbus_interface_get_vtable;
+}
+
+static void
+org_bluez_manager_skeleton_iface_init (OrgBluezManagerIface *iface)
+{
+ iface->property_changed = _org_bluez_manager_on_signal_property_changed;
+ iface->adapter_added = _org_bluez_manager_on_signal_adapter_added;
+ iface->adapter_removed = _org_bluez_manager_on_signal_adapter_removed;
+ iface->default_adapter_changed = _org_bluez_manager_on_signal_default_adapter_changed;
+}
+
+/**
+ * org_bluez_manager_skeleton_new:
+ *
+ * Creates a skeleton object for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Manager.top_of_page">org.bluez.Manager</link>.
+ *
+ * Returns: (transfer full) (type OrgBluezManagerSkeleton): The skeleton object.
+ */
+OrgBluezManager *
+org_bluez_manager_skeleton_new (void)
+{
+ return ORG_BLUEZ_MANAGER (g_object_new (TYPE_ORG_BLUEZ_MANAGER_SKELETON, NULL));
+}
+
diff --git a/plugins/common/bluetoothmanagerproxy.h b/plugins/common/bluetoothmanagerproxy.h
new file mode 100644
index 00000000..fd9b02fd
--- /dev/null
+++ b/plugins/common/bluetoothmanagerproxy.h
@@ -0,0 +1,292 @@
+/*
+ * Generated by gdbus-codegen 2.32.1. DO NOT EDIT.
+ *
+ * The license of this code is the same as for the source it was derived from.
+ */
+
+#ifndef __BLUETOOTHMANAGERPROXY_H__
+#define __BLUETOOTHMANAGERPROXY_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+
+/* ------------------------------------------------------------------------ */
+/* Declarations for org.bluez.Manager */
+
+#define TYPE_ORG_BLUEZ_MANAGER (org_bluez_manager_get_type ())
+#define ORG_BLUEZ_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_ORG_BLUEZ_MANAGER, OrgBluezManager))
+#define IS_ORG_BLUEZ_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_ORG_BLUEZ_MANAGER))
+#define ORG_BLUEZ_MANAGER_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), TYPE_ORG_BLUEZ_MANAGER, OrgBluezManagerIface))
+
+struct _OrgBluezManager;
+typedef struct _OrgBluezManager OrgBluezManager;
+typedef struct _OrgBluezManagerIface OrgBluezManagerIface;
+
+struct _OrgBluezManagerIface
+{
+ GTypeInterface parent_iface;
+
+
+ gboolean (*handle_default_adapter) (
+ OrgBluezManager *object,
+ GDBusMethodInvocation *invocation);
+
+ gboolean (*handle_find_adapter) (
+ OrgBluezManager *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_unnamed_arg0);
+
+ gboolean (*handle_get_properties) (
+ OrgBluezManager *object,
+ GDBusMethodInvocation *invocation);
+
+ gboolean (*handle_list_adapters) (
+ OrgBluezManager *object,
+ GDBusMethodInvocation *invocation);
+
+ void (*adapter_added) (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0);
+
+ void (*adapter_removed) (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0);
+
+ void (*default_adapter_changed) (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0);
+
+ void (*property_changed) (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1);
+
+};
+
+GType org_bluez_manager_get_type (void) G_GNUC_CONST;
+
+GDBusInterfaceInfo *org_bluez_manager_interface_info (void);
+guint org_bluez_manager_override_properties (GObjectClass *klass, guint property_id_begin);
+
+
+/* D-Bus method call completion functions: */
+void org_bluez_manager_complete_get_properties (
+ OrgBluezManager *object,
+ GDBusMethodInvocation *invocation,
+ GVariant *unnamed_arg0);
+
+void org_bluez_manager_complete_default_adapter (
+ OrgBluezManager *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *unnamed_arg0);
+
+void org_bluez_manager_complete_find_adapter (
+ OrgBluezManager *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *unnamed_arg1);
+
+void org_bluez_manager_complete_list_adapters (
+ OrgBluezManager *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *const *unnamed_arg0);
+
+
+
+/* D-Bus signal emissions functions: */
+void org_bluez_manager_emit_property_changed (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0,
+ GVariant *arg_unnamed_arg1);
+
+void org_bluez_manager_emit_adapter_added (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0);
+
+void org_bluez_manager_emit_adapter_removed (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0);
+
+void org_bluez_manager_emit_default_adapter_changed (
+ OrgBluezManager *object,
+ const gchar *arg_unnamed_arg0);
+
+
+
+/* D-Bus method calls: */
+void org_bluez_manager_call_get_properties (
+ OrgBluezManager *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_manager_call_get_properties_finish (
+ OrgBluezManager *proxy,
+ GVariant **out_unnamed_arg0,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_manager_call_get_properties_sync (
+ OrgBluezManager *proxy,
+ GVariant **out_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_manager_call_default_adapter (
+ OrgBluezManager *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_manager_call_default_adapter_finish (
+ OrgBluezManager *proxy,
+ gchar **out_unnamed_arg0,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_manager_call_default_adapter_sync (
+ OrgBluezManager *proxy,
+ gchar **out_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_manager_call_find_adapter (
+ OrgBluezManager *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_manager_call_find_adapter_finish (
+ OrgBluezManager *proxy,
+ gchar **out_unnamed_arg1,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_manager_call_find_adapter_sync (
+ OrgBluezManager *proxy,
+ const gchar *arg_unnamed_arg0,
+ gchar **out_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_manager_call_list_adapters (
+ OrgBluezManager *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_manager_call_list_adapters_finish (
+ OrgBluezManager *proxy,
+ gchar ***out_unnamed_arg0,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_manager_call_list_adapters_sync (
+ OrgBluezManager *proxy,
+ gchar ***out_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error);
+
+
+
+/* ---- */
+
+#define TYPE_ORG_BLUEZ_MANAGER_PROXY (org_bluez_manager_proxy_get_type ())
+#define ORG_BLUEZ_MANAGER_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_ORG_BLUEZ_MANAGER_PROXY, OrgBluezManagerProxy))
+#define ORG_BLUEZ_MANAGER_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TYPE_ORG_BLUEZ_MANAGER_PROXY, OrgBluezManagerProxyClass))
+#define ORG_BLUEZ_MANAGER_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_ORG_BLUEZ_MANAGER_PROXY, OrgBluezManagerProxyClass))
+#define IS_ORG_BLUEZ_MANAGER_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_ORG_BLUEZ_MANAGER_PROXY))
+#define IS_ORG_BLUEZ_MANAGER_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_ORG_BLUEZ_MANAGER_PROXY))
+
+typedef struct _OrgBluezManagerProxy OrgBluezManagerProxy;
+typedef struct _OrgBluezManagerProxyClass OrgBluezManagerProxyClass;
+typedef struct _OrgBluezManagerProxyPrivate OrgBluezManagerProxyPrivate;
+
+struct _OrgBluezManagerProxy
+{
+ /*< private >*/
+ GDBusProxy parent_instance;
+ OrgBluezManagerProxyPrivate *priv;
+};
+
+struct _OrgBluezManagerProxyClass
+{
+ GDBusProxyClass parent_class;
+};
+
+GType org_bluez_manager_proxy_get_type (void) G_GNUC_CONST;
+
+void org_bluez_manager_proxy_new (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+OrgBluezManager *org_bluez_manager_proxy_new_finish (
+ GAsyncResult *res,
+ GError **error);
+OrgBluezManager *org_bluez_manager_proxy_new_sync (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_manager_proxy_new_for_bus (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+OrgBluezManager *org_bluez_manager_proxy_new_for_bus_finish (
+ GAsyncResult *res,
+ GError **error);
+OrgBluezManager *org_bluez_manager_proxy_new_for_bus_sync (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error);
+
+
+/* ---- */
+
+#define TYPE_ORG_BLUEZ_MANAGER_SKELETON (org_bluez_manager_skeleton_get_type ())
+#define ORG_BLUEZ_MANAGER_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_ORG_BLUEZ_MANAGER_SKELETON, OrgBluezManagerSkeleton))
+#define ORG_BLUEZ_MANAGER_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TYPE_ORG_BLUEZ_MANAGER_SKELETON, OrgBluezManagerSkeletonClass))
+#define ORG_BLUEZ_MANAGER_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_ORG_BLUEZ_MANAGER_SKELETON, OrgBluezManagerSkeletonClass))
+#define IS_ORG_BLUEZ_MANAGER_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_ORG_BLUEZ_MANAGER_SKELETON))
+#define IS_ORG_BLUEZ_MANAGER_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_ORG_BLUEZ_MANAGER_SKELETON))
+
+typedef struct _OrgBluezManagerSkeleton OrgBluezManagerSkeleton;
+typedef struct _OrgBluezManagerSkeletonClass OrgBluezManagerSkeletonClass;
+typedef struct _OrgBluezManagerSkeletonPrivate OrgBluezManagerSkeletonPrivate;
+
+struct _OrgBluezManagerSkeleton
+{
+ /*< private >*/
+ GDBusInterfaceSkeleton parent_instance;
+ OrgBluezManagerSkeletonPrivate *priv;
+};
+
+struct _OrgBluezManagerSkeletonClass
+{
+ GDBusInterfaceSkeletonClass parent_class;
+};
+
+GType org_bluez_manager_skeleton_get_type (void) G_GNUC_CONST;
+
+OrgBluezManager *org_bluez_manager_skeleton_new (void);
+
+
+G_END_DECLS
+
+#endif /* __BLUETOOTHMANAGERPROXY_H__ */
diff --git a/plugins/common/bluetoothserialproxy.c b/plugins/common/bluetoothserialproxy.c
new file mode 100644
index 00000000..f4d6128f
--- /dev/null
+++ b/plugins/common/bluetoothserialproxy.c
@@ -0,0 +1,1397 @@
+/*
+ * Generated by gdbus-codegen 2.32.1. DO NOT EDIT.
+ *
+ * The license of this code is the same as for the source it was derived from.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "bluetoothserialproxy.h"
+
+#ifdef G_OS_UNIX
+# include <gio/gunixfdlist.h>
+#endif
+
+typedef struct
+{
+ GDBusArgInfo parent_struct;
+ gboolean use_gvariant;
+} _ExtendedGDBusArgInfo;
+
+typedef struct
+{
+ GDBusMethodInfo parent_struct;
+ const gchar *signal_name;
+ gboolean pass_fdlist;
+} _ExtendedGDBusMethodInfo;
+
+typedef struct
+{
+ GDBusSignalInfo parent_struct;
+ const gchar *signal_name;
+} _ExtendedGDBusSignalInfo;
+
+typedef struct
+{
+ GDBusPropertyInfo parent_struct;
+ const gchar *hyphen_name;
+ gboolean use_gvariant;
+} _ExtendedGDBusPropertyInfo;
+
+typedef struct
+{
+ GDBusInterfaceInfo parent_struct;
+ const gchar *hyphen_name;
+} _ExtendedGDBusInterfaceInfo;
+
+typedef struct
+{
+ const _ExtendedGDBusPropertyInfo *info;
+ guint prop_id;
+ GValue orig_value; /* the value before the change */
+} ChangedProperty;
+
+static void
+_changed_property_free (ChangedProperty *data)
+{
+ g_value_unset (&data->orig_value);
+ g_free (data);
+}
+
+static gboolean
+_g_strv_equal0 (gchar **a, gchar **b)
+{
+ gboolean ret = FALSE;
+ guint n;
+ if (a == NULL && b == NULL)
+ {
+ ret = TRUE;
+ goto out;
+ }
+ if (a == NULL || b == NULL)
+ goto out;
+ if (g_strv_length (a) != g_strv_length (b))
+ goto out;
+ for (n = 0; a[n] != NULL; n++)
+ if (g_strcmp0 (a[n], b[n]) != 0)
+ goto out;
+ ret = TRUE;
+out:
+ return ret;
+}
+
+static gboolean
+_g_variant_equal0 (GVariant *a, GVariant *b)
+{
+ gboolean ret = FALSE;
+ if (a == NULL && b == NULL)
+ {
+ ret = TRUE;
+ goto out;
+ }
+ if (a == NULL || b == NULL)
+ goto out;
+ ret = g_variant_equal (a, b);
+out:
+ return ret;
+}
+
+G_GNUC_UNUSED static gboolean
+_g_value_equal (const GValue *a, const GValue *b)
+{
+ gboolean ret = FALSE;
+ g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));
+ switch (G_VALUE_TYPE (a))
+ {
+ case G_TYPE_BOOLEAN:
+ ret = (g_value_get_boolean (a) == g_value_get_boolean (b));
+ break;
+ case G_TYPE_UCHAR:
+ ret = (g_value_get_uchar (a) == g_value_get_uchar (b));
+ break;
+ case G_TYPE_INT:
+ ret = (g_value_get_int (a) == g_value_get_int (b));
+ break;
+ case G_TYPE_UINT:
+ ret = (g_value_get_uint (a) == g_value_get_uint (b));
+ break;
+ case G_TYPE_INT64:
+ ret = (g_value_get_int64 (a) == g_value_get_int64 (b));
+ break;
+ case G_TYPE_UINT64:
+ ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));
+ break;
+ case G_TYPE_DOUBLE:
+ ret = (g_value_get_double (a) == g_value_get_double (b));
+ break;
+ case G_TYPE_STRING:
+ ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);
+ break;
+ case G_TYPE_VARIANT:
+ ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b));
+ break;
+ default:
+ if (G_VALUE_TYPE (a) == G_TYPE_STRV)
+ ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b));
+ else
+ g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a)));
+ break;
+ }
+ return ret;
+}
+
+/* ------------------------------------------------------------------------
+ * Code for interface org.bluez.Serial
+ * ------------------------------------------------------------------------
+ */
+
+/**
+ * SECTION:OrgBluezSerial
+ * @title: OrgBluezSerial
+ * @short_description: Generated C code for the org.bluez.Serial D-Bus interface
+ *
+ * This section contains code for working with the <link linkend="gdbus-interface-org-bluez-Serial.top_of_page">org.bluez.Serial</link> D-Bus interface in C.
+ */
+
+/* ---- Introspection data for org.bluez.Serial ---- */
+
+static const _ExtendedGDBusArgInfo _org_bluez_serial_method_info_connect_IN_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_serial_method_info_connect_IN_ARG_pointers[] =
+{
+ &_org_bluez_serial_method_info_connect_IN_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_serial_method_info_connect_OUT_ARG_unnamed_arg1 =
+{
+ {
+ -1,
+ "unnamed_arg1",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_serial_method_info_connect_OUT_ARG_pointers[] =
+{
+ &_org_bluez_serial_method_info_connect_OUT_ARG_unnamed_arg1,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_serial_method_info_connect =
+{
+ {
+ -1,
+ "Connect",
+ (GDBusArgInfo **) &_org_bluez_serial_method_info_connect_IN_ARG_pointers,
+ (GDBusArgInfo **) &_org_bluez_serial_method_info_connect_OUT_ARG_pointers,
+ NULL
+ },
+ "handle-connect",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_serial_method_info_connect_fd_IN_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_serial_method_info_connect_fd_IN_ARG_pointers[] =
+{
+ &_org_bluez_serial_method_info_connect_fd_IN_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_serial_method_info_connect_fd_OUT_ARG_unnamed_arg1 =
+{
+ {
+ -1,
+ "unnamed_arg1",
+ "h",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_serial_method_info_connect_fd_OUT_ARG_pointers[] =
+{
+ &_org_bluez_serial_method_info_connect_fd_OUT_ARG_unnamed_arg1,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_serial_method_info_connect_fd =
+{
+ {
+ -1,
+ "ConnectFD",
+ (GDBusArgInfo **) &_org_bluez_serial_method_info_connect_fd_IN_ARG_pointers,
+ (GDBusArgInfo **) &_org_bluez_serial_method_info_connect_fd_OUT_ARG_pointers,
+ NULL
+ },
+ "handle-connect-fd",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _org_bluez_serial_method_info_disconnect_IN_ARG_unnamed_arg0 =
+{
+ {
+ -1,
+ "unnamed_arg0",
+ "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _org_bluez_serial_method_info_disconnect_IN_ARG_pointers[] =
+{
+ &_org_bluez_serial_method_info_disconnect_IN_ARG_unnamed_arg0,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _org_bluez_serial_method_info_disconnect =
+{
+ {
+ -1,
+ "Disconnect",
+ (GDBusArgInfo **) &_org_bluez_serial_method_info_disconnect_IN_ARG_pointers,
+ NULL,
+ NULL
+ },
+ "handle-disconnect",
+ FALSE
+};
+
+static const _ExtendedGDBusMethodInfo * const _org_bluez_serial_method_info_pointers[] =
+{
+ &_org_bluez_serial_method_info_connect,
+ &_org_bluez_serial_method_info_connect_fd,
+ &_org_bluez_serial_method_info_disconnect,
+ NULL
+};
+
+static const _ExtendedGDBusInterfaceInfo _org_bluez_serial_interface_info =
+{
+ {
+ -1,
+ "org.bluez.Serial",
+ (GDBusMethodInfo **) &_org_bluez_serial_method_info_pointers,
+ NULL,
+ NULL,
+ NULL
+ },
+ "org-bluez-serial",
+};
+
+
+/**
+ * org_bluez_serial_interface_info:
+ *
+ * Gets a machine-readable description of the <link linkend="gdbus-interface-org-bluez-Serial.top_of_page">org.bluez.Serial</link> D-Bus interface.
+ *
+ * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free.
+ */
+GDBusInterfaceInfo *
+org_bluez_serial_interface_info (void)
+{
+ return (GDBusInterfaceInfo *) &_org_bluez_serial_interface_info;
+}
+
+/**
+ * org_bluez_serial_override_properties:
+ * @klass: The class structure for a #GObject<!-- -->-derived class.
+ * @property_id_begin: The property id to assign to the first overridden property.
+ *
+ * Overrides all #GObject properties in the #OrgBluezSerial interface for a concrete class.
+ * The properties are overridden in the order they are defined.
+ *
+ * Returns: The last property id.
+ */
+guint
+org_bluez_serial_override_properties (GObjectClass *klass, guint property_id_begin)
+{
+ return property_id_begin - 1;
+}
+
+
+
+/**
+ * OrgBluezSerial:
+ *
+ * Abstract interface type for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Serial.top_of_page">org.bluez.Serial</link>.
+ */
+
+/**
+ * OrgBluezSerialIface:
+ * @parent_iface: The parent interface.
+ * @handle_connect: Handler for the #OrgBluezSerial::handle-connect signal.
+ * @handle_connect_fd: Handler for the #OrgBluezSerial::handle-connect-fd signal.
+ * @handle_disconnect: Handler for the #OrgBluezSerial::handle-disconnect signal.
+ *
+ * Virtual table for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Serial.top_of_page">org.bluez.Serial</link>.
+ */
+
+static void
+org_bluez_serial_default_init (OrgBluezSerialIface *iface)
+{
+ /* GObject signals for incoming D-Bus method calls: */
+ /**
+ * OrgBluezSerial::handle-connect:
+ * @object: A #OrgBluezSerial.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_unnamed_arg0: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Serial.Connect">Connect()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_serial_complete_connect() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-connect",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezSerialIface, handle_connect),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 2,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING);
+
+ /**
+ * OrgBluezSerial::handle-connect-fd:
+ * @object: A #OrgBluezSerial.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_unnamed_arg0: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Serial.ConnectFD">ConnectFD()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_serial_complete_connect_fd() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-connect-fd",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezSerialIface, handle_connect_fd),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 2,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING);
+
+ /**
+ * OrgBluezSerial::handle-disconnect:
+ * @object: A #OrgBluezSerial.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_unnamed_arg0: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-bluez-Serial.Disconnect">Disconnect()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call org_bluez_serial_complete_disconnect() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-disconnect",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (OrgBluezSerialIface, handle_disconnect),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 2,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING);
+
+}
+
+typedef OrgBluezSerialIface OrgBluezSerialInterface;
+G_DEFINE_INTERFACE (OrgBluezSerial, org_bluez_serial, G_TYPE_OBJECT);
+
+/**
+ * org_bluez_serial_call_connect:
+ * @proxy: A #OrgBluezSerialProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Serial.Connect">Connect()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_serial_call_connect_finish() to get the result of the operation.
+ *
+ * See org_bluez_serial_call_connect_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_serial_call_connect (
+ OrgBluezSerial *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "Connect",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_serial_call_connect_finish:
+ * @proxy: A #OrgBluezSerialProxy.
+ * @out_unnamed_arg1: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_serial_call_connect().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_serial_call_connect().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_serial_call_connect_finish (
+ OrgBluezSerial *proxy,
+ gchar **out_unnamed_arg1,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(s)",
+ out_unnamed_arg1);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_serial_call_connect_sync:
+ * @proxy: A #OrgBluezSerialProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @out_unnamed_arg1: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Serial.Connect">Connect()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_serial_call_connect() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_serial_call_connect_sync (
+ OrgBluezSerial *proxy,
+ const gchar *arg_unnamed_arg0,
+ gchar **out_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "Connect",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(s)",
+ out_unnamed_arg1);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_serial_call_connect_fd:
+ * @proxy: A #OrgBluezSerialProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Serial.ConnectFD">ConnectFD()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_serial_call_connect_fd_finish() to get the result of the operation.
+ *
+ * See org_bluez_serial_call_connect_fd_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_serial_call_connect_fd (
+ OrgBluezSerial *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "ConnectFD",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_serial_call_connect_fd_finish:
+ * @proxy: A #OrgBluezSerialProxy.
+ * @out_unnamed_arg1: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_serial_call_connect_fd().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_serial_call_connect_fd().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_serial_call_connect_fd_finish (
+ OrgBluezSerial *proxy,
+ GVariant **out_unnamed_arg1,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(@h)",
+ out_unnamed_arg1);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_serial_call_connect_fd_sync:
+ * @proxy: A #OrgBluezSerialProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @out_unnamed_arg1: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Serial.ConnectFD">ConnectFD()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_serial_call_connect_fd() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_serial_call_connect_fd_sync (
+ OrgBluezSerial *proxy,
+ const gchar *arg_unnamed_arg0,
+ GVariant **out_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "ConnectFD",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(@h)",
+ out_unnamed_arg1);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_serial_call_disconnect:
+ * @proxy: A #OrgBluezSerialProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-org-bluez-Serial.Disconnect">Disconnect()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_serial_call_disconnect_finish() to get the result of the operation.
+ *
+ * See org_bluez_serial_call_disconnect_sync() for the synchronous, blocking version of this method.
+ */
+void
+org_bluez_serial_call_disconnect (
+ OrgBluezSerial *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "Disconnect",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * org_bluez_serial_call_disconnect_finish:
+ * @proxy: A #OrgBluezSerialProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_serial_call_disconnect().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with org_bluez_serial_call_disconnect().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_serial_call_disconnect_finish (
+ OrgBluezSerial *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_serial_call_disconnect_sync:
+ * @proxy: A #OrgBluezSerialProxy.
+ * @arg_unnamed_arg0: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-org-bluez-Serial.Disconnect">Disconnect()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_serial_call_disconnect() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+org_bluez_serial_call_disconnect_sync (
+ OrgBluezSerial *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "Disconnect",
+ g_variant_new ("(s)",
+ arg_unnamed_arg0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * org_bluez_serial_complete_connect:
+ * @object: A #OrgBluezSerial.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @unnamed_arg1: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Serial.Connect">Connect()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_serial_complete_connect (
+ OrgBluezSerial *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *unnamed_arg1)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(s)",
+ unnamed_arg1));
+}
+
+/**
+ * org_bluez_serial_complete_connect_fd:
+ * @object: A #OrgBluezSerial.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @unnamed_arg1: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Serial.ConnectFD">ConnectFD()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_serial_complete_connect_fd (
+ OrgBluezSerial *object,
+ GDBusMethodInvocation *invocation,
+ GVariant *unnamed_arg1)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(@h)",
+ unnamed_arg1));
+}
+
+/**
+ * org_bluez_serial_complete_disconnect:
+ * @object: A #OrgBluezSerial.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-bluez-Serial.Disconnect">Disconnect()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+org_bluez_serial_complete_disconnect (
+ OrgBluezSerial *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/* ------------------------------------------------------------------------ */
+
+/**
+ * OrgBluezSerialProxy:
+ *
+ * The #OrgBluezSerialProxy structure contains only private data and should only be accessed using the provided API.
+ */
+
+/**
+ * OrgBluezSerialProxyClass:
+ * @parent_class: The parent class.
+ *
+ * Class structure for #OrgBluezSerialProxy.
+ */
+
+struct _OrgBluezSerialProxyPrivate
+{
+ GData *qdata;
+};
+
+static void org_bluez_serial_proxy_iface_init (OrgBluezSerialIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (OrgBluezSerialProxy, org_bluez_serial_proxy, G_TYPE_DBUS_PROXY,
+ G_IMPLEMENT_INTERFACE (TYPE_ORG_BLUEZ_SERIAL, org_bluez_serial_proxy_iface_init));
+
+static void
+org_bluez_serial_proxy_finalize (GObject *object)
+{
+ OrgBluezSerialProxy *proxy = ORG_BLUEZ_SERIAL_PROXY (object);
+ g_datalist_clear (&proxy->priv->qdata);
+ G_OBJECT_CLASS (org_bluez_serial_proxy_parent_class)->finalize (object);
+}
+
+static void
+org_bluez_serial_proxy_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+}
+
+static void
+org_bluez_serial_proxy_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+}
+
+static void
+org_bluez_serial_proxy_g_signal (GDBusProxy *proxy,
+ const gchar *sender_name,
+ const gchar *signal_name,
+ GVariant *parameters)
+{
+ _ExtendedGDBusSignalInfo *info;
+ GVariantIter iter;
+ GVariant *child;
+ GValue *paramv;
+ guint num_params;
+ guint n;
+ guint signal_id;
+ info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_org_bluez_serial_interface_info, signal_name);
+ if (info == NULL)
+ return;
+ num_params = g_variant_n_children (parameters);
+ paramv = g_new0 (GValue, num_params + 1);
+ g_value_init (&paramv[0], TYPE_ORG_BLUEZ_SERIAL);
+ g_value_set_object (&paramv[0], proxy);
+ g_variant_iter_init (&iter, parameters);
+ n = 1;
+ while ((child = g_variant_iter_next_value (&iter)) != NULL)
+ {
+ _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1];
+ if (arg_info->use_gvariant)
+ {
+ g_value_init (&paramv[n], G_TYPE_VARIANT);
+ g_value_set_variant (&paramv[n], child);
+ n++;
+ }
+ else
+ g_dbus_gvariant_to_gvalue (child, &paramv[n++]);
+ g_variant_unref (child);
+ }
+ signal_id = g_signal_lookup (info->signal_name, TYPE_ORG_BLUEZ_SERIAL);
+ g_signal_emitv (paramv, signal_id, 0, NULL);
+ for (n = 0; n < num_params + 1; n++)
+ g_value_unset (&paramv[n]);
+ g_free (paramv);
+}
+
+static void
+org_bluez_serial_proxy_g_properties_changed (GDBusProxy *_proxy,
+ GVariant *changed_properties,
+ const gchar *const *invalidated_properties)
+{
+ OrgBluezSerialProxy *proxy = ORG_BLUEZ_SERIAL_PROXY (_proxy);
+ guint n;
+ const gchar *key;
+ GVariantIter *iter;
+ _ExtendedGDBusPropertyInfo *info;
+ g_variant_get (changed_properties, "a{sv}", &iter);
+ while (g_variant_iter_next (iter, "{&sv}", &key, NULL))
+ {
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_org_bluez_serial_interface_info, key);
+ g_datalist_remove_data (&proxy->priv->qdata, key);
+ if (info != NULL)
+ g_object_notify (G_OBJECT (proxy), info->hyphen_name);
+ }
+ g_variant_iter_free (iter);
+ for (n = 0; invalidated_properties[n] != NULL; n++)
+ {
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_org_bluez_serial_interface_info, invalidated_properties[n]);
+ g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]);
+ if (info != NULL)
+ g_object_notify (G_OBJECT (proxy), info->hyphen_name);
+ }
+}
+
+static void
+org_bluez_serial_proxy_init (OrgBluezSerialProxy *proxy)
+{
+ proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, TYPE_ORG_BLUEZ_SERIAL_PROXY, OrgBluezSerialProxyPrivate);
+ g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), org_bluez_serial_interface_info ());
+}
+
+static void
+org_bluez_serial_proxy_class_init (OrgBluezSerialProxyClass *klass)
+{
+ GObjectClass *gobject_class;
+ GDBusProxyClass *proxy_class;
+
+ g_type_class_add_private (klass, sizeof (OrgBluezSerialProxyPrivate));
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = org_bluez_serial_proxy_finalize;
+ gobject_class->get_property = org_bluez_serial_proxy_get_property;
+ gobject_class->set_property = org_bluez_serial_proxy_set_property;
+
+ proxy_class = G_DBUS_PROXY_CLASS (klass);
+ proxy_class->g_signal = org_bluez_serial_proxy_g_signal;
+ proxy_class->g_properties_changed = org_bluez_serial_proxy_g_properties_changed;
+
+}
+
+static void
+org_bluez_serial_proxy_iface_init (OrgBluezSerialIface *iface)
+{
+}
+
+/**
+ * org_bluez_serial_proxy_new:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: (allow-none): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously creates a proxy for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Serial.top_of_page">org.bluez.Serial</link>. See g_dbus_proxy_new() for more details.
+ *
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_serial_proxy_new_finish() to get the result of the operation.
+ *
+ * See org_bluez_serial_proxy_new_sync() for the synchronous, blocking version of this constructor.
+ */
+void
+org_bluez_serial_proxy_new (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_async_initable_new_async (TYPE_ORG_BLUEZ_SERIAL_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.bluez.Serial", NULL);
+}
+
+/**
+ * org_bluez_serial_proxy_new_finish:
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_serial_proxy_new().
+ * @error: Return location for error or %NULL
+ *
+ * Finishes an operation started with org_bluez_serial_proxy_new().
+ *
+ * Returns: (transfer full) (type OrgBluezSerialProxy): The constructed proxy object or %NULL if @error is set.
+ */
+OrgBluezSerial *
+org_bluez_serial_proxy_new_finish (
+ GAsyncResult *res,
+ GError **error)
+{
+ GObject *ret;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (res);
+ ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
+ g_object_unref (source_object);
+ if (ret != NULL)
+ return ORG_BLUEZ_SERIAL (ret);
+ else
+ return NULL;
+}
+
+/**
+ * org_bluez_serial_proxy_new_sync:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: (allow-none): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL
+ *
+ * Synchronously creates a proxy for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Serial.top_of_page">org.bluez.Serial</link>. See g_dbus_proxy_new_sync() for more details.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_serial_proxy_new() for the asynchronous version of this constructor.
+ *
+ * Returns: (transfer full) (type OrgBluezSerialProxy): The constructed proxy object or %NULL if @error is set.
+ */
+OrgBluezSerial *
+org_bluez_serial_proxy_new_sync (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GInitable *ret;
+ ret = g_initable_new (TYPE_ORG_BLUEZ_SERIAL_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.bluez.Serial", NULL);
+ if (ret != NULL)
+ return ORG_BLUEZ_SERIAL (ret);
+ else
+ return NULL;
+}
+
+
+/**
+ * org_bluez_serial_proxy_new_for_bus:
+ * @bus_type: A #GBusType.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like org_bluez_serial_proxy_new() but takes a #GBusType instead of a #GDBusConnection.
+ *
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call org_bluez_serial_proxy_new_for_bus_finish() to get the result of the operation.
+ *
+ * See org_bluez_serial_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor.
+ */
+void
+org_bluez_serial_proxy_new_for_bus (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_async_initable_new_async (TYPE_ORG_BLUEZ_SERIAL_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.bluez.Serial", NULL);
+}
+
+/**
+ * org_bluez_serial_proxy_new_for_bus_finish:
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to org_bluez_serial_proxy_new_for_bus().
+ * @error: Return location for error or %NULL
+ *
+ * Finishes an operation started with org_bluez_serial_proxy_new_for_bus().
+ *
+ * Returns: (transfer full) (type OrgBluezSerialProxy): The constructed proxy object or %NULL if @error is set.
+ */
+OrgBluezSerial *
+org_bluez_serial_proxy_new_for_bus_finish (
+ GAsyncResult *res,
+ GError **error)
+{
+ GObject *ret;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (res);
+ ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
+ g_object_unref (source_object);
+ if (ret != NULL)
+ return ORG_BLUEZ_SERIAL (ret);
+ else
+ return NULL;
+}
+
+/**
+ * org_bluez_serial_proxy_new_for_bus_sync:
+ * @bus_type: A #GBusType.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL
+ *
+ * Like org_bluez_serial_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * See org_bluez_serial_proxy_new_for_bus() for the asynchronous version of this constructor.
+ *
+ * Returns: (transfer full) (type OrgBluezSerialProxy): The constructed proxy object or %NULL if @error is set.
+ */
+OrgBluezSerial *
+org_bluez_serial_proxy_new_for_bus_sync (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GInitable *ret;
+ ret = g_initable_new (TYPE_ORG_BLUEZ_SERIAL_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.bluez.Serial", NULL);
+ if (ret != NULL)
+ return ORG_BLUEZ_SERIAL (ret);
+ else
+ return NULL;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+/**
+ * OrgBluezSerialSkeleton:
+ *
+ * The #OrgBluezSerialSkeleton structure contains only private data and should only be accessed using the provided API.
+ */
+
+/**
+ * OrgBluezSerialSkeletonClass:
+ * @parent_class: The parent class.
+ *
+ * Class structure for #OrgBluezSerialSkeleton.
+ */
+
+struct _OrgBluezSerialSkeletonPrivate
+{
+ GValue *properties;
+ GList *changed_properties;
+ GSource *changed_properties_idle_source;
+ GMainContext *context;
+ GMutex lock;
+};
+
+static void
+_org_bluez_serial_skeleton_handle_method_call (
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ OrgBluezSerialSkeleton *skeleton = ORG_BLUEZ_SERIAL_SKELETON (user_data);
+ _ExtendedGDBusMethodInfo *info;
+ GVariantIter iter;
+ GVariant *child;
+ GValue *paramv;
+ guint num_params;
+ guint num_extra;
+ guint n;
+ guint signal_id;
+ GValue return_value = G_VALUE_INIT;
+ info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation);
+ g_assert (info != NULL);
+ num_params = g_variant_n_children (parameters);
+ num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra);
+ n = 0;
+ g_value_init (&paramv[n], TYPE_ORG_BLUEZ_SERIAL);
+ g_value_set_object (&paramv[n++], skeleton);
+ g_value_init (&paramv[n], G_TYPE_DBUS_METHOD_INVOCATION);
+ g_value_set_object (&paramv[n++], invocation);
+ if (info->pass_fdlist)
+ {
+#ifdef G_OS_UNIX
+ g_value_init (&paramv[n], G_TYPE_UNIX_FD_LIST);
+ g_value_set_object (&paramv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation)));
+#else
+ g_assert_not_reached ();
+#endif
+ }
+ g_variant_iter_init (&iter, parameters);
+ while ((child = g_variant_iter_next_value (&iter)) != NULL)
+ {
+ _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra];
+ if (arg_info->use_gvariant)
+ {
+ g_value_init (&paramv[n], G_TYPE_VARIANT);
+ g_value_set_variant (&paramv[n], child);
+ n++;
+ }
+ else
+ g_dbus_gvariant_to_gvalue (child, &paramv[n++]);
+ g_variant_unref (child);
+ }
+ signal_id = g_signal_lookup (info->signal_name, TYPE_ORG_BLUEZ_SERIAL);
+ g_value_init (&return_value, G_TYPE_BOOLEAN);
+ g_signal_emitv (paramv, signal_id, 0, &return_value);
+ if (!g_value_get_boolean (&return_value))
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name);
+ g_value_unset (&return_value);
+ for (n = 0; n < num_params + num_extra; n++)
+ g_value_unset (&paramv[n]);
+ g_free (paramv);
+}
+
+static GVariant *
+_org_bluez_serial_skeleton_handle_get_property (
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GError **error,
+ gpointer user_data)
+{
+ OrgBluezSerialSkeleton *skeleton = ORG_BLUEZ_SERIAL_SKELETON (user_data);
+ GValue value = G_VALUE_INIT;
+ GParamSpec *pspec;
+ _ExtendedGDBusPropertyInfo *info;
+ GVariant *ret;
+ ret = NULL;
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_org_bluez_serial_interface_info, property_name);
+ g_assert (info != NULL);
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
+ if (pspec == NULL)
+ {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
+ }
+ else
+ {
+ g_value_init (&value, pspec->value_type);
+ g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value);
+ ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature));
+ g_value_unset (&value);
+ }
+ return ret;
+}
+
+static gboolean
+_org_bluez_serial_skeleton_handle_set_property (
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GVariant *variant,
+ GError **error,
+ gpointer user_data)
+{
+ OrgBluezSerialSkeleton *skeleton = ORG_BLUEZ_SERIAL_SKELETON (user_data);
+ GValue value = G_VALUE_INIT;
+ GParamSpec *pspec;
+ _ExtendedGDBusPropertyInfo *info;
+ gboolean ret;
+ ret = FALSE;
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_org_bluez_serial_interface_info, property_name);
+ g_assert (info != NULL);
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
+ if (pspec == NULL)
+ {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
+ }
+ else
+ {
+ if (info->use_gvariant)
+ g_value_set_variant (&value, variant);
+ else
+ g_dbus_gvariant_to_gvalue (variant, &value);
+ g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value);
+ g_value_unset (&value);
+ ret = TRUE;
+ }
+ return ret;
+}
+
+static const GDBusInterfaceVTable _org_bluez_serial_skeleton_vtable =
+{
+ _org_bluez_serial_skeleton_handle_method_call,
+ _org_bluez_serial_skeleton_handle_get_property,
+ _org_bluez_serial_skeleton_handle_set_property
+};
+
+static GDBusInterfaceInfo *
+org_bluez_serial_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton)
+{
+ return org_bluez_serial_interface_info ();
+}
+
+static GDBusInterfaceVTable *
+org_bluez_serial_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton)
+{
+ return (GDBusInterfaceVTable *) &_org_bluez_serial_skeleton_vtable;
+}
+
+static GVariant *
+org_bluez_serial_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton)
+{
+ OrgBluezSerialSkeleton *skeleton = ORG_BLUEZ_SERIAL_SKELETON (_skeleton);
+
+ GVariantBuilder builder;
+ guint n;
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ if (_org_bluez_serial_interface_info.parent_struct.properties == NULL)
+ goto out;
+ for (n = 0; _org_bluez_serial_interface_info.parent_struct.properties[n] != NULL; n++)
+ {
+ GDBusPropertyInfo *info = _org_bluez_serial_interface_info.parent_struct.properties[n];
+ if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
+ {
+ GVariant *value;
+ value = _org_bluez_serial_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.bluez.Serial", info->name, NULL, skeleton);
+ if (value != NULL)
+ {
+ g_variant_take_ref (value);
+ g_variant_builder_add (&builder, "{sv}", info->name, value);
+ g_variant_unref (value);
+ }
+ }
+ }
+out:
+ return g_variant_builder_end (&builder);
+}
+
+static void
+org_bluez_serial_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton)
+{
+}
+
+static void org_bluez_serial_skeleton_iface_init (OrgBluezSerialIface *iface);
+G_DEFINE_TYPE_WITH_CODE (OrgBluezSerialSkeleton, org_bluez_serial_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,
+ G_IMPLEMENT_INTERFACE (TYPE_ORG_BLUEZ_SERIAL, org_bluez_serial_skeleton_iface_init));
+
+static void
+org_bluez_serial_skeleton_finalize (GObject *object)
+{
+ OrgBluezSerialSkeleton *skeleton = ORG_BLUEZ_SERIAL_SKELETON (object);
+ g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);
+ if (skeleton->priv->changed_properties_idle_source != NULL)
+ g_source_destroy (skeleton->priv->changed_properties_idle_source);
+ g_main_context_unref (skeleton->priv->context);
+ g_mutex_clear (&skeleton->priv->lock);
+ G_OBJECT_CLASS (org_bluez_serial_skeleton_parent_class)->finalize (object);
+}
+
+static void
+org_bluez_serial_skeleton_init (OrgBluezSerialSkeleton *skeleton)
+{
+ skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, TYPE_ORG_BLUEZ_SERIAL_SKELETON, OrgBluezSerialSkeletonPrivate);
+ g_mutex_init (&skeleton->priv->lock);
+ skeleton->priv->context = g_main_context_ref_thread_default ();
+}
+
+static void
+org_bluez_serial_skeleton_class_init (OrgBluezSerialSkeletonClass *klass)
+{
+ GObjectClass *gobject_class;
+ GDBusInterfaceSkeletonClass *skeleton_class;
+
+ g_type_class_add_private (klass, sizeof (OrgBluezSerialSkeletonPrivate));
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = org_bluez_serial_skeleton_finalize;
+
+ skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
+ skeleton_class->get_info = org_bluez_serial_skeleton_dbus_interface_get_info;
+ skeleton_class->get_properties = org_bluez_serial_skeleton_dbus_interface_get_properties;
+ skeleton_class->flush = org_bluez_serial_skeleton_dbus_interface_flush;
+ skeleton_class->get_vtable = org_bluez_serial_skeleton_dbus_interface_get_vtable;
+}
+
+static void
+org_bluez_serial_skeleton_iface_init (OrgBluezSerialIface *iface)
+{
+}
+
+/**
+ * org_bluez_serial_skeleton_new:
+ *
+ * Creates a skeleton object for the D-Bus interface <link linkend="gdbus-interface-org-bluez-Serial.top_of_page">org.bluez.Serial</link>.
+ *
+ * Returns: (transfer full) (type OrgBluezSerialSkeleton): The skeleton object.
+ */
+OrgBluezSerial *
+org_bluez_serial_skeleton_new (void)
+{
+ return ORG_BLUEZ_SERIAL (g_object_new (TYPE_ORG_BLUEZ_SERIAL_SKELETON, NULL));
+}
+
diff --git a/plugins/common/bluetoothserialproxy.h b/plugins/common/bluetoothserialproxy.h
new file mode 100644
index 00000000..cf3ef531
--- /dev/null
+++ b/plugins/common/bluetoothserialproxy.h
@@ -0,0 +1,230 @@
+/*
+ * Generated by gdbus-codegen 2.32.1. DO NOT EDIT.
+ *
+ * The license of this code is the same as for the source it was derived from.
+ */
+
+#ifndef __BLUETOOTHSERIALPROXY_H__
+#define __BLUETOOTHSERIALPROXY_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+
+/* ------------------------------------------------------------------------ */
+/* Declarations for org.bluez.Serial */
+
+#define TYPE_ORG_BLUEZ_SERIAL (org_bluez_serial_get_type ())
+#define ORG_BLUEZ_SERIAL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_ORG_BLUEZ_SERIAL, OrgBluezSerial))
+#define IS_ORG_BLUEZ_SERIAL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_ORG_BLUEZ_SERIAL))
+#define ORG_BLUEZ_SERIAL_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), TYPE_ORG_BLUEZ_SERIAL, OrgBluezSerialIface))
+
+struct _OrgBluezSerial;
+typedef struct _OrgBluezSerial OrgBluezSerial;
+typedef struct _OrgBluezSerialIface OrgBluezSerialIface;
+
+struct _OrgBluezSerialIface
+{
+ GTypeInterface parent_iface;
+
+ gboolean (*handle_connect) (
+ OrgBluezSerial *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_unnamed_arg0);
+
+ gboolean (*handle_connect_fd) (
+ OrgBluezSerial *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_unnamed_arg0);
+
+ gboolean (*handle_disconnect) (
+ OrgBluezSerial *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_unnamed_arg0);
+
+};
+
+GType org_bluez_serial_get_type (void) G_GNUC_CONST;
+
+GDBusInterfaceInfo *org_bluez_serial_interface_info (void);
+guint org_bluez_serial_override_properties (GObjectClass *klass, guint property_id_begin);
+
+
+/* D-Bus method call completion functions: */
+void org_bluez_serial_complete_connect (
+ OrgBluezSerial *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *unnamed_arg1);
+
+void org_bluez_serial_complete_connect_fd (
+ OrgBluezSerial *object,
+ GDBusMethodInvocation *invocation,
+ GVariant *unnamed_arg1);
+
+void org_bluez_serial_complete_disconnect (
+ OrgBluezSerial *object,
+ GDBusMethodInvocation *invocation);
+
+
+
+/* D-Bus method calls: */
+void org_bluez_serial_call_connect (
+ OrgBluezSerial *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_serial_call_connect_finish (
+ OrgBluezSerial *proxy,
+ gchar **out_unnamed_arg1,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_serial_call_connect_sync (
+ OrgBluezSerial *proxy,
+ const gchar *arg_unnamed_arg0,
+ gchar **out_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_serial_call_connect_fd (
+ OrgBluezSerial *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_serial_call_connect_fd_finish (
+ OrgBluezSerial *proxy,
+ GVariant **out_unnamed_arg1,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_serial_call_connect_fd_sync (
+ OrgBluezSerial *proxy,
+ const gchar *arg_unnamed_arg0,
+ GVariant **out_unnamed_arg1,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_serial_call_disconnect (
+ OrgBluezSerial *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean org_bluez_serial_call_disconnect_finish (
+ OrgBluezSerial *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean org_bluez_serial_call_disconnect_sync (
+ OrgBluezSerial *proxy,
+ const gchar *arg_unnamed_arg0,
+ GCancellable *cancellable,
+ GError **error);
+
+
+
+/* ---- */
+
+#define TYPE_ORG_BLUEZ_SERIAL_PROXY (org_bluez_serial_proxy_get_type ())
+#define ORG_BLUEZ_SERIAL_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_ORG_BLUEZ_SERIAL_PROXY, OrgBluezSerialProxy))
+#define ORG_BLUEZ_SERIAL_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TYPE_ORG_BLUEZ_SERIAL_PROXY, OrgBluezSerialProxyClass))
+#define ORG_BLUEZ_SERIAL_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_ORG_BLUEZ_SERIAL_PROXY, OrgBluezSerialProxyClass))
+#define IS_ORG_BLUEZ_SERIAL_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_ORG_BLUEZ_SERIAL_PROXY))
+#define IS_ORG_BLUEZ_SERIAL_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_ORG_BLUEZ_SERIAL_PROXY))
+
+typedef struct _OrgBluezSerialProxy OrgBluezSerialProxy;
+typedef struct _OrgBluezSerialProxyClass OrgBluezSerialProxyClass;
+typedef struct _OrgBluezSerialProxyPrivate OrgBluezSerialProxyPrivate;
+
+struct _OrgBluezSerialProxy
+{
+ /*< private >*/
+ GDBusProxy parent_instance;
+ OrgBluezSerialProxyPrivate *priv;
+};
+
+struct _OrgBluezSerialProxyClass
+{
+ GDBusProxyClass parent_class;
+};
+
+GType org_bluez_serial_proxy_get_type (void) G_GNUC_CONST;
+
+void org_bluez_serial_proxy_new (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+OrgBluezSerial *org_bluez_serial_proxy_new_finish (
+ GAsyncResult *res,
+ GError **error);
+OrgBluezSerial *org_bluez_serial_proxy_new_sync (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error);
+
+void org_bluez_serial_proxy_new_for_bus (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+OrgBluezSerial *org_bluez_serial_proxy_new_for_bus_finish (
+ GAsyncResult *res,
+ GError **error);
+OrgBluezSerial *org_bluez_serial_proxy_new_for_bus_sync (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error);
+
+
+/* ---- */
+
+#define TYPE_ORG_BLUEZ_SERIAL_SKELETON (org_bluez_serial_skeleton_get_type ())
+#define ORG_BLUEZ_SERIAL_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_ORG_BLUEZ_SERIAL_SKELETON, OrgBluezSerialSkeleton))
+#define ORG_BLUEZ_SERIAL_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TYPE_ORG_BLUEZ_SERIAL_SKELETON, OrgBluezSerialSkeletonClass))
+#define ORG_BLUEZ_SERIAL_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_ORG_BLUEZ_SERIAL_SKELETON, OrgBluezSerialSkeletonClass))
+#define IS_ORG_BLUEZ_SERIAL_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_ORG_BLUEZ_SERIAL_SKELETON))
+#define IS_ORG_BLUEZ_SERIAL_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_ORG_BLUEZ_SERIAL_SKELETON))
+
+typedef struct _OrgBluezSerialSkeleton OrgBluezSerialSkeleton;
+typedef struct _OrgBluezSerialSkeletonClass OrgBluezSerialSkeletonClass;
+typedef struct _OrgBluezSerialSkeletonPrivate OrgBluezSerialSkeletonPrivate;
+
+struct _OrgBluezSerialSkeleton
+{
+ /*< private >*/
+ GDBusInterfaceSkeleton parent_instance;
+ OrgBluezSerialSkeletonPrivate *priv;
+};
+
+struct _OrgBluezSerialSkeletonClass
+{
+ GDBusInterfaceSkeletonClass parent_class;
+};
+
+GType org_bluez_serial_skeleton_get_type (void) G_GNUC_CONST;
+
+OrgBluezSerial *org_bluez_serial_skeleton_new (void);
+
+
+G_END_DECLS
+
+#endif /* __BLUETOOTHSERIALPROXY_H__ */
diff --git a/plugins/common/canadapter.cpp b/plugins/common/canadapter.cpp
new file mode 100644
index 00000000..8f63ccdb
--- /dev/null
+++ b/plugins/common/canadapter.cpp
@@ -0,0 +1,42 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "canobserver.h"
+#include "cansocketadapter.h"
+#include "logger.h"
+#include "canadapter.h"
+
+
+CANAdapter* CANAdapter::createCANAdapter(CANObserver& observer)
+{
+ LOG_TRACE("");
+
+ CANAdapter* adapter = new CANSocketAdapter(observer);
+ return adapter;
+}
+
+CANAdapter::CANAdapter(CANObserver& observer) :
+ mObserver(observer)
+{
+ LOG_TRACE("");
+}
+
+CANAdapter::~CANAdapter()
+{
+ LOG_TRACE("");
+}
diff --git a/plugins/common/canadapter.h b/plugins/common/canadapter.h
new file mode 100644
index 00000000..fa78c102
--- /dev/null
+++ b/plugins/common/canadapter.h
@@ -0,0 +1,90 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef CANADAPTER_H
+#define CANADAPTER_H
+
+/**
+ * \addtogroup libcanbus
+ * @{
+ */
+
+#include <linux/can.h>
+
+class CANObserver;
+
+/**
+* \brief Abstracts CAN hardware object representation.
+* Has protected constructor.
+* Instance of the object has to be done via CANAdapter#createCANAdapter method.
+*
+* @code CANAdapter* pAdapter = CANAdapter::createCANAdapter(this); @endcode
+*
+* @class CANAdapter
+*/
+class CANAdapter
+{
+public:
+ virtual ~CANAdapter();/*LCOV_EXCL_LINE*/
+ /**
+ * Creates and initializes CANAdapter instance
+ * @fn createCANAdapter
+ * @param observer @link CANObserver Observer @endlink that will receives CAN bus frames
+ * @return Pointer to CANAdapter instance
+ * @static
+ */
+ static CANAdapter* createCANAdapter(CANObserver& observer);
+ /**
+ * Starts listening to CAN bus on the specified interface
+ * @fn start
+ * @param name Name of the CAN bus interface
+ * @return True if no error occurs.
+ */
+ virtual bool start(const char* name) = 0;
+ /**
+ * Stops listening to CAN bus
+ * @fn stop
+ */
+ virtual void stop() = 0;
+ /**
+ * Sends CAN frame over the bus
+ * @fn sendFrame
+ * @param frame CAN frame to be sent
+ * @return True if frame was sent
+ */
+ virtual bool sendFrame(const can_frame& frame) = 0;
+
+protected:
+ /**
+ * @param observer @link CANObserver Observer @endlink that will receives CAN bus frames
+ */
+ CANAdapter(CANObserver& observer);
+
+protected:
+ /**
+ * #CANObserver instance reference
+ * @property mObserver
+ * @protected
+ */
+ CANObserver& mObserver;
+
+};
+
+#endif // CANADAPTER_H
+
+/** @} */
diff --git a/plugins/common/canbus.h b/plugins/common/canbus.h
new file mode 100644
index 00000000..b34f62d4
--- /dev/null
+++ b/plugins/common/canbus.h
@@ -0,0 +1,89 @@
+/*****************************************************************
+ * INTEL CONFIDENTIAL
+ * Copyright 2011 - 2013 Intel Corporation All Rights Reserved.
+ *
+ * The source code contained or described herein and all documents related to the
+ * source code("Material") are owned by Intel Corporation or its suppliers or
+ * licensors.Title to the Material remains with Intel Corporation or its
+ * suppliers and licensors.The Material may contain trade secrets and proprietary
+ * and confidential information of Intel Corporation and its suppliers and
+ * licensors, and is protected by worldwide copyright and trade secret laws and
+ * treaty provisions.No part of the Material may be used, copied, reproduced,
+ * modified, published, uploaded, posted, transmitted, distributed, or disclosed
+ * in any way without Intels prior express written permission.
+ * No license under any patent, copyright, trade secret or other intellectual
+ * property right is granted to or conferred upon you by disclosure or delivery
+ * of the Materials, either expressly, by implication, inducement, estoppel or
+ * otherwise.Any license under such intellectual property rights must be
+ * express and approved by Intel in writing.
+ *
+ * Unless otherwise agreed by Intel in writing, you may not remove or alter this
+ * notice or any other notice embedded in Materials by Intel or Intels suppliers
+ * or licensors in any way.
+ *****************************************************************/
+
+#ifndef CANBUS_H
+#define CANBUS_H
+
+/**
+ * @defgroup libcanbus libcanbus static library
+ * \brief SocketCAN based CAN bus library.
+ * @{
+ */
+
+#include "canobserver.h"
+
+/**
+* \brief Encapsulation of the raw CAN bus.
+*
+* @class CANBus
+*/
+class CANBus
+{
+public:
+ /**
+ * @param observer Object derived from #CANObserver that will receive CAN bus frames
+ */
+ CANBus(CANObserver& observer);
+ virtual ~CANBus();
+
+ /**
+ * Starts the CAN bus instance on the specified interface
+ * @fn start
+ * @param name Name of the CAN bus network interface
+ * @return True if no error occurs.
+ */
+ virtual bool start(const char* name);
+ /**
+ * Stops the CAN bus instance
+ * @fn stop
+ */
+ virtual void stop();
+ /**
+ * Sends standard(11bit) CAN frame over the bus
+ * @fn sendStandardFrame
+ * @param frame CAN frame to be sent
+ * @return True if frame was sent
+ */
+ virtual bool sendStandardFrame(const can_frame& frame);
+ /**
+ * Sends extended(29bit) CAN frame over the bus
+ * @fn sendExtendedFrame
+ * @param frame CAN frame to be sent
+ * @return True if frame was sent
+ */
+ virtual bool sendExtendedFrame(const can_frame& frame);
+
+ class Impl;
+protected:
+ /**
+ * CANBus class private implementation
+ * @property d
+ * @protected
+ */
+ Impl* d;
+};
+
+#endif // CANBUS_H
+
+/** @} */
diff --git a/plugins/common/canbusimpl.cpp b/plugins/common/canbusimpl.cpp
new file mode 100644
index 00000000..993e4a0f
--- /dev/null
+++ b/plugins/common/canbusimpl.cpp
@@ -0,0 +1,140 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "canbusimpl.h"
+#include "canobserver.h"
+#include "canadapter.h"
+#include "logger.h"
+
+//----------------------------------------------------------------------------
+// CANBusImpl
+//----------------------------------------------------------------------------
+
+CANBus::Impl::Impl(CANObserver& observer) :
+ mObserver(observer),
+ mAdapter(NULL)
+{
+ LOG_TRACE("");
+}
+
+CANBus::Impl::~Impl()
+{
+ LOG_TRACE("");
+
+ stop();
+}
+
+bool CANBus::Impl::start(const char* name)
+{
+ LOG_TRACE("");
+
+ if(!mAdapter) {
+ init();
+ }
+ return mAdapter ? mAdapter->start(name) : false;
+}
+
+void CANBus::Impl::stop()
+{
+ LOG_TRACE("");
+
+ if(mAdapter) {
+ mAdapter->stop();
+ delete mAdapter;
+ mAdapter = 0;
+ }
+}
+
+bool CANBus::Impl::sendStandardFrame(const can_frame& frame)
+{
+ LOG_TRACE("");
+
+ if(mAdapter) {
+ struct can_frame frm(frame);
+ frm.can_id &= CAN_SFF_MASK;
+ return mAdapter->sendFrame(frm);
+ }
+ return false;
+}
+
+bool CANBus::Impl::sendExtendedFrame(const can_frame& frame)
+{
+ LOG_TRACE("");
+
+ if(mAdapter) {
+ struct can_frame frm(frame);
+ frm.can_id &= CAN_EFF_MASK;
+ frm.can_id |= CAN_EFF_FLAG;
+ return mAdapter->sendFrame(frm);
+ }
+ return false;
+}
+
+void CANBus::Impl::init()
+{
+ mAdapter = CANAdapter::createCANAdapter(mObserver);
+}
+
+//----------------------------------------------------------------------------
+// CANBus
+//----------------------------------------------------------------------------
+
+CANBus::CANBus(CANObserver& observer) :
+ d(new CANBus::Impl(observer))
+{
+ LOG_TRACE("");
+}
+
+CANBus::~CANBus()
+{
+ LOG_TRACE("");
+
+ if(d) {
+ delete d;
+ d = 0;
+ }
+}
+
+bool CANBus::start(const char* name)
+{
+ LOG_TRACE("");
+
+ return d ? d->start(name) : false;
+}
+
+void CANBus::stop()
+{
+ LOG_TRACE("");
+
+ if(d)
+ d->stop();
+}
+
+bool CANBus::sendStandardFrame(const can_frame& frame)
+{
+ LOG_TRACE("");
+
+ return d ? d->sendStandardFrame(frame) : false;
+}
+
+bool CANBus::sendExtendedFrame(const can_frame& frame)
+{
+ LOG_TRACE("");
+
+ return d ? d->sendExtendedFrame(frame) : false;
+}
diff --git a/plugins/common/canbusimpl.h b/plugins/common/canbusimpl.h
new file mode 100644
index 00000000..e2ccdd9c
--- /dev/null
+++ b/plugins/common/canbusimpl.h
@@ -0,0 +1,98 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef CANBUSIMPL_H
+#define CANBUSIMPL_H
+
+/**
+ * \addtogroup libcanbus
+ * @{
+ */
+
+#include "canbus.h"
+
+class CANObserver;
+class CANAdapter;
+
+/**
+* \brief CANBus class implementation
+*
+* @class CANBus::Impl
+*/
+
+class CANBus::Impl
+{
+public:
+ /**
+ * @param observer \link #CANObserver Observer \endlink that will receives CAN bus frames
+ */
+ Impl(CANObserver& observer);
+ virtual ~Impl();
+
+ /**
+ * Starts the CAN bus instance on the specified interface
+ * @fn start
+ * @param name Name of the CAN bus network interface
+ * @return True if no error occurs.
+ */
+ bool start(const char*name);
+ /**
+ * Stops the CAN bus instance
+ * @fn stop
+ */
+ void stop();
+ /**
+ * Sends standard(11bit) CAN frame over the bus
+ * @fn sendStandardFrame
+ * @param frame CAN frame to be sent
+ * @return True if frame was sent
+ */
+ bool sendStandardFrame(const can_frame& frame);
+ /**
+ * Sends extended(29bit) CAN frame over the bus
+ * @fn sendExtendedFrame
+ * @param frame CAN frame to be sent
+ * @return True if frame was sent
+ */
+ bool sendExtendedFrame(const can_frame& frame);
+
+protected:
+ /**
+ * CAN bus initialization
+ * @fn init
+ */
+ virtual void init();
+
+private:
+ /**
+ * #CANObserver instance reference
+ * @property mObserver
+ * @protected
+ */
+ CANObserver& mObserver;
+ /**
+ * Pointer to #CANAdapter - CAN hardware object representation
+ * @property mAdapter
+ * @protected
+ */
+ CANAdapter* mAdapter;
+};
+
+#endif // CANBUSIMPL_H
+
+/** @} */
diff --git a/plugins/common/canobserver.h b/plugins/common/canobserver.h
new file mode 100644
index 00000000..cf4b4e4f
--- /dev/null
+++ b/plugins/common/canobserver.h
@@ -0,0 +1,91 @@
+/*****************************************************************
+ * INTEL CONFIDENTIAL
+ * Copyright 2011 - 2013 Intel Corporation All Rights Reserved.
+ *
+ * The source code contained or described herein and all documents related to the
+ * source code("Material") are owned by Intel Corporation or its suppliers or
+ * licensors.Title to the Material remains with Intel Corporation or its
+ * suppliers and licensors.The Material may contain trade secrets and proprietary
+ * and confidential information of Intel Corporation and its suppliers and
+ * licensors, and is protected by worldwide copyright and trade secret laws and
+ * treaty provisions.No part of the Material may be used, copied, reproduced,
+ * modified, published, uploaded, posted, transmitted, distributed, or disclosed
+ * in any way without Intels prior express written permission.
+ * No license under any patent, copyright, trade secret or other intellectual
+ * property right is granted to or conferred upon you by disclosure or delivery
+ * of the Materials, either expressly, by implication, inducement, estoppel or
+ * otherwise.Any license under such intellectual property rights must be
+ * express and approved by Intel in writing.
+ *
+ * Unless otherwise agreed by Intel in writing, you may not remove or alter this
+ * notice or any other notice embedded in Materials by Intel or Intels suppliers
+ * or licensors in any way.
+ *****************************************************************/
+
+#ifndef CANOBSERVER_H
+#define CANOBSERVER_H
+
+/**
+ * \addtogroup libcanbus
+ * @{
+ */
+
+#include <linux/can.h>
+
+/**
+* \brief Interface. Receives notifications about the CAN bus traffic and errors.
+*
+* CANBus user has to derive from this interface.
+* @class CANObserver
+*/
+
+class CANObserver
+{
+public:
+ /**
+ * General CAN bus error. Currently only GENERAL_ERROR is specified.
+ * @enum CANError
+ * @public
+ */
+ enum CANError {
+ GENERAL_ERROR = 0
+ };
+
+ virtual ~CANObserver(){} /*LCOV_EXCL_LINE*/
+ /**
+ * Called when error occurred on the bus.
+ * @fn errorOccured
+ * @param error Bus error code
+ */
+ virtual void errorOccured(CANObserver::CANError error) = 0; /* socket error */
+ /**
+ * Called when standard frame was is received from the bus.
+ * @fn standardFrameReceived
+ * @param frame Received frame
+ */
+ virtual void standardFrameReceived(const can_frame& frame) = 0; /* SFF was present */
+ /**
+ * Called when extended frame was is received from the bus.
+ * @fn extendedFrameReceived
+ * @param frame Received frame
+ */
+ virtual void extendedFrameReceived(const can_frame& frame) = 0; /* EFF was present */
+ /**
+ * Called when error frame was received from the bus.
+ * @fn errorFrameReceived
+ * @param frame Error frame
+ */
+ virtual void errorFrameReceived(const can_frame& frame) = 0; /* error frame */
+ /**
+ * Called when remote transmission frame was received from the bus.
+ * @fn remoteTransmissionRequest
+ * @param frame RTR frame
+ */
+ virtual void remoteTransmissionRequest(const can_frame& frame) = 0; /* remote transmission request (SFF/EFF is still present)*/
+
+};
+
+#endif // CANOBSERVER_H
+
+/** @} */
+
diff --git a/plugins/common/cansocket.cpp b/plugins/common/cansocket.cpp
new file mode 100644
index 00000000..b59c6bd5
--- /dev/null
+++ b/plugins/common/cansocket.cpp
@@ -0,0 +1,158 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include "logger.h"
+#include "cansocket.h"
+
+
+CANSocket::CANSocket() :
+ mSocket(-1)
+{
+ LOG_TRACE("");
+}
+
+CANSocket::~CANSocket()
+{
+ LOG_TRACE("");
+
+ stop();
+}
+
+bool CANSocket::start(const char* ifName)
+{
+ LOG_TRACE("");
+
+ if(mSocket < 0) {
+ if(!createSocket()) {
+ LOG_ERROR("Socket error");
+ } else {
+ can_err_mask_t errorMask = 0xFFFFFFFF;
+ if(!enableCANErrors(errorMask)) {
+ LOG_ERROR("Socket error");
+ } else {
+ mPoll.fd = mSocket;
+ mPoll.events = POLLIN | POLLPRI;
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, ifName);
+ if(!locateInterfaceIndex(ifr)) {
+ LOG_ERROR("Socket error");
+ stop();
+ } else {
+ struct sockaddr_can addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.can_family = AF_CAN;
+ addr.can_ifindex = ifr.ifr_ifindex;
+ if(!bindSocket(addr)) {
+ LOG_ERROR("Socket error");
+ stop();
+ } else {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void CANSocket::stop()
+{
+ LOG_TRACE("");
+
+ if(mSocket >= 0) {
+ closeSocket();
+ mSocket = -1;
+ }
+}
+
+bool CANSocket::write(const struct can_frame &frame, int &bytesWritten)
+{
+ LOG_TRACE("");
+
+ bytesWritten = (int)writeFrame(frame);
+ return bytesWritten == sizeof(struct can_frame);
+}
+
+CANSocket::CANSocketReadSuccess CANSocket::read(
+ struct can_frame& frame, int &bytesRead, unsigned int timeout)
+{
+ LOG_TRACE("timeout: " << timeout);
+
+ CANSocket::CANSocketReadSuccess success;
+
+ switch(waitData(timeout)) {
+ case -1:
+ LOG_ERROR("reading error");
+ success = CANSocket::READING_FAILED;
+ break;
+ case 0:
+ bytesRead = 0;
+ success = CANSocket::READING_TIMED_OUT;
+ break;
+ default:
+ bytesRead = (int)readFrame(frame);
+ success = bytesRead >= 0 ?CANSocket::READING_SUCCEEDED : CANSocket::READING_FAILED;
+ }
+ return success;
+}
+
+bool CANSocket::createSocket()
+{
+ return ((mSocket = ::socket(PF_CAN, SOCK_RAW, CAN_RAW)) >= 0);
+}
+
+bool CANSocket::enableCANErrors(can_err_mask_t errorMask)
+{
+ return (setsockopt(mSocket, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &errorMask, sizeof(errorMask)) == 0);
+}
+
+bool CANSocket::locateInterfaceIndex(struct ifreq& ifr)
+{
+ return (::ioctl(mSocket, SIOCGIFINDEX, &ifr) == 0);
+}
+
+bool CANSocket::bindSocket(struct sockaddr_can& addr)
+{
+ return (::bind(mSocket, (struct sockaddr*)&addr, sizeof(addr)) == 0);
+}
+
+bool CANSocket::closeSocket()
+{
+ return (::close(mSocket) == 0);
+}
+
+int CANSocket::waitData(unsigned int timeout)
+{
+ return ::poll(&mPoll, 1, timeout);
+}
+
+ssize_t CANSocket::writeFrame(const can_frame& frame)
+{
+ return ::write(mSocket, &frame, sizeof(struct can_frame));
+}
+
+ssize_t CANSocket::readFrame(can_frame& frame)
+{
+ return ::recv(mSocket, &frame, sizeof(struct can_frame), 0);
+}
diff --git a/plugins/common/cansocket.h b/plugins/common/cansocket.h
new file mode 100644
index 00000000..f6eaa50a
--- /dev/null
+++ b/plugins/common/cansocket.h
@@ -0,0 +1,116 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef CANSOCKET_H
+#define CANSOCKET_H
+
+/**
+ * \addtogroup libcanbus
+ * @{
+ */
+
+#include <net/if.h>
+#include <sys/poll.h>
+#include <string>
+#include <linux/can/raw.h>
+
+/**
+* \brief CAN Socket wrapper.
+* @class CANSocket
+*/
+class CANSocket
+{
+public:
+
+ /**
+ * CAN bus socket error.
+ * @enum CANSocketReadSuccess
+ * @public
+ */
+ enum CANSocketReadSuccess {
+ READING_FAILED = -1,
+ READING_TIMED_OUT,
+ READING_SUCCEEDED
+ };
+
+public:
+ CANSocket();
+ virtual ~CANSocket();
+
+ /**
+ * Opens and initialize CAN socket
+ * @fn start
+ * @param ifName Name of the CAN bus network interface.
+ * @return True if no error occurs.
+ */
+ virtual bool start(const char* ifName);
+ /**
+ * Closes socket
+ * @fn stop
+ */
+ virtual void stop();
+ /**
+ * Writes CAN frame using the socket
+ * @fn write
+ * @param frame CAN frame buffer
+ * @param bytesWritten Number of written bytes.
+ * @return True if no error occurs.
+ */
+ virtual bool write(const struct can_frame &frame, int &bytesWritten);
+
+ /**
+ * Try to read CAN frame
+ * @fn read
+ * @param frame CAN frame buffer
+ * @param bytesRead Number of read bytes.
+ * @param timeout Timeout for reading.
+ * @return Reading operation status code.
+ */
+ virtual CANSocket::CANSocketReadSuccess read( struct can_frame& frame, int &bytesRead, unsigned int timeout = 1000);
+
+private:
+ /**
+ * @internal
+ */
+ virtual bool createSocket();
+ virtual bool enableCANErrors(can_err_mask_t errorMask);
+ virtual bool locateInterfaceIndex(struct ifreq& ifr);
+ virtual bool bindSocket(struct sockaddr_can &addr);
+ virtual bool closeSocket();
+ virtual int waitData(unsigned int timeout);
+ virtual ssize_t writeFrame(const struct can_frame &frame);
+ virtual ssize_t readFrame(struct can_frame& frame);
+
+private:
+ /**
+ * Socket file descriptor.
+ * @property mSocket
+ * @private
+ */
+ int mSocket;
+ /**
+ * Data structure describing a polling request.
+ * @property mPoll
+ * @private
+ */
+ struct pollfd mPoll;
+};
+
+#endif // CANSOCKET_H
+
+/** @} */
diff --git a/plugins/common/cansocketadapter.cpp b/plugins/common/cansocketadapter.cpp
new file mode 100644
index 00000000..fded5a22
--- /dev/null
+++ b/plugins/common/cansocketadapter.cpp
@@ -0,0 +1,98 @@
+/*****************************************************************
+ * INTEL CONFIDENTIAL
+ * Copyright 2011 - 2013 Intel Corporation All Rights Reserved.
+ *
+ * The source code contained or described herein and all documents related to the
+ * source code("Material") are owned by Intel Corporation or its suppliers or
+ * licensors.Title to the Material remains with Intel Corporation or its
+ * suppliers and licensors.The Material may contain trade secrets and proprietary
+ * and confidential information of Intel Corporation and its suppliers and
+ * licensors, and is protected by worldwide copyright and trade secret laws and
+ * treaty provisions.No part of the Material may be used, copied, reproduced,
+ * modified, published, uploaded, posted, transmitted, distributed, or disclosed
+ * in any way without Intels prior express written permission.
+ * No license under any patent, copyright, trade secret or other intellectual
+ * property right is granted to or conferred upon you by disclosure or delivery
+ * of the Materials, either expressly, by implication, inducement, estoppel or
+ * otherwise.Any license under such intellectual property rights must be
+ * express and approved by Intel in writing.
+ *
+ * Unless otherwise agreed by Intel in writing, you may not remove or alter this
+ * notice or any other notice embedded in Materials by Intel or Intels suppliers
+ * or licensors in any way.
+ *****************************************************************/
+
+#include "cansocketadapter.h"
+#include "cansocket.h"
+#include "canobserver.h"
+#include "cansocketreader.h"
+#include "logger.h"
+
+// TODO: handle socket errors
+
+CANSocketAdapter::CANSocketAdapter(CANObserver& observer) :
+ CANAdapter(observer),
+ mSocket(NULL),
+ mReader(NULL)
+{
+ LOG_TRACE("");
+}
+
+CANSocketAdapter::~CANSocketAdapter()
+{
+ LOG_TRACE("");
+
+ stop();
+}
+
+bool CANSocketAdapter::start(const char* ifName)
+{
+ LOG_TRACE("");
+
+ if(!mSocket || !mReader) {
+ init();
+ }
+
+ if(mSocket && mReader && mSocket->start(ifName) && mReader->start()) {
+ return true;
+ }
+
+ stop();
+ return false;
+}
+
+void CANSocketAdapter::stop()
+{
+ LOG_TRACE("");
+
+ if(mReader) {
+ mReader->stop();
+ delete mReader;
+ mReader = 0;
+ }
+ if(mSocket) {
+ mSocket->stop();
+ delete mSocket;
+ mSocket = 0;
+ }
+}
+
+bool CANSocketAdapter::sendFrame(const can_frame& frame)
+{
+ LOG_TRACE("");
+
+ if(mSocket) {
+ int bytesWritten(0);
+ return mSocket->write(frame, bytesWritten);
+ }
+ return false;
+}
+
+void CANSocketAdapter::init()
+{
+ if(!mSocket)
+ mSocket = new CANSocket();
+ if(!mReader)
+ mReader = new CANSocketReader(mObserver, *mSocket);
+}
+
diff --git a/plugins/common/cansocketadapter.h b/plugins/common/cansocketadapter.h
new file mode 100644
index 00000000..cb73404b
--- /dev/null
+++ b/plugins/common/cansocketadapter.h
@@ -0,0 +1,98 @@
+/*****************************************************************
+ * INTEL CONFIDENTIAL
+ * Copyright 2011 - 2013 Intel Corporation All Rights Reserved.
+ *
+ * The source code contained or described herein and all documents related to the
+ * source code("Material") are owned by Intel Corporation or its suppliers or
+ * licensors.Title to the Material remains with Intel Corporation or its
+ * suppliers and licensors.The Material may contain trade secrets and proprietary
+ * and confidential information of Intel Corporation and its suppliers and
+ * licensors, and is protected by worldwide copyright and trade secret laws and
+ * treaty provisions.No part of the Material may be used, copied, reproduced,
+ * modified, published, uploaded, posted, transmitted, distributed, or disclosed
+ * in any way without Intels prior express written permission.
+ * No license under any patent, copyright, trade secret or other intellectual
+ * property right is granted to or conferred upon you by disclosure or delivery
+ * of the Materials, either expressly, by implication, inducement, estoppel or
+ * otherwise.Any license under such intellectual property rights must be
+ * express and approved by Intel in writing.
+ *
+ * Unless otherwise agreed by Intel in writing, you may not remove or alter this
+ * notice or any other notice embedded in Materials by Intel or Intels suppliers
+ * or licensors in any way.
+ *****************************************************************/
+
+#ifndef CANSOCKETADAPTER_H
+#define CANSOCKETADAPTER_H
+
+/**
+ * \addtogroup libcanbus
+ * @{
+ */
+
+#include "canadapter.h"
+
+class CANObserver;
+class CANSocket;
+class CANSocketReader;
+
+/**
+* \brief Socket CAN device implementation based on <a href="http://developer.berlios.de/projects/socketcan">BerliOS Socket CAN</a> API.
+*
+* @class CANSocketAdapter
+*/
+class CANSocketAdapter : public CANAdapter
+{
+public:
+ /**
+ * @param observer @link CANObserver Observer @endlink that will receives CAN bus frames
+ */
+ CANSocketAdapter(CANObserver& observer);
+ virtual ~CANSocketAdapter();
+
+ /**
+ * Creates connection the specified network interface and starts listening on it.
+ * @fn start
+ * @param ifName Name of the CAN bus network interface
+ * @return True if no error occurs.
+ */
+ virtual bool start(const char* ifName);
+ /**
+ * Closes socket connection and exits listening thread.
+ * @fn stop
+ */
+ virtual void stop();
+ /**
+ * Sends CAN frame over the socket CAN interface
+ * @fn sendFrame
+ * @param frame CAN frame to be sent
+ * @return True if frame was sent
+ */
+ virtual bool sendFrame(const can_frame& frame);
+
+protected:
+ /**
+ * Socket initialization and starts reading thread
+ * @fn init
+ * @protected
+ */
+ virtual void init();
+
+private:
+ /**
+ * @link CANSocket CAN Socket wrapper @endlink instance reference
+ * @property mSocket
+ * @protected
+ */
+ CANSocket* mSocket;
+ /**
+ * @link CANSocketReader CANSocket reader @endlink instance reference
+ * @property mReader
+ * @protected
+ */
+ CANSocketReader* mReader;
+};
+
+#endif // CANSOCKETADAPTER_H
+
+/** @} */
diff --git a/plugins/common/cansocketreader.cpp b/plugins/common/cansocketreader.cpp
new file mode 100644
index 00000000..a9663e7f
--- /dev/null
+++ b/plugins/common/cansocketreader.cpp
@@ -0,0 +1,95 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "logger.h"
+#include "cansocket.h"
+#include "cansocketreader.h"
+
+CANSocketReader::CANSocketReader(CANObserver& observer, CANSocket& socket) :
+ mObserver(observer),
+ mSocket(socket)
+{
+ LOG_TRACE("");
+}
+
+CANSocketReader::~CANSocketReader()
+{
+ LOG_TRACE("");
+
+ stop();
+}
+
+bool CANSocketReader::start()
+{
+ LOG_TRACE("");
+
+ return CUtil::Thread::start();
+}
+
+void CANSocketReader::stop()
+{
+ LOG_TRACE("");
+
+ CUtil::Thread::stop();
+ return;
+}
+
+void CANSocketReader::run()
+{
+ LOG_TRACE("");
+
+ while(isRunnable()) {
+
+ struct can_frame frame;
+ int bytesRead;
+
+ CANSocket::CANSocketReadSuccess success = mSocket.read(frame, bytesRead);
+
+ switch(success) {
+ case CANSocket::READING_FAILED:
+ LOG_ERROR("reading failed");
+ mObserver.errorOccured(CANObserver::GENERAL_ERROR);
+ return;
+ case CANSocket::READING_TIMED_OUT:
+ // read again
+ break;
+ default: //CANSocketWrapper::READING_SUCCEEDED
+ if(frame.can_id & CAN_ERR_FLAG) {
+ frame.can_id &= (CAN_ERR_FLAG|CAN_ERR_MASK);
+ mObserver.errorFrameReceived(frame);
+ }
+ else if(frame.can_id & CAN_RTR_FLAG){
+ if(!(frame.can_id & CAN_EFF_FLAG)){
+ frame.can_id &= CAN_SFF_MASK;
+ }
+ else{
+ frame.can_id &= (~CAN_RTR_FLAG);
+ }
+ mObserver.remoteTransmissionRequest(frame);
+ }
+ else if(frame.can_id & CAN_EFF_FLAG){
+ frame.can_id &= CAN_EFF_MASK;
+ mObserver.extendedFrameReceived(frame);
+ }
+ else{
+ frame.can_id &= CAN_SFF_MASK;
+ mObserver.standardFrameReceived(frame);
+ }
+ }
+ }
+}
diff --git a/plugins/common/cansocketreader.h b/plugins/common/cansocketreader.h
new file mode 100644
index 00000000..623430ae
--- /dev/null
+++ b/plugins/common/cansocketreader.h
@@ -0,0 +1,86 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef CANSOCKETREADER_H
+#define CANSOCKETREADER_H
+
+/**
+ * \addtogroup libcanbus
+ * @{
+ */
+
+#include <sys/socket.h>
+
+#include "thread.h"
+#include "canobserver.h"
+
+class CANSocket;
+/**
+* \brief Asynchronous socket CAN reader.
+*
+* @class CANSocketReader
+*/
+class CANSocketReader : public CUtil::Thread
+{
+public:
+ /**
+ * @param observer @link CANObserver Observer @endlink that will receives CAN bus frames.
+ * @param socket @link CANSocket CAN Socket wrapper @endlink
+ */
+ CANSocketReader(CANObserver& observer, CANSocket& socket);
+ virtual ~CANSocketReader();
+
+ /**
+ * Starts a new thread for listening to CAN bus.
+ * @fn start
+ * @return True if no error occurs.
+ */
+
+ virtual bool start();
+ /**
+ * Stops listening thread.
+ * @fn stop
+ */
+
+ virtual void stop();
+
+private:
+ /**
+ * Listening thread's main function.
+ * @fn run
+ */
+ virtual void run();
+
+private:
+ /**
+ * #CANObserver instance reference
+ * @property mObserver
+ * @protected
+ */
+ CANObserver& mObserver;
+ /**
+ * @link CANSocket CAN Socket wrapper @endlink instance reference
+ * @property mSocket
+ * @protected
+ */
+ CANSocket& mSocket;
+};
+
+#endif // CANSOCKETREADER_H
+
+/** @} */
diff --git a/plugins/common/dbusexport.cpp b/plugins/common/dbusexport.cpp
new file mode 100644
index 00000000..e83883a9
--- /dev/null
+++ b/plugins/common/dbusexport.cpp
@@ -0,0 +1,9 @@
+#include "dbusexport.h"
+
+
+amb::Exporter* amb::Exporter::mInstance = nullptr;
+
+amb::Exporter::Exporter()
+{
+
+}
diff --git a/plugins/common/dbusexport.h b/plugins/common/dbusexport.h
new file mode 100644
index 00000000..15a9b96d
--- /dev/null
+++ b/plugins/common/dbusexport.h
@@ -0,0 +1,136 @@
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <listplusplus.h>
+#include <abstractsink.h>
+#include <abstractroutingengine.h>
+
+#include "varianttype.h"
+
+#define DBusConnected "DBusConnected"
+
+namespace amb
+{
+
+class Exporter
+{
+public:
+
+ std::shared_ptr<GDBusConnection> connection;
+
+ std::unordered_map<std::string, std::unordered_set<Zone::Type>> getUniqueSourcesList(AbstractRoutingEngine *re, PropertyList implementedProperties)
+ {
+ std::unordered_map<std::string, std::unordered_set<Zone::Type>> uniqueSourcesList;
+
+ for(auto property : implementedProperties)
+ {
+ std::vector<std::string> sources = re->sourcesForProperty(property);
+
+ for(auto source : sources)
+ {
+ PropertyInfo info = re->getPropertyInfo(property, source);
+
+ std::unordered_set<Zone::Type> uniqueZoneList;
+
+ if(uniqueSourcesList.count(source))
+ {
+ uniqueZoneList = uniqueSourcesList[source];
+ }
+
+ Zone::ZoneList zoneList = info.zones();
+
+ if(!zoneList.size())
+ {
+ uniqueZoneList.emplace(Zone::None);
+ }
+
+ for(auto zoneItr : zoneList)
+ {
+ uniqueZoneList.emplace(zoneItr);
+ }
+
+ uniqueSourcesList[source] = uniqueZoneList;
+ }
+ }
+
+ return uniqueSourcesList;
+ }
+
+ template <typename T>
+ void exportProperty(std::string interfaceName, std::unordered_map<std::string, std::string> properties, AbstractRoutingEngine *re)
+ {
+ T* t = new T(interfaceName, re, connection.get());
+
+ std::string prop = t->objectName();
+
+ for(auto props : properties)
+ {
+ t->wantPropertyVariant(props.first, props.second, VariantType::ReadWrite);
+ }
+
+ PropertyList implementedProperties = t->wantsProperties();
+
+ std::unordered_map<std::string, std::unordered_set<Zone::Type> > uniqueSourcesList = getUniqueSourcesList(re, implementedProperties);
+
+ delete t;
+
+ PropertyList supported = re->supported();
+
+ for(auto itr : uniqueSourcesList)
+ {
+ std::unordered_set<Zone::Type> zones = itr.second;
+
+ std::string source = itr.first;
+
+ std::string objectPath = "/" + source;
+
+ boost::algorithm::erase_all(objectPath, "-");
+
+ for(auto zone : zones)
+ {
+ T* t = new T(prop, re, connection.get());
+
+ for(auto props : properties)
+ {
+ t->wantPropertyVariant(props.first, props.second, VariantType::ReadWrite);
+ }
+
+ std::stringstream fullobjectPath;
+ fullobjectPath<< objectPath << "/" << zone << "/" <<t->objectName();
+ t->setObjectPath(fullobjectPath.str());
+ t->setSourceFilter(source);
+ t->setZoneFilter(zone);
+ t->supportedChanged(supported);
+ }
+
+ }
+ }
+
+ template <typename T>
+ void exportProperty(AbstractRoutingEngine *re)
+ {
+ exportProperty<T>("", std::unordered_map<std::string, std::string>(), re);
+ }
+
+ template <typename T>
+ void exportProperty(VehicleProperty::Property prop, AbstractRoutingEngine *re)
+ {
+ exportProperty<T>(prop, std::unordered_map<std::string, std::string>(), re);
+ }
+
+ static Exporter * instance()
+ {
+ if(mInstance)
+ return mInstance;
+ return mInstance = new Exporter();
+ }
+
+protected:
+ Exporter();
+
+private:
+ static Exporter* mInstance;
+
+};
+
+}
diff --git a/plugins/common/dbusplugin.cpp b/plugins/common/dbusplugin.cpp
new file mode 100644
index 00000000..e56b403b
--- /dev/null
+++ b/plugins/common/dbusplugin.cpp
@@ -0,0 +1,99 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "dbusplugin.h"
+
+#include <boost/lexical_cast.hpp>
+#include <map>
+#include <string>
+
+#include "abstractroutingengine.h"
+#include "debugout.h"
+#include "listplusplus.h"
+
+std::map<std::string, std::string> DBusSink::dbusConfig;
+
+DBusSink::DBusSink(std::string propertyName, AbstractRoutingEngine* engine, GDBusConnection* connection, std::map<std::string, std::string> config)
+ :AbstractDBusInterface("org.automotive."+propertyName, propertyName, connection),
+ AbstractSink(engine, dbusConfig)
+{
+ AbstractDBusInterface::re = engine;
+
+ int timeout = 60;
+
+ if(configuration.find("frequency") != configuration.end())
+ {
+ int t = boost::lexical_cast<int>(configuration["frequency"]);
+
+ timeout = 1000 / t;
+ }
+
+ setTimeout(timeout);
+}
+
+void DBusSink::supportedChanged(const PropertyList &supportedProperties)
+{
+ startRegistration();
+
+ for(auto itr : propertyDBusMap)
+ {
+ if(contains(supportedProperties, itr->ambPropertyName()))
+ {
+ PropertyInfo info = re->getPropertyInfo(itr->ambPropertyName(), mSourceFilter);
+
+ if (!info.isValid() || !contains(info.zones(), zoneFilter))
+ {
+ continue;
+ }
+
+ VariantType* prop = itr;
+ prop->setSourceFilter(mSourceFilter);
+ prop->setZoneFilter(zoneFilter);
+ prop->initialize();
+ VehicleProperty::Property p = itr->ambPropertyName();
+ routingEngine->subscribeToProperty(p, mSourceFilter, this);
+ addProperty(prop);
+ supported = true;
+ mTime = amb::currentTime();
+ }
+ }
+}
+
+void DBusSink::propertyChanged(AbstractPropertyType *value)
+{
+ VehicleProperty::Property property = value->name;
+
+ if( value->zone != zoneFilter)
+ return;
+
+ for(auto i : propertyDBusMap)
+ {
+ if(i->ambPropertyName() == property)
+ {
+ VariantType* prop = i;
+ mTime = value->timestamp;
+ prop->updateValue(value);
+ updateValue(prop);
+ }
+ }
+}
+
+const string DBusSink::uuid()
+{
+ return "c2e6cafa-eef5-4b8a-99a0-0f2c9be1057d";
+}
diff --git a/plugins/common/dbusplugin.h b/plugins/common/dbusplugin.h
new file mode 100644
index 00000000..21fa5fdc
--- /dev/null
+++ b/plugins/common/dbusplugin.h
@@ -0,0 +1,74 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef DBUSSINK_H_
+#define DBUSSINK_H_
+
+#include "abstractsink.h"
+#include "abstractdbusinterface.h"
+#include "varianttype.h"
+
+#include <map>
+
+class DBusSink : public AbstractSink, public AbstractDBusInterface
+{
+
+public:
+ DBusSink(std::string objectName, AbstractRoutingEngine* engine, GDBusConnection* connection, map<string, string> config = std::map<std::string, std::string>());
+ virtual ~DBusSink()
+ {
+ for(auto i : propertyDBusMap)
+ {
+ delete i;
+ }
+ }
+ virtual void supportedChanged(const PropertyList & supportedProperties);
+ virtual void propertyChanged(AbstractPropertyType *value);
+ virtual const std::string uuid();
+
+ static std::map<std::string, std::string> dbusConfig;
+
+ PropertyList wantsProperties()
+ {
+ PropertyList l;
+ for(auto i : propertyDBusMap)
+ {
+ l.push_back(i->ambPropertyName());
+ }
+
+ return l;
+ }
+
+ void setSourceFilter(std::string sourceFilter)
+ {
+ mSourceFilter = sourceFilter;
+ }
+
+ void setZoneFilter(Zone::Type zone)
+ {
+ zoneFilter = zone;
+ }
+
+ void wantPropertyVariant(VehicleProperty::Property ambProperty, std::string propertyName, VariantType::Access access)
+ {
+ propertyDBusMap.push_back(new VariantType(routingEngine, ambProperty, propertyName, access));
+ }
+
+};
+
+#endif
diff --git a/plugins/common/dbussignaller.cpp b/plugins/common/dbussignaller.cpp
new file mode 100644
index 00000000..b016bd94
--- /dev/null
+++ b/plugins/common/dbussignaller.cpp
@@ -0,0 +1,3 @@
+#include "dbussignaller.h"
+
+DBusSignaller* DBusSignaller::singleton = nullptr;
diff --git a/plugins/common/dbussignaller.h b/plugins/common/dbussignaller.h
new file mode 100644
index 00000000..fb82383d
--- /dev/null
+++ b/plugins/common/dbussignaller.h
@@ -0,0 +1,163 @@
+#ifndef _DBUSSIGNALLER_H_
+#define _DBUSSIGNALLER_H_
+
+#include <gio/gio.h>
+
+#include <vector>
+#include <string>
+#include <memory>
+#include <unordered_map>
+
+#include "debugout.h"
+#include "varianttype.h"
+#include "superptr.hpp"
+#include "listplusplus.h"
+
+class DBusSignal
+{
+public:
+ DBusSignal():connection(nullptr), property(nullptr){}
+ DBusSignal(GDBusConnection* conn, const std::string & objPath, const std::string & iface, const std::string & sigName, VariantType* var)
+ : connection(conn), objectPath(objPath), interface(iface), signalName(sigName), property(var)
+ {
+
+ }
+
+ ~DBusSignal()
+ {
+
+ }
+
+ bool operator == (const DBusSignal &other) const
+ {
+ return connection == other.connection &&
+ objectPath == other.objectPath &&
+ interface == other.interface &&
+ signalName == other.signalName &&
+ property == other.property;
+ }
+
+ GDBusConnection* connection;
+ std::string objectPath;
+ std::string interface;
+ std::string signalName;
+ VariantType* property;
+};
+
+class DBusSignaller
+{
+public:
+
+ static DBusSignaller* factory(int timeout)
+ {
+ if(!singleton)
+ return singleton = new DBusSignaller(timeout);
+ return singleton;
+ }
+
+ void fireSignal(GDBusConnection* conn, const std::string & objPath, const std::string & iface,
+ const std::string & sigName, VariantType* prop)
+ {
+ DBusSignal * signal = new DBusSignal(conn, objPath, iface, sigName, prop);
+
+ if(queue.find(objPath) != queue.end())
+ {
+ bool isFound = false;
+ for(auto i : queue[objPath])
+ {
+ if(*i == *signal)
+ {
+ isFound = true;
+ break;
+ }
+ }
+
+ if(!isFound)
+ queue[objPath].push_back(signal);
+ }
+ else
+ {
+ queue[objPath].push_back(signal);
+ }
+ }
+
+private:
+
+ DBusSignaller() { }
+
+ DBusSignaller(int timeout)
+ {
+ g_timeout_add(timeout,[](gpointer userData)
+ {
+ std::unordered_map<std::string, std::vector<DBusSignal*>> *q = static_cast<std::unordered_map<std::string, std::vector<DBusSignal*>>*>(userData);
+ std::unordered_map<std::string, std::vector<DBusSignal*>> queue = *q;
+
+ for(auto itr : queue)
+ {
+ std::string objectPath;
+ GDBusConnection* connection;
+ std::string interfaceName;
+ std::string signalName;
+
+ std::unordered_map<std::string, GVariant*> variantMap;
+
+ for(auto s : itr.second)
+ {
+ std::unique_ptr<DBusSignal> signal(s);
+ objectPath = signal->objectPath;
+ connection = signal->connection;
+ interfaceName = signal->interface;
+ signalName = signal->signalName;
+
+ VariantType* property = signal->property;
+
+ auto val = g_variant_ref(property->toVariant());
+ std::string sequenceName = property->name() + "Sequence";
+
+ variantMap[property->name()] = val;
+ variantMap[sequenceName] = g_variant_new("i", property->sequence());
+ variantMap["Time"] = g_variant_new("d", property->timestamp());
+ variantMap["Zone"] = g_variant_new("i", property->zoneFilter());
+ }
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_DICTIONARY);
+
+ for(auto sv : variantMap)
+ {
+ /// Send PropertiesChanged signal
+ auto key = sv.first;
+ auto value = sv.second;
+
+ g_variant_builder_add(&builder, "{sv}", key.c_str(), value);
+ }
+
+ GError* error = nullptr;
+
+ g_dbus_connection_emit_signal(connection, NULL, objectPath.c_str(),
+ "org.freedesktop.DBus.Properties",
+ signalName.c_str(),
+ g_variant_new("(sa{sv}as)", interfaceName.c_str(), &builder, NULL),
+ &error);
+
+ auto errorPtr = amb::make_super(error);
+
+ if(errorPtr)
+ {
+ DebugOut(DebugOut::Error)<<errorPtr->message<<std::endl;
+ }
+ }
+
+ q->clear();
+
+ return 1;
+
+ },&queue);
+ }
+
+ std::unordered_map<std::string, std::vector<DBusSignal*>> queue;
+
+ static DBusSignaller * singleton;
+};
+
+#endif
diff --git a/plugins/common/logger.cpp b/plugins/common/logger.cpp
new file mode 100644
index 00000000..47e92e0e
--- /dev/null
+++ b/plugins/common/logger.cpp
@@ -0,0 +1,226 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <iostream>
+#include <new>
+#include <cstdlib>
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <signal.h>
+
+
+#include "logger.h"
+
+using namespace CUtil;
+
+// Definition (and initialization) of static attributes
+Logger* Logger::m_ = 0;
+
+// Define the function to be called when ctrl-c (SIGINT) signal is sent to process
+void signal_callback_handler(int signum)
+{
+ std::cerr << std::endl << " ... Caught signal " << signum << std::endl;
+
+ Logger::getInstance().flush();
+
+ // Terminate program
+ exit(signum);
+}
+
+
+#ifdef LOGGER_MULTITHREAD
+pthread_mutex_t Logger::lock_ = PTHREAD_MUTEX_INITIALIZER;
+inline void Logger::lock()
+{
+ pthread_mutex_lock(&lock_);
+}
+
+inline void Logger::unlock()
+{
+ pthread_mutex_unlock(&lock_);
+}
+#else
+void Logger::lock(){}
+void Logger::unlock(){}
+#endif
+
+
+
+/**
+ * \brief Constructor.
+ * It is a private constructor, called only by getInstance() and only the
+ * first time. It is called inside a lock, so lock inside this method
+ * is not required.
+ * It only initializes the initial time. All configuration is done inside the
+ * configure() method.
+ */
+Logger::Logger() :
+ configured_(false),
+ logFile_(""),
+ logFileName_(""),
+ configuration_(L_nofile_|L_noscreen_),
+ initialTime_usec_(0)
+{
+ struct timeval initialTime;
+ gettimeofday(&initialTime, NULL);
+ initialTime_usec_ = int64_t(1000000LL*int64_t(initialTime.tv_sec)) + int64_t(initialTime.tv_usec);
+
+}
+
+/**
+ * \brief Method to configure the logger. Called by the DEBUG_CONF() macro.
+ * To make implementation easier, the old stream is always closed.
+ * Then, in case, it is open again in append mode.
+ * @param outputFile Name of the file used for logging.
+ * @param configuration Configuration (i.e., log on file and on screen on or off).
+ * @param fileVerbosityLevel Verbosity threshold for file.
+ * @param screenVerbosityLevel Verbosity threshold for screen.
+ */
+void Logger::configure (const std::string& outputFile,
+ const loggerConf configuration,
+ const int fileVerbosityLevel,
+ const int screenVerbosityLevel)
+{
+ Logger::lock();
+
+ logFileName_ = outputFile;
+ fileVerbosityLevel_ = fileVerbosityLevel;
+ screenVerbosityLevel_ = screenVerbosityLevel;
+
+ // Close the old stream, if needed
+ if (configuration_&file_on)
+ out_.close();
+
+ // Compute a new file name, if needed
+ if (outputFile != logFile_){
+ std::ostringstream oss;
+ /*time_t currTime;
+ time(&currTime);
+ struct tm *currTm = localtime(&currTime);*/
+ oss << outputFile << /*"_" <<
+ (1900 + currTm->tm_year) << "_" <<
+ currTm->tm_mon << "_" <<
+ currTm->tm_mday << "_" <<
+ currTm->tm_hour << "-" <<
+ currTm->tm_min << "-" <<
+ currTm->tm_sec << */
+ ".log";
+ logFile_ = oss.str().c_str();
+ }
+
+ // Open a new stream, if needed
+ if (configuration&file_on)
+ out_.open(logFile_.c_str(), std::ios::app);
+
+ configuration_ = configuration;
+ configured_ = true;
+
+ Logger::unlock();
+
+ // Register signal and signal handler
+ // we need a flush log file at program termination
+ signal(SIGINT, signal_callback_handler);
+ signal(SIGTERM, signal_callback_handler);
+ signal(SIGABRT, signal_callback_handler);
+ signal(SIGKILL, signal_callback_handler);
+
+}
+
+/**
+ * \brief Destructor.
+ * It only closes the file, if open, and cleans memory.
+ */
+
+Logger::~Logger()
+{
+ Logger::lock();
+ if (configuration_&file_on)
+ out_.close();
+ delete m_;
+ Logger::unlock();
+
+}
+
+/**
+ * \brief Method to get a reference to the object (i.e., Singleton)
+ * It is a static method.
+ * @return Reference to the object.
+ */
+Logger& Logger::getInstance()
+{
+ Logger::lock();
+ if (m_ == 0)
+ m_ = new Logger;
+ Logger::unlock();
+ return *m_;
+}
+
+
+/**
+ * \brief Method used to print messages.
+ * Called by the LOGGER() macro.
+ * @param verbosityLevel Priority of the message
+ * @param file Source file where the method has been called (set equal to __FILE__
+ * by the LOGGER macro)
+ * @param line Source line where the method has been called (set equal to __LINE__
+ by the macro)
+ * @param message Message text
+ */
+void Logger::print(const unsigned int verbosityLevel,
+ const std::string& file,
+ const int line,
+ const std::string& message)
+{
+ if (!configured_) {
+ std::cerr << "ERROR: Logger not configured!" <<
+ std::endl;
+ return;
+ }
+
+ if( ((configuration_&file_on) && (verbosityLevel > fileVerbosityLevel_)) &&
+ ((configuration_&screen_on) && (verbosityLevel > screenVerbosityLevel_)) )
+ return;
+
+ struct timeval currentTime;
+ Logger::lock();
+
+ gettimeofday(&currentTime, NULL);
+ int64_t currentTime_usec;
+ currentTime_usec = int64_t(1000000LL*int64_t(currentTime.tv_sec)) + int64_t(currentTime.tv_usec);
+
+ unsigned int li_tid = (unsigned int)pthread_self();
+
+ if ( (configuration_&file_on) && (verbosityLevel <= fileVerbosityLevel_) )
+ out_ << double(currentTime_usec - initialTime_usec_)/1000000.0f <<
+ " (" << std::hex << li_tid << std::dec << ") " <<
+ " [" << file << ":" << line << "] @ " <<
+ message << std::endl;
+
+ if ( (configuration_&screen_on) && (verbosityLevel <= screenVerbosityLevel_) )
+ std::cout <<
+ double(currentTime_usec - initialTime_usec_)/1000000.0f <<
+ " (" << std::hex << li_tid << std::dec << ") " <<
+ logFileName_ << " [" << file << ":" << line << "] @ " <<
+ message << std::endl;
+
+
+ Logger::unlock();
+}
+
+
diff --git a/plugins/common/logger.h b/plugins/common/logger.h
new file mode 100644
index 00000000..820f3d2f
--- /dev/null
+++ b/plugins/common/logger.h
@@ -0,0 +1,296 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef LOGGER_H
+#define LOGGER_H
+
+#include <fstream>
+#include <ostream>
+#include <string>
+#include <sstream>
+#include <sys/time.h>
+#include <sys/types.h>
+
+// Comment this line if you don't need multithread support
+#define LOGGER_MULTITHREAD
+#ifdef LOGGER_MULTITHREAD
+#include <pthread.h>
+#endif
+
+/** \addtogroup libamb-plugins-common
+ * @{
+ */
+
+namespace CUtil {
+
+/**
+ * \brief Simple logger to log messages on file and console.
+ *
+ * This is the implementation of a simple logger in C++. It is implemented
+ * as a Singleton, so it can be easily called through two DEBUG macros.
+ * It is Pthread-safe.
+ * It allows to log on both file and screen, and to specify a verbosity
+ * threshold for both of them.
+ *
+ * @class Logger
+ */
+class Logger
+{
+ /**
+ * Type used for the configuration
+ */
+ enum loggerConf_ {L_nofile_ = 1 << 0,
+ L_file_ = 1 << 1,
+ L_noscreen_ = 1 << 2,
+ L_screen_ = 1 << 3};
+
+#ifdef LOGGER_MULTITHREAD
+ /**
+ * \brief Lock for mutual exclusion between different threads
+ */
+ static pthread_mutex_t lock_;
+#endif
+
+ bool configured_;
+
+ /**
+ * \brief Pointer to the unique Logger (i.e., Singleton)
+ */
+ static Logger* m_;
+
+ /**
+ * \brief Initial part of the name of the file used for Logging.
+ * Date and time are automatically appended.
+ */
+ std::string logFile_;
+
+ /**
+ * \brief Initial part of the name of the file used for Logging.
+ * Date and time are automatically appended.
+ */
+ std::string logFileName_;
+
+ /**
+ * \brief Current configuration of the logger.
+ * Variable to know if logging on file and on screen are enabled.
+ * Note that if the log on file is enabled, it means that the
+ * logger has been already configured, therefore the stream is
+ * already open.
+ */
+ loggerConf_ configuration_;
+
+ /**
+ * \brief Stream used when logging on a file
+ */
+ std::ofstream out_;
+
+ /**
+ * \brief Initial time (used to print relative times)
+ */
+ int64_t initialTime_usec_;
+
+ /**
+ * \brief Verbosity threshold for files
+ */
+ unsigned int fileVerbosityLevel_;
+
+ /**
+ * \brief Verbosity threshold for screen
+ */
+ unsigned int screenVerbosityLevel_;
+
+ Logger();
+ ~Logger();
+
+ /**
+ * \brief Method to lock in case of multithreading
+ */
+ inline static void lock();
+
+ /**
+ * \brief Method to unlock in case of multithreading
+ */
+ inline static void unlock();
+
+public:
+
+ /**
+ * Logging level
+ * \enum Level
+ * \public
+ */
+ enum Level {
+ EError = 0,
+ EWarning,
+ EMessage,
+ EInfo,
+ ETrace,
+ EDebug
+ };
+
+ /**
+ * Macro to create and configure logger.
+ * \def DEBUG_CONF
+ *
+ * Example of configuration of the Logger:
+ * \code
+ * DEBUG_CONF("outputfile", Logger::file_on|Logger::screen_on, DBG_DEBUG, DBG_ERROR);
+ * \endcode
+ */
+ #define DEBUG_CONF(outputFile, \
+ configuration, \
+ fileVerbosityLevel, \
+ screenVerbosityLevel) { \
+ CUtil::Logger::getInstance().configure(outputFile, \
+ configuration, \
+ fileVerbosityLevel, \
+ screenVerbosityLevel); \
+ }
+
+ /**
+ * \brief Macro to print log messages.
+ * \def LOGGER
+ *
+ * Example of usage of the Logger:
+ * \code
+ * LOGGER(DBG_DEBUG, "hello " << "world");
+ * \endcode
+ */
+ #define LOGGER(priority, msg) { \
+ std::ostringstream __debug_stream__; \
+ __debug_stream__ << msg; \
+ CUtil::Logger::getInstance().print(priority, __FILE__, __LINE__, \
+ __debug_stream__.str()); \
+ }
+
+ #ifndef _LOGGER_NO_LOG
+
+ /**
+ * Macro to log errors.
+ * \def LOG_ERROR
+ */
+ #define LOG_ERROR(M) LOGGER(CUtil::Logger::EError, M)
+ /**
+ * Macro to log warnings.
+ * \def LOG_WARNING
+ */
+ #define LOG_WARNING(M) LOGGER(CUtil::Logger::EWarning, M)
+ /**
+ * Macro to log messages.
+ * \def LOG_MESSAGE
+ */
+ #define LOG_MESSAGE(M) LOGGER(CUtil::Logger::EMessage, M)
+ /**
+ * Macro to log info messages.
+ * \def LOG_INFO
+ */
+ #define LOG_INFO(M) LOGGER(CUtil::Logger::EInfo, M)
+ /**
+ * Macro to log trace messages.
+ * \def LOG_TRACE
+ */
+ #define LOG_TRACE(M) LOGGER(CUtil::Logger::ETrace, M)
+ /**
+ * Macro to log debug messages.
+ * \def LOG_DEBUG
+ */
+ #define LOG_DEBUG(M) LOGGER(CUtil::Logger::EDebug, M)
+
+ #else
+
+ #define LOG_ERROR(M) {}
+ #define LOG_WARNING(M) {}
+ #define LOG_MESSAGE(M) {}
+ #define LOG_INFO(M) {}
+ #define LOG_TRACE(M) {}
+ #define LOG_DEBUG(M) {}
+
+ #endif
+
+ /**
+ * Type used for the configuration
+ */
+ typedef loggerConf_ loggerConf;
+ /**
+ * Disable logging to file
+ */
+ static const loggerConf file_on= L_nofile_;
+ /**
+ * Enable logging to file
+ */
+ static const loggerConf file_off= L_file_;
+ /**
+ * Enable logging to screen
+ */
+ static const loggerConf screen_on= L_noscreen_;
+ /**
+ * Disable logging to screen
+ */
+ static const loggerConf screen_off= L_screen_;
+
+ static Logger& getInstance();
+
+ void print(const unsigned int verbosityLevel,
+ const std::string& sourceFile,
+ const int codeLine,
+ const std::string& message);
+
+ void configure (const std::string& outputFile,
+ const loggerConf configuration,
+ const int fileVerbosityLevel,
+ const int screenVerbosityLevel);
+
+ /**
+ * Flush output buffer
+ */
+ inline void flush()
+ {
+ out_.flush();
+ }
+};
+
+/**
+ * operator| - Can be used in Logger::configure
+ * \param __a Configuration (i.e., log on file and on screen on or off).
+ * \param __b Configuration (i.e., log on file and on screen on or off).
+ * \return Configuration (i.e., log on file and on screen on or off).
+ */
+inline Logger::loggerConf operator|
+ (Logger::loggerConf __a, Logger::loggerConf __b)
+{
+ return Logger::loggerConf(static_cast<int>(__a) |
+ static_cast<int>(__b));
+}
+
+/**
+ * operator& - Can be used in Logger::configure
+ * \param __a Configuration (i.e., log on file and on screen on or off).
+ * \param __b Configuration (i.e., log on file and on screen on or off).
+ * \return Configuration (i.e., log on file and on screen on or off).
+ */
+inline Logger::loggerConf operator&
+ (Logger::loggerConf __a, Logger::loggerConf __b)
+{
+ return Logger::loggerConf(static_cast<int>(__a) &
+ static_cast<int>(__b)); }
+
+}
+
+#endif /* LOGGER_H */
+
+/** @} */
diff --git a/plugins/common/mutex.cpp b/plugins/common/mutex.cpp
new file mode 100644
index 00000000..c9195fa7
--- /dev/null
+++ b/plugins/common/mutex.cpp
@@ -0,0 +1,58 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/******************************************************************
+*
+* File: Mutex.cpp
+*
+* Revision;
+* - first revision
+*
+******************************************************************/
+
+#include "mutex.h"
+
+using namespace CUtil;
+
+////////////////////////////////////////////////
+// Mutex
+////////////////////////////////////////////////
+
+Mutex::Mutex()
+{
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init( &attr );
+ pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
+ pthread_mutex_init( &mutexID, &attr );
+ pthread_mutexattr_destroy( &attr );
+}
+
+Mutex::~Mutex()
+{
+ pthread_mutex_destroy( &mutexID );
+}
+
+void Mutex::lock()
+{
+ pthread_mutex_lock( &mutexID );
+}
+
+void Mutex::unlock()
+{
+ pthread_mutex_unlock( &mutexID );
+}
diff --git a/plugins/common/mutex.h b/plugins/common/mutex.h
new file mode 100644
index 00000000..9367d4b1
--- /dev/null
+++ b/plugins/common/mutex.h
@@ -0,0 +1,78 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _CUTIL_MUTEX_H_
+#define _CUTIL_MUTEX_H_
+
+#include <pthread.h>
+
+/**
+ * @defgroup libamb-plugins-common amb-plugins-common static library.
+ * \brief Project common C++ utilities.
+ *
+ * Contains Logger, Thread and Mutex, SerialPort and other utility classes.
+ *
+ * @{
+ */
+
+/**
+ * \brief Project common C++ utilities namespace
+ * @namespace CUtil
+ */
+
+namespace CUtil {
+
+/**
+* \brief Encapsulation of the recursive posix mutex.
+*
+* @class Mutex
+*/
+
+class Mutex
+{
+ /**
+ * Encapsulated posix mutex object
+ * @property mutexID
+ * @private
+ */
+ pthread_mutex_t mutexID;
+
+public:
+
+ Mutex();
+ ~Mutex();
+
+ /**
+ * Locks mutex object
+ * @fn lock
+ * @public
+ */
+ void lock();
+ /**
+ * Unlocks mutex object
+ * @fn unlock
+ * @public
+ */
+ void unlock();
+};
+
+}
+
+#endif
+
+/** @} */
diff --git a/plugins/common/serialport.hpp b/plugins/common/serialport.hpp
new file mode 100644
index 00000000..238a4a48
--- /dev/null
+++ b/plugins/common/serialport.hpp
@@ -0,0 +1,169 @@
+#ifndef _SERIALPORT_H_
+#define _SERIALPORT_H_
+
+#include "abstractio.hpp"
+#include "debugout.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <errno.h>
+#include <stdio.h>
+
+class SerialPort: public AbstractIo
+{
+private:
+ speed_t speed;
+
+public:
+ SerialPort()
+ :fd(0), speed(B9600)
+ {
+
+ }
+
+ SerialPort(int fileDesc)
+ :fd(fileDesc)
+ {
+ speed = B9600;
+
+ setDescriptor(fd);
+ }
+
+ SerialPort(std::string _tty)
+ :tty(_tty), fd(0)
+ {
+ speed = B9600;
+ }
+
+ ~SerialPort()
+ {
+ close();
+ }
+
+ int setSpeed(int newspeed)
+ {
+ int ret = 0;
+ switch(newspeed)
+ {
+ case 2400:
+ speed = B2400;
+ break;
+ case 4800:
+ speed = B4800;
+ break;
+ case 9600:
+ speed = B9600;
+ break;
+ case 19200:
+ speed = B19200;
+ break;
+ case 38400:
+ speed = B38400;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
+ }
+
+ bool open()
+ {
+ fd = ::open(tty.c_str(), O_RDWR, O_NOCTTY);
+
+ return setupDevice();
+ }
+
+ bool isOpen()
+ {
+ return (fd > 0);
+ }
+
+ int fileDescriptor() { return fd; }
+
+ bool close()
+ {
+ ::close(fd);
+ }
+
+ std::string read()
+ {
+ char buff;
+ std::string result;
+ int bytesread = 0;
+ while( bytesread = ::read(fd, &buff, 1) > 0 )
+ {
+ result += buff;
+ }
+
+ if(bytesread == -1)
+ perror("Error while reading: ");
+
+ return result;
+ }
+
+ void write(std::string data)
+ {
+ int written = ::write(fd,data.c_str(),data.length());
+ if(written == -1)
+ {
+ DebugOut(DebugOut::Warning)<<"Unable to write ("<<fd<<")"<<endl;
+ perror("write error: ");
+ }
+ }
+
+ void setDescriptor(int d)
+ {
+ fd = d;
+ //setupDevice();
+ }
+
+private: ///methods
+
+ bool setupDevice()
+ {
+ if(fd == -1)
+ {
+ DebugOut()<<"Cannot open serial device."<<endl;
+ return false;
+ }
+
+ struct termios oldtio;
+ tcgetattr(fd,&oldtio);
+
+ oldtio.c_cflag |= CS8 | CLOCAL | CREAD;
+
+ oldtio.c_iflag |= IGNPAR;
+ oldtio.c_iflag &= ~(ICRNL | IMAXBEL);
+
+
+ oldtio.c_oflag &= ~OPOST;
+
+ oldtio.c_lflag |= ECHOE | ECHOK | ECHOCTL | ECHOKE;
+ oldtio.c_lflag &= ~(ECHO | ICANON | ISIG);
+
+ //oldtio.c_cc[VEOL] = '\r';
+
+ cfsetispeed(&oldtio, speed);
+ cfsetospeed(&oldtio, speed);
+
+ tcflush(fd, TCIFLUSH);
+ tcsetattr(fd, TCSANOW, &oldtio);
+
+ fcntl(fd,F_SETFL,O_NONBLOCK);
+
+ return true;
+ }
+
+private:
+ int fd;
+ std::string tty;
+
+};
+
+
+#endif
diff --git a/plugins/common/thread.cpp b/plugins/common/thread.cpp
new file mode 100644
index 00000000..d9d9c999
--- /dev/null
+++ b/plugins/common/thread.cpp
@@ -0,0 +1,167 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/******************************************************************
+*
+* CUtil for C++
+*
+* File: Thread.cpp
+*
+* Revision;
+*
+* 07/07/13
+* - first revision
+******************************************************************/
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "mutex.h"
+#include "thread.h"
+#include <stdlib.h>
+
+////////////////////////////////////////////////
+// Thread Func
+////////////////////////////////////////////////
+
+static CUtil::Mutex gMutex;
+static int gActiveThreadCount(0);
+
+static void *PosixThreadProc(void *param)
+{
+ gMutex.lock();
+ ++gActiveThreadCount;
+ gMutex.unlock();
+
+ CUtil::Thread *thread = (CUtil::Thread *)param;
+ thread->run();
+
+ gMutex.lock();
+ --gActiveThreadCount;
+ LOG_INFO("PosixThreadProc() - active threads: " << gActiveThreadCount);
+ gMutex.unlock();
+ return 0;
+}
+
+namespace CUtil{
+////////////////////////////////////////////////
+// Thread
+////////////////////////////////////////////////
+
+Thread::Thread() :
+ thread(0),
+ runnableFlag(false)
+{
+ pthread_cond_init( &cond, NULL );
+ pthread_mutex_init( &mutex, NULL );
+}
+
+bool Thread::start()
+{
+ pthread_mutex_lock(&mutex);
+ if (runnableFlag) {// already running
+ pthread_mutex_unlock(&mutex);
+ return false;
+ }
+ // try to run
+ if (pthread_create(&thread, NULL/*&thread_attr*/, PosixThreadProc, this) != 0) {
+ //pthread_attr_destroy(&thread_attr);
+ pthread_mutex_unlock(&mutex);
+ return false;
+ }
+ //pthread_attr_destroy(&thread_attr);
+ runnableFlag = true;
+ pthread_mutex_unlock(&mutex);
+ return true;
+}
+
+Thread::~Thread()
+{
+ stop();
+ pthread_cond_destroy( &cond );
+ pthread_mutex_destroy( &mutex );
+ thread = 0;
+}
+
+void Thread::stop()
+{
+ if (setRunnableFlag(false) == true) {
+ if( thread != 0 ){
+ if (thread == pthread_self()){
+ int s = pthread_detach(thread);
+ ((void)s);// prevent compiler warning in RELEASE build
+ LOG_MESSAGE("Thread::stop() - thread " << std::hex << int(thread) << std::dec << " detached, returned value was " << s);
+ }
+ else{
+ int s = pthread_join(thread, NULL);
+ if (s != 0){
+ LOG_ERROR("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
+ }
+ else{
+ LOG_MESSAGE("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
+ }
+ }
+ thread = 0;
+ }
+ }
+ return;
+}
+
+bool Thread::setRunnableFlag(bool flag)
+{
+ pthread_mutex_lock(&mutex);
+ bool retval(runnableFlag);
+ runnableFlag = flag;
+
+ if(!runnableFlag)
+ pthread_cond_signal(&cond);
+ pthread_mutex_unlock(&mutex);
+ return retval;
+}
+
+bool Thread::isRunnable(long miliseconds)
+{
+ bool runnable(false);
+
+ pthread_mutex_lock(&mutex);
+ if (miliseconds != 0){
+ wait(miliseconds);
+ }
+ runnable = runnableFlag;
+
+ pthread_mutex_unlock(&mutex);
+ return runnable;
+}
+
+bool Thread::wait( long miliseconds )
+{
+ struct timespec abstime;
+ clock_gettime(CLOCK_REALTIME, &abstime);
+ abstime.tv_sec += ( miliseconds / 1000 );
+ miliseconds %= 1000;
+ abstime.tv_nsec += ( miliseconds * 1000000L ); // in nanoseconds
+ if ( abstime.tv_nsec > 1000000000L /* > 1s */ ){
+ abstime.tv_sec += 1; // +1s
+ abstime.tv_nsec -= 1000000000L; // -1s
+ }
+
+ int status = pthread_cond_timedwait( &cond, &mutex, &abstime );
+ return ( status == ETIMEDOUT );
+}
+
+}
diff --git a/plugins/common/thread.h b/plugins/common/thread.h
new file mode 100644
index 00000000..8879b5b4
--- /dev/null
+++ b/plugins/common/thread.h
@@ -0,0 +1,154 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _CUTIL_THREAD_H_
+#define _CUTIL_THREAD_H_
+
+#include <pthread.h>
+#include <sys/prctl.h>
+#include "logger.h"
+
+/** \addtogroup libamb-plugins-common
+ * @{
+ */
+
+namespace CUtil {
+
+/**
+ * \brief Encapsulation of the POSIX thread.
+ *
+ * Supports starting, stopping, restarting and thread status checking.
+ * @class Thread
+ */
+class Thread
+{
+ /**
+ * Condition variable used to signal runnable status changes
+ * @property cond
+ * @private
+ */
+ pthread_cond_t cond;
+ /**
+ * Mutex used to lock runnable status changes
+ * @property mutex
+ * @private
+ */
+ pthread_mutex_t mutex;
+ /**
+ * Instance of the encapsulated posix thread
+ * @property thread
+ * @private
+ */
+ pthread_t thread;
+ /**
+ * Runnable status of the thread. True means that thread is running
+ * @property runnableFlag
+ * @private
+ */
+ bool runnableFlag;
+
+private:
+
+ /**
+ * Sets new runnable status of the thread. Holds mutex and signals condition variable
+ * @fn setRunnableFlag
+ * @private
+ * @param[in] flag New status of the thread to be set
+ * @return Actual runnable status after operation
+ */
+ bool setRunnableFlag(bool flag);
+
+ /**
+ * Sleeps current thread for specified time in miliseconds. Wait can be canceled if thread is in stopped/stopping state.
+ * @fn wait
+ * @private
+ * @param miliseconds Sleep time in miliseconds.
+ * @return True if wait wasn't canceled, false otherwise.
+ */
+ bool wait( long miliseconds );
+
+public:
+
+ /**
+ * Method to be executed in this thread. Has to be overwritten.
+ * @fn run
+ * @public
+ */
+ virtual void run() = 0;
+
+protected:
+
+ /**
+ * Gets runnable status of current thread. Sleeps calling thread for a specified time.
+ * @protected
+ * @fn isRunnable
+ * @param miliseconds Time in miliseconds. 0 means no sleep.
+ * @return True if thread should still run.
+ *
+ * \b Example
+ * @code
+ *
+ * void MyCustomThread::run()
+ * {
+ * while(isRunnable(1000)) { // execute some op once per second. Exits thread if stop() was called.
+ * ...
+ * }
+ * }
+ * @endcode
+ */
+ bool isRunnable(long miliseconds = 0);
+
+public:
+
+ Thread();
+ virtual ~Thread();
+
+ /**
+ * Starts the thread
+ * @fn start
+ * @return True if thread was started
+ * @public
+ */
+ virtual bool start();
+
+ /**
+ * Stops the thread
+ * @fn stop
+ * @public
+ */
+ virtual void stop();
+
+ /**
+ * Restarts the thread.
+ * @fn restart
+ * @return True if thread was started again
+ * @public
+ */
+ bool restart()
+ {
+ stop();
+ return start();
+ }
+};
+
+}
+
+#endif
+
+/** @} */
+
diff --git a/plugins/common/varianttype.cpp b/plugins/common/varianttype.cpp
new file mode 100644
index 00000000..37024261
--- /dev/null
+++ b/plugins/common/varianttype.cpp
@@ -0,0 +1,105 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "varianttype.h"
+#include "abstractdbusinterface.h"
+#include <listplusplus.h>
+
+VariantType::VariantType(AbstractRoutingEngine* re, VehicleProperty::Property ambPropertyName, std::string propertyName, Access access)
+ :mPropertyName(propertyName), mAccess(access), mValue(nullptr), mZoneFilter(Zone::None), mUpdateFrequency(0), mInitialized(false)
+{
+ mAmbPropertyName = ambPropertyName;
+ routingEngine = re;
+ //set default value:
+ setValue(VehicleProperty::getPropertyTypeForPropertyNameValue(mAmbPropertyName));
+}
+
+void VariantType::initialize()
+{
+ if(mInitialized) return;
+ AsyncPropertyRequest request;
+ request.property = mAmbPropertyName;
+ request.sourceUuidFilter = mSourceFilter;
+ request.zoneFilter = mZoneFilter;
+
+ using namespace std::placeholders;
+ request.completed = [this](AsyncPropertyReply* r)
+ {
+ auto reply = amb::make_unique(r);
+ if(reply->success)
+ setValue(reply->value->copy());
+ else
+ DebugOut(DebugOut::Error)<<"get request unsuccessful for "<<reply->property<<" : "<<reply->error<<endl;
+
+ mInitialized = true;
+ };
+
+ /// do not request if not supported:
+ PropertyList proplist = routingEngine->supported();
+
+ if(contains(proplist, mAmbPropertyName))
+ routingEngine->getPropertyAsync(request);
+}
+
+VariantType::~VariantType()
+{
+ if(mValue){
+ delete mValue;
+ mValue = nullptr;
+ }
+}
+
+GVariant *VariantType::toVariant()
+{
+ if(!value())
+ {
+ setValue(VehicleProperty::getPropertyTypeForPropertyNameValue(name()));
+ }
+
+ auto v = value();
+
+ return v->toVariant();
+}
+
+void VariantType::fromVariant(GVariant *val, std::function<void (bool, AsyncPropertyReply::Error)> callback)
+{
+ AbstractPropertyType *v = VehicleProperty::getPropertyTypeForPropertyNameValue(ambPropertyName());
+
+ if(!v)
+ {
+ DebugOut(DebugOut::Error) << "could not get AbstractPropertyType for: " << ambPropertyName() << endl;
+ return;
+ }
+
+ v->fromVariant(val);
+
+ AsyncSetPropertyRequest request;
+ request.property = ambPropertyName();
+ request.value = v;
+ request.zoneFilter = zoneFilter();
+ request.completed = [&](AsyncPropertyReply* r)
+ {
+ auto reply = amb::make_unique(r);
+
+ if(callback)
+ callback(reply->success, reply->error);
+ };
+
+ routingEngine->setProperty(request);
+}
diff --git a/plugins/common/varianttype.h b/plugins/common/varianttype.h
new file mode 100644
index 00000000..1904ab64
--- /dev/null
+++ b/plugins/common/varianttype.h
@@ -0,0 +1,168 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef VARIANTTYPE_H_
+#define VARIANTTYPE_H_
+
+#include <string>
+#include <functional>
+#include <boost/any.hpp>
+#include <glib.h>
+
+#include "debugout.h"
+#include "abstractpropertytype.h"
+#include "abstractroutingengine.h"
+#include "vehicleproperty.h"
+
+class AbstractDBusInterface;
+
+class VariantType
+{
+
+public:
+
+ enum Access {
+ Read,
+ Write,
+ ReadWrite
+ };
+
+ VariantType(AbstractRoutingEngine* re, VehicleProperty::Property ambPropertyName, std::string propertyName, Access access);
+ virtual ~VariantType();
+
+ bool operator == (VariantType & other)
+ {
+ return (other.name() == name()
+ && other.ambPropertyName() == ambPropertyName()
+ && other.sourceFilter() == sourceFilter()
+ && other.zoneFilter() == zoneFilter());
+ }
+
+ virtual const string signature()
+ {
+ GVariant* var = toVariant();
+ if(!var) return "";
+
+ const string s = g_variant_get_type_string(var);
+ g_variant_unref(var);
+ return s;
+ }
+
+ virtual string name()
+ {
+ return mPropertyName;
+ }
+
+ virtual VehicleProperty::Property ambPropertyName()
+ {
+ return mAmbPropertyName;
+ }
+
+ virtual Access access()
+ {
+ return mAccess;
+ }
+
+ void setSourceFilter(std::string filter) { mSourceFilter = filter; }
+ void setZoneFilter(Zone::Type zone)
+ {
+ if(mValue)
+ mValue->zone = zone;
+
+ mZoneFilter = zone;
+ }
+
+ std::string sourceFilter() { return mSourceFilter; }
+ Zone::Type zoneFilter() { return mZoneFilter; }
+
+ virtual GVariant* toVariant();
+ virtual void fromVariant(GVariant *value, std::function<void (bool, AsyncPropertyReply::Error)> callback);
+
+ double timestamp()
+ {
+ if(mValue)
+ return mValue->timestamp;
+ return 0;
+ }
+
+ int sequence()
+ {
+ if(mValue)
+ return mValue->sequence;
+ return 0;
+ }
+
+ virtual void setValue(AbstractPropertyType* val)
+ {
+ if(!val)
+ return;
+
+ if(!mValue)
+ {
+ mValue = val->copy();
+ }
+ else
+ {
+ mValue->quickCopy(val);
+ }
+
+ if(mUpdateFrequency == 0)
+ {
+ PropertyInfo info = routingEngine->getPropertyInfo(mValue->name, mValue->sourceUuid);
+
+ if(info.isValid())
+ mUpdateFrequency = info.updateFrequency();
+ else
+ mUpdateFrequency = -1;
+ }
+ }
+
+ virtual void updateValue(AbstractPropertyType* val)
+ {
+ setValue(val);
+ }
+
+ int updateFrequency()
+ {
+ return mUpdateFrequency;
+ }
+
+ AbstractPropertyType* value()
+ {
+ return mValue;
+ }
+
+ void initialize();
+
+protected:
+
+ std::string mSourceFilter;
+ Zone::Type mZoneFilter;
+ int mUpdateFrequency;
+ AbstractRoutingEngine* routingEngine;
+ string mPropertyName;
+ VehicleProperty::Property mAmbPropertyName;
+ Access mAccess;
+ AbstractPropertyType* mValue;
+ AbstractDBusInterface* mInterface;
+
+private:
+ bool mInitialized;
+};
+
+#endif // ABSTRACTPROPERTY_H
diff --git a/plugins/database/CMakeLists.txt b/plugins/database/CMakeLists.txt
new file mode 100644
index 00000000..980300b3
--- /dev/null
+++ b/plugins/database/CMakeLists.txt
@@ -0,0 +1,28 @@
+if(database_plugin)
+
+include(CheckIncludeFiles)
+
+pkg_check_modules(sqlite REQUIRED sqlite3)
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${sqlite_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/plugins/common)
+
+set(database_table_create "CREATE TABLE IF NOT EXISTS data (key TEXT, value BLOB, source TEXT, zone INTEGER, time REAL, sequence REAL, tripId TEXT)" CACHE INTERNAL "database plugin table create command")
+add_definitions(-Ddatabase_table_create="${database_table_create}")
+
+set(databasesinkplugin_headers databasesink.h utils.h basedb.hpp baseobject.h sqlitedatabase.h sqlitequery.h)
+set(databasesinkplugin_sources databasesink.cpp utils.cpp sqlitedatabase.cpp sqlitequery.cpp basedb.hpp)
+add_library(databasesinkplugin MODULE ${databasesinkplugin_sources})
+set_target_properties(databasesinkplugin PROPERTIES PREFIX "")
+target_link_libraries(databasesinkplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${sqlite_LIBRARIES} amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common)
+
+install(TARGETS databasesinkplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_BINARY_DIR}/database.README.md @ONLY)
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/database.in.json ${CMAKE_CURRENT_BINARY_DIR}/database @ONLY)
+
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/database DESTINATION ${PLUGIN_SEGMENT_INSTALL_PATH})
+
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/database.README.md DESTINATION ${DOC_INSTALL_DIR}/plugins)
+
+endif(database_plugin)
diff --git a/plugins/database/README b/plugins/database/README
new file mode 100644
index 00000000..c1a38c14
--- /dev/null
+++ b/plugins/database/README
@@ -0,0 +1,119 @@
+# Database plugin {#database_plugin}
+Version: @PROJECT_VERSION@
+
+This plugin logs properties in a sqlite database file. It can also be used as a source to
+play back previous logs to AMB.
+
+To enable the Database plugin, run cmake and enable the database_plugin option:
+
+cmake -Ddatabase_plugin=On ..
+
+To use the Database plugin, add the following to the "sources" array in /etc/ambd/config:
+
+~~~~~~~~~~~~~{.json}
+{
+ "name" : "Database",
+ "path" : "@PLUGIN_INSTALL_PATH@/databasesinkplugin.so",
+ "databaseFile" : "storage",
+ "bufferLength" : "100",
+ "properties" : "{ 'properties' : ['VehicleSpeed','EngineSpeed'] }",
+ "startOnLoad" : "false",
+ "playbackOnLoad" : "false",
+ "playbackMultiplier" : "1",
+ "frequency" : "1"
+}
+~~~~~~~~~~~~~
+
+## Configuration Key Definitions:
+
+"name"
+name of plugin.
+
+"path"
+path to plugin on the filesystem.
+
+"databaseFile"
+path to log file
+
+Default: "storage"
+
+"bufferLength"
+Number of logged items to keep in memory before flushing to the database file.
+A higher number will reduce writes and improve performance.
+
+Default: 100
+
+"properties"
+List of properties to log.
+
+"startOnLoad"
+Start logging when AMB starts.
+
+Default: false
+
+"playbackOnLoad"
+Play back the specified log (see "databaseFile") when AMB starts.
+
+Default: false
+
+"playbackMultiplier"
+Speed at which to play back the specified log.
+1 = realtime
+2 = 2x speed
+etc.
+
+Default: 1
+
+"frequency"
+Frequency in Hz in which the database will write contents. Only the newest values
+will be written. Other values are discarded. If bufferLength is not full,the
+database will not be written to until it is.
+
+Default: 1
+
+## AMB Properties:
+
+DatabaseFile
+Type: string
+File to be used to log or play back.
+
+corresponds to configuration option "databaseFile".
+
+DatabaseLogging
+Type: bool
+Access: read/write
+
+Indicates whether logging to the database is occuring. Set to true to turn on
+logging. Set to false to stop logging. This property is mutually exclusive with
+the DatabasePlayback property. Setting this to true will turn off playback.
+
+Default: false when configuration option "startOnLoad" is not set.
+
+DatabasePlayback
+Type: bool
+Access: read/write
+
+Indicates whether database playback is occuring. Set to true to turn on playback.
+Set to false to turn off playback. This property is mutually exclusive with the
+DatabaseLogging property. Setting this to true will turn off logging.
+
+Default: false when configuration option "playbackOnLoad" is not set.
+
+
+## AMB DBus Interfaces:
+
+org.automotive.DataLogger
+
+Properties:
+LogFile - Corresponds to "DatabaseFile"
+Logging - Corresponds to "DatabaseLogging"
+Playback - Corresponds to "DatabasePlayback"
+
+~~~~~~~~~~~~~{.idl}
+interface Datalogger
+{
+ attribute DOMString LogFile;
+ attribute boolean Logging;
+ attribute boolean Playback;
+}
+~~~~~~~~~~~~~
diff --git a/plugins/database/basedb.hpp b/plugins/database/basedb.hpp
new file mode 100644
index 00000000..4d6a1296
--- /dev/null
+++ b/plugins/database/basedb.hpp
@@ -0,0 +1,346 @@
+/*
+ * timedate - Displays time and date and daily events
+ * Copyright (c) <2009>, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef _BASEDB_H_
+#define _BASEDB_H_
+
+#include "sqlitedatabase.h"
+#include "sqlitequery.h"
+#include "debugout.h"
+#include <string>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <vector>
+
+using namespace std;
+
+template<typename T>
+class NameValuePair
+{
+ public:
+ NameValuePair(){ }
+ NameValuePair(std::string n, T v){name = n; value = v;}
+ std::string name;
+ T value;
+};
+
+template<typename T>
+class DictionaryList: public std::vector<NameValuePair<T> >
+{
+
+};
+
+class BaseDB
+{
+public:
+ BaseDB():db(NULL),q(NULL)
+ {
+
+ }
+
+
+ virtual ~BaseDB()
+ {
+ DebugOut()<<"BaseDB: Destroying db object. Table: "<<table<<endl;
+ delete q;
+ delete db;
+ }
+
+ void setTable(string tablename)
+ {
+ if(tablename == "") return;
+ table = tablename;
+
+ if(!tableExists())
+ reloadTable();
+ }
+
+ virtual void
+ init(string dbname, string tablename, string tablestring)
+ {
+ DebugOut()<<"BaseDB: Initializing db object. Table: "<<tablename.c_str()<<endl;
+ tableString = tablestring;
+
+ db = new sqlitedatabase();
+
+ db->init(dbname);
+
+ DebugOut()<<"BaseDB: Using db/db-file: "<<dbname.c_str()<<endl;
+
+ if(! db->Connected())
+ {
+ DebugOut(0)<<"BaseDB: database not found "<<dbname<<endl;
+ return;
+ }
+ q = new sqlitequery();
+
+ q->init(db);
+
+ setTable(tablename);
+ }
+
+ virtual void
+ reloadTable()
+ {
+ DebugOut()<<"BaseDB: reloading table "<<table<<endl;
+ dropTable();
+ createTable();
+ }
+
+ virtual bool tableExists()
+ {
+ bool exists=false;
+ string query = "SELECT * FROM "+table+" LIMIT 0,1";
+ DebugOut()<<"BaseDB: checking for existing table with "<<query.c_str()<<endl;
+ q->getResult(query);
+ int numrows = q->numRows();
+ if(numrows <= 0 )
+ exists = false;
+ else exists = true;
+
+ DebugOut()<<"BaseDB: Table '"<<table<<"' exists? "<<exists<<" because "<<numrows<<" rows where found."<<endl;
+ q->freeResult();
+ return exists;
+ }
+
+ virtual void
+ renameTable(string newname)
+ {
+ dropTable(newname);
+ string query = "ALTER TABLE "+table+" RENAME TO "+newname;
+ q->execute(query);
+ }
+
+ template<typename T>
+ void insert(DictionaryList<T> params)
+ {
+ string query = "INSERT INTO "+table+" (";
+ ostringstream endquery;
+ endquery<<" VALUES ( ";
+ for(size_t i=0; i< params.size(); i++)
+ {
+ query+=" `"+fixInvalids(params[i].name)+"`";
+ ostringstream tempval;
+ tempval<<params[i].value;
+ endquery<<"'"<<fixInvalids(tempval.str())<<"'";
+ if(i < params.size()-1)
+ {
+ query+=",";
+ endquery<<",";
+ }
+ }
+ endquery<<" )";
+ query+=" )"+endquery.str();
+ DebugOut()<<"BaseDB: "<<query<<endl;
+ q->execute(query);
+ }
+
+ template<typename T>
+ void
+ insert(NameValuePair<T> param)
+ {
+ string query = "INSERT INTO "+table+" (";
+ ostringstream endquery;
+ endquery<<" VALUES ( ";
+ query+=" `"+fixInvalids(param.name)+"`";
+ ostringstream tempval;
+ tempval<<param.value;
+ endquery<<"'"<<fixInvalids(tempval.str())<<"'";
+ endquery<<" )";
+ query+=" )"+endquery.str();
+ DebugOut()<<"BaseDB: "<<query<<endl;
+ q->execute(query);
+ }
+
+ virtual void
+ insert(DictionaryList<string> params)
+ {
+ insert<string>(params);
+ }
+
+ template<typename T, typename TT, typename T3>
+ void
+ update(T col, TT colval, NameValuePair<T3> qualifier)
+ {
+ ostringstream query;
+ ostringstream tempval;
+ ostringstream tempcolval;
+ tempval<<qualifier.value;
+ tempcolval<<colval;
+ query << "UPDATE "<< table <<
+ " SET `"<<col<<"` = '"<<fixInvalids(tempcolval.str())<<
+ "' WHERE `"<<fixInvalids(qualifier.name)<<"` = '"<<fixInvalids(tempval.str())<<"'";
+ DebugOut() << "BaseDB: Update: " << query.str() << endl;
+ q->execute(query.str());
+ }
+
+ template<typename T, typename TT>
+ void
+ update(NameValuePair<T> param, NameValuePair<TT> qualifier)
+ {
+ update<string,T,TT>(param.name, param.value, qualifier);
+ }
+
+ template<typename T, typename TT>
+ void
+ update(DictionaryList<T> params, NameValuePair<TT> qualifier)
+ {
+ for(size_t i=0;i<params.size();i++)
+ {
+ update<T,TT>(params[i],qualifier);
+ }
+ }
+
+ virtual void update(NameValuePair<string> param, NameValuePair<string> qualifier)
+ {
+ update<string,string>(param,qualifier);
+ }
+
+ template<typename T>
+ void deleteRow(NameValuePair<T> qualifier)
+ {
+ ostringstream query;
+ ostringstream tempval;
+ tempval<<qualifier.value;
+ query << "DELETE FROM "<< table<<
+ " WHERE `"<<qualifier.name<<"` = '"<<fixInvalids(tempval.str())<<"'";
+ DebugOut() << "BaseDB: " << __FUNCTION__ << " : " << query.str() << endl;
+ q->execute(query.str());
+ }
+
+ virtual void
+ deleteRow(NameValuePair<string> qualifier)
+ {
+ deleteRow<string>(qualifier);
+ }
+
+ virtual void
+ dropTable()
+ {
+ dropTable(table);
+ }
+
+ virtual void
+ dropTable(string tablename)
+ {
+ string query="DROP TABLE IF EXISTS "+tablename;
+ DebugOut() << "BaseDB: Dropping Table " << tablename <<" with query: " << query << endl;
+ q->execute(query);
+ }
+
+ virtual void
+ createTable()
+ {
+ string t = tableString;
+ string query;
+ string::size_type i=t.find("%s",0);
+ if(i!=string::npos) query=t.replace(i, 2, table);
+ else query = t;
+ DebugOut() << "BaseDB: Creating Table" << table << " with query: " << query << endl;
+ q->execute(query);
+ }
+
+
+
+ string
+ fixInvalids(string filename)
+ {
+ return filename;
+ }
+
+ vector<vector<string> > select(string query)
+ {
+ DebugOut()<<query<<endl;
+
+ vector<vector<string>> dataMap;
+
+ q->getResult(query);
+
+ if(q->numRows() <= 0)
+ {
+ q->freeResult();
+ return dataMap;
+ }
+
+ int i=0;
+
+ while(q->fetchRow())
+ {
+ string v;
+ dataMap.push_back(vector<string>());
+
+ while((v = q->getStr()) != "")
+ {
+ dataMap[i].push_back(v);
+ }
+ i++;
+ }
+
+ q->freeResult();
+
+ return dataMap;
+
+ }
+
+ void exec(string query)
+ {
+ q->execute(query);
+ }
+
+protected:
+
+ void
+ fixFilename(string* filename)
+ {
+ std::string::size_type i=0;
+ while(1)
+ {
+ i = filename->find(" ",i);
+ if(i == string::npos)
+ break;
+ filename->replace(i,1,"\\ ");
+ i+=2;
+ }
+ }
+
+ void
+ unfixFilename(string* filename)
+ {
+ std::string::size_type i=0;
+ i=filename->find("\\",0);
+ if(i == string::npos)
+ return;
+ else
+ {
+ filename->replace(i,1,"");
+ unfixFilename(filename);
+ }
+
+ }
+
+ sqlitedatabase *db;
+ sqlitequery *q;
+ string table;
+ string tableString;
+
+}; //BaseDB class
+
+#endif
+
diff --git a/plugins/database/baseobject.h b/plugins/database/baseobject.h
new file mode 100644
index 00000000..a36ddd46
--- /dev/null
+++ b/plugins/database/baseobject.h
@@ -0,0 +1,37 @@
+/*
+ * timedate - Displays time and date and daily events
+ * Copyright (c) <2009>, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef _BASEOBJECTDAO_H_
+#define _BASEOBJECTDAO_H_
+
+#include "basedb.hpp"
+
+#include<string>
+#include<vector>
+
+class BaseObject
+{
+public:
+ BaseObject():id(-1){}
+ virtual ~BaseObject(){}
+ int id;
+};
+
+#endif
+
diff --git a/plugins/database/database.in.json b/plugins/database/database.in.json
new file mode 100644
index 00000000..78651624
--- /dev/null
+++ b/plugins/database/database.in.json
@@ -0,0 +1,12 @@
+{
+ "name" : "Database",
+ "path" : "@PLUGIN_INSTALL_PATH@/databasesinkplugin.so",
+ "databaseFile" : "/tmp/storage",
+ "enabled" : false,
+ "bufferLength" : "100",
+ "properties" : ["VehicleSpeed", "EngineSpeed"],
+ "startOnLoad" : "false",
+ "playbackOnLoad" : "false",
+ "playbackMultiplier" : "1",
+ "frequency" : "1"
+}
diff --git a/plugins/database/databasesink.cpp b/plugins/database/databasesink.cpp
new file mode 100644
index 00000000..8a6f3b1e
--- /dev/null
+++ b/plugins/database/databasesink.cpp
@@ -0,0 +1,559 @@
+#include "databasesink.h"
+#include "abstractroutingengine.h"
+#include "listplusplus.h"
+#include "superptr.hpp"
+#include "uuidhelper.h"
+#include "ambplugin.h"
+
+#include <dbusplugin.h>
+#include <dbusexport.h>
+#include <picojson.h>
+#include <thread>
+
+int bufferLength = 100;
+int timeout=1000;
+
+extern "C" void create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ auto plugin = new AmbPlugin<DatabaseSink>(routingengine, config);
+ plugin->init();
+}
+
+class DataLogger: public DBusSink
+{
+public:
+ DataLogger(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("DataLogger", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(DatabaseLogging, "LogFile", VariantType::ReadWrite);
+ wantPropertyVariant(DatabasePlayback, "Playback", VariantType::ReadWrite);
+ wantPropertyVariant(DatabaseLogging, "Logging", VariantType::ReadWrite);
+ }
+};
+
+
+static void * cbFunc(Shared* shared)
+{
+ if(!shared)
+ {
+ throw std::runtime_error("Could not get shared object.");
+ }
+
+ ///new tripID:
+ shared->tripId = amb::createUuid();
+
+ vector<DictionaryList<string> > insertList;
+
+ double startTime = amb::currentTime();
+
+ while(1)
+ {
+ DBObject obj = shared->queue.pop();
+
+ if( obj.quit )
+ {
+ break;
+ }
+
+ DictionaryList<string> dict;
+
+ NameValuePair<string> one("key", obj.key);
+ NameValuePair<string> two("value", obj.value);
+ NameValuePair<string> three("source", obj.source);
+ NameValuePair<string> zone("zone", boost::lexical_cast<string>(obj.zone));
+ NameValuePair<string> four("time", boost::lexical_cast<string>(amb::Timestamp::instance()->epochTime(obj.time)));
+ NameValuePair<string> five("sequence", boost::lexical_cast<string>(obj.sequence));
+ NameValuePair<string> six("tripId", shared->tripId);
+
+ dict.push_back(one);
+ dict.push_back(two);
+ dict.push_back(three);
+ dict.push_back(zone);
+ dict.push_back(four);
+ dict.push_back(five);
+ dict.push_back(six);
+
+ insertList.push_back(dict);
+
+ if(insertList.size() >= bufferLength && amb::currentTime() - startTime >= timeout / 1000)
+ {
+ startTime = amb::currentTime();
+
+ shared->db->exec("BEGIN IMMEDIATE TRANSACTION");
+ for(int i=0; i< insertList.size(); i++)
+ {
+ DictionaryList<string> d = insertList[i];
+ shared->db->insert(d);
+ }
+ shared->db->exec("END TRANSACTION");
+ insertList.clear();
+ }
+ //delete obj;
+ }
+
+ /// final flush of whatever is still in the queue:
+
+ shared->db->exec("BEGIN IMMEDIATE TRANSACTION");
+ for(auto d : insertList)
+ {
+ shared->db->insert(d);
+ }
+ shared->db->exec("END TRANSACTION");
+
+ return NULL;
+}
+
+int getNextEvent(gpointer data)
+{
+ PlaybackShared* pbshared = static_cast<PlaybackShared*>(data);
+
+ if(!pbshared)
+ throw std::runtime_error("failed to cast PlaybackShared object");
+
+ if(pbshared->stop)
+ return 0;
+
+ auto itr = pbshared->playbackQueue.begin();
+
+ if(itr == pbshared->playbackQueue.end())
+ {
+ return 0;
+ }
+
+ DBObject obj = *itr;
+
+ auto value = amb::make_unique(VehicleProperty::getPropertyTypeForPropertyNameValue(obj.key, obj.value));
+
+ if(value)
+ {
+ value->priority = AbstractPropertyType::Instant;
+ value->timestamp = obj.time;
+ value->sequence = obj.sequence;
+ value->sourceUuid = obj.source;
+ value->zone = obj.zone;
+ pbshared->routingEngine->updateProperty(value.get(), pbshared->uuid);
+ }
+
+ if(++itr != pbshared->playbackQueue.end())
+ {
+ DBObject o2 = *itr;
+ double t = o2.time - obj.time;
+
+ if(t > 0)
+ g_timeout_add((t*1000) / pbshared->playBackMultiplier, getNextEvent, pbshared);
+ else
+ g_timeout_add(1, getNextEvent, pbshared);
+ }
+
+ pbshared->playbackQueue.remove(obj);
+ DebugOut()<<"playback Queue size: "<<pbshared->playbackQueue.size()<<endl;
+
+ return 0;
+}
+
+DatabaseSink::DatabaseSink(AbstractRoutingEngine *engine, map<std::string, std::string> config, AbstractSource &parent)
+ :AmbPluginImpl(engine, config, parent), shared(nullptr), playback(false), playbackShared(nullptr), playbackMultiplier(1)
+{
+ tablename = "data";
+ tablecreate = database_table_create;
+
+ if(config.find("bufferLength") != config.end())
+ {
+ bufferLength = boost::lexical_cast<int>(config["bufferLength"]);
+ }
+
+ if(config.find("frequency") != config.end())
+ {
+ try
+ {
+ int t = boost::lexical_cast<int>(config["frequency"]);
+ timeout = 1000 / t;
+ }
+ catch(...)
+ {
+ DebugOut(DebugOut::Error)<<"Failed to parse frequency: Invalid value "<<config["frequency"]<<endl;
+ }
+ }
+
+ if(config.find("properties") != config.end())
+ {
+ parseConfig();
+ }
+
+ for(auto itr : propertiesToSubscribeTo)
+ {
+ engine->subscribeToProperty(itr, &parent);
+ }
+
+ databaseName = addPropertySupport(Zone::None, [](){ return new DatabaseFileType("storage"); });
+ playback = addPropertySupport(Zone::None, [](){ return new DatabasePlaybackType(false); });
+ databaseLogging = addPropertySupport(Zone::None, [](){ return new DatabaseLoggingType(false); });
+
+ if(config.find("startOnLoad")!= config.end())
+ {
+ DebugOut() << "start on load? " << config["startOnLoad"] << endl;
+ databaseLogging->setValue(config["startOnLoad"] == "true");
+ }
+
+ if(config.find("playbackMultiplier")!= config.end())
+ {
+ playbackMultiplier = boost::lexical_cast<uint>(config["playbackMultiplier"]);
+ }
+
+ if(config.find("playbackOnLoad")!= config.end())
+ {
+ playback->setValue(config["playbackOnLoad"] == "true");
+ }
+}
+
+DatabaseSink::~DatabaseSink()
+{
+ if(shared)
+ {
+ stopDb();
+ }
+
+ if(playbackShared)
+ {
+ delete playbackShared;
+ }
+}
+
+
+void DatabaseSink::supportedChanged(const PropertyList &supportedProperties)
+{
+
+}
+
+void DatabaseSink::parseConfig()
+{
+ std::string properties = configuration["properties"];
+ std::string jsonError;
+ picojson::value value;
+ picojson::parse (value, properties.begin(), properties.end(), &jsonError);
+
+ picojson::array array = value.get<picojson::array>();
+
+ for(auto i : array)
+ {
+ std::string prop = i.to_str();
+ propertiesToSubscribeTo.push_back(prop);
+ DebugOut()<<"DatabaseSink logging: "<<prop<<endl;
+ }
+}
+
+void DatabaseSink::stopDb()
+{
+ databaseLogging->setValue(false);
+
+ if(!shared)
+ return;
+
+ DBObject obj;
+ obj.quit = true;
+ shared->queue.append(obj);
+
+ if(thread && thread->joinable())
+ thread->join();
+
+ delete shared;
+ shared = NULL;
+
+ routingEngine->updateProperty(databaseLogging.get(), source.uuid());
+}
+
+void DatabaseSink::startDb()
+{
+ if(playback->value<bool>())
+ {
+ DebugOut(DebugOut::Error)<<"ERROR: tried to start logging during playback. Only logging or playback can be used at one time"<<endl;
+ return;
+ }
+
+ if(shared)
+ {
+ DebugOut(DebugOut::Warning)<<"WARNING: logging already started. doing nothing."<<endl;
+ return;
+ }
+
+ initDb();
+
+ if(thread && thread->joinable())
+ thread->detach();
+
+ thread = amb::make_unique(new std::thread(cbFunc, shared));
+
+ databaseLogging->setValue(true);
+ routingEngine->updateProperty(databaseLogging.get(), source.uuid());
+}
+
+void DatabaseSink::startPlayback()
+{
+ if(playback->value<bool>())
+ return;
+
+ playback->setValue(true);
+
+ initDb();
+
+ /// populate playback queue:
+
+ vector<vector<string> > results = shared->db->select("SELECT * FROM "+tablename);
+
+ stopDb();
+
+ if(playbackShared)
+ {
+ delete playbackShared;
+ }
+
+ playbackShared = new PlaybackShared(routingEngine, uuid(), playbackMultiplier);
+
+ for(int i=0;i<results.size();i++)
+ {
+ if(results[i].size() < 5)
+ {
+ throw std::runtime_error("column mismatch in query");
+ }
+
+ DBObject obj;
+
+ obj.key = results[i][0];
+ obj.value = results[i][1];
+ obj.source = results[i][2];
+ obj.zone = boost::lexical_cast<int>(results[i][3]);
+ obj.time = boost::lexical_cast<double>(results[i][4]);
+ obj.sequence = boost::lexical_cast<double>(results[i][5]);
+
+ playbackShared->playbackQueue.push_back(obj);
+ }
+
+ g_timeout_add(0, getNextEvent, playbackShared);
+}
+
+void DatabaseSink::initDb()
+{
+ if(shared) delete shared;
+
+ shared = new Shared;
+ shared->db->init(databaseName->value<std::string>(), tablename, tablecreate);
+}
+
+void DatabaseSink::updateForNewDbFilename()
+{
+ bool wasLogging = databaseLogging->value<bool>();
+
+ stopDb();
+ initDb();
+
+ vector<vector<string> > supportedStr = shared->db->select("SELECT DISTINCT key, zone, source FROM " + tablename);
+
+ for(int i=0; i < supportedStr.size(); i++)
+ {
+ std::string name = supportedStr[i][0];
+
+ if(!contains(supported(), name))
+ {
+ std::string zoneStr = supportedStr[i][1];
+ std::string sourceStr = supportedStr[i][2];
+
+ DebugOut() << "adding property " << name << " in zone: " << zoneStr << "for source: " << sourceStr << endl;
+
+ Zone::Type zone = boost::lexical_cast<Zone::Type>(zoneStr);
+ auto property = addPropertySupport(zone, [name]() { return VehicleProperty::getPropertyTypeForPropertyNameValue(name); });
+ property->sourceUuid = sourceStr;
+ }
+ }
+
+ if(wasLogging)
+ {
+ stopDb();
+ startDb();
+ }
+
+ routingEngine->updateSupported(supported(), PropertyList(), &source);
+}
+
+void DatabaseSink::propertyChanged(AbstractPropertyType *value)
+{
+ VehicleProperty::Property property = value->name;
+
+ DebugOut() << "Received property change for " << property << endl;
+
+ if(!shared)
+ return;
+
+ if(!contains(supported(), property))
+ {
+ addPropertySupport(value->zone, [property]() { return VehicleProperty::getPropertyTypeForPropertyNameValue(property);});
+ routingEngine->updateSupported(supported(), PropertyList(), &source);
+ }
+
+ DBObject obj;
+ obj.key = property;
+ obj.value = value->toString();
+ obj.source = value->sourceUuid;
+ obj.time = value->timestamp;
+ obj.sequence = value->sequence;
+ obj.zone = value->zone;
+
+ shared->queue.append(obj);
+}
+
+
+const std::string DatabaseSink::uuid() const
+{
+ return "9f88156e-cb92-4472-8775-9c08addf50d3";
+}
+
+void DatabaseSink::init()
+{
+ if(configuration.find("databaseFile") != configuration.end())
+ {
+ setValue(databaseName, configuration["databaseFile"]);
+ updateForNewDbFilename();
+ }
+
+ DebugOut() << "databaseLogging: " << databaseLogging->value<bool>() << endl;
+
+ routingEngine->updateSupported(supported(), PropertyList(), &source);
+
+ routingEngine->subscribeToProperty(DBusConnected, [this](AbstractPropertyType* value)
+ {
+ if(value->name == DBusConnected)
+ {
+ if(value->value<bool>())
+ {
+ amb::Exporter::instance()->exportProperty<DataLogger>(routingEngine);
+ }
+ }
+ });
+
+}
+
+void DatabaseSink::getRangePropertyAsync(AsyncRangePropertyReply *reply)
+{
+ BaseDB * db = new BaseDB();
+ db->init(databaseName->value<std::string>(), tablename, tablecreate);
+
+ ostringstream query;
+ query.precision(15);
+
+ query<<"SELECT * from "<<tablename<<" WHERE (";
+
+ for(auto itr = reply->properties.begin(); itr != reply->properties.end(); itr++)
+ {
+ DebugOut() << "prop: " << (*itr) << endl;
+ if(itr != reply->properties.begin())
+ query<<" OR ";
+
+ query<<"key='"<<(*itr)<<"'";
+ }
+
+ query<<")";
+
+ if(reply->timeEnd)
+ {
+ query<<" AND time BETWEEN "<<reply->timeBegin<<" AND "<<reply->timeEnd;
+ }
+
+ if(reply->sequenceBegin >= 0 && reply->sequenceEnd >=0)
+ {
+ query<<" AND sequence BETWEEN "<<reply->sequenceBegin<<" AND "<<reply->sequenceEnd;
+ }
+
+ if(reply->sourceUuid != "")
+ query<<" AND source='"<<reply->sourceUuid<<"'";
+
+ query<<" AND zone="<<reply->zone;
+
+ std::vector<std::vector<string>> data = db->select(query.str());
+
+ DebugOut()<<"Dataset size "<<data.size()<<endl;
+
+ if(!data.size())
+ {
+ reply->success = false;
+ reply->error = AsyncPropertyReply::InvalidOperation;
+ }
+ else
+ {
+ reply->success = true;
+ }
+
+ for(auto i=0; i<data.size(); i++)
+ {
+ if(data[i].size() != 7)
+ continue;
+
+ DBObject dbobj;
+ dbobj.key = data[i][0];
+ dbobj.value = data[i][1];
+ dbobj.source = data[i][2];
+ dbobj.zone = boost::lexical_cast<double>(data[i][3]);
+ dbobj.time = boost::lexical_cast<double>(data[i][4]);
+ dbobj.sequence = boost::lexical_cast<double>(data[i][5]);
+ dbobj.tripId = data[i][6];
+
+ AbstractPropertyType* property = VehicleProperty::getPropertyTypeForPropertyNameValue(dbobj.key, dbobj.value);
+ if(property)
+ {
+ property->timestamp = dbobj.time;
+ property->sequence = dbobj.sequence;
+
+ reply->values.push_back(property);
+ }
+ }
+
+
+ reply->completed(reply);
+
+ delete db;
+}
+
+AsyncPropertyReply *DatabaseSink::setProperty(const AsyncSetPropertyRequest &request)
+{
+ AsyncPropertyReply* reply = AmbPluginImpl::setProperty(request);
+
+ if(request.property == DatabaseLogging)
+ {
+ if(databaseLogging->value<bool>())
+ {
+ startDb();
+ }
+ else
+ {
+ stopDb();
+ }
+ }
+ else if(request.property == DatabaseFile)
+ {
+ updateForNewDbFilename();
+ }
+ else if( request.property == DatabasePlayback)
+ {
+ if(playback->value<bool>())
+ {
+ startPlayback();
+ }
+ else
+ {
+ if(playbackShared)
+ playbackShared->stop = true;
+
+ playback = false;
+ }
+ }
+
+ return reply;
+}
+
+void DatabaseSink::subscribeToPropertyChanges(VehicleProperty::Property )
+{
+
+}
+
+void DatabaseSink::unsubscribeToPropertyChanges(VehicleProperty::Property )
+{
+}
+
diff --git a/plugins/database/databasesink.h b/plugins/database/databasesink.h
new file mode 100644
index 00000000..3b7efdbf
--- /dev/null
+++ b/plugins/database/databasesink.h
@@ -0,0 +1,182 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef DATABASESINK_H
+#define DATABASESINK_H
+
+#include "abstractsink.h"
+#include "abstractsource.h"
+#include "basedb.hpp"
+#include <asyncqueue.hpp>
+#include "listplusplus.h"
+#include "ambpluginimpl.h"
+
+#include <glib.h>
+
+#include <functional>
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <unordered_map>
+
+const std::string DatabaseLogging = "DatabaseLogging";
+const std::string DatabasePlayback = "DatabasePlayback";
+const std::string DatabaseFile = "DatabaseFile";
+
+class DBObject {
+public:
+ DBObject(): zone(0), time(0), sequence(0), quit(false) {}
+ std::string key;
+ std::string value;
+ std::string source;
+ int32_t zone;
+ double time;
+ int32_t sequence;
+ std::string tripId;
+
+ bool quit;
+
+ 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);
+ }
+
+ bool operator != (const DBObject & other)
+ {
+ return (*this == other) == false;
+ }
+};
+
+namespace amb
+{
+
+struct DBObjectCompare
+{
+ bool operator()(DBObject const & lhs, DBObject & rhs) const
+ {
+ if (lhs == rhs)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+};
+
+}
+
+namespace std {
+ template <> struct hash<DBObject>
+ {
+ size_t operator()(const DBObject & x) const
+ {
+ return x.key.length() * x.value.length() + x.time;
+ }
+ };
+}
+
+class Shared
+{
+public:
+ Shared()
+ :queue(true, true)
+ {
+ db = new BaseDB;
+ }
+ ~Shared()
+ {
+ delete db;
+ }
+
+ BaseDB * db;
+ amb::Queue<DBObject, amb::DBObjectCompare> queue;
+ std::string tripId;
+};
+
+class PlaybackShared
+{
+public:
+ PlaybackShared(AbstractRoutingEngine* re, std::string u, uint playbackMult)
+ :routingEngine(re),uuid(u),playBackMultiplier(playbackMult),stop(false) {}
+ ~PlaybackShared()
+ {
+ for(auto itr = playbackQueue.begin(); itr != playbackQueue.end(); itr++)
+ {
+ DBObject obj = *itr;
+ }
+
+ playbackQueue.clear();
+ }
+
+ AbstractRoutingEngine* routingEngine;
+ std::list<DBObject> playbackQueue;
+ uint playBackMultiplier;
+ std::string uuid;
+ bool stop;
+};
+
+PROPERTYTYPEBASIC(DatabaseLogging, bool)
+PROPERTYTYPEBASIC(DatabasePlayback, bool)
+PROPERTYTYPE(DatabaseFile, DatabaseFileType, StringPropertyType, std::string)
+
+class DatabaseSink : public AmbPluginImpl
+{
+
+public:
+ DatabaseSink(AbstractRoutingEngine* engine, map<string, string> config, AbstractSource &parent);
+ ~DatabaseSink();
+ virtual void supportedChanged(const PropertyList & supportedProperties);
+ virtual void propertyChanged(AbstractPropertyType *value);
+ const std::string uuid() const;
+
+ void init();
+
+ ///source role:
+ virtual void getRangePropertyAsync(AsyncRangePropertyReply *reply);
+ virtual AsyncPropertyReply * setProperty(const AsyncSetPropertyRequest & request);
+ virtual void subscribeToPropertyChanges(VehicleProperty::Property property);
+ virtual void unsubscribeToPropertyChanges(VehicleProperty::Property property);
+ int supportedOperations() const { return AbstractSource::GetRanged | AbstractSource::Get | AbstractSource::Set;}
+
+private: //methods:
+
+ void parseConfig();
+ void stopDb();
+ void startDb();
+ void startPlayback();
+ void initDb();
+ void updateForNewDbFilename();
+
+private:
+ PropertyList mSubscriptions;
+ Shared *shared;
+ std::unique_ptr<std::thread> thread;
+ std::string tablename;
+ std::string tablecreate;
+ PropertyList propertiesToSubscribeTo;
+ PlaybackShared* playbackShared;
+ uint playbackMultiplier;
+ std::shared_ptr<AbstractPropertyType> playback;
+ std::shared_ptr<AbstractPropertyType> databaseName;
+ std::shared_ptr<AbstractPropertyType> databaseLogging;
+};
+
+#endif // DATABASESINK_H
diff --git a/plugins/database/sqlitedatabase.cpp b/plugins/database/sqlitedatabase.cpp
new file mode 100644
index 00000000..05aed130
--- /dev/null
+++ b/plugins/database/sqlitedatabase.cpp
@@ -0,0 +1,88 @@
+/*
+ * timedate - Displays time and date and daily events
+ * Copyright (c) <2009>, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "sqlitedatabase.h"
+#include <stdio.h>
+#include <sqlite3.h>
+
+
+bool
+sqlitedatabase::init(const std::string & d)
+{
+ setDatabase(d);
+ return true;
+}
+
+sqlitedatabase::~sqlitedatabase()
+{
+ sqlite3_close((sqlite3 *)m_odb->db);
+ delete m_odb;
+}
+
+bool sqlitedatabase::Connected()
+{
+ SqliteDB * odb = grabdb();
+ if(!odb)
+ {
+ return false;
+ }
+ freedb(odb);
+ return true;
+}
+
+void sqlitedatabase::freedb(SqliteDB * odb)
+{
+ if(odb)
+ {
+ odb->busy = false;
+ }
+}
+
+SqliteDB * sqlitedatabase::grabdb()
+{
+ SqliteDB * odb = NULL;
+
+ if(!odb)
+ {
+ odb = new SqliteDB;
+ if(!odb)
+ {
+ printf("grabdb: SqliteDB struct couldn't be created");
+ return NULL;
+ }
+ void * p = &odb->db;
+ if(sqlite3_open(database.c_str(), (sqlite3 **)p))
+ {
+ printf("Can't open database: %s\n", sqlite3_errmsg((sqlite3 *)odb->db));
+ sqlite3_close((sqlite3 *)odb->db);
+ delete odb;
+ return NULL;
+ }
+ odb->busy = true;
+ }
+ else
+ {
+ odb->busy = true;
+ }
+ m_odb = odb;
+
+ return odb;
+}
+
+
diff --git a/plugins/database/sqlitedatabase.h b/plugins/database/sqlitedatabase.h
new file mode 100644
index 00000000..953013c8
--- /dev/null
+++ b/plugins/database/sqlitedatabase.h
@@ -0,0 +1,61 @@
+/*
+ * timedate - Displays time and date and daily events
+ * Copyright (c) <2009>, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef SQLITEDATABASE_H
+#define SQLITEDATABASE_H
+
+#include <string>
+#include <pthread.h>
+#include <stdint.h>
+#include <list>
+
+
+struct SqliteDB
+{
+ SqliteDB() : busy(false){}
+ void * db;
+ bool busy;
+}; // struct SqliteDB
+
+class sqlitedatabase
+{
+public:
+ sqlitedatabase() {}
+ virtual ~sqlitedatabase();
+
+ bool init(const std::string & d);
+
+ virtual void setHost(const std::string &){}
+ virtual void setUser(const std::string &){}
+ virtual void setPassword(const std::string &){}
+ virtual void setDatabase(const std::string & db){database = db;}
+
+ virtual void OnInit(SqliteDB *){}
+ virtual bool Connected();
+ virtual SqliteDB * grabdb();
+ virtual void freedb(SqliteDB * odb);
+
+protected:
+ SqliteDB *m_odb;
+ bool m_embedded;
+ std::string database;
+};
+
+#endif
+
diff --git a/plugins/database/sqlitequery.cpp b/plugins/database/sqlitequery.cpp
new file mode 100644
index 00000000..223c4d0b
--- /dev/null
+++ b/plugins/database/sqlitequery.cpp
@@ -0,0 +1,402 @@
+/*
+ * timedate - Displays time and date and daily events
+ * Copyright (c) <2009>, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "sqlitequery.h"
+#include <stdio.h>
+#include <sqlite3.h>
+#include <string>
+#include "utils.h"
+
+using namespace std;
+
+bool
+sqlitequery::init(sqlitedatabase * db)
+{
+ m_db = db;
+ odb = (db ? db->grabdb() : NULL);
+ return true;
+}
+
+bool
+sqlitequery::init(sqlitedatabase * dbin, const std::string & sql)
+{
+ init(dbin);
+ return execute(sql);
+}
+
+sqlitequery::~sqlitequery()
+{
+ if(result)
+ {
+ printf( "sqlite3_finalize in destructor\n");
+ sqlite3_finalize(result);
+ }
+ if(odb)
+ {
+ m_db->freedb(odb);
+ }
+}
+
+bool sqlitequery::execute(const std::string & sql)
+{
+ std::string sql_sqlite=sql;
+ m_last_query = sql_sqlite;
+ if(odb && result)
+ {
+ string err = "execute: query busy: "+sql_sqlite;
+ printf("%s\n", err.c_str());
+ }
+ if(odb && !result)
+ {
+ const char * s = NULL;
+ int err = sqlite3_busy_timeout((sqlite3 *)odb->db, 10000 );
+
+ if(err!= SQLITE_OK)
+ {
+ printf("execute: busy timeout occured: \n");
+ return false;
+ }
+ int rc = sqlite3_prepare_v2((sqlite3 *)odb->db, sql_sqlite.c_str(), sql_sqlite.size(), &result, &s);
+
+ if(rc != SQLITE_OK)
+ {
+ string err = "execute: prepare query failed: "+sql_sqlite;
+ printf("%s\n", err.c_str());
+ result = NULL;
+ return false;
+ }
+ if(!result)
+ {
+ printf( "execute: query failed\n");
+ result = NULL;
+ return false;
+ }
+ rc = sqlite3_step(result);
+ sqlite3_finalize(result);
+ result = NULL;
+ switch(rc)
+ {
+ case SQLITE_BUSY:
+ printf( "execute: database busy\n");
+ return false;
+ case SQLITE_DONE:
+ case SQLITE_ROW:
+ return true;
+ case SQLITE_SCHEMA:
+ printf( "execute: Schema error\n");
+ return false;
+ case SQLITE_ERROR:
+ printf("%s\n", sqlite3_errmsg((sqlite3 *)odb->db));
+ return false;
+ case SQLITE_MISUSE:
+ printf( "execute: database misuse\n");
+ return false;
+ default:
+ printf( "execute: unknown result code\n");
+ }
+ }
+ return false;
+}
+
+bool sqlitequery::fetchRow()
+{
+ rowcount = 0;
+ row = false;
+ if(odb && result)
+ {
+ int rc = cache_rc_valid ? cache_rc : sqlite3_step(result);
+ cache_rc_valid = false;
+ switch(rc)
+ {
+ case SQLITE_BUSY:
+ printf( "execute: database busy\n");
+ return false;
+ case SQLITE_DONE:
+ return false;
+ case SQLITE_ROW:
+ row = true;
+ return true;
+ case SQLITE_ERROR:
+ printf("%s\n", sqlite3_errmsg((sqlite3 *)odb->db));
+ return false;
+ case SQLITE_MISUSE:
+ printf( "execute: database misuse\n");
+ return false;
+ default:
+ printf( "execute: unknown result code\n");
+ }
+ }
+ return false;
+}
+
+void sqlitequery::freeResult()
+{
+ if(odb && result)
+ {
+ sqlite3_finalize(result);
+ result = NULL;
+ row = false;
+ cache_rc_valid = false;
+ }
+ while(m_nmap.size())
+ {
+ std::map<std::string, int>::iterator it = m_nmap.begin();
+ m_nmap.erase(it);
+ }
+}
+
+void sqlitequery::resetStatement()
+{
+ if( odb && result )
+ sqlite3_reset(result);
+}
+
+long sqlitequery::getCount(const std::string & sql)
+{
+ long l(0);
+ if(getResult(sql))
+ {
+ if(fetchRow())
+ {
+ l = getVal(rowcount++);
+ }
+ freeResult();
+ }
+ return l;
+}
+
+bool sqlitequery::prepareStatement(const std::string & sql)
+{
+ std::string sql_sqlite=sql;
+ m_last_query = sql_sqlite;
+ if(odb && result)
+ {
+ string err = "prepareStatement: query busy: "+sql_sqlite;
+ printf("%s\n", err.c_str());
+ }
+ if(odb && !result)
+ {
+ const char * s = NULL;
+ int rc = sqlite3_prepare_v2((sqlite3 *)odb->db, sql_sqlite.c_str(), sql_sqlite.size(), &result, &s);
+ if(rc != SQLITE_OK)
+ {
+ string err = "prepareStatement: prepare query failed: "+sql_sqlite;
+ printf("%s\n", err.c_str());
+ return false;
+ }
+ if(!result)
+ {
+ printf( "prepareStatement: query failed\n");
+ return false;
+ }
+ }
+ return result;
+}
+
+bool sqlitequery::getResult(const std::string & sql)
+{
+ if(prepareStatement(sql))
+ {
+ int i(0);
+ const char * p = sqlite3_column_name(result, i);
+ while(p)
+ {
+ m_nmap[p] = ++i;
+ p = sqlite3_column_name(result, i);
+ }
+ m_num_cols = i;
+ cache_rc = sqlite3_step(result);
+ cache_rc_valid = true;
+ m_row_count = (cache_rc == SQLITE_ROW) ? 1 : 0;
+ }
+ return result;
+}
+
+bool sqlitequery::bind(const std::string bindMatch)
+{
+ if(!odb || !result) return false;
+
+ int r = sqlite3_bind_text(result,1,bindMatch.c_str(),bindMatch.length(),NULL);
+
+ if(r != SQLITE_OK)
+ {
+ printf("sqlitequery::bind - error binding query\n");
+ return false;
+ }
+
+ int i(0);
+ const char * p = sqlite3_column_name(result, i);
+ while(p)
+ {
+ m_nmap[p] = ++i;
+ p = sqlite3_column_name(result, i);
+ }
+ m_num_cols = i;
+ cache_rc = sqlite3_step(result);
+ cache_rc_valid = true;
+ m_row_count = (cache_rc == SQLITE_ROW) ? 1 : 0;
+
+ return true;
+}
+
+bool sqlitequery::bind(const int value)
+{
+ if(!odb || !result) return false;
+
+ int r = sqlite3_bind_int(result,1,value);
+
+ if(r != SQLITE_OK)
+ {
+ printf("sqlitequery::bind - error binding query\n");
+ return false;
+ }
+
+ int i(0);
+ const char * p = sqlite3_column_name(result, i);
+ while(p)
+ {
+ m_nmap[p] = ++i;
+ p = sqlite3_column_name(result, i);
+ }
+
+ m_num_cols = i;
+ cache_rc = sqlite3_step(result);
+ cache_rc_valid = true;
+ m_row_count = (cache_rc == SQLITE_ROW) ? 1 : 0;
+
+ return true;
+}
+
+bool sqlitequery::bind(const double value)
+{
+ if(!odb || !result) return false;
+
+ int r = sqlite3_bind_double(result,1,value);
+
+ if(r != SQLITE_OK)
+ {
+ printf("sqlitequery::bind - error binding query\n");
+ return false;
+ }
+
+ int i(0);
+ const char * p = sqlite3_column_name(result, i);
+ while(p)
+ {
+ m_nmap[p] = ++i;
+ p = sqlite3_column_name(result, i);
+ }
+ m_num_cols = i;
+ cache_rc = sqlite3_step(result);
+ cache_rc_valid = true;
+ m_row_count = (cache_rc == SQLITE_ROW) ? 1 : 0;
+
+ return cache_rc == SQLITE_OK;
+}
+
+int64_t sqlitequery::getBigInt(int x)
+{
+ if(odb && result && row)
+ {
+ return sqlite3_column_int64(result, x);
+ }
+ return 0;
+}
+
+int sqlitequery::GetErrno()
+{
+ if(odb)
+ {
+ return sqlite3_errcode((sqlite3 *)odb->db);
+ }
+ return 0;
+}
+
+std::string sqlitequery::GetError()
+{
+ if(odb)
+ {
+ return sqlite3_errmsg((sqlite3 *)odb->db);
+ }
+ return "";
+}
+
+double sqlitequery::getNum(int x)
+{
+ if(odb && result && row)
+ {
+ return sqlite3_column_double(result, x);
+ }
+ return 0;
+}
+
+const char * sqlitequery::getStr(int x)
+{
+ if(odb && result && row && x < sqlite3_column_count(result))
+ {
+ const unsigned char * tmp = sqlite3_column_text(result, x);
+ return tmp ? (const char *)tmp : "";
+ }
+ return "";
+}
+
+uint64_t sqlitequery::getUBigInt(int x)
+{
+ if(odb && result && row)
+ {
+ return (uint64_t)sqlite3_column_int64(result, x);
+ }
+ return 0;
+}
+
+unsigned long sqlitequery::getUVal(int x)
+{
+ if(odb && result && row)
+ {
+ return (unsigned long)sqlite3_column_int(result, x);
+ }
+ return 0;
+}
+
+long sqlitequery::getVal(int x)
+{
+ if(odb && result && row)
+ {
+ return sqlite3_column_int(result, x);
+ }
+ return 0;
+}
+
+bool sqlitequery::isNull(int x)
+{
+ if(odb && result && row)
+ {
+ if(sqlite3_column_type(result, x) == SQLITE_NULL)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+long sqlitequery::numRows()
+{
+ return odb && result ? m_row_count : 0;
+}
+
diff --git a/plugins/database/sqlitequery.h b/plugins/database/sqlitequery.h
new file mode 100644
index 00000000..4679619d
--- /dev/null
+++ b/plugins/database/sqlitequery.h
@@ -0,0 +1,86 @@
+/*
+ * timedate - Displays time and date and daily events
+ * Copyright (c) <2009>, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef SQLITEQUERY_H
+#define SQLITEQUERY_H
+
+#include "sqlitedatabase.h"
+#include <map>
+
+class sqlite3_stmt;
+
+class sqlitequery
+{
+public:
+ sqlitequery() : result(NULL), row(false), cache_rc(0), cache_rc_valid(false), m_row_count(0), m_db(NULL), m_num_cols(0) {}
+ virtual ~sqlitequery();
+
+ bool init(sqlitedatabase * dbin);
+ bool init(sqlitedatabase * dbin, const std::string & sql);
+
+ virtual bool Connected(){return odb ? true : false;}
+ virtual bool execute(const std::string & sql);
+ virtual bool fetchRow();
+ virtual long numRows();
+ virtual void freeResult();
+ virtual void resetStatement();
+ virtual long getCount(const std::string & sql);
+ virtual bool prepareStatement(const std::string & sql);
+ virtual bool getResult(const std::string & sql);
+ virtual bool bind(const std::string bindMatch);
+ virtual bool bind(const int value);
+ virtual bool bind(const double value);
+ virtual int64_t getBigInt(){return getBigInt(rowcount++);}
+ virtual int64_t getBigInt(int x);
+ virtual int GetErrno();
+ virtual std::string GetError();
+ virtual double getNum(){ return getNum(rowcount++); }
+ virtual double getNum(int x);
+ virtual const char * getStr(){return getStr(rowcount++);}
+ virtual const char * getStr(int x);
+ virtual uint64_t getUBigInt(){ return getUBigInt(rowcount++); }
+ virtual uint64_t getUBigInt(int x);
+ virtual unsigned long getUVal(){ return getUVal(rowcount++); }
+ virtual unsigned long getUVal(int x);
+ virtual long getVal(){ return getVal(rowcount++); }
+ virtual long getVal(int x);
+ virtual bool isNull(int x);
+protected:
+ sqlite3_stmt * result;
+ bool row;
+ int cache_rc;
+ bool cache_rc_valid;
+ int m_row_count;
+
+ virtual sqlitequery & operator=(const sqlitequery &){return *this;}
+
+ sqlitedatabase * m_db;
+ std::string m_last_query;
+ short rowcount;
+ std::string m_tmpstr;
+ std::map<std::string, int> m_nmap;
+ int m_num_cols;
+ SqliteDB * odb;
+
+private:
+ std::string sql_replace_tokens(std::string sqlstring,std::string &dest);
+};
+
+#endif
+
diff --git a/plugins/database/utils.cpp b/plugins/database/utils.cpp
new file mode 100644
index 00000000..208da86e
--- /dev/null
+++ b/plugins/database/utils.cpp
@@ -0,0 +1,52 @@
+/*
+ * timedate - Displays time and date and daily events
+ * Copyright (c) <2009>, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "utils.h"
+#include <stdlib.h>
+
+using namespace std;
+
+string
+DaoUtils::findReplace(string name, string tofind, string replacewith, string exclusions)
+{
+ uint i=0;
+
+ uint exclusionPos = exclusions.find(tofind,0);
+
+ while(1)
+ {
+ i = name.find(tofind,i);
+
+ if(i != string::npos && exclusionPos != string::npos)
+ {
+ if(name.substr(i-exclusionPos,exclusions.length()) == exclusions)
+ {
+ i+=replacewith.size();
+ continue;
+ }
+ }
+
+ if(i == string::npos)
+ break;
+ name.replace(i,tofind.size(),replacewith);
+ i+=replacewith.size();
+ }
+ return name;
+}
+
diff --git a/plugins/database/utils.h b/plugins/database/utils.h
new file mode 100644
index 00000000..c1c395d4
--- /dev/null
+++ b/plugins/database/utils.h
@@ -0,0 +1,35 @@
+/*
+ * timedate - Displays time and date and daily events
+ * Copyright (c) <2009>, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef _DAOUTILS_H_
+#define _DAOUTILS_H_
+
+#include <string>
+
+class DaoUtils
+{
+public:
+ DaoUtils(){}
+ virtual ~DaoUtils(){}
+
+ static std::string findReplace(std::string name, std::string tofind, std::string replacewith, std::string exclusions="");
+};
+
+
+#endif
diff --git a/plugins/dbus/CMakeLists.txt b/plugins/dbus/CMakeLists.txt
new file mode 100644
index 00000000..e3cd2477
--- /dev/null
+++ b/plugins/dbus/CMakeLists.txt
@@ -0,0 +1,34 @@
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${CMAKE_SOURCE_DIR}/plugins/common)
+
+pkg_check_modules(gio REQUIRED gio-2.0)
+
+set(dbussinkplugin_headers automotivemanager.h dbusinterfacemanager.h runningstatus.h
+ custompropertyinterface.h uncategorizedproperty.h environmentproperties.h vehicleinfo.h maintenance.h parking.h fakeidlheader.h drivingsafety.h personalization.h)
+set(dbussinkplugin_sources automotivemanager.cpp dbusinterfacemanager.cpp runningstatus.cpp
+ custompropertyinterface.cpp uncategorizedproperty.cpp environmentproperties.cpp vehicleinfo.cpp maintenance.cpp parking.cpp drivingsafety.cpp personalization.cpp)
+
+add_library(dbussinkplugin MODULE ${dbussinkplugin_sources})
+set_target_properties(dbussinkplugin PROPERTIES PREFIX "")
+target_link_libraries(dbussinkplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${gio_LIBRARIES} -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common amb-plugins-common)
+
+install (TARGETS dbussinkplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/amb.conf DESTINATION /etc/dbus-1/system.d )
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/amb.conf ${CMAKE_CURRENT_SOURCE_DIR}/amb.conf)
+
+set(dbus_mapping_headers ${CMAKE_CURRENT_SOURCE_DIR}/runningstatus.h CACHE INTERNAL "dbus mapping headers")
+set(dbus_mapping_headers ${dbus_mapping_headers} ${CMAKE_CURRENT_SOURCE_DIR}/environmentproperties.h CACHE INTERNAL "dbus mapping headers")
+set(dbus_mapping_headers ${dbus_mapping_headers} ${CMAKE_CURRENT_SOURCE_DIR}/vehicleinfo.h CACHE INTERNAL "dbus mapping headers")
+set(dbus_mapping_headers ${dbus_mapping_headers} ${CMAKE_CURRENT_SOURCE_DIR}/maintenance.h CACHE INTERNAL "dbus mapping headers")
+set(dbus_mapping_headers ${dbus_mapping_headers} ${CMAKE_CURRENT_SOURCE_DIR}/parking.h CACHE INTERNAL "dbus mapping headers")
+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.md @ONLY)
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/dbus.README.md 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/README b/plugins/dbus/README
new file mode 100644
index 00000000..f902ffad
--- /dev/null
+++ b/plugins/dbus/README
@@ -0,0 +1,28 @@
+# DBus plugin {#dbus_plugin}
+Version: @PROJECT_VERSION@
+
+This plugin provides a nice DBus API to application who want access to AMB data.
+
+To use the DBus plugin, add the following to the "sinks" array in /etc/ambd/config:
+
+~~~~~~~~~~~~~{.json}
+{
+ "name" : "dbussink",
+ "path" : "@PLUGIN_INSTALL_PATH@/dbussinkplugin.so",
+ "frequency" : "60"
+}
+~~~~~~~~~~~~~
+
+## Configuration Key Definitions:
+
+"name"
+name of plugin. This key is not used by the plugin at this moment.
+
+"path"
+path to plugin on the filesystem.
+
+"frequency"
+Frequency in Hz which AMB will fire dbus signals. AMB will fire the most recent values at this rate.
+
+Default: 60
+
diff --git a/plugins/dbus/amb-qt/CMakeLists.txt b/plugins/dbus/amb-qt/CMakeLists.txt
new file mode 100644
index 00000000..a1ae739c
--- /dev/null
+++ b/plugins/dbus/amb-qt/CMakeLists.txt
@@ -0,0 +1,39 @@
+if(qt_bindings)
+
+find_package(Qt5Core REQUIRED)
+find_package(Qt5Quick REQUIRED)
+find_package(Qt5DBus REQUIRED)
+
+if(Qt5Core_FOUND)
+ message(STATUS "using Qt5")
+
+ set(QT_INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS} ${Qt5Quick_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS})
+ set(QT_LIBRARIES ${Qt5Core_LIBRARIES} ${Qt5Quick_LIBRARIES} ${Qt5DBus_LIBRARIES})
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
+ add_definitions(${Qt5Core_DEFINITIONS})
+ set(CMAKE_AUTOMOC ON)
+endif(Qt5Core_FOUND)
+
+set(ambqt_headers ambqt.h amb-qt_global.h)
+set(ambqt_sources ambqt.cpp)
+set(ambqtquick_sources ambqtquick.cpp)
+set(ambqtquick_headers ambqtquick.h)
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${QT_INCLUDE_DIRS})
+
+add_library(amb-qt SHARED ${ambqt_sources} ${ambqt_headers_moc})
+add_library(ambqtquick MODULE ${ambqtquick_sources} ${ambqtquick_headers_moc})
+
+target_link_libraries(amb-qt amb ${QT_LIBRARIES} -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${gio_LIBRARIES})
+target_link_libraries(ambqtquick amb-qt ${QT_LIBRARIES} -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${gio_LIBRARIES})
+
+add_executable(ambtestclient test.cpp)
+target_link_libraries(ambtestclient amb amb-qt ${QT_LIBRARIES} -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${gio_LIBRARIES})
+
+install (TARGETS amb-qt LIBRARY DESTINATION lib${LIB_SUFFIX})
+
+install (FILES ${ambqt_headers} DESTINATION ${INCLUDE_INSTALL_DIR}/ COMPONENT Devel)
+install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/qmldir DESTINATION ${LIB_INSTALL_DIR}/qt5/qml/amb COMPONENT Devel)
+install (TARGETS ambqtquick DESTINATION ${LIB_INSTALL_DIR}/qt5/qml/amb)
+install (TARGETS ambtestclient RUNTIME DESTINATION bin)
+endif(qt_bindings)
diff --git a/plugins/dbus/amb-qt/amb-qt_global.h b/plugins/dbus/amb-qt/amb-qt_global.h
new file mode 100644
index 00000000..e971664e
--- /dev/null
+++ b/plugins/dbus/amb-qt/amb-qt_global.h
@@ -0,0 +1,12 @@
+#ifndef AMBQT_GLOBAL_H
+#define AMBQT_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(AMBQT_LIBRARY)
+# define AMBQTSHARED_EXPORT Q_DECL_EXPORT
+#else
+# define AMBQTSHARED_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // AMBQT_GLOBAL_H
diff --git a/plugins/dbus/amb-qt/ambqt.cpp b/plugins/dbus/amb-qt/ambqt.cpp
new file mode 100644
index 00000000..6a3faebb
--- /dev/null
+++ b/plugins/dbus/amb-qt/ambqt.cpp
@@ -0,0 +1,92 @@
+#include "ambqt.h"
+#include <QDBusConnection>
+#include <QDBusInterface>
+#include <QtDebug>
+#include <QDBusReply>
+
+AmbProperty::AmbProperty(QString op, QString iface, QString propName)
+ :QObject(), mPropertyName(propName),mInterfaceName(iface), mObjectPath(op),mDBusInterface(NULL),mZone(0)
+{
+ connect();
+}
+
+
+void AmbProperty::propertyChangedSlot(QString, QVariantMap values, QVariantMap )
+{
+ valueChanged(values);
+}
+
+void AmbProperty::propertyChanged1(QDBusVariant val, double t)
+{
+ mTime = t;
+ mValue = val.variant();
+
+ signalChanged(mValue);
+}
+
+void AmbProperty::connect()
+{
+ if(mDBusInterface)
+ {
+ delete mDBusInterface;
+ }
+
+ if(mObjectPath.isEmpty())
+ getObjectPath();
+
+ if(mInterfaceName.isEmpty())
+ mInterfaceName = "org.automotive."+mPropertyName;
+
+ mDBusInterface = new QDBusInterface("org.automotive.message.broker",objectPath(), interfaceName(), QDBusConnection::systemBus(),this);
+
+ if(!mDBusInterface->isValid())
+ {
+ qDebug()<<"Failed to create dbus interface for property "<<propertyName();
+ qDebug()<<"Path: "<<objectPath();
+ qDebug()<<"Interface: "<<interfaceName();
+ qDebug()<<"Error: "<<QDBusConnection::systemBus().lastError().message();
+ }
+
+ QString signalName = propertyName() + "Changed";
+
+
+ if(!QDBusConnection::systemBus().connect("org.automotive.message.broker", objectPath(), "org.freedesktop.DBus.Properties",
+ "PropertiesChanged", this, SLOT(propertyChangedSlot(QString,QVariantMap,QVariantMap))))
+ {
+ qDebug()<<"Failed to connect to signal";
+ qDebug()<<"path: "<<objectPath();
+ qDebug()<<"interface: "<<interfaceName();
+ qDebug()<<"signal: "<<propertyName();
+ qDebug()<<"Error: "<<QDBusConnection::systemBus().lastError().message();
+ }
+
+ ///TODO: only use PropertiesChanged... treat AmbProperty like an object rather than a representation of just a single property in the object
+
+ if(!QDBusConnection::systemBus().connect("org.automotive.message.broker", objectPath(), mInterfaceName,
+ signalName, this, SLOT(propertyChanged1(QDBusVariant,double))))
+ {
+ qDebug()<<"Failed to connect to signal";
+ qDebug()<<"path: "<<objectPath();
+ qDebug()<<"interface: "<<interfaceName();
+ qDebug()<<"signal: "<<propertyName();
+ qDebug()<<"Error: "<<QDBusConnection::systemBus().lastError().message();
+ }
+}
+
+void AmbProperty::getObjectPath()
+{
+ QDBusInterface managerIface("org.automotive.message.broker","/","org.automotive.Manager", QDBusConnection::systemBus(), this);
+
+ if(!managerIface.isValid())
+ {
+ qDebug()<<"Failed to create manager interface";
+ return;
+ }
+
+ QDBusReply<QDBusObjectPath> reply = managerIface.call("FindObjectForZone", mPropertyName, mZone);
+
+ if(reply.isValid())
+ {
+ mObjectPath = reply.value().path();
+ }
+}
diff --git a/plugins/dbus/amb-qt/ambqt.h b/plugins/dbus/amb-qt/ambqt.h
new file mode 100644
index 00000000..3d7e793b
--- /dev/null
+++ b/plugins/dbus/amb-qt/ambqt.h
@@ -0,0 +1,75 @@
+#ifndef AMBQT_H
+#define AMBQT_H
+
+#include <QObject>
+#include <QDBusInterface>
+#include <QtDebug>
+
+#define AUTOPROPERTY(type, name, Name) \
+ public: \
+ void set ## Name(type s) { m ## Name = s; } \
+ type name() { return m ## Name; } \
+ private: \
+ type m ## Name;
+
+class QDBusInterface;
+
+class AmbProperty: public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString propertyName READ propertyName WRITE setPropertyName)
+ AUTOPROPERTY(QString, propertyName, PropertyName)
+ Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
+ Q_PROPERTY(QString interfaceName READ interfaceName WRITE setInterfaceName)
+ AUTOPROPERTY(QString, interfaceName, InterfaceName)
+ Q_PROPERTY(QString objectPath READ objectPath WRITE setObjectPath)
+ AUTOPROPERTY(QString, objectPath, ObjectPath)
+ Q_PROPERTY(int zone READ zone WRITE setZone)
+ AUTOPROPERTY(int, zone, Zone)
+ Q_PROPERTY(double time READ time)
+
+
+ public:
+
+ AmbProperty():mDBusInterface(NULL),mZone(0),mTime(0) { }
+
+ AmbProperty(QString op, QString iface, QString propName);
+
+ QVariant value()
+ {
+ return mValue;
+ }
+
+ void setValue(QVariant v)
+ {
+ if(!mDBusInterface || !mDBusInterface->isValid())
+ {
+ qDebug()<<"error Interface is not valid "<<interfaceName();
+ }
+
+ mDBusInterface->setProperty(propertyName().toUtf8(), v);
+ }
+
+ double time(){ return mTime; }
+
+Q_SIGNALS:
+ void valueChanged(QVariant val);
+
+ ///TODO: remove
+ void signalChanged(QVariant val);
+
+public Q_SLOTS:
+ void connect();
+
+private Q_SLOTS:
+ void propertyChangedSlot(QString, QVariantMap values, QVariantMap);
+ void propertyChanged1(QDBusVariant, double);
+
+private:
+ void getObjectPath();
+ QDBusInterface* mDBusInterface;
+ double mTime;
+ QVariant mValue;
+};
+
+#endif // AMBQT_H
diff --git a/plugins/dbus/amb-qt/ambqtquick.cpp b/plugins/dbus/amb-qt/ambqtquick.cpp
new file mode 100644
index 00000000..c5102a9a
--- /dev/null
+++ b/plugins/dbus/amb-qt/ambqtquick.cpp
@@ -0,0 +1,14 @@
+#include "ambqtquick.h"
+#include <QtQml/qqml.h>
+
+void Components::registerTypes(const char *uri)
+{
+ qmlRegisterType<AmbProperty>(uri,0,1,"AutomotivePropertyItem");
+
+}
+
+void Components::initializeEngine(QQmlEngine *, const char *)
+{
+
+}
+
diff --git a/plugins/dbus/amb-qt/ambqtquick.h b/plugins/dbus/amb-qt/ambqtquick.h
new file mode 100644
index 00000000..a48104a3
--- /dev/null
+++ b/plugins/dbus/amb-qt/ambqtquick.h
@@ -0,0 +1,14 @@
+#include <QQmlExtensionPlugin>
+#include "ambqt.h"
+
+class Components : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.automotive.qmlplugin")
+public:
+
+
+ void registerTypes(const char *uri);
+ void initializeEngine(QQmlEngine *engine, const char *uri);
+
+};
diff --git a/plugins/dbus/amb-qt/qmldir b/plugins/dbus/amb-qt/qmldir
new file mode 100644
index 00000000..a2d986c2
--- /dev/null
+++ b/plugins/dbus/amb-qt/qmldir
@@ -0,0 +1 @@
+plugin ambqtquick
diff --git a/plugins/dbus/amb-qt/test.cpp b/plugins/dbus/amb-qt/test.cpp
new file mode 100644
index 00000000..6eb88eb4
--- /dev/null
+++ b/plugins/dbus/amb-qt/test.cpp
@@ -0,0 +1,35 @@
+#include "ambqt.h"
+#include "timestamp.h"
+
+#include <QCoreApplication>
+
+#include <debugout.h>
+#include <iostream>
+
+int main(int argc, char** argv)
+{
+ QCoreApplication app(argc,argv);
+
+ AmbProperty speed;
+
+ double totalLatency=0;
+ int numSamples=0;
+
+ QObject::connect(&speed, &AmbProperty::signalChanged,[&](QVariant val)
+ {
+ double t1 = speed.time();
+ double t2 = amb::currentTime();
+
+ double latency = (t2-t1)*1000.0;
+
+ DebugOut(0)<<"latency: "<<latency<<std::endl;
+ totalLatency+=latency;
+ numSamples++;
+ DebugOut(0)<<"Average: "<<totalLatency / numSamples<<std::endl;
+ });
+
+ speed.setPropertyName("VehicleSpeed");
+ speed.connect();
+
+ return app.exec();
+}
diff --git a/plugins/dbus/amb.conf b/plugins/dbus/amb.conf
new file mode 100644
index 00000000..0cc4c7b2
--- /dev/null
+++ b/plugins/dbus/amb.conf
@@ -0,0 +1,21 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+ <policy context="default">
+ <allow own="org.automotive.message.broker"/>
+ <allow send_destination="org.automotive.message.broker"/>
+
+ <!-- Example: in the default context, this interface is denied write control -->
+ <deny send_destination="org.automotive.message.broker" send_interface="org.freedesktop.DBus.Properties"
+ send_path="/org/automotive/uncategorized/MachineGunTurretStatus" send_member="Set" />
+
+ </policy>
+
+ <!-- Example: the following is an example on how a specific interface can be protected using SMACK
+ <policy smack="allow_write_machinegun" >
+ <allow send_destination="org.automotive.message.broker" send_interface="org.freedesktop.DBus.Properties"
+ send_path="/org/automotive/uncategorized/MachineGunTurretStatus" send_member="Set" />
+ </policy> -->
+
+</busconfig>
diff --git a/plugins/dbus/automotivemanager.cpp b/plugins/dbus/automotivemanager.cpp
new file mode 100644
index 00000000..64919e05
--- /dev/null
+++ b/plugins/dbus/automotivemanager.cpp
@@ -0,0 +1,458 @@
+#include "automotivemanager.h"
+#include "abstractdbusinterface.h"
+#include "listplusplus.h"
+
+static const gchar introspection_xml[] =
+ "<node>"
+ " <interface name='org.automotive.Manager'>"
+ " <method name='FindObject'>"
+ " <arg type='s' name='searchstring' direction='in'/>"
+ " <arg type='ao' name='response' direction='out'/>"
+ " </method>"
+ " <method name='FindObjectForZone'>"
+ " <arg type='s' name='searchstring' direction='in'/>"
+ " <arg type='i' name='zone' direction='in'/>"
+ " <arg type='o' name='response' direction='out'/>"
+ " </method>"
+ " <method name='FindObjectForSourceZone'>"
+ " <arg type='s' name='searchstring' direction='in'/>"
+ " <arg type='s' name='source' direction='in'/>"
+ " <arg type='i' name='zone' direction='in'/>"
+ " <arg type='o' name='response' direction='out'/>"
+ " </method>"
+ " <method name='List'>"
+ " <arg type='as' name='response' direction='out'/>"
+ " </method>"
+ " <method name='ZonesForObjectName'>"
+ " <arg type='s' name='searchstring' direction='in'/>"
+ " <arg type='ai' name='response' direction='out'/>"
+ " </method>"
+ " <method name='SourcesForObjectName'>"
+ " <arg type='s' name='searchstring' direction='in'/>"
+ " <arg type='as' name='response' direction='out'/>"
+ " </method>"
+ " <method name='SupportsProperty'>"
+ " <arg type='s' name='objectName' direction='in'/>"
+ " <arg type='s' name='propertyName' direction='in'/>"
+ " <arg type='b' name='response' direction='out'/>"
+ " </method>"
+ " </interface>"
+ "</node>";
+
+static void handleMethodCall(GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+
+ AutomotiveManager* manager = static_cast<AutomotiveManager*>(user_data);
+
+ std::string method = method_name;
+
+ uint pid = getPid(sender);
+
+ if(DebugOut::getDebugThreshhold() >= 6)
+ {
+ DebugOut(6)<<"DBus method call from: "<<sender<< " pid: " <<pid<< " interface: "<<interface_name<<" method: "<<method<<endl;
+ DebugOut(6)<<"DBus method call path: "<<object_path<<endl;
+ }
+
+ if(method == "FindObject")
+ {
+ gchar* arg;
+
+ g_variant_get(parameters,"(s)",&arg);
+
+ std::string objectToFind = arg;
+
+ if(objectToFind == "")
+ {
+ g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR,G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
+ return;
+ }
+
+ std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(objectToFind);
+
+ if(!interfaces.size())
+ {
+ g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Object not found");
+ return;
+ }
+
+ GVariantBuilder params;
+ g_variant_builder_init(&params, G_VARIANT_TYPE_ARRAY);
+
+ bool hasItems = false;
+
+ for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
+ {
+ AbstractDBusInterface* t = *itr;
+ if(!t->isSupported())
+ continue;
+
+ hasItems = true;
+
+ if(!t->isRegistered())
+ t->registerObject();
+
+ std::list<std::string> processes = manager->subscribedProcesses[t];
+
+ if(!contains(processes,sender))
+ {
+ DebugOut()<<"Referencing "<<t->objectPath()<<" with sender: "<<sender<<endl;
+ manager->subscribedProcesses[t].push_back(sender);
+ }
+
+ GVariant *newvar = g_variant_new("o",t->objectPath().c_str());
+ g_variant_builder_add_value(&params, newvar);
+ }
+
+ if(hasItems)
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(ao)",&params));
+ else
+ g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
+
+ }
+
+ else if(method == "FindObjectForZone")
+ {
+ gchar* arg;
+ int zone;
+
+ g_variant_get(parameters,"(si)", &arg, &zone);
+
+ std::string propertyToFind = arg;
+
+ if(propertyToFind == "")
+ {
+ g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
+ return;
+ }
+
+ std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(propertyToFind);
+
+ if(!interfaces.size())
+ {
+ g_dbus_method_invocation_return_dbus_error(invocation, "org.automotive.Manager.ObjectNotFound", "Property not found");
+ return;
+ }
+
+
+
+ for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
+ {
+ AbstractDBusInterface* t = *itr;
+
+ if(t->zone() == (Zone::Type)zone)
+ {
+ if(!t->isRegistered())
+ t->registerObject();
+
+ std::list<std::string> processes = manager->subscribedProcesses[t];
+
+ if(!contains(processes,sender))
+ {
+ DebugOut()<<"Referencing "<<t->objectPath()<<" with sender: "<<sender<<endl;
+ manager->subscribedProcesses[t].push_back(sender);
+ }
+
+ g_dbus_method_invocation_return_value(invocation,g_variant_new("(o)", t->objectPath().c_str()));
+ return;
+ }
+ }
+
+ g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.InvalidZone", "zone not found");
+ }
+
+ else if (method == "ZonesForObjectName")
+ {
+ gchar* arg;
+
+ g_variant_get(parameters,"(s)",&arg);
+
+ std::string propertyToFind = arg;
+
+ if(propertyToFind == "")
+ {
+ g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
+ return;
+ }
+
+ std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(propertyToFind);
+
+ if(!interfaces.size())
+ {
+ g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
+ return;
+ }
+
+ GVariantBuilder params;
+ g_variant_builder_init(&params, G_VARIANT_TYPE_ARRAY);
+
+ for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
+ {
+ AbstractDBusInterface* t = *itr;
+ GVariant *newvar = g_variant_new("i",t->zone());
+ g_variant_builder_add_value(&params, newvar);
+
+ }
+
+ g_dbus_method_invocation_return_value(invocation,g_variant_new("(ai)",&params));
+ }
+
+ else if(method == "List")
+ {
+ std::vector<std::string> supportedProperties = AbstractDBusInterface::supportedInterfaces();
+
+ if(!supportedProperties.size())
+ {
+ g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.Error", "No supported objects");
+ return;
+ }
+
+ std::sort(supportedProperties.begin(), supportedProperties.end());
+ auto itr = std::unique(supportedProperties.begin(), supportedProperties.end());
+
+ supportedProperties.erase(itr, supportedProperties.end());
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
+
+ for(auto objectName : supportedProperties)
+ {
+ g_variant_builder_add(&builder, "s", objectName.c_str());
+ }
+
+ g_dbus_method_invocation_return_value(invocation,g_variant_new("(as)",&builder));
+ }
+ else if(method == "SourcesForObjectName")
+ {
+ gchar* arg;
+
+ g_variant_get(parameters,"(s)",&arg);
+
+ std::string propertyToFind = arg;
+
+ if(propertyToFind == "")
+ {
+ g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
+ return;
+ }
+
+ std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(propertyToFind);
+
+ if(!interfaces.size())
+ {
+ g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
+ return;
+ }
+
+ GVariantBuilder params;
+ g_variant_builder_init(&params, G_VARIANT_TYPE_ARRAY);
+
+ for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
+ {
+ AbstractDBusInterface* t = *itr;
+ string source = t->source();
+ boost::algorithm::erase_all(source, "-");
+ GVariant *newvar = g_variant_new("s", source.c_str());
+ g_variant_builder_add_value(&params, newvar);
+
+ }
+
+ g_dbus_method_invocation_return_value(invocation,g_variant_new("(as)",&params));
+ }
+ else if(method == "FindObjectForSourceZone")
+ {
+ gchar* arg;
+ gchar* arg2;
+ int zone;
+
+ g_variant_get(parameters,"(ssi)", &arg, &arg2, &zone);
+
+ std::string propertyToFind = arg;
+ std::string source = arg2;
+
+ if(propertyToFind == "" || source == "")
+ {
+ g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR,G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
+ return;
+ }
+
+ std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(propertyToFind);
+
+ if(!interfaces.size())
+ {
+ g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
+ return;
+ }
+
+ for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
+ {
+ AbstractDBusInterface* t = *itr;
+ string targetSource = t->source();
+ boost::algorithm::erase_all(targetSource, "-");
+ if(t->zone() == (Zone::Type)zone && source == targetSource)
+ {
+ if(!t->isRegistered())
+ t->registerObject();
+
+ std::list<std::string> processes = manager->subscribedProcesses[t];
+
+ if(!contains(processes,sender))
+ {
+ DebugOut()<<"Referencing "<<t->objectPath()<<" with sender: "<<sender<<endl;
+ manager->subscribedProcesses[t].push_back(sender);
+ }
+
+ g_dbus_method_invocation_return_value(invocation,g_variant_new("(o)", t->objectPath().c_str()));
+ return;
+ }
+ }
+
+ g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
+ }
+ else if(method == "SupportsProperty")
+ {
+ gchar* objectName;
+ gchar* propertyToFindStr;
+
+ g_variant_get(parameters,"(ss)",&objectName, &propertyToFindStr);
+
+ auto objectNamePtr = amb::make_super(objectName);
+ auto propertyToFindStrPtr = amb::make_super(propertyToFindStr);
+
+ DebugOut(6) << "Checking " << objectNamePtr.get() << " for member: " << propertyToFindStrPtr.get() << endl;
+
+ std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(objectNamePtr.get());
+
+ for(auto i : interfaces)
+ {
+ if(i->hasPropertyDBus(propertyToFindStrPtr.get()))
+ {
+ DebugOut(6) << "member " << propertyToFindStrPtr.get() << " of " << objectNamePtr.get() << " was found!!" << endl;
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", true));
+ return;
+ }
+ }
+ DebugOut(6) << "member " << propertyToFindStrPtr.get() << " of " << objectNamePtr.get() << " was not found." << endl;
+ 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.");
+ }
+}
+
+static void signalCallback( GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ AutomotiveManager* manager = static_cast<AutomotiveManager*>(user_data);
+
+ if(!manager)
+ {
+ DebugOut(DebugOut::Error)<<"Bad user_data"<<endl;
+ return;
+ }
+
+ gchar* name=nullptr;
+ gchar* newOwner=nullptr;
+ gchar* oldOwner = nullptr;
+ g_variant_get(parameters,"(sss)",&name, &oldOwner, &newOwner);
+
+ std::list<AbstractDBusInterface*> toRemove;
+
+ if(std::string(newOwner) == "")
+ {
+ for(auto &i : manager->subscribedProcesses)
+ {
+ AbstractDBusInterface* iface = i.first;
+
+ for(auto itr = i.second.begin(); itr != i.second.end(); itr++)
+ {
+ std::string n = *itr;
+ if(n == name)
+ {
+ DebugOut()<<"unreferencing "<<n<<" from the subscription of "<<iface->objectPath()<<endl;
+ itr = manager->subscribedProcesses[iface].erase(itr);
+ DebugOut()<<"new ref count: "<<manager->subscribedProcesses[iface].size()<<endl;
+ }
+ }
+
+ if(manager->subscribedProcesses[iface].empty())
+ {
+ DebugOut()<<"No more subscribers. Unregistering: "<<iface->objectPath()<<endl;
+ ///Defer removal to not screw up the list
+ toRemove.push_back(iface);
+ iface->unregisterObject();
+ }
+ }
+
+ for(auto & i : toRemove)
+ {
+ manager->subscribedProcesses.erase(i);
+ }
+ }
+
+ g_free(name);
+ g_free(newOwner);
+ g_free(oldOwner);
+}
+
+static GVariant* getProperty(GDBusConnection* connection, const gchar* sender, const gchar* objectPath, const gchar* interfaceName, const gchar* propertyName, GError** error, gpointer userData)
+{
+ return NULL;
+}
+
+static gboolean setProperty(GDBusConnection * connection, const gchar * sender, const gchar *objectPath,
+ const gchar *interfaceName, const gchar * propertyName, GVariant *value,
+ GError** error, gpointer userData)
+{
+ return false;
+}
+
+static const GDBusInterfaceVTable interfaceVTable =
+{
+ handleMethodCall,
+ getProperty,
+ setProperty
+};
+
+AutomotiveManager::AutomotiveManager(GDBusConnection *connection)
+ :mConnection(connection)
+{
+ GError* error = NULL;
+
+ GDBusNodeInfo* introspection = g_dbus_node_info_new_for_xml(introspection_xml, &error);
+ GDBusInterfaceInfo* mInterfaceInfo = g_dbus_node_info_lookup_interface(introspection, "org.automotive.Manager");
+
+ regId = g_dbus_connection_register_object(mConnection, "/", mInterfaceInfo, &interfaceVTable, this, NULL, &error);
+ g_dbus_node_info_unref(introspection);
+
+ 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(mConnection, "org.freedesktop.DBus", "org.freedesktop.DBus",
+ "NameOwnerChanged", "/org/freedesktop/DBus", NULL, G_DBUS_SIGNAL_FLAGS_NONE,
+ signalCallback, this, NULL);
+}
+
+AutomotiveManager::~AutomotiveManager()
+{
+ g_dbus_connection_unregister_object(mConnection, regId);
+}
diff --git a/plugins/dbus/automotivemanager.h b/plugins/dbus/automotivemanager.h
new file mode 100644
index 00000000..e8d1c11b
--- /dev/null
+++ b/plugins/dbus/automotivemanager.h
@@ -0,0 +1,27 @@
+#ifndef AUTOMOTIVEMANGER_H_
+#define AUTOMOTIVEMANAGER_H_
+
+#include <gio/gio.h>
+#include <map>
+#include <list>
+
+class AbstractDBusInterface;
+
+class AutomotiveManager
+{
+public:
+
+ AutomotiveManager(GDBusConnection* connection);
+ ~AutomotiveManager();
+
+ std::map<AbstractDBusInterface*, std::list<std::string>> subscribedProcesses;
+
+private:
+
+ GDBusConnection* mConnection;
+ guint regId;
+
+};
+
+
+#endif //AUTOMOTOVEMANAGER_H_
diff --git a/plugins/dbus/custompropertyinterface.cpp b/plugins/dbus/custompropertyinterface.cpp
new file mode 100644
index 00000000..3c93db3f
--- /dev/null
+++ b/plugins/dbus/custompropertyinterface.cpp
@@ -0,0 +1,30 @@
+#include "custompropertyinterface.h"
+#include "vehicleproperty.h"
+#include "varianttype.h"
+#include "listplusplus.h"
+
+CustomPropertyInterface::CustomPropertyInterface(VehicleProperty::Property prop, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink(prop, re, connection, map<string, string>())
+{
+ PropertyList list = VehicleProperty::customProperties();
+
+ if(contains(list,prop))
+ {
+ AbstractPropertyType* temp = VehicleProperty::getPropertyTypeForPropertyNameValue(prop);
+
+ if(!temp)
+ {
+ throw std::runtime_error("Cannot create custom property: " + prop);
+ }
+
+ GVariant* var = temp->toVariant();
+ std::string signature = g_variant_get_type_string(var);
+ g_variant_unref(var);
+
+ propertyDBusMap.push_back( new VariantType(re, prop, prop, VariantType::ReadWrite));
+
+ delete temp;
+ }
+
+
+}
diff --git a/plugins/dbus/custompropertyinterface.h b/plugins/dbus/custompropertyinterface.h
new file mode 100644
index 00000000..39eb383e
--- /dev/null
+++ b/plugins/dbus/custompropertyinterface.h
@@ -0,0 +1,13 @@
+#ifndef CUSTOMPROPERTYINTERFACE_H_
+#define CUSTOMPROPERTYINTERFACE_H_
+
+#include "dbusplugin.h"
+
+class CustomPropertyInterface: public DBusSink
+{
+public:
+ CustomPropertyInterface(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection);
+};
+
+
+#endif
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/dbus/dbusinterfacemanager.cpp b/plugins/dbus/dbusinterfacemanager.cpp
new file mode 100644
index 00000000..b556fd14
--- /dev/null
+++ b/plugins/dbus/dbusinterfacemanager.cpp
@@ -0,0 +1,230 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "dbusinterfacemanager.h"
+
+
+#include <gio/gio.h>
+#include <string>
+
+#include "listplusplus.h"
+#include "automotivemanager.h"
+#include <unordered_set>
+
+#include <dbusexport.h>
+#include <ambplugin.h>
+
+///properties:
+#include "runningstatus.h"
+#include "custompropertyinterface.h"
+#include "uncategorizedproperty.h"
+#include "environmentproperties.h"
+#include "vehicleinfo.h"
+#include "maintenance.h"
+#include "parking.h"
+#include "drivingsafety.h"
+#include "personalization.h"
+
+extern "C" void create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ auto plugin = new AmbPlugin<DBusInterfaceManager>(routingengine, config);
+ plugin->init();
+}
+
+static void
+on_bus_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data)
+{
+ DBusInterfaceManager* iface = static_cast<DBusInterfaceManager*>(user_data);
+
+ iface->connection = std::shared_ptr<GDBusConnection>(connection, [=](GDBusConnection* conn){
+ amb::traits<GDBusConnection>::delete_functor functor;
+ functor(conn);
+ });
+
+ iface->setValue(iface->dbusConnected, true);
+
+ new AutomotiveManager(connection);
+
+ iface->registerTypes();
+}
+
+static void
+on_name_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data)
+{
+
+}
+
+static void
+on_name_lost (GDBusConnection *connection, const gchar *name, gpointer user_data)
+{
+ DebugOut(DebugOut::Error)<<"DBus: Lost bus name"<<endl;
+
+ DBusInterfaceManager* iface = static_cast<DBusInterfaceManager*>(user_data);
+
+ iface->setValue(iface->dbusConnected, false);
+
+ if(!connection){
+ DebugOut(DebugOut::Error)<<"DBus: Connection could not be established."<<endl;
+ throw std::runtime_error("Could not establish DBus connection.");
+ }
+}
+
+
+
+DBusInterfaceManager::DBusInterfaceManager(AbstractRoutingEngine * engine, std::map<std::string,std::string> config, AbstractSource & parent)
+ :AmbPluginImpl(engine, config, parent), connection(nullptr)
+{
+ DBusSink::dbusConfig = config;
+ dbusConnected = addPropertySupport(Zone::None, []() { return new BasicPropertyType<bool>(DBusConnected, false); });
+
+ ownerId = g_bus_own_name(G_BUS_TYPE_SYSTEM,
+ DBusServiceName,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ on_bus_acquired,
+ on_name_acquired,
+ on_name_lost,
+ this,
+ nullptr);
+
+}
+
+DBusInterfaceManager::~DBusInterfaceManager()
+{
+ g_bus_unown_name(ownerId);
+}
+
+void DBusInterfaceManager::supportedChanged(const PropertyList &supportedProperties)
+{
+ DebugOut()<<"supported Properties: "<<supportedProperties.size()<<endl;
+ if(!connection)
+ {
+ return;
+ }
+
+ registerTypes();
+}
+
+void DBusInterfaceManager::registerTypes()
+{
+ /// properties:
+ auto re = routingEngine;
+
+ auto exporter = amb::Exporter::instance();
+
+ exporter->connection = connection;
+
+ exporter->exportProperty<AccelerationProperty>(re);
+ exporter->exportProperty<VehicleSpeedProperty>(re);
+ exporter->exportProperty<TireProperty>(re);
+ exporter->exportProperty<EngineSpeedProperty>(re);
+ exporter->exportProperty<VehiclePowerModeProperty>(re);
+ exporter->exportProperty<TripMeterProperty>(re);
+ exporter->exportProperty<TransmissionProperty>(re);
+ exporter->exportProperty<CruiseControlProperty>(re);
+ exporter->exportProperty<BrakeOperation>(re);
+ exporter->exportProperty<LightStatusProperty>(re);
+ exporter->exportProperty<HornProperty>(re);
+ exporter->exportProperty<FuelProperty>(re);
+ exporter->exportProperty<EngineOilProperty>(re);
+ exporter->exportProperty<ExteriorBrightnessProperty>(re);
+ exporter->exportProperty<Temperature>(re);
+ exporter->exportProperty<RainSensor>(re);
+ exporter->exportProperty<ClimateControlProperty>(re);
+ exporter->exportProperty<WindowStatusProperty>(re);
+ exporter->exportProperty<DefrostProperty>(re);
+ exporter->exportProperty<Sunroof>(re);
+ exporter->exportProperty<ConvertibleRoof>(re);
+ exporter->exportProperty<VehicleId>(re);
+ exporter->exportProperty<VehicleTypeProperty>(re);
+ exporter->exportProperty<FuelInfoProperty>(re);
+ exporter->exportProperty<SizeProperty>(re);
+ exporter->exportProperty<DoorsProperty>(re);
+ exporter->exportProperty<WheelInformationProperty>(re);
+ exporter->exportProperty<OdometerProperty>(re);
+ exporter->exportProperty<FluidProperty>(re);
+ exporter->exportProperty<BatteryStatusProperty>(re);
+ exporter->exportProperty<ParkingBrakeProperty>(re);
+ exporter->exportProperty<HazardLightProperty>(re);
+ exporter->exportProperty<LocationProperty>(re);
+ exporter->exportProperty<AntilockBrakingSystemProperty>(re);
+ exporter->exportProperty<TractionControlSystemProperty>(re);
+ exporter->exportProperty<VehicleTopSpeedLimitProperty>(re);
+ exporter->exportProperty<AirbagStatusProperty>(re);
+ exporter->exportProperty<DoorStatusProperty>(re);
+ exporter->exportProperty<SeatBeltStatusProperty>(re);
+ exporter->exportProperty<OccupantStatusProperty>(re);
+ exporter->exportProperty<ObstacleDistanceProperty>(re);
+ exporter->exportProperty<SteeringWheelPositionProperty>(re);
+ exporter->exportProperty<SteeringWheel>(re);
+ exporter->exportProperty<ThrottlePosition>(re);
+ exporter->exportProperty<EngineCoolant>(re);
+ exporter->exportProperty<NightMode>(re);
+ exporter->exportProperty<DrivingMode>(re);
+ exporter->exportProperty<PowertrainTorque>(re);
+ exporter->exportProperty<AcceleratorPedalPosition>(re);
+ exporter->exportProperty<Chime>(re);
+ exporter->exportProperty<WheelTick>(re);
+ exporter->exportProperty<IgnitionTime>(re);
+ exporter->exportProperty<YawRate>(re);
+ exporter->exportProperty<TransmissionClutch>(re);
+ exporter->exportProperty<TransmissionOil>(re);
+ exporter->exportProperty<BrakeMaintenance>(re);
+ exporter->exportProperty<WasherFluid>(re);
+ exporter->exportProperty<MalfunctionIndicator>(re);
+ exporter->exportProperty<Diagnostics>(re);
+ exporter->exportProperty<MirrorProperty>(re);
+ exporter->exportProperty<SeatAdjustment>(re);
+ exporter->exportProperty<DriveMode>(re);
+ exporter->exportProperty<VehicleSound>(re);
+ exporter->exportProperty<ElectronicStabilityControl>(re);
+ exporter->exportProperty<ChildSafetyLock>(re);
+ exporter->exportProperty<SeatProperty>(re);
+ exporter->exportProperty<DoorProperty>(re);
+ exporter->exportProperty<WindshieldWiperStatus>(re);
+ exporter->exportProperty<SideWindowStatusProperty>(re);
+ exporter->exportProperty<AtmosphericPressure>(re);
+ exporter->exportProperty<LaneDepartureStatus>(re);
+ exporter->exportProperty<AlarmStatus>(re);
+
+ PropertyList list = VehicleProperty::customProperties();
+ PropertyList implemented = AbstractDBusInterface::implementedProperties();
+
+ for (auto prop : list)
+ {
+ if(!contains(implemented, prop))
+ {
+ exporter->exportProperty<CustomPropertyInterface>(prop, re);
+ }
+ }
+
+ /// Create objects for unimplemented properties:
+
+ implemented = AbstractDBusInterface::implementedProperties();
+
+ PropertyList capabilitiesList = VehicleProperty::capabilities();
+
+ for (auto itr = capabilitiesList.begin(); itr != capabilitiesList.end(); itr++)
+ {
+ VehicleProperty::Property prop = *itr;
+
+ if(!contains(implemented, prop))
+ {
+ exporter->exportProperty<UncategorizedPropertyInterface>(prop, re);
+ }
+ }
+}
diff --git a/plugins/dbus/dbusinterfacemanager.h b/plugins/dbus/dbusinterfacemanager.h
new file mode 100644
index 00000000..3fc50f65
--- /dev/null
+++ b/plugins/dbus/dbusinterfacemanager.h
@@ -0,0 +1,53 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef DBUSINTERFACEMANAGER_H
+#define DBUSINTERFACEMANAGER_H
+
+#include "ambpluginimpl.h"
+#include "gio/gio.h"
+#include <memory>
+
+class AbstractRoutingEngine;
+
+class DBusInterfaceManager: public AmbPluginImpl
+{
+
+public:
+ DBusInterfaceManager(AbstractRoutingEngine* re, std::map<string, string> config, AbstractSource & parent);
+ ~DBusInterfaceManager();
+
+ /// From AbstractSink:
+ virtual const string uuid() const { return "DBusInterfaceManager"; }
+ virtual void supportedChanged(const PropertyList & supportedProperties);
+
+ std::shared_ptr<GDBusConnection> connection;
+ std::shared_ptr<AbstractPropertyType> dbusConnected;
+
+ void registerTypes();
+
+private:
+
+ unsigned int ownerId;
+
+
+
+};
+
+#endif // DBUSINTERFACEMANAGER_H
diff --git a/plugins/dbus/drivingsafety.cpp b/plugins/dbus/drivingsafety.cpp
new file mode 100644
index 00000000..354ccb24
--- /dev/null
+++ b/plugins/dbus/drivingsafety.cpp
@@ -0,0 +1 @@
+#include "drivingsafety.h"
diff --git a/plugins/dbus/drivingsafety.h b/plugins/dbus/drivingsafety.h
new file mode 100644
index 00000000..0c1a0d48
--- /dev/null
+++ b/plugins/dbus/drivingsafety.h
@@ -0,0 +1,160 @@
+#ifndef DRIVINGSAFETY_H_
+#define DRIVINGSAFETY_H_
+
+#include "dbusplugin.h"
+#include "abstractdbusinterface.h"
+#include "abstractroutingengine.h"
+
+class AntilockBrakingSystemProperty: public DBusSink
+{
+public:
+ AntilockBrakingSystemProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("AntilockBrakingSystem", re, connection, map<string, string>())
+ {
+ /// TODO: Deprecated. Remove in 0.14
+ wantPropertyVariant(VehicleProperty::AntilockBrakingSystem, "AntilockBrakingSystem", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::AntilockBrakingSystem, "Engaged", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::AntilockBrakingSystemEnabled, "Enabled", VariantType::Read);
+ }
+};
+
+class TractionControlSystemProperty: public DBusSink
+{
+public:
+ TractionControlSystemProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("TractionControlSystem", re, connection, map<string, string>())
+ {
+ /// TODO: Deprecated. Remove in 0.14
+ wantPropertyVariant(VehicleProperty::TractionControlSystem, "TractionControlSystem", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::TractionControlSystemEnabled, "Enabled", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::TractionControlSystem, "Engaged", VariantType::Read);
+ }
+};
+
+
+class VehicleTopSpeedLimitProperty: public DBusSink
+{
+public:
+ VehicleTopSpeedLimitProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("VehicleTopSpeedLimit", re, connection, map<string, string>())
+ {
+ /// TODO: Deprecated. Remove in 0.14
+ wantPropertyVariant(VehicleProperty::VehicleTopSpeedLimit, "VehicleTopSpeedLimit", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::VehicleTopSpeedLimit, "Speed", VariantType::Read);
+ }
+};
+
+class AirbagStatusProperty: public DBusSink
+{
+public:
+ AirbagStatusProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("AirbagStatus", re, connection, map<string, string>())
+ {
+ /// TODO: Deprecated in 0.14
+ wantPropertyVariant(VehicleProperty::AirbagStatus, "AirbagStatus", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::AirbagActivated, "AirbagActivated", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::AirbagDeployed, "AirbagDeployed", VariantType::Read);
+ }
+};
+
+/// TODO: deprecated. remove in 0.14
+class DoorStatusProperty: public DBusSink
+{
+public:
+ DoorStatusProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("DoorStatus", re, connection, map<string, string>())
+ {
+
+ wantPropertyVariant(VehicleProperty::DoorStatus, "DoorStatus", VariantType::Read);
+
+ wantPropertyVariant(VehicleProperty::DoorLockStatus, "DoorLockStatus", VariantType::Read);
+
+ ///TODO: Deprecated in 0.14
+ wantPropertyVariant(VehicleProperty::ChildLockStatus, "ChildLockStatus", VariantType::Read);
+ }
+};
+
+class DoorProperty: public DBusSink
+{
+public:
+ DoorProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("Door", re, connection, map<string, string>())
+ {
+
+ wantPropertyVariant(VehicleProperty::DoorStatusW3C, "Status", VariantType::Read);
+
+ wantPropertyVariant(VehicleProperty::DoorLockStatus, "Lock", VariantType::ReadWrite);
+
+ ///TODO: Deprecated in 0.14
+ wantPropertyVariant(VehicleProperty::ChildLockStatus, "ChildLock", VariantType::Read);
+ }
+};
+
+/// TODO: Deprecated in 0.14
+class SeatBeltStatusProperty: public DBusSink
+{
+public:
+ SeatBeltStatusProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("SeatBelt", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::SeatBeltStatus, "Status", VariantType::Read);
+ }
+};
+
+/// TODO: Deprecated in 0.14
+class OccupantStatusProperty: public DBusSink
+{
+public:
+ OccupantStatusProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("OccupantStatus", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::OccupantStatus, "OccupantStatus", VariantType::Read);
+ }
+};
+
+class ObstacleDistanceProperty: public DBusSink
+{
+public:
+ ObstacleDistanceProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("ObstacleDistance", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::ObstacleDistance, "ObstacleDistance", VariantType::Read);
+ }
+};
+
+class ElectronicStabilityControl: public DBusSink
+{
+public:
+ ElectronicStabilityControl(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("ElectronicStabilityControl", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::ElectronicStabilityControlEnabled, "Enabled", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::ElectronicStabilityControlEngaged, "Engaged", VariantType::Read);
+ }
+};
+
+class ChildSafetyLock: public DBusSink
+{
+public:
+ ChildSafetyLock(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("ChildSafetyLock", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::ChildLockStatus, "Lock", VariantType::ReadWrite);
+ }
+};
+
+class SeatProperty: public DBusSink
+{
+public:
+ SeatProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("Seat", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::OccupantStatusW3C, "Occupant", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::SeatBeltStatus, "SeatBelt", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::OccupantName, "OccupantName", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::OccupantIdentificationType, "IdentificationType", VariantType::ReadWrite);
+ }
+};
+
+#endif
+
diff --git a/plugins/dbus/environmentproperties.cpp b/plugins/dbus/environmentproperties.cpp
new file mode 100644
index 00000000..a5584393
--- /dev/null
+++ b/plugins/dbus/environmentproperties.cpp
@@ -0,0 +1 @@
+#include "environmentproperties.h"
diff --git a/plugins/dbus/environmentproperties.h b/plugins/dbus/environmentproperties.h
new file mode 100644
index 00000000..7796865b
--- /dev/null
+++ b/plugins/dbus/environmentproperties.h
@@ -0,0 +1,139 @@
+#ifndef ENVIRONMENTPROPERTIES_H_
+#define ENVIRONMENTPROPERTIES_H_
+
+#include "dbusplugin.h"
+#include "abstractdbusinterface.h"
+#include "abstractroutingengine.h"
+
+/** @interface ExteriorBrightness : VehiclePropertyType **/
+class ExteriorBrightnessProperty: public DBusSink
+{
+public:
+ ExteriorBrightnessProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("ExteriorBrightness", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::ExteriorBrightness, "ExteriorBrightness", VariantType::Read);
+ }
+};
+
+/** @interface Temperature : VehiclePropertyType **/
+class Temperature: public DBusSink
+{
+public:
+ Temperature(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("Temperature", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::InteriorTemperature, "InteriorTemperature", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::ExteriorTemperature, "ExteriorTemperature", VariantType::Read);
+ }
+};
+
+/** @interface RainSensor : VehiclePropertyType **/
+class RainSensor: public DBusSink
+{
+public:
+ RainSensor(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("RainSensor", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::RainSensor, "RainIntensity", VariantType::Read);
+ }
+};
+
+class WindshieldWiperStatus: public DBusSink
+{
+public:
+ WindshieldWiperStatus(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("WiperStatus", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::WindshieldWiperSpeed, "WiperSpeed", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::WindshieldWiperSetting, "WiperSetting", VariantType::ReadWrite);
+ }
+};
+
+class ClimateControlProperty: public DBusSink
+{
+public:
+ ClimateControlProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("ClimateControl", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::AirflowDirectionW3C, "AirflowDirection", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::FanSpeed, "FanSpeedLevel", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::TargetTemperature, "TargetTemperature", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::AirConditioning, "AirConditioning", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::AirRecirculation, "AirRecirculation", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::Heater, "Heater", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::SteeringWheelHeater, "SteeringWheelHeater", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::SeatHeater, "SeatHeater", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::SeatCooler, "SeatCooler", VariantType::ReadWrite);
+ }
+};
+
+/** @interface WindowStatus : VehiclePropertyType **/
+/// TODO: Depricated in 0.14. Use SideWindow
+class WindowStatusProperty: public DBusSink
+{
+public:
+ WindowStatusProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("WindowStatus", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::WindowStatus, "Openness", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::Defrost, "Defrost", VariantType::ReadWrite);
+ }
+};
+
+class SideWindowStatusProperty: public DBusSink
+{
+public:
+ SideWindowStatusProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("SideWindow", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::WindowStatus, "Openness", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::WindowLockStatus, "Lock", VariantType::ReadWrite);
+ }
+};
+
+class DefrostProperty: public DBusSink
+{
+public:
+ DefrostProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("Defrost", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::DefrostWindow, "DefrostWindow", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::DefrostMirror, "DefrostMirror", VariantType::ReadWrite);
+ }
+};
+
+/** @interface Sunroof : VehiclePropertyType **/
+class Sunroof: public DBusSink
+{
+public:
+ Sunroof(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("Sunroof", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::Sunroof, "Openness", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::SunroofTilt, "Tilt", VariantType::ReadWrite);
+ }
+};
+
+/** @interface ConvertibleRoof : VehiclePropertyType **/
+class ConvertibleRoof: public DBusSink
+{
+public:
+ ConvertibleRoof(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("ConvertibleRoof", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::ConvertibleRoof, "Setting", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::ConvertibleRoofStatus, "Status", VariantType::Read);
+ }
+};
+
+class AtmosphericPressure: public DBusSink
+{
+public:
+ AtmosphericPressure(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("AtmosphericPressure", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::AtmosphericPressure, "Pressure", VariantType::ReadWrite);
+ }
+};
+#endif
diff --git a/plugins/dbus/fakeidlheader.h b/plugins/dbus/fakeidlheader.h
new file mode 100644
index 00000000..f83aec2c
--- /dev/null
+++ b/plugins/dbus/fakeidlheader.h
@@ -0,0 +1,76 @@
+#ifndef _FAKEIDLHEADER_H_
+#define _FAKEIDLHEADER_H_
+
+/** @module Vehicle **/
+
+/** @moduleComment
+*
+* Details.
+*
+* \def-api-feature http://tizen.org/api/vehicle
+* \brief Allows access to the vehicle API
+*
+**/
+
+/** @interface Navigator
+ * @interfaceType partial **/
+ /**
+ * @attributeName vehicle
+ * @type Vehicle
+ * @access readonly
+} **/
+
+/** @interface VehiclePropertyType **/
+/** @attributeName timeStamp
+ * @type Date
+ * @access readonly
+**/
+
+/** @raw callback VehiclePropertyCallback = void (VehiclePropertyType value); **/
+
+/** @raw callback VehiclePropertyErrorCallback = void (VehiclePropertyError error); **/
+
+/** @raw callback VehiclePropertyListCallback = void (sequence<VehiclePropertyType> values); **/
+
+/** @interface VehiclePropertyError
+*
+* @enum const unsigned short PERMISSION_DENIED = 1;
+* @enum const unsigned short PROPERTY_UNAVAILABLE = 2;
+* @enum const unsigned short TIMEOUT = 3;
+*
+* @attributeName code
+* @type unsigned short
+* @access readonly
+* @attributeComment MUST return error code.
+*
+* @attributeName message
+* @type DOMString
+* @access readonly
+* @attributeComment MUST return error message
+**/
+
+/** @interface Vehicle **/
+/** @method sequence<DOMString> getSupported();
+ * @methodComment \brief returns supported properties
+ * @method get(DOMString property, VehiclePropertyCallback successCallback, optional VehiclePropertyErrorCallback errorCallback);
+ * @methodComment \brief fetch the current value for 'property'.
+ * @methodComment \arg DOMString property is the property
+ * @methodComment \arg VehiclePropertyCallback successCallback function to be called when method has completed successfully
+ * @methodComment \arg VehiclePropertyErrorCallback this function is called when an error has occured.
+ * @method set(DOMString property, VehiclePropertyType value, optional SuccessCallback successCallback, optional VehiclePropertyErrorCallback errorCallback);
+ * @methodComment \brief set the given property to value
+ * @methodComment \arg DOMString property property to set
+ * @methodComment \arg VehiclePropertyType value value to set
+ * @methodComment \arg SuccessCallback successCallback callback if operation is successfull
+ * @methodComment \arg VehiclePropertyErrorCallback errorCallback callback if error has been called.
+ * @method getHistory(DOMString property, Date startTime, Date endTime, VehiclePropertyListCallback successCallback, optional VehiclePropertyErrorCallback errorCallback);
+ * @methodComment \brief get values for a given property within a certain past time period between 'startTime' and 'endTime'
+ * @methodComment \arg DOMString property property to request
+ * @methodComment \arg Date startTime, starting period of time.
+ * @methodComment \arg Date endTime, ending period of time.
+ * @methodComment \arg VehiclePropertyListCallback successCallback. Callback with the result of the method call
+ * @methodComment \arg VehiclePropertyErrorCallback errorCallback. Callback if an error has occurred.
+ **/
+
+
+#endif
diff --git a/plugins/dbus/maintenance.cpp b/plugins/dbus/maintenance.cpp
new file mode 100644
index 00000000..010bf9ae
--- /dev/null
+++ b/plugins/dbus/maintenance.cpp
@@ -0,0 +1 @@
+#include "maintenance.h"
diff --git a/plugins/dbus/maintenance.h b/plugins/dbus/maintenance.h
new file mode 100644
index 00000000..303824af
--- /dev/null
+++ b/plugins/dbus/maintenance.h
@@ -0,0 +1,146 @@
+#ifndef _MAINTENANCE_H_
+#define _MAINTENANCE_H_
+
+
+#include "dbusplugin.h"
+#include "abstractdbusinterface.h"
+#include "abstractroutingengine.h"
+
+/** @interface Odometer : VehiclePropertyType **/
+class OdometerProperty: public DBusSink
+{
+public:
+ OdometerProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("Odometer", re, connection, map<string, string>())
+ {
+ /** @attributeName Odometer
+ * @type unsigned long
+ * @access readonly
+ * @attributeComment \brief MUST return Distance traveled in km
+ **/
+ wantPropertyVariant(VehicleProperty::Odometer, "Odometer", VariantType::Read);
+
+ wantPropertyVariant(VehicleProperty::DistanceTotal, "DistanceTotal", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::DistanceSinceStart, "DistanceSinceStart", VariantType::Read);
+ }
+};
+
+/** @interface Fluid : VehiclePropertyType **/
+
+class FluidProperty : public DBusSink
+{
+public:
+ FluidProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("Fluid", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::TransmissionFluidLevel, "Transmission", VariantType::Read);
+ }
+};
+
+/** @interface Battery : VehiclePropertyType **/
+class BatteryStatusProperty: public DBusSink
+{
+public:
+ BatteryStatusProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("BatteryStatus", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::BatteryVoltage, "Voltage", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::BatteryCurrent, "Current", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::BatteryChargeLevel, "ChargeLevel", VariantType::Read);
+ }
+};
+
+/** @interface TirePressure : VehiclePropertyType **/
+class TireProperty: public DBusSink
+{
+public:
+ TireProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("Tire", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::TirePressure, "Pressure", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::TirePressureLow, "PressureLow", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::TireTemperature, "Temperature", VariantType::Read);
+ }
+};
+
+
+class EngineCoolant: public DBusSink
+{
+public:
+ EngineCoolant(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("EngineCoolant", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::EngineCoolantLevel, "Level", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::EngineCoolantTemperature, "Temperature", VariantType::Read);
+ }
+};
+
+class TransmissionOil: public DBusSink
+{
+public:
+ TransmissionOil(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("TransmissionOil", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::TransmissionOilWear, "Wear", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::TransmissionOilTemperature, "Temperature", VariantType::Read);
+ }
+};
+
+class TransmissionClutch: public DBusSink
+{
+public:
+ TransmissionClutch(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("TransmissionClutch", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::TransmissionClutchWear, "Wear", VariantType::Read);
+ }
+};
+
+class BrakeMaintenance: public DBusSink
+{
+public:
+ BrakeMaintenance(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("BrakeMaintenance", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::BrakePadWear, "PadWear", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::BrakeFluidLevel, "FluidLevel", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::BrakeFluidLevelLow, "FluidLevelLow", VariantType::Read);
+ }
+};
+
+class WasherFluid: public DBusSink
+{
+public:
+ WasherFluid(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("WasherFluid", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::WasherFluidLevel, "Level", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::WasherFluidLevelLow, "LevelLow", VariantType::Read);
+ }
+};
+
+class MalfunctionIndicator: public DBusSink
+{
+public:
+ MalfunctionIndicator(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("MalfunctionIndicator", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::MalfunctionIndicatorOn, "On", VariantType::Read);
+ }
+};
+
+class Diagnostics: public DBusSink
+{
+public:
+ Diagnostics(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("Diagnostic", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::AccumulatedEngineRuntime, "AccumulatedEngineRuntime", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::DistanceWithMILOn, "DistanceWithMILOn", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::DistanceSinceCodeCleared, "DistanceSinceCodeCleared", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::TimeRunMILOn, "TimeRunMILOn", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::TimeTroubleCodeClear, "TimeTroubleCodeClear", VariantType::Read);
+ }
+};
+
+#endif
diff --git a/plugins/dbus/parking.cpp b/plugins/dbus/parking.cpp
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/plugins/dbus/parking.cpp
diff --git a/plugins/dbus/parking.h b/plugins/dbus/parking.h
new file mode 100644
index 00000000..1e86c742
--- /dev/null
+++ b/plugins/dbus/parking.h
@@ -0,0 +1,51 @@
+#ifndef _PARKING_H_
+#define _PARKING_H_
+
+
+#include "dbusplugin.h"
+#include "abstractdbusinterface.h"
+#include "abstractroutingengine.h"
+
+/** @interface ParkingBrake : VehiclePropertyType **/
+class ParkingBrakeProperty: public DBusSink
+{
+public:
+ ParkingBrakeProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("ParkingBrake", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::ParkingBrakeStatusW3C, "Status", VariantType::Read);
+ }
+};
+
+/** @interface HazardLight : VehiclePropertyType **/
+class HazardLightProperty: public DBusSink
+{
+public:
+ HazardLightProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("HazardLight", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::HazardLightStatus, "HazardLight", VariantType::ReadWrite);
+ }
+};
+
+class LaneDepartureStatus: public DBusSink
+{
+public:
+ LaneDepartureStatus(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("LaneDepartureDetection", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::LaneDepartureStatus, "Status", VariantType::Read);
+ }
+};
+
+class AlarmStatus: public DBusSink
+{
+public:
+ AlarmStatus(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("Alarm", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::AlarmStatus, "Status", VariantType::ReadWrite);
+ }
+};
+
+#endif
diff --git a/plugins/dbus/personalization.cpp b/plugins/dbus/personalization.cpp
new file mode 100644
index 00000000..9dc503f2
--- /dev/null
+++ b/plugins/dbus/personalization.cpp
@@ -0,0 +1,2 @@
+#include "personalization.h"
+
diff --git a/plugins/dbus/personalization.h b/plugins/dbus/personalization.h
new file mode 100644
index 00000000..20e2f2c6
--- /dev/null
+++ b/plugins/dbus/personalization.h
@@ -0,0 +1,69 @@
+#ifndef PERSONALIZATION_H_
+#define PERSONALIZATION_H_
+
+#include "dbusplugin.h"
+#include "abstractdbusinterface.h"
+#include "abstractroutingengine.h"
+
+class SteeringWheelPositionProperty: public DBusSink
+{
+public:
+ SteeringWheelPositionProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("SteeringWheelPosition", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::SteeringWheelPositionSlide, "Slide", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::SteeringWheelPositionTilt, "Tilt", VariantType::ReadWrite);
+ }
+};
+
+class MirrorProperty: public DBusSink
+{
+public:
+ MirrorProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("Mirror", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::MirrorSettingPan, "MirrorPan", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::MirrorSettingTilt, "MirrorTilt", VariantType::ReadWrite);
+ }
+};
+
+class SeatAdjustment: public DBusSink
+{
+public:
+ SeatAdjustment(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("SeatAdjustment", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::SeatPositionBackCushion, "SeatBackCushion", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::SeatPositionRecline, "SeatReclineBack", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::SeatPositionSlide, "SeatSlide", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::SeatPositionCushionHeight, "SeatCushionHeight", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::SeatPositionHeadrest, "SeatHeadrest", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::SeatPositionSideCushion, "SeatSideCushion", VariantType::ReadWrite);
+ }
+};
+
+class DriveMode: public DBusSink
+{
+public:
+ DriveMode(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("DriveMode", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::VehicleDriveMode, "DriveMode", VariantType::ReadWrite);
+ }
+};
+
+class VehicleSound: public DBusSink
+{
+public:
+ VehicleSound(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("VehicleSound", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::ActiveNoiseControlMode, "ActiveNoiseControlMode", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::EngineSoundEnhancementMode, "EngineSoundEnhancementMode", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::AvailableSounds, "AvailableSounds", VariantType::ReadWrite);
+ }
+};
+
+
+
+#endif
diff --git a/plugins/dbus/runningstatus.cpp b/plugins/dbus/runningstatus.cpp
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/plugins/dbus/runningstatus.cpp
diff --git a/plugins/dbus/runningstatus.h b/plugins/dbus/runningstatus.h
new file mode 100644
index 00000000..16321cb2
--- /dev/null
+++ b/plugins/dbus/runningstatus.h
@@ -0,0 +1,323 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _PROPERTIES_H_H_H_
+#define _PROPERTIES_H_H_H_
+
+#include "dbusplugin.h"
+#include "abstractdbusinterface.h"
+#include "abstractroutingengine.h"
+
+/** @interface VehicleSpeed : VehiclePropertyType **/
+class VehicleSpeedProperty: public DBusSink
+{
+public:
+ VehicleSpeedProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("VehicleSpeed", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::VehicleSpeed, "Speed", VariantType::Read);
+ }
+};
+
+/** @interface EngineSpeed : VehiclePropertyType **/
+class EngineSpeedProperty: public DBusSink
+{
+public:
+ EngineSpeedProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("EngineSpeed", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::EngineSpeed, "Speed", VariantType::Read);
+ }
+};
+
+/** @interface VehiclePowerMode : VehiclePropertyType **/
+class VehiclePowerModeProperty: public DBusSink
+{
+public:
+ VehiclePowerModeProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("VehiclePowerMode", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::VehiclePowerMode, "VehiclePowerMode",VariantType::Read);
+ }
+};
+
+/** @interface TripMeter : VehiclePropertyType **/
+class TripMeterProperty: public DBusSink
+{
+public:
+ TripMeterProperty(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("TripMeter", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::TripMeters, "TripMeters", VariantType::ReadWrite);
+ }
+};
+
+/** @interface Acceleration : VehiclePropertyType **/
+class AccelerationProperty: public DBusSink
+{
+public:
+ AccelerationProperty(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("Acceleration", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::AccelerationX, "X", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::AccelerationY, "Y", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::AccelerationZ, "Z", VariantType::Read);
+ }
+};
+
+/** @interface Transmission : VehiclePropertyType **/
+class TransmissionProperty: public DBusSink
+{
+public:
+ TransmissionProperty(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("Transmission", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::TransmissionShiftPosition, "ShiftPosition", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::TransmissionGearPosition, "GearPosition", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::TransmissionGearPosition, "Gear", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::TransmissionModeW3C, "Mode", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::TransmissionGearType, "Type", VariantType::Read);
+ }
+};
+
+/** @interface CruiseControlStatus : VehiclePropertyType **/
+class CruiseControlProperty: public DBusSink
+{
+public:
+ CruiseControlProperty(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("CruiseControlStatus", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::CruiseControlSpeed, "Speed", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::CruiseControlActive, "Status", VariantType::Read);
+ }
+};
+
+/** @interface WheelBrake : VehiclePropertyType **/
+class BrakeOperation: public DBusSink
+{
+public:
+ BrakeOperation(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("BrakeOperation", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::WheelBrake, "BrakePedalDepressed", VariantType::Read);
+ }
+};
+
+/** @interface LightStatus : VehiclePropertyType **/
+class LightStatusProperty: public DBusSink
+{
+public:
+ LightStatusProperty(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("LightStatus", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::LightHead, "Head", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightRightTurn, "RightTurn", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightLeftTurn, "LeftTurn", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightBrake, "Brake", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightFog, "Fog", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightHazard, "Hazard", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightParking, "Parking", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightHighBeam, "HighBeam", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightAutomatic, "AutomaticHeadlights", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::LightDynamicHighBeam, "DynamicHighBeam", VariantType::ReadWrite);
+ }
+};
+
+class InteriorLightStatusProperty: public DBusSink
+{
+public:
+ InteriorLightStatusProperty(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("InteriorLightStatus", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::InteriorLightStatus, "Status", VariantType::ReadWrite);
+ }
+};
+
+/** @interface Horn : VehiclePropertyType **/
+class HornProperty: public DBusSink
+{
+public:
+ HornProperty(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("Horn", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::Horn, "Status", VariantType::Read);
+ }
+};
+
+/** @interface Fuel : VehiclePropertyType **/
+class FuelProperty: public DBusSink
+{
+public:
+ FuelProperty(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("Fuel", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::FuelLevel, "Level", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::FuelRange, "Range", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::FuelConsumption, "InstantConsumption", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::FuelEconomy, "InstantEconomy", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::FuelAverageEconomy, "AverageEconomy", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::FuelAverageConsumption, "AverageConsumption", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::FuelConsumptionSinceRestart, "FuelConsumedSinceRestart", VariantType::ReadWrite);
+ wantPropertyVariant(VehicleProperty::FuelTimeSinceRestart, "TimeSinceRestart", VariantType::ReadWrite);
+ }
+};
+
+/** @interface EngineOil : VehiclePropertyType **/
+class EngineOilProperty: public DBusSink
+{
+public:
+ EngineOilProperty(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("EngineOil", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::EngineOilRemaining, "Level", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::EngineOilTemperature, "Temperature", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::EngineOilPressure, "Pressure", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::EngineOilChangeIndicator, "Change", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::EngineOilLifeRemaining, "LifeRemaining", VariantType::Read);
+ }
+};
+
+/** @interface Location : VehiclePropertyType **/
+class LocationProperty: public DBusSink
+{
+public:
+ LocationProperty(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("Location", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::Latitude, "Latitude", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::Longitude, "Longitude", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::Altitude, "Altitude", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::Direction, "Direction", VariantType::Read);
+
+ }
+};
+
+class SteeringWheel: public DBusSink
+{
+public:
+ SteeringWheel(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("SteeringWheel", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::SteeringWheelAngleW3C, "Angle", VariantType::Read);
+ }
+};
+
+class ThrottlePosition: public DBusSink
+{
+public:
+ ThrottlePosition(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("ThrottlePosition", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::ThrottlePosition, "Value", VariantType::Read);
+ }
+};
+
+class NightMode: public DBusSink
+{
+public:
+ NightMode(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("NightMode", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::NightMode, "NightMode", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::NightMode, "Mode", VariantType::Read);
+ }
+};
+
+class DrivingMode: public DBusSink
+{
+public:
+ DrivingMode(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("DrivingMode", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::DrivingMode, "DrivingMode", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::DrivingModeW3C, "Mode", VariantType::Read);
+ }
+};
+
+class PowertrainTorque: public DBusSink
+{
+public:
+ PowertrainTorque(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("PowertrainTorque", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::PowertrainTorque, "Value", VariantType::Read);
+ }
+};
+
+class AcceleratorPedalPosition: public DBusSink
+{
+public:
+ AcceleratorPedalPosition(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("AcceleratorPedalPosition", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::AcceleratorPedalPosition, "Value", VariantType::Read);
+ }
+};
+
+class Chime: public DBusSink
+{
+public:
+ Chime(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("Chime", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::Chime, "Status", VariantType::Read);
+ }
+};
+
+class WheelTick: public DBusSink
+{
+public:
+ WheelTick(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("WheelTick", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::WheelTick, "Value", VariantType::Read);
+ }
+};
+
+class IgnitionTime: public DBusSink
+{
+public:
+ IgnitionTime(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("IgnitionTime", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::IgnitionTimeOn, "IgnitionTimeOn", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::IgnitionTimeOff, "IgnitionTimeOff", VariantType::Read);
+ }
+};
+
+class YawRate: public DBusSink
+{
+public:
+ YawRate(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("YawRate", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::YawRate, "Value", VariantType::Read);
+ }
+};
+
+class ButtonEvent: public DBusSink
+{
+public:
+ ButtonEvent(VehicleProperty::Property, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink("ButtonEvent", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::YawRate, "Value", VariantType::Read);
+ }
+};
+
+#endif
diff --git a/plugins/dbus/uncategorizedproperty.cpp b/plugins/dbus/uncategorizedproperty.cpp
new file mode 100644
index 00000000..1ac34aba
--- /dev/null
+++ b/plugins/dbus/uncategorizedproperty.cpp
@@ -0,0 +1,25 @@
+#include "uncategorizedproperty.h"
+#include "vehicleproperty.h"
+#include "varianttype.h"
+#include "listplusplus.h"
+
+UncategorizedPropertyInterface::UncategorizedPropertyInterface(VehicleProperty::Property prop, AbstractRoutingEngine *re, GDBusConnection *connection)
+ :DBusSink(prop, re, connection, map<string, string>())
+{
+ AbstractPropertyType* temp = VehicleProperty::getPropertyTypeForPropertyNameValue(prop);
+
+ if(!temp)
+ {
+ throw std::runtime_error("Cannot create uncategorized property: " + prop);
+ }
+
+ GVariant* var = temp->toVariant();
+ std::string signature = g_variant_get_type_string(var);
+ g_variant_unref(var);
+
+ propertyDBusMap.push_back( new VariantType(re, prop, prop, VariantType::ReadWrite));
+
+ delete temp;
+
+
+}
diff --git a/plugins/dbus/uncategorizedproperty.h b/plugins/dbus/uncategorizedproperty.h
new file mode 100644
index 00000000..1c5446c6
--- /dev/null
+++ b/plugins/dbus/uncategorizedproperty.h
@@ -0,0 +1,13 @@
+#ifndef UncategorizedPropertyInterface_H_
+#define UncategorizedPropertyInterface_H_
+
+#include "dbusplugin.h"
+
+class UncategorizedPropertyInterface: public DBusSink
+{
+public:
+ UncategorizedPropertyInterface(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection);
+};
+
+
+#endif
diff --git a/plugins/dbus/vehicleinfo.cpp b/plugins/dbus/vehicleinfo.cpp
new file mode 100644
index 00000000..693fa556
--- /dev/null
+++ b/plugins/dbus/vehicleinfo.cpp
@@ -0,0 +1 @@
+#include "vehicleinfo.h"
diff --git a/plugins/dbus/vehicleinfo.h b/plugins/dbus/vehicleinfo.h
new file mode 100644
index 00000000..16d9a304
--- /dev/null
+++ b/plugins/dbus/vehicleinfo.h
@@ -0,0 +1,101 @@
+#ifndef _VEHICLEINFO_H_
+#define _VEHICLEINFO_H_
+
+
+#include "dbusplugin.h"
+#include "abstractdbusinterface.h"
+#include "abstractroutingengine.h"
+
+/** @interface VehicleId : VehiclePropertyType **/
+class VehicleId: public DBusSink
+{
+public:
+ VehicleId(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("VehicleId", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::WMI, "WMI", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::VIN, "VIN", VariantType::Read);
+ }
+};
+
+/** @interface Size : VehiclePropertyType **/
+class SizeProperty: public DBusSink
+{
+public:
+ SizeProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("Size", re, connection, map<string, string>())
+ {
+ /** @attributeName Width
+ * @type unsigned long
+ * @access readonly
+ * @attributeComment \brief MUST return width of vehicle in mm
+ **/
+ wantPropertyVariant(VehicleProperty::VehicleWidth, "Width", VariantType::Read);
+
+ /** @attributeName Height
+ * @type unsigned long
+ * @access readonly
+ * @attributeComment \brief MUST return height of vehicle in mm
+ **/
+ wantPropertyVariant(VehicleProperty::VehicleHeight, "Height", VariantType::Read);
+
+ /** @attributeName Length
+ * @type unsigned long
+ * @access readonly
+ * @attributeComment \brief MUST return length of vehicle in mm
+ **/
+ wantPropertyVariant(VehicleProperty::VehicleLength, "Length", VariantType::Read);
+
+
+ }
+};
+
+/** @interface FuelInfo : VehiclePropertyType **/
+class FuelInfoProperty: public DBusSink
+{
+public:
+ FuelInfoProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("FuelInfo", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::FuelType, "Type", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::FuelPositionSide, "RefuelPosition", VariantType::Read);
+ }
+};
+
+/** @interface VehicleType : VehiclePropertyType **/
+class VehicleTypeProperty: public DBusSink
+{
+public:
+ VehicleTypeProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("VehicleType", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::VehicleType, "Type", VariantType::Read);
+ }
+};
+
+/** @interface Doors : VehiclePropertyType **/
+class DoorsProperty: public DBusSink
+{
+public:
+ DoorsProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("Doors", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::DoorsPerRow, "DoorsPerRow", VariantType::Read);
+ }
+};
+
+/** @interface WheelInformation : VehiclePropertyType **/
+class WheelInformationProperty: public DBusSink
+{
+public:
+ WheelInformationProperty(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("WheelInformation", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(VehicleProperty::FrontWheelRadius, "FrontWheelRadius", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::RearWheelRadius, "RearWheelRadius", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::WheelTrack, "WheelTrack", VariantType::Read);
+ wantPropertyVariant(VehicleProperty::AntilockBrakingSystem, "AntilockBrakingSystem", VariantType::Read);
+ }
+};
+
+#endif
diff --git a/plugins/demosink/CMakeLists.txt b/plugins/demosink/CMakeLists.txt
new file mode 100644
index 00000000..8fde5e36
--- /dev/null
+++ b/plugins/demosink/CMakeLists.txt
@@ -0,0 +1,16 @@
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs})
+
+pkg_check_modules(giounix REQUIRED gio-unix-2.0)
+set(link_libraries ${link_libraries} ${giounix_LIBRARIES})
+#set(include_dirs ${include_dirs} ${giounix_INCLUDE_DIRS})
+include_directories(${giounix_INCLUDE_DIRS})
+
+set(demosinkplugin_headers demosinkplugin.h)
+set(demosinkplugin_sources demosinkplugin.cpp)
+
+add_library(demosinkplugin MODULE ${demosinkplugin_sources})
+set_target_properties(demosinkplugin PROPERTIES PREFIX "")
+target_link_libraries(demosinkplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries})
+
+install(TARGETS demosinkplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
diff --git a/plugins/demosink/demosinkplugin.cpp b/plugins/demosink/demosinkplugin.cpp
new file mode 100644
index 00000000..b7658351
--- /dev/null
+++ b/plugins/demosink/demosinkplugin.cpp
@@ -0,0 +1,123 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "demosinkplugin.h"
+#include "abstractroutingengine.h"
+
+#include <iostream>
+#include <stdexcept>
+#include <boost/assert.hpp>
+#include <glib.h>
+
+using namespace std;
+
+#include "debugout.h"
+
+string findReplace(string str, string tofind, string replacewith, string exclusions="")
+{
+ size_t i=0;
+
+ size_t exclusionPos = exclusions.find(tofind,0);
+
+ while((i = str.find(tofind,i)) != string::npos)
+ {
+ if( exclusionPos != string::npos )
+ {
+ if(str.substr(i-exclusionPos,exclusions.length()) == exclusions)
+ {
+ i+=replacewith.size();
+ continue;
+ }
+ }
+
+ str.replace(i,tofind.size(),replacewith);
+ i+=replacewith.size();
+ }
+
+ return str;
+}
+
+
+DemoSink::DemoSink(AbstractRoutingEngine* re, map<string, string> config)
+:AbstractSink(re, config)
+{
+ routingEngine->subscribeToProperty(VehicleProperty::ButtonEvent, this);
+ routingEngine->subscribeToProperty(VehicleProperty::TurnSignal, this);
+ routingEngine->subscribeToProperty(VehicleProperty::MachineGunTurretStatus, this);
+}
+
+DemoSink::~DemoSink()
+{
+
+}
+
+extern "C" void create(AbstractRoutingEngine* routingEngine, map<string, string> config)
+{
+ new DemoSink(routingEngine, config);
+}
+
+const string DemoSink::uuid()
+{
+ return "5b0e8a04-d6d7-43af-b827-1663627a25d9";
+}
+
+void DemoSink::propertyChanged(AbstractPropertyType *value)
+{
+ VehicleProperty::Property property = value->name;
+
+ std::string app = configuration["script"];
+ std::string strValue = value->toString();
+
+ if(property == VehicleProperty::TurnSignal)
+ {
+ if(value->value<TurnSignals::TurnSignalType>() == TurnSignals::Right)
+ {
+ strValue = "Right";
+ }
+ else if(value->value<TurnSignals::TurnSignalType>() == TurnSignals::Left)
+ {
+ strValue = "Left";
+ }
+ else if(value->value<TurnSignals::TurnSignalType>() == TurnSignals::Off)
+ {
+ strValue = "Off";
+ }
+ } else if (property == VehicleProperty::ButtonEvent) {
+ if (value->value<ButtonEvents::ButtonEventType>() == ButtonEvents::Preset1Button)
+ strValue = "Button1";
+ else if (value->value<ButtonEvents::ButtonEventType>() == ButtonEvents::Preset2Button)
+ strValue = "Button2";
+ else if (value->value<ButtonEvents::ButtonEventType>() == ButtonEvents::Preset3Button)
+ strValue = "Button3";
+ else if (value->value<ButtonEvents::ButtonEventType>() == ButtonEvents::Preset4Button)
+ strValue = "Button4";
+ }
+
+ string cmdline = findReplace(app,"%1",strValue);
+ GError* error = NULL;
+
+ if(!g_spawn_command_line_async(cmdline.c_str(), &error))
+ DebugOut()<<"Failed to launch command: "<<cmdline<<endl;
+
+}
+
+void DemoSink::supportedChanged(const PropertyList & list)
+{
+ routingEngine->subscribeToProperty(VehicleProperty::ButtonEvent, this);
+ routingEngine->subscribeToProperty(VehicleProperty::TurnSignal, this);
+}
diff --git a/plugins/demosink/demosinkplugin.h b/plugins/demosink/demosinkplugin.h
new file mode 100644
index 00000000..ce57a5da
--- /dev/null
+++ b/plugins/demosink/demosinkplugin.h
@@ -0,0 +1,47 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef WHEELPLUGIN_H
+#define WHEELPLUGIN_H
+
+#include <abstractsink.h>
+#include <string>
+
+using namespace std;
+
+class DemoSink: public AbstractSink
+{
+
+public:
+ DemoSink(AbstractRoutingEngine* re, map<string, string> config);
+ ~DemoSink();
+
+ const string uuid();
+
+ void propertyChanged( AbstractPropertyType* value);
+ void supportedChanged(const PropertyList &);
+
+ friend class WheelPrivate;
+
+private:
+
+ PropertySet mRequests;
+};
+
+
+#endif // WHEELPLUGIN_H
diff --git a/plugins/exampleplugin.cpp b/plugins/exampleplugin.cpp
new file mode 100644
index 00000000..4b643c67
--- /dev/null
+++ b/plugins/exampleplugin.cpp
@@ -0,0 +1,426 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "exampleplugin.h"
+#include "timestamp.h"
+#include "listplusplus.h"
+
+#include <iostream>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <glib.h>
+
+using namespace std;
+
+#include "debugout.h"
+
+uint16_t accelerationX = 0;
+Transmission::TransmissionPositions transmissionShiftPostion = Transmission::Neutral;
+uint16_t steeringWheelAngle=0;
+uint16_t throttlePos = 0;
+int engineCoolant = 40;
+bool machineGun = false;
+
+const char* id = "6dd4268a-c605-4a06-9034-59c1e8344c8e";
+
+static gboolean timeoutCallback(gpointer data)
+{
+ ExampleSourcePlugin* src = (ExampleSourcePlugin*)data;
+
+ src->randomizeProperties();
+
+ return true;
+}
+
+ExampleSourcePlugin::ExampleSourcePlugin(AbstractRoutingEngine* re, map<string, string> config)
+:AbstractSource(re, config), velocity(0), engineSpeed(0)
+{
+ debugOut("setting timeout");
+
+ int delay = 1000;
+
+ if(config.find("delay") != config.end())
+ {
+ delay = boost::lexical_cast<int>(config["delay"]);
+ }
+
+ g_timeout_add(delay, timeoutCallback, this );
+
+ addPropertySupport(VehicleProperty::EngineSpeed, Zone::None);
+ addPropertySupport(VehicleProperty::VehicleSpeed, Zone::None);
+ addPropertySupport(VehicleProperty::AccelerationX, Zone::None);
+ addPropertySupport(VehicleProperty::TransmissionShiftPosition, Zone::None);
+ addPropertySupport(VehicleProperty::TransmissionGearPosition, Zone::None);
+ addPropertySupport(VehicleProperty::SteeringWheelAngle, Zone::None);
+ addPropertySupport(VehicleProperty::ThrottlePosition, Zone::None);
+ addPropertySupport(VehicleProperty::EngineCoolantTemperature, Zone::None);
+ addPropertySupport(VehicleProperty::VIN, Zone::None);
+ addPropertySupport(VehicleProperty::WMI, Zone::None);
+ addPropertySupport(VehicleProperty::BatteryVoltage, Zone::None);
+ addPropertySupport(VehicleProperty::MachineGunTurretStatus, Zone::None);
+ addPropertySupport(VehicleProperty::ExteriorBrightness, Zone::None);
+ addPropertySupport(VehicleProperty::DoorsPerRow, Zone::None);
+ addPropertySupport(VehicleProperty::AirbagStatus, Zone::None);
+
+ Zone::ZoneList airbagZones;
+ airbagZones.push_back(Zone::FrontLeft | Zone::FrontSide);
+ airbagZones.push_back(Zone::FrontRight | Zone::FrontSide);
+ airbagZones.push_back(Zone::RearLeft | Zone::LeftSide);
+ airbagZones.push_back(Zone::RearRight | Zone::RightSide);
+
+ airbagStatus[Zone::FrontLeft | Zone::FrontSide] = Airbag::Active;
+ airbagStatus[Zone::FrontRight | Zone::FrontSide] = Airbag::Inactive;
+ airbagStatus[Zone::RearLeft | Zone::LeftSide] = Airbag::Deployed;
+ airbagStatus[Zone::RearRight | Zone::RightSide] = Airbag::Deployed;
+
+ PropertyInfo airbagInfo(0,airbagZones);
+
+ propertyInfoMap[VehicleProperty::AirbagStatus] = airbagInfo;
+
+ addPropertySupport(VehicleProperty::AirConditioning, Zone::None);
+
+ Zone::ZoneList acZones;
+ acZones.push_back(Zone::FrontLeft);
+ acZones.push_back(Zone::Front | Zone::Right);
+
+ acStatus[Zone::Front | Zone::Left] = true;
+ acStatus[Zone::Front | Zone::Right] = false;
+
+ PropertyInfo acInfo(0,acZones);
+ propertyInfoMap[VehicleProperty::AirConditioning] = acInfo;
+}
+
+
+
+extern "C" void create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ new ExampleSourcePlugin(routingengine, config);
+}
+
+const string ExampleSourcePlugin::uuid()
+{
+ return id;
+}
+
+
+void ExampleSourcePlugin::getPropertyAsync(AsyncPropertyReply *reply)
+{
+ DebugOut()<<"ExampleSource: getPropertyAsync called for property: "<<reply->property<<endl;
+
+ if(reply->property == VehicleProperty::VehicleSpeed)
+ {
+ VehicleProperty::VehicleSpeedType temp(velocity);
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::EngineSpeed)
+ {
+ VehicleProperty::EngineSpeedType temp(engineSpeed);
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::AccelerationX)
+ {
+ VehicleProperty::AccelerationXType temp(accelerationX);
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::TransmissionShiftPosition)
+ {
+ VehicleProperty::TransmissionShiftPositionType temp(transmissionShiftPostion);
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::TransmissionGearPosition)
+ {
+ VehicleProperty::TransmissionGearPositionType temp(transmissionShiftPostion);
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::SteeringWheelAngle)
+ {
+ VehicleProperty::SteeringWheelAngleType temp(steeringWheelAngle);
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::VIN)
+ {
+ VehicleProperty::VINType temp("ABC00000000000000");
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::WMI)
+ {
+ VehicleProperty::WMIType temp("abc");
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::BatteryVoltage)
+ {
+ VehicleProperty::BatteryVoltageType temp(12.6);
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::ExteriorBrightness)
+ {
+ VehicleProperty::ExteriorBrightnessType temp(1000);
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::DoorsPerRow)
+ {
+ VehicleProperty::DoorsPerRowType temp;
+
+ BasicPropertyType<uint16_t> row1(2);
+ BasicPropertyType<uint16_t> row2(2);
+ BasicPropertyType<uint16_t> row3(1);
+
+ temp.append(row1);
+ temp.append(row2);
+ temp.append(row3);
+
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::AirbagStatus)
+ {
+ if(airbagStatus.find(reply->zoneFilter) == airbagStatus.end())
+ {
+ reply->success = false;
+ reply->error = AsyncPropertyReply::ZoneNotSupported;
+ reply->completed(reply);
+ }
+
+ else
+ {
+
+ VehicleProperty::AirbagStatusType temp;
+ temp.setValue(airbagStatus[reply->zoneFilter]);
+ temp.zone = reply->zoneFilter;
+
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ }
+ else if(reply->property == VehicleProperty::MachineGunTurretStatus)
+ {
+ VehicleProperty::MachineGunTurretStatusType temp(true);
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::ThrottlePosition)
+ {
+ VehicleProperty::ThrottlePositionType temp(throttlePos);
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::EngineCoolantTemperature)
+ {
+ VehicleProperty::EngineCoolantTemperatureType temp(engineCoolant);
+ reply->value = &temp;
+ reply->success = true;
+ reply->completed(reply);
+ }
+ else if(reply->property == VehicleProperty::AirbagStatus)
+ {
+ if(airbagStatus.find(reply->zoneFilter) == airbagStatus.end())
+ {
+ reply->success = false;
+ reply->error = AsyncPropertyReply::ZoneNotSupported;
+ reply->completed(reply);
+ }
+ else
+ {
+ VehicleProperty::AirbagStatusType temp(airbagStatus[reply->zoneFilter]);
+ reply->success = true;
+ reply->value = &temp;
+ reply->completed(reply);
+ }
+ }
+ else if(reply->property == VehicleProperty::AirConditioning)
+ {
+ if(acStatus.find(reply->zoneFilter) == acStatus.end())
+ {
+ reply->success = false;
+ reply->error = AsyncPropertyReply::ZoneNotSupported;
+ reply->completed(reply);
+ }
+ else
+ {
+ VehicleProperty::AirConditioningType temp(acStatus[reply->zoneFilter]);
+ reply->success = true;
+ reply->value = &temp;
+ reply->completed(reply);
+ }
+ }
+
+ else
+ {
+ reply->success=false;
+ reply->error = AsyncPropertyReply::InvalidOperation;
+ reply->completed(reply);
+ }
+}
+
+void ExampleSourcePlugin::getRangePropertyAsync(AsyncRangePropertyReply *reply)
+{
+
+}
+
+AsyncPropertyReply *ExampleSourcePlugin::setProperty(AsyncSetPropertyRequest request )
+{
+ AsyncPropertyReply *reply = new AsyncPropertyReply(request);
+ reply->success = false;
+
+ if(reply->property == VehicleProperty::AirConditioning)
+ {
+ if(acStatus.find(reply->zoneFilter) == acStatus.end())
+ {
+ reply->success = false;
+ reply->error = AsyncPropertyReply::ZoneNotSupported;
+ reply->completed(reply);
+ }
+ else
+ {
+ acStatus[reply->zoneFilter] = reply->value->value<bool>();
+
+ ///we need to update subscribers of this change:
+ routingEngine->updateProperty(reply->value,uuid());
+
+ ///Now reply to the set request:
+ reply->success = true;
+ reply->completed(reply);
+
+ }
+
+ return reply;
+ }
+
+ reply->error = AsyncPropertyReply::InvalidOperation;
+ reply->completed(reply);
+ return reply;
+}
+
+void ExampleSourcePlugin::subscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ mRequests.push_back(property);
+}
+
+PropertyList ExampleSourcePlugin::supported()
+{
+ return mSupported;
+}
+
+int ExampleSourcePlugin::supportedOperations()
+{
+ return Get | Set | GetRanged;
+}
+
+void ExampleSourcePlugin::unsubscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ if(contains(mRequests,property))
+ removeOne(&mRequests, property);
+}
+
+void ExampleSourcePlugin::randomizeProperties()
+{
+ velocity = 1 + (255.00 * (rand() / (RAND_MAX + 1.0)));
+ engineSpeed = 1 + (15000.00 * (rand() / (RAND_MAX + 1.0)));
+ accelerationX = 1 + (15000.00 * (rand() / (RAND_MAX + 1.0)));
+ transmissionShiftPostion = Transmission::TransmissionPositions(1 + (6.00 * (rand() / (RAND_MAX + 1.0))));
+ steeringWheelAngle = 1 + (359.00 * (rand() / (RAND_MAX + 1.0)));
+ throttlePos = 1 + (100.00 * (rand() / (RAND_MAX + 1.0)));
+ engineCoolant = 1 + (40.00 * (rand() / (RAND_MAX + 140.0)));
+
+ DebugOut()<<"setting velocity to: "<<velocity<<endl;
+ 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);
+ tsp.setValue(transmissionShiftPostion);
+ tgp.setValue(transmissionShiftPostion);
+ tsp.priority = AbstractPropertyType::Low;
+ tp.setValue(throttlePos);
+ ec.setValue(engineCoolant);
+ mgt.setValue(machineGun);
+
+ machineGun = !machineGun;
+
+ routingEngine->updateProperty(&vel, uuid());
+ routingEngine->updateProperty(&es, uuid());
+ routingEngine->updateProperty(&ac, uuid());
+ routingEngine->updateProperty(&swa, uuid());
+ routingEngine->updateProperty(&tsp, uuid());
+ routingEngine->updateProperty(&tp, uuid());
+ routingEngine->updateProperty(&ec, uuid());
+ routingEngine->updateProperty(&tgp, uuid());
+
+}
+
+void ExampleSourcePlugin::addPropertySupport(VehicleProperty::Property property, Zone::Type zone)
+{
+ mSupported.push_back(property);
+
+ Zone::ZoneList zones;
+
+ zones.push_back(zone);
+
+ PropertyInfo info(0, zones);
+
+ propertyInfoMap[property] = info;
+}
+
+int main(int argc, char** argv)
+{
+ ExampleSourcePlugin plugin;
+
+ AsyncPropertyReply request;
+
+ request.property = VehicleProperty::VehicleSpeed;
+ request.completed = [](AsyncPropertyReply* reply)
+ {
+ g_assert(reply->success);
+ };
+
+ plugin.getPropertyAsync(&request);
+
+ GMainLoop* mainLoop = g_main_loop_new(NULL, false);
+
+ g_main_loop_run(mainLoop);
+ return 1;
+}
diff --git a/plugins/exampleplugin.h b/plugins/exampleplugin.h
new file mode 100644
index 00000000..3427769c
--- /dev/null
+++ b/plugins/exampleplugin.h
@@ -0,0 +1,79 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef EXAMPLEPLUGIN_H
+#define EXAMPLEPLUGIN_H
+
+#include <abstractsource.h>
+#include <string>
+
+using namespace std;
+
+class ExampleSourcePlugin: public AbstractSource
+{
+
+public:
+ ExampleSourcePlugin(): AbstractSource(nullptr, map<string, string>()) {}
+ ExampleSourcePlugin(AbstractRoutingEngine* re, map<string, string> config);
+
+ const string uuid();
+ void getPropertyAsync(AsyncPropertyReply *reply);
+ void getRangePropertyAsync(AsyncRangePropertyReply *reply);
+ AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request);
+ void subscribeToPropertyChanges(VehicleProperty::Property property);
+ void unsubscribeToPropertyChanges(VehicleProperty::Property property);
+ PropertyList supported();
+
+ int supportedOperations();
+
+ void supportedChanged(const PropertyList &) {}
+
+ void randomizeProperties();
+
+ PropertyInfo getPropertyInfo(const VehicleProperty::Property & property)
+ {
+ if(propertyInfoMap.find(property) != propertyInfoMap.end())
+ return propertyInfoMap[property];
+
+ return PropertyInfo::invalid();
+ }
+
+private:
+
+ void addPropertySupport(VehicleProperty::Property property, Zone::Type zone);
+
+ std::map<VehicleProperty::Property, PropertyInfo> propertyInfoMap;
+ std::map<Zone::Type, Airbag::Status> airbagStatus;
+ std::map<Zone::Type, bool> acStatus;
+ PropertyList mRequests;
+ PropertyList mSupported;
+ uint16_t velocity;
+ uint16_t engineSpeed;
+
+ VehicleProperty::VehicleSpeedType vel;
+ VehicleProperty::EngineSpeedType es;
+ VehicleProperty::AccelerationXType ac;
+ VehicleProperty::SteeringWheelAngleType swa;
+ VehicleProperty::TransmissionShiftPositionType tsp;
+ VehicleProperty::TransmissionGearPositionType tgp;
+ VehicleProperty::ThrottlePositionType tp;
+ VehicleProperty::EngineCoolantTemperatureType ec;
+ VehicleProperty::MachineGunTurretStatusType mgt;
+};
+
+#endif // EXAMPLEPLUGIN_H
diff --git a/plugins/exampleplugins.README.txt b/plugins/exampleplugins.README.txt
new file mode 100644
index 00000000..dbee43ec
--- /dev/null
+++ b/plugins/exampleplugins.README.txt
@@ -0,0 +1,36 @@
+example source and sink plugins
+Version: @PROJECT_VERSION@
+
+The example plugins are source and sink plugin that provide a simple example of how to create a plugin.
+They are useful for testing AMB but only support a limited number of properties.
+
+The example plugins is enabled by default.
+
+
+To use the example source plugin, add the following to the "sources" array in /etc/ambd/config:
+
+{
+ "name" : "ExampleSouce",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so",
+ "delay" : "1"
+}
+
+To use the example sink, add the following to the "sinks" array in /etc/ambd/config:
+
+{
+ "name" : "ExampleSink",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesinkplugin.so"
+}
+
+Configuration Key Definitions:
+
+"name"
+name of plugin. This key is not used by the plugin at this moment.
+
+"path"
+path to plugin on the filesystem.
+
+"delay" (source plugin only)
+Delay in miliseconds when the source will generate a changed event
+
+default: 1000
diff --git a/plugins/examplesink.cpp b/plugins/examplesink.cpp
new file mode 100644
index 00000000..f696479d
--- /dev/null
+++ b/plugins/examplesink.cpp
@@ -0,0 +1,210 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "examplesink.h"
+#include "abstractroutingengine.h"
+#include "debugout.h"
+#include "listplusplus.h"
+
+#include <glib.h>
+
+
+extern "C" void create(AbstractRoutingEngine* routingEngine, map<string, string> config)
+{
+ new ExampleSink(routingEngine, config);
+}
+
+ExampleSink::ExampleSink(AbstractRoutingEngine* engine, map<string, string> config): AbstractSink(engine, config)
+{
+ routingEngine->subscribeToProperty(VehicleProperty::EngineSpeed, this);
+ routingEngine->subscribeToProperty(VehicleProperty::VehicleSpeed, this);
+ routingEngine->subscribeToProperty(VehicleProperty::Latitude, this);
+ routingEngine->subscribeToProperty(VehicleProperty::Longitude, this);
+ routingEngine->subscribeToProperty(VehicleProperty::ExteriorBrightness, this);
+
+ supportedChanged(engine->supported());
+}
+
+
+PropertyList ExampleSink::subscriptions()
+{
+
+}
+
+void ExampleSink::supportedChanged(const PropertyList & supportedProperties)
+{
+ DebugOut()<<"Support changed!"<<endl;
+
+ if(contains(supportedProperties, VehicleProperty::VehicleSpeed))
+ {
+ AsyncPropertyRequest velocityRequest;
+ velocityRequest.property = VehicleProperty::VehicleSpeed;
+ velocityRequest.completed = [](AsyncPropertyReply* reply)
+ {
+ if(!reply->success)
+ DebugOut(DebugOut::Error)<<"Velocity Async request failed ("<<reply->error<<")"<<endl;
+ else
+ DebugOut(0)<<"Velocity Async request completed: "<<reply->value->toString()<<endl;
+ delete reply;
+ };
+
+ routingEngine->getPropertyAsync(velocityRequest);
+ }
+
+ if(contains(supportedProperties, VehicleProperty::VIN))
+ {
+ AsyncPropertyRequest vinRequest;
+ vinRequest.property = VehicleProperty::VIN;
+ vinRequest.completed = [](AsyncPropertyReply* reply)
+ {
+ if(!reply->success)
+ DebugOut(DebugOut::Error)<<"VIN Async request failed ("<<reply->error<<")"<<endl;
+ else
+ DebugOut(0)<<"VIN Async request completed: "<<reply->value->toString()<<endl;
+ delete reply;
+ };
+
+ routingEngine->getPropertyAsync(vinRequest);
+ }
+ if(contains(supportedProperties, VehicleProperty::WMI))
+ {
+ AsyncPropertyRequest wmiRequest;
+ wmiRequest.property = VehicleProperty::WMI;
+ wmiRequest.completed = [](AsyncPropertyReply* reply)
+ {
+ if(!reply->success)
+ DebugOut(DebugOut::Error)<<"WMI Async request failed ("<<reply->error<<")"<<endl;
+ else
+ DebugOut(1)<<"WMI Async request completed: "<<reply->value->toString()<<endl;
+ delete reply;
+ };
+
+ routingEngine->getPropertyAsync(wmiRequest);
+ }
+ if(contains(supportedProperties, VehicleProperty::BatteryVoltage))
+ {
+ AsyncPropertyRequest batteryVoltageRequest;
+ batteryVoltageRequest.property = VehicleProperty::BatteryVoltage;
+ batteryVoltageRequest.completed = [](AsyncPropertyReply* reply)
+ {
+ if(!reply->success)
+ DebugOut(DebugOut::Error)<<"BatteryVoltage Async request failed ("<<reply->error<<")"<<endl;
+ else
+ DebugOut(1)<<"BatteryVoltage Async request completed: "<<reply->value->toString()<<endl;
+ delete reply;
+ };
+
+ routingEngine->getPropertyAsync(batteryVoltageRequest);
+ }
+ if(contains(supportedProperties, VehicleProperty::DoorsPerRow))
+ {
+ AsyncPropertyRequest doorsPerRowRequest;
+ doorsPerRowRequest.property = VehicleProperty::DoorsPerRow;
+ doorsPerRowRequest.completed = [](AsyncPropertyReply* reply)
+ {
+ if(!reply->success)
+ DebugOut(DebugOut::Error)<<"Doors per row Async request failed ("<<reply->error<<")"<<endl;
+ else
+ DebugOut(1)<<"Doors per row: "<<reply->value->toString()<<endl;
+ delete reply;
+ };
+
+ routingEngine->getPropertyAsync(doorsPerRowRequest);
+ }
+
+ if(contains(supportedProperties,VehicleProperty::AirbagStatus))
+ {
+ AsyncPropertyRequest airbagStatus;
+ airbagStatus.property = VehicleProperty::AirbagStatus;
+ airbagStatus.zoneFilter = Zone::FrontRight | Zone::FrontSide;
+ airbagStatus.completed = [](AsyncPropertyReply* reply)
+ {
+ if(!reply->success)
+ {
+ DebugOut(DebugOut::Error)<<"Airbag Async request failed ("<<reply->error<<")"<<endl;
+ }
+ else
+ DebugOut(1)<<"Airbag Status: "<<reply->value->toString()<<endl;
+ delete reply;
+ };
+
+ routingEngine->getPropertyAsync(airbagStatus);
+ }
+
+ if(contains(supportedProperties, VehicleProperty::ExteriorBrightness))
+ {
+ AsyncPropertyRequest exteriorBrightness;
+ exteriorBrightness.property = VehicleProperty::ExteriorBrightness;
+ exteriorBrightness.completed = [](AsyncPropertyReply* reply)
+ {
+ if(!reply->success)
+ DebugOut(DebugOut::Error)<<"Exterior Brightness Async request failed ("<<reply->error<<")"<<endl;
+ else
+ DebugOut(1)<<"Exterior Brightness: "<<reply->value->toString()<<endl;
+ delete reply;
+ };
+
+ routingEngine->getPropertyAsync(exteriorBrightness);
+ }
+
+ auto getRangedCb = [](gpointer data)
+ {
+ AbstractRoutingEngine* routingEngine = (AbstractRoutingEngine*)data;
+
+ AsyncRangePropertyRequest vehicleSpeedFromLastWeek;
+
+ vehicleSpeedFromLastWeek.timeBegin = amb::Timestamp::instance()->epochTime() - 10;
+ vehicleSpeedFromLastWeek.timeEnd = amb::Timestamp::instance()->epochTime();
+
+ PropertyList requestList;
+ requestList.push_back(VehicleProperty::VehicleSpeed);
+ requestList.push_back(VehicleProperty::EngineSpeed);
+
+ vehicleSpeedFromLastWeek.properties = requestList;
+ vehicleSpeedFromLastWeek.completed = [](AsyncRangePropertyReply* reply)
+ {
+ std::list<AbstractPropertyType*> values = reply->values;
+ for(auto itr = values.begin(); itr != values.end(); itr++)
+ {
+ auto val = *itr;
+ DebugOut(1) <<"Value from past: (" << val->name << "): " << val->toString()
+ <<" time: " << val->timestamp << " sequence: " << val->sequence << endl;
+ }
+
+ delete reply;
+ };
+
+ routingEngine->getRangePropertyAsync(vehicleSpeedFromLastWeek);
+
+ return 0;
+ };
+
+ g_timeout_add(10000, getRangedCb, routingEngine);
+}
+
+void ExampleSink::propertyChanged(AbstractPropertyType *value)
+{
+ VehicleProperty::Property property = value->name;
+ DebugOut()<<property<<" value: "<<value->toString()<<endl;
+}
+
+const string ExampleSink::uuid()
+{
+ return "f7e4fab2-eb73-4842-9fb0-e1c550eb2d81";
+}
diff --git a/plugins/examplesink.h b/plugins/examplesink.h
new file mode 100644
index 00000000..d75feb48
--- /dev/null
+++ b/plugins/examplesink.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef EXAMPLESINK_H
+#define EXAMPLESINK_H
+
+#include "abstractsink.h"
+
+
+class ExampleSink : public AbstractSink
+{
+
+public:
+ ExampleSink(AbstractRoutingEngine* engine, map<string, string> config);
+ virtual PropertyList subscriptions();
+ virtual void supportedChanged(const PropertyList & supportedProperties);
+ virtual void propertyChanged( AbstractPropertyType* value);
+ virtual const std::string uuid();
+};
+
+#endif // EXAMPLESINK_H
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..513bce69
--- /dev/null
+++ b/plugins/examplesource.in.json
@@ -0,0 +1,6 @@
+{
+ "name" : "ExampleSource",
+ "path" : "@PLUGIN_INSTALL_PATH@/examplesourceplugin.so",
+ "delay" : "5000",
+ "enabled" : true
+}
diff --git a/plugins/gpsnmea/CMakeLists.txt b/plugins/gpsnmea/CMakeLists.txt
new file mode 100644
index 00000000..2bcbb1db
--- /dev/null
+++ b/plugins/gpsnmea/CMakeLists.txt
@@ -0,0 +1,18 @@
+if(gpsnmea_plugin)
+
+set(gpsnmea_headers gpsnmea.h)
+set(gpsnmea_sources gpsnmea.cpp )
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${gio_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/plugins/common)
+
+add_library(gpsnmea MODULE ${gpsnmea_sources})
+set_target_properties(gpsnmea PROPERTIES PREFIX "")
+target_link_libraries(gpsnmea amb -L${CMAKE_CURRENT_BINARY_DIR}/lib amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common ${link_libraries} ${gio_LIBRARIES})
+
+install(TARGETS gpsnmea LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_BINARY_DIR}/gpsnmea.README.md @ONLY)
+
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/gpsnmea.README.md DESTINATION ${DOC_INSTALL_DIR}/plugins)
+
+endif(gpsnmea_plugin)
diff --git a/plugins/gpsnmea/README b/plugins/gpsnmea/README
new file mode 100644
index 00000000..28c6fcbe
--- /dev/null
+++ b/plugins/gpsnmea/README
@@ -0,0 +1,99 @@
+# GPS NMEA plugin {#gpsnmea_plugin}
+Version: @PROJECT_VERSION@
+
+This plugin uses NMEA-compatible devices to provide location information to AMB.
+
+To enable the GPS NMEA plugin, run cmake and enable the gpsnmea_plugin option:
+
+cmake -Dgpsnmea_plugin=On ..
+
+To use the Database plugin, add the following to the "sources" array in /etc/ambd/config:
+
+~~~~~~~~~~~~~{.json}
+{
+ "name" : "gpsnmea",
+ "path" : "@PLUGIN_INSTALL_PATH@/gpsnmea.so",
+ "device" : "/dev/ttyUSB0",
+ "baudrate" : "4800",
+ "bluetoothAdapter" : "00:00:00:00:00:00"
+}
+~~~~~~~~~~~~~
+
+## Configuration Key Definitions:
+
+"name"
+name of plugin. This key is not used by the plugin at this moment.
+
+"path"
+path to plugin on the filesystem.
+
+"device"
+gps device. This must be a serial device. It can also be a bluetooth address.
+
+Default: none
+
+"baudrate"
+Baudrate for serial devices : 2400,4800,9600,19200 or 38400.
+
+Default: 9600
+
+"bluetoothAdapter"
+bluetooth adapter to use. This is only used if "device" is also a bluetooth device.
+If left blank, the system default adapter will be used.
+
+Default: none
+
+## AMB Properties:
+
+GpsTime
+Timestamp in seconds from unix epoc (UTC) parsed from the NMEA output.
+
+Type: double
+Access: readonly
+
+GpsSpeed
+Speed as reported by GPS
+
+Type: UInt16
+Access: readonly
+
+GpsFix
+Fix status.
+
+~~~~~~~~~~~~(.cpp}
+enum FixType {
+ NoFix = 1,
+ Fix2D = 2,
+ Fix3D = 3
+};
+~~~~~~~~~~~~
+
+Type: int
+Access: readonly
+
+GpsSatsUsed {#GpsSatsUsed}
+How many satellites are being used in the fix
+
+Type: UInt16
+Access: readonly
+
+GpsNmea
+Raw NMEA message. Useful for debugging
+
+Type: String
+Access: readonly
+
+## DBus Interfaces:
+
+### org.automotive.GpsInfo
+**Properties**
+GpsTime - Corresponds with the GpsTime AMB Property
+Speed - Corresponds with the GpsSpeed AMB Property
+Fix - Corresponds with the GpsFix AMB Property
+SattelitesUsed - Corresponds with the GpsSatsUsed AMB Property
+RawNmea - Corresponds with the GpsNmea AMB Property
+
+interface GpsInfo
+{
+
+}
diff --git a/plugins/gpsnmea/gpsnmea.cpp b/plugins/gpsnmea/gpsnmea.cpp
new file mode 100644
index 00000000..7cfa75cb
--- /dev/null
+++ b/plugins/gpsnmea/gpsnmea.cpp
@@ -0,0 +1,756 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "gpsnmea.h"
+#include "timestamp.h"
+#include "serialport.hpp"
+#include "bluetooth.hpp"
+#include "bluetooth5.h"
+#include <listplusplus.h>
+#include <superptr.hpp>
+#include <ambplugin.h>
+
+#include <dbusplugin.h>
+#include <dbusexport.h>
+
+#include <iostream>
+#include <boost/assert.hpp>
+#include <boost/algorithm/string.hpp>
+#include <time.h>
+
+
+using namespace std;
+
+#include "debugout.h"
+#include "abstractpropertytype.h"
+
+#define GPSTIME "GpsTime"
+#define GPSSPEED "GpsSpeed"
+#define GpsFix "GpsFix"
+#define GpsSatsUsed "GpsSatsUsed"
+#define GpsNmea "GpsNmea"
+
+template<typename T2>
+inline T2 lexical_cast(const std::string &in) {
+ T2 out;
+ std::stringstream ss;
+ ss << std::hex << in;
+ ss >> out;
+ return out;
+}
+
+class GpsInfo: public DBusSink
+{
+public:
+ GpsInfo(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection)
+ :DBusSink("GpsInfo", re, connection, map<string, string>())
+ {
+ wantPropertyVariant(GPSTIME, "GpsTime", VariantType::Read);
+ wantPropertyVariant(GPSSPEED, "Speed", VariantType::Read);
+ wantPropertyVariant(GpsFix, "Fix", VariantType::Read);
+ wantPropertyVariant(GpsSatsUsed, "SattelitesUsed", VariantType::Read);
+ wantPropertyVariant(GpsNmea, "RawNmea", VariantType::Read);
+ }
+};
+
+class Location
+{
+public:
+ enum FixType {
+ NoFix = 1,
+ Fix2D = 2,
+ Fix3D = 3
+ };
+
+ Location(AmbPluginImpl *source, std::shared_ptr<AbstractPropertyType> lat,
+ std::shared_ptr<AbstractPropertyType> lon,
+ std::shared_ptr<AbstractPropertyType> alt,
+ std::shared_ptr<AbstractPropertyType> dir,
+ std::shared_ptr<AbstractPropertyType> spd,
+ std::shared_ptr<AbstractPropertyType> time,
+ std::shared_ptr<AbstractPropertyType> fix,
+ std::shared_ptr<AbstractPropertyType> satsUsed);
+
+ void parse(std::string gprmc);
+
+ AbstractPropertyType * latitude()
+ {
+ return mLatitude.get();
+ }
+
+ AbstractPropertyType * longitude()
+ {
+ return mLongitude.get();
+ }
+
+ AbstractPropertyType * altitude()
+ {
+ return mAltitude.get();
+ }
+
+ AbstractPropertyType * direction()
+ {
+ return mDirection.get();
+ }
+
+ AbstractPropertyType * speed()
+ {
+ return mSpeed.get();
+ }
+
+ AbstractPropertyType * gpsTime()
+ {
+ return mGpsTime.get();
+ }
+
+ std::list<AbstractPropertyType*> fix()
+ {
+ std::list<AbstractPropertyType*> l;
+
+ l.push_back(mLatitude.get());
+ l.push_back(mLongitude.get());
+ l.push_back(mAltitude.get());
+ l.push_back(mDirection.get());
+ l.push_back(mSpeed.get());
+ l.push_back(mGpsTime.get());
+
+ return l;
+ }
+
+private: ///methods:
+
+ void parseGprmc(string gprmc);
+ void parseGpgga(string gpgga);
+ void parseGpgsa(string gpgsa);
+
+ void parseTime(std::string h, std::string m, std::string s, string dd, string mm, string yy);
+ void parseLatitude(std::string d, std::string m, std::string ns);
+ void parseLongitude(std::string d, string m, string ew);
+ void parseSpeed(std::string spd);
+ void parseDirection(std::string dir);
+ void parseAltitude(std::string alt);
+
+ double degsToDecimal(double degs);
+
+private:
+
+ std::shared_ptr<AbstractPropertyType> mLatitude;
+ std::shared_ptr<AbstractPropertyType> mLongitude;
+ std::shared_ptr<AbstractPropertyType> mAltitude;
+ std::shared_ptr<AbstractPropertyType> mDirection;
+ std::shared_ptr<AbstractPropertyType> mSpeed;
+ std::shared_ptr<AbstractPropertyType> mGpsTime;
+ std::shared_ptr<AbstractPropertyType> mFix;
+ std::shared_ptr<AbstractPropertyType> mSatelitesUsed;
+
+ bool isActive;
+
+ AmbPluginImpl * parent;
+
+};
+
+Location::Location(AmbPluginImpl* source,
+ std::shared_ptr<AbstractPropertyType> lat,
+ std::shared_ptr<AbstractPropertyType> lon,
+ std::shared_ptr<AbstractPropertyType> alt,
+ std::shared_ptr<AbstractPropertyType> dir,
+ std::shared_ptr<AbstractPropertyType> spd,
+ std::shared_ptr<AbstractPropertyType> time,
+ std::shared_ptr<AbstractPropertyType> fix,
+ std::shared_ptr<AbstractPropertyType> satsUsed)
+ :parent(source), isActive(false)
+{
+ mLatitude = lat;
+ mLongitude = lon;
+ mAltitude = alt;
+ mDirection = dir;
+ mSpeed = spd;
+ mGpsTime = time;
+ mFix = fix;
+ mSatelitesUsed = satsUsed;
+}
+
+void Location::parse(string nmea)
+{
+ if(boost::algorithm::starts_with(nmea,"GPRMC"))
+ {
+ parseGprmc(nmea);
+ }
+ else if(boost::algorithm::starts_with(nmea,"GPGGA"))
+ {
+ parseGpgga(nmea);
+ }
+ else if(boost::algorithm::starts_with(nmea, "GPGSA"))
+ {
+ parseGpgsa(nmea);
+ }
+ else
+ {
+ DebugOut(7)<<"unknown/unhandled message: "<<nmea<<endl;
+ }
+}
+
+void Location::parseGprmc(string gprmc)
+{
+ DebugOut(7)<<"parsing gprmc message"<<endl;
+
+ std::vector<std::string> tokens;
+ boost::split(tokens, gprmc, boost::is_any_of(","));
+
+ if(!tokens.size())
+ {
+ return;
+ }
+
+ if(tokens[2] == "A")
+ {
+ isActive = true;
+ }
+
+ if(tokens[1].empty() || tokens[9].empty() || tokens[3].empty() || tokens[4].empty() || tokens[5].empty() || tokens[6].empty() || tokens[7].empty() || tokens[8].empty())
+ {
+ return;
+ }
+
+ parseTime(tokens[1].substr(0,2),tokens[1].substr(2,2),tokens[1].substr(4,2),tokens[9].substr(0,2),tokens[9].substr(2,2),tokens[9].substr(4,2));
+
+ parseLatitude(tokens[3], "", tokens[4]);
+ parseLongitude(tokens[5], "", tokens[6]);
+ parseSpeed(tokens[7]);
+ parseDirection(tokens[8]);
+
+}
+
+void Location::parseGpgga(string gpgga)
+{
+
+ std::vector<std::string> tokens;
+ boost::split(tokens, gpgga, boost::is_any_of(","));
+
+ if(tokens.size() != 15)
+ {
+ DebugOut()<<"Invalid GPGGA message: "<<gpgga<<endl;
+ return;
+ }
+
+ parseLatitude(tokens[2],"",tokens[3]);
+ parseLongitude(tokens[4],"",tokens[5]);
+ if(tokens[6] != "0")
+ {
+ isActive = true;
+ }
+ else isActive = false;
+
+ parseAltitude(tokens[9]);
+}
+
+void Location::parseGpgsa(string gpgsa)
+{
+ std::vector<std::string> tokens;
+ boost::split(tokens, gpgsa, boost::is_any_of(","));
+
+ if(tokens.size() != 18)
+ {
+ DebugOut()<<"Invalid GPGSA message: "<<gpgsa<<endl;
+ return;
+ }
+
+ Location::FixType fix = (Location::FixType)boost::lexical_cast<int>(tokens[2]);
+
+ uint16_t numsats = 0;
+
+ for(int i=3; i<15; i++)
+ {
+ std::string sat = tokens[i];
+ if(!sat.empty())
+ {
+ numsats ++;
+ }
+ }
+
+ if(mFix->value<Location::FixType>() != fix)
+ parent->setValue(mFix, fix);
+
+ if(mSatelitesUsed->value<uint16_t>() != numsats)
+ parent->setValue(mSatelitesUsed, numsats);
+}
+
+void Location::parseTime(string h, string m, string s, string dd, string mm, string yy)
+{
+ try
+ {
+ tm t;
+ t.tm_hour = boost::lexical_cast<int>(h);
+ t.tm_min = boost::lexical_cast<int>(m);
+ t.tm_sec = boost::lexical_cast<int>(s);
+ t.tm_mday = boost::lexical_cast<int>(dd);
+ t.tm_mon = boost::lexical_cast<int>(mm) - 1;
+ t.tm_year = boost::lexical_cast<int>(yy) + 100;
+
+ time_t time = timegm(&t);
+
+ if(mGpsTime->value<double>() != (double(time)))
+ {
+ parent->setValue(mGpsTime, double(time));
+ }
+ }
+ catch(...)
+ {
+ DebugOut(5)<<"Failed to parse time "<<endl;
+ }
+}
+
+void Location::parseLatitude(string d, string m, string ns)
+{
+ try
+ {
+ if(d.empty() )
+ return;
+
+ double degs = boost::lexical_cast<double>(d + m);
+ double dec = degsToDecimal(degs);
+
+ if(ns == "S")
+ dec *= -1;
+
+ if(mLatitude->value<double>() != dec)
+ {
+ parent->setValue(mLatitude, dec);
+ }
+ }
+ catch(...)
+ {
+ DebugOut(5)<<"Failed to parse latitude"<<endl;
+ }
+}
+
+void Location::parseLongitude(string d, string m, string ew)
+{
+ try
+ {
+ if(d.empty()) return;
+
+ double degs = boost::lexical_cast<double>(d + m);
+ double dec = degsToDecimal(degs);
+
+ if(ew == "W")
+ dec *= -1;
+
+ if(mLongitude->value<double>() != dec)
+ {
+ parent->setValue(mLongitude, dec);
+ }
+ }
+ catch(...)
+ {
+ DebugOut(5)<<"failed to parse longitude: "<<d<<" "<<m<<" "<<ew<<endl;
+ }
+}
+
+void Location::parseSpeed(string spd)
+{
+ try
+ {
+ double s = boost::lexical_cast<double>(spd);
+
+ ///to kph:
+ s *= 1.852;
+
+ uint16_t speed = static_cast<uint16_t>(s);
+
+ if(mSpeed->value<uint16_t>() != speed)
+ {
+ parent->setValue(mSpeed, speed);
+ }
+ }
+ catch(...)
+ {
+ DebugOut(5)<<"failed to parse speed"<<endl;
+ }
+}
+
+void Location::parseDirection(string dir)
+{
+ try {
+ uint16_t d = boost::lexical_cast<double>(dir);
+
+ if(mDirection->value<uint16_t>() != d)
+ {
+ parent->setValue(mDirection, d);
+ }
+ }
+ catch(...)
+ {
+ DebugOut(5)<<"Failed to parse direction: "<<dir<<endl;
+ }
+}
+
+void Location::parseAltitude(string alt)
+{
+ try{
+
+ if(alt.empty()) return;
+
+ double a = boost::lexical_cast<double>(alt);
+
+ if(mAltitude->value<double>() != a)
+ {
+ parent->setValue(mAltitude, a);
+ }
+ }
+ catch(...)
+ {
+ DebugOut(5)<<"failed to parse altitude"<<endl;
+ }
+}
+
+double Location::degsToDecimal(double degs)
+{
+ double deg;
+ double min = 100.0 * modf(degs / 100.0, &deg);
+ return deg + (min / 60.0);
+}
+
+bool readCallback(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+// DebugOut(5) << "Polling..." << condition << endl;
+
+ if(condition & G_IO_ERR)
+ {
+ DebugOut(DebugOut::Error)<<"GpsNmeaSource polling error."<<endl;
+ }
+
+ if (condition & G_IO_HUP)
+ {
+ //Hang up. Returning false closes out the GIOChannel.
+ //printf("Callback on G_IO_HUP\n");
+ DebugOut(DebugOut::Warning)<<"socket hangup event..."<<endl;
+ return false;
+ }
+
+ GpsNmeaSource* src = static_cast<GpsNmeaSource*>(data);
+
+ src->canHasData();
+
+ return true;
+}
+
+extern "C" void create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ auto plugin = new AmbPlugin<GpsNmeaSource>(routingengine, config);
+ plugin->init();
+}
+
+GpsNmeaSource::GpsNmeaSource(AbstractRoutingEngine *re, map<string, string> config, AbstractSource &parent)
+ :AmbPluginImpl(re, config, parent), mUuid("33d86462-1708-4f78-a001-99ea8d55422b"), device(nullptr), bt(nullptr)
+{
+ int baudrate = 0;
+
+ auto lat = addPropertySupport<VehicleProperty::LatitudeType>(Zone::None);
+ auto lon = addPropertySupport<VehicleProperty::LongitudeType>(Zone::None);
+ auto alt = addPropertySupport<VehicleProperty::AltitudeType>(Zone::None);
+ auto spd = addPropertySupport(Zone::None, [](){ return new BasicPropertyType<uint16_t>(GPSSPEED, 0); });
+ auto dir = addPropertySupport<VehicleProperty::DirectionType>(Zone::None);
+ auto time = addPropertySupport(Zone::None, [](){ return new BasicPropertyType<double>(GPSTIME, 0); });
+ auto fix = addPropertySupport(Zone::None, []() { return new BasicPropertyType<Location::FixType>(GpsFix, Location::NoFix); });
+ auto satsUsed = addPropertySupport(Zone::None, []() { return new BasicPropertyType<uint16_t>(GpsSatsUsed, 0); });
+ rawNmea = addPropertySupport(Zone::None, []() { return new StringPropertyType(GpsNmea); });
+
+ location = new Location(this, lat, lon, alt, dir, spd, time, fix, satsUsed);
+
+ std::string btaddapter = config["bluetoothAdapter"];
+
+ if(config.find("baudrate")!= config.end())
+ {
+ baudrate = boost::lexical_cast<int>( config["baudrate"] );
+ }
+
+ if(config.find("device")!= config.end())
+ {
+ std::string dev = config["device"];
+
+ if(dev.find(":") != string::npos)
+ {
+#ifdef USE_BLUEZ5
+ bt = new Bluetooth5();
+ bt->getDeviceForAddress(dev, [this](int fd) {
+ DebugOut() << "fd: " << fd << endl;
+ device = new SerialPort(fd);
+ int baudrate=0;
+
+ if(baudrate!=0)
+ {
+ if((static_cast<SerialPort*>(device))->setSpeed(baudrate))
+ DebugOut(DebugOut::Error)<<"Unsupported baudrate " << configuration["baudrate"] << endl;
+ }
+
+ DebugOut()<<"read from device: "<<device->read()<<endl;
+
+ GIOChannel *chan = g_io_channel_unix_new(device->fileDescriptor());
+ g_io_add_watch(chan, GIOCondition(G_IO_IN | G_IO_HUP | G_IO_ERR),(GIOFunc)readCallback, this);
+ g_io_channel_set_close_on_unref(chan, true);
+ g_io_channel_unref(chan);
+ });
+#else
+ bt = new BluetoothDevice();
+ dev = bt->getDeviceForAddress(dev, btaddapter);
+
+ device = new SerialPort(dev);
+
+ if(baudrate!=0)
+ {
+ if((static_cast<SerialPort*>(device))->setSpeed(baudrate))
+ DebugOut(DebugOut::Error)<<"Unsupported baudrate " << config["baudrate"] << endl;
+ }
+
+ if(!device->open())
+ {
+ DebugOut(DebugOut::Error)<<"Failed to open gps tty: "<<config["device"]<<endl;
+ perror("Error");
+ return;
+ }
+
+ DebugOut()<<"read from device: "<<device->read()<<endl;
+
+ GIOChannel *chan = g_io_channel_unix_new(device->fileDescriptor());
+ g_io_add_watch(chan, GIOCondition(G_IO_IN | G_IO_HUP | G_IO_ERR),(GIOFunc)readCallback, this);
+ g_io_channel_set_close_on_unref(chan, true);
+ g_io_channel_unref(chan);
+#endif
+ }
+ else
+ {
+ device = new SerialPort(dev);
+
+ if(baudrate!=0)
+ {
+ if((static_cast<SerialPort*>(device))->setSpeed(baudrate))
+ DebugOut(DebugOut::Error)<<"Unsupported baudrate " << config["baudrate"] << endl;
+ }
+
+ if(!device->open())
+ {
+ DebugOut(DebugOut::Error) << "Failed to open gps tty: " << config["device"] << endl;
+ perror("Error");
+ return;
+ }
+
+ DebugOut()<<"read from device: "<<device->read()<<endl;
+
+ GIOChannel *chan = g_io_channel_unix_new(device->fileDescriptor());
+ g_io_add_watch(chan, GIOCondition(G_IO_IN | G_IO_HUP | G_IO_ERR), (GIOFunc)readCallback, this);
+ g_io_channel_set_close_on_unref(chan, true);
+ g_io_channel_unref(chan);
+ }
+ }
+}
+
+GpsNmeaSource::~GpsNmeaSource()
+{
+ if(device && device->isOpen())
+ device->close();
+ if(bt)
+ delete bt;
+}
+
+const string GpsNmeaSource::uuid() const
+{
+ return mUuid;
+}
+
+int GpsNmeaSource::supportedOperations() const
+{
+ return AbstractSource::Get;
+}
+
+void GpsNmeaSource::init()
+{
+ if(configuration.find("test") != configuration.end())
+ {
+ test();
+ }
+
+ routingEngine->subscribeToProperty(DBusConnected,[this](AbstractPropertyType* value)
+ {
+ if(value->name == DBusConnected)
+ {
+ if(value->value<bool>())
+ {
+ amb::Exporter::instance()->exportProperty<GpsInfo>(routingEngine);
+ }
+ }
+ });
+}
+
+void GpsNmeaSource::canHasData()
+{
+ std::string data = device->read();
+
+ tryParse(data);
+}
+
+void GpsNmeaSource::test()
+{
+ location->parse("GPRMC,061211,A,2351.9605,S,15112.5239,E,000.0,053.4,170303,009.9,E*6E");
+
+ DebugOut(0)<<"lat: "<<location->latitude()->toString()<<endl;
+ DebugOut(0)<<"lat: "<<location->gpsTime()->toString()<<endl;
+
+ g_assert(location->latitude()->toString() == "-23.86600833");
+ g_assert(location->gpsTime()->toString() == "1050585131");
+
+ location->parse("GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47");
+
+ DebugOut(0)<<"alt: "<<location->altitude()->toString()<<endl;
+ DebugOut(0)<<"lat: "<<location->latitude()->toString()<<endl;
+ g_assert(location->altitude()->toString() == "545.4");
+ g_assert(location->latitude()->toString() == "48.1173");
+
+ location->parse("GPRMC,060136.00,A,3101.40475,N,12126.87095,E,0.760,,160114,,,A*74");
+ DebugOut(0)<<"lon: "<<location->longitude()->toString()<<endl;
+ DebugOut(0)<<"lat: "<<location->latitude()->toString()<<endl;
+
+ ///test gpgsa
+ location->parse("GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39");
+
+ //Test incomplete message:
+ location->parse("GPRMC,023633.00,V,,,,,,,180314,,,N*75");
+ DebugOut(0)<<"lon: "<<location->longitude()->toString()<<endl;
+ DebugOut(0)<<"lat: "<<location->latitude()->toString()<<endl;
+
+ std::string testChecksuming = "GPRMC,195617.00,V,,,,,,,310314,,,N*74";
+
+ g_assert(checksum(testChecksuming));
+
+ std::string multimessage1 = "GA,235320.00,4532.48633,N,12257.";
+ std::string multimessage2 = "57383,W,";
+ std::string multimessage3 = "1,03,7.53,51.6,M,-21.3,M,,*55";
+ std::string multimessage4 = "GPGSA,A,";
+ std::string multimessage5 = "2,27,23,19,,,,,,,,,,7.60";
+ std::string multimessage6 = ",7.53,1.00*";
+ std::string multimessage7 = "0E";
+
+ bool multimessageParse = false;
+
+ multimessageParse |= tryParse(multimessage1);
+ multimessageParse |= tryParse(multimessage2);
+ multimessageParse |= tryParse(multimessage3);
+ multimessageParse |= tryParse(multimessage4);
+ multimessageParse |= tryParse(multimessage5);
+ multimessageParse |= tryParse(multimessage6);
+ multimessageParse |= tryParse(multimessage7);
+
+ g_assert(multimessageParse);
+
+ //Test meaningingless message:
+ location->parse("GPRMC,,V,,,,,,,,,,N*53");
+
+ //test false message:
+
+ g_assert(!checksum("GPRMC,172758.296,V"));
+}
+
+bool GpsNmeaSource::tryParse(string data)
+{
+ std::vector<std::string> lines;
+
+ boost::split(lines, data, boost::is_any_of("$"));
+
+ bool weFoundAMessage = false;
+
+ for(auto line : lines)
+ {
+ if(checksum(line))
+ {
+ buffer = line;
+ }
+ else
+ {
+ buffer += line;
+ }
+
+ std::string::size_type pos = buffer.find('G');
+
+ if(pos != std::string::npos && pos != 0)
+ {
+ ///Throw the incomplete stuff away. if it doesn't begin with "G" it'll never be complete
+ buffer = buffer.substr(pos);
+ }
+
+ if(checksum(buffer))
+ {
+ /// we have a complete message. parse it!
+ DebugOut(7)<<"Complete message: "<<buffer<<endl;
+ location->parse(buffer);
+ boost::algorithm::erase_all(buffer, "\n");
+ boost::algorithm::erase_all(buffer, "\r");
+ setValue(rawNmea, buffer);
+ weFoundAMessage = true;
+ buffer = "";
+ }
+ else
+ {
+ if(pos == 0 )
+ {
+ std::string::size_type cs = buffer.find('*');
+ if (cs != std::string::npos && cs != buffer.length()-1)
+ {
+ buffer = buffer.substr(cs+(buffer.length() - cs));
+ }
+ }
+ }
+
+ DebugOut(7)<<"buffer: "<<buffer<<endl;
+ }
+
+ return weFoundAMessage;
+}
+
+bool GpsNmeaSource::checksum(std::string sentence)
+{
+ if(sentence.empty() || sentence.length() < 4 || sentence.find("*") == string::npos || sentence.find("*") >= sentence.length()-2)
+ {
+ return false;
+ }
+
+ int checksum = 0;
+
+ for(auto i : sentence)
+ {
+ if(i == '*')
+ break;
+ if(i != '\n' || i != '\r')
+ checksum ^= i;
+ }
+
+ std::string sentenceCheckStr = sentence.substr(sentence.find('*')+1,2);
+
+ try
+ {
+ int sentenceCheck = lexical_cast<int>(sentenceCheckStr);
+
+ return sentenceCheck == checksum;
+ }
+ catch(...)
+
+ {
+ return false;
+ }
+
+ return false;
+}
diff --git a/plugins/gpsnmea/gpsnmea.h b/plugins/gpsnmea/gpsnmea.h
new file mode 100644
index 00000000..f1cee601
--- /dev/null
+++ b/plugins/gpsnmea/gpsnmea.h
@@ -0,0 +1,76 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef GPSNMEAPLUGIN_H
+#define GPSNMEAPLUGIN_H
+
+#include <abstractsource.h>
+
+#include <string>
+
+#include <abstractio.hpp>
+#include <ambpluginimpl.h>
+
+using namespace std;
+
+class Location;
+class Bluetooth5;
+class BluetoothDevice;
+
+class GpsNmeaSource: public AmbPluginImpl
+{
+
+public:
+ GpsNmeaSource(AbstractRoutingEngine* re, map<string, string> config, AbstractSource &parent);
+ ~GpsNmeaSource();
+
+ const string uuid() const;
+
+ void canHasData();
+
+ void test();
+
+ int supportedOperations() const;
+
+ void init();
+
+private:
+ bool tryParse(std::string data);
+
+ bool checksum(string sentence);
+
+ PropertyList mRequests;
+ PropertyList mSupported;
+
+ AbstractIo* device;
+ Location *location;
+
+ std::string mUuid;
+
+ std::string buffer;
+
+ std::shared_ptr<AbstractPropertyType> rawNmea;
+
+#ifdef USE_BLUEZ5
+ Bluetooth5 * bt;
+#else
+ BluetoothDevice *bt;
+#endif
+};
+
+#endif // EXAMPLEPLUGIN_H
diff --git a/plugins/murphyplugin/CMakeLists.txt b/plugins/murphyplugin/CMakeLists.txt
new file mode 100644
index 00000000..a484d029
--- /dev/null
+++ b/plugins/murphyplugin/CMakeLists.txt
@@ -0,0 +1,34 @@
+if(murphy_plugin)
+
+include(CheckIncludeFiles)
+include(FindPkgConfig)
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${MURPHY_COMMON_INCLUDE_DIRS})
+
+pkg_check_modules(MURPHY_COMMON REQUIRED murphy-common)
+
+#if(qtmainloop)
+# pkg_check_modules(MURPHY_QT REQUIRED murphy-qt)
+
+ #set(include_dirs ${include_dirs} ${MURPHY_QT_INCLUDE_DIRS})
+ #set(murphy_libraries ${murphy_libraries} ${MURPHY_QT_LIBRARIES})
+#else(qtmainloop)
+ pkg_check_modules(MURPHY_GLIB REQUIRED murphy-glib)
+
+ set(include_dirs ${include_dirs} ${MURPHY_GLIB_INCLUDE_DIRS})
+ set(murphy_libraries ${murphy_libraries} ${MURPHY_GLIB_LIBRARIES})
+#endif(qtmainloop)
+
+
+set(murphysourceplugin_headers murphysource.h)
+set(murphysourceplugin_sources murphysource.cpp)
+
+link_directories(${CMAKE_CURRENT_BINARY_DIR}/lib ${MURPHY_COMMON_LIBRARY_DIRS})
+
+add_library(murphysourceplugin MODULE ${murphysourceplugin_sources})
+set_target_properties(murphysourceplugin PROPERTIES PREFIX "")
+target_link_libraries(murphysourceplugin amb ${MURPHY_COMMON_LIBRARIES} -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${murphy_libraries})
+
+install(TARGETS murphysourceplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+
+endif(murphy_plugin)
diff --git a/plugins/murphyplugin/murphysource.cpp b/plugins/murphyplugin/murphysource.cpp
new file mode 100644
index 00000000..6ec37b17
--- /dev/null
+++ b/plugins/murphyplugin/murphysource.cpp
@@ -0,0 +1,462 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "murphysource.h"
+
+#include <iostream>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <glib.h>
+#include <sstream>
+#include <listplusplus.h>
+#include <timestamp.h>
+
+#include <murphy/common.h>
+#include <murphy/glib/glib-glue.h>
+
+#include "debugout.h"
+
+void MurphySource::processValue(string propertyName, AbstractPropertyType *prop)
+{
+ if (murphyProperties.find(propertyName) != murphyProperties.end())
+ {
+ delete murphyProperties[propertyName];
+ murphyProperties[propertyName] = prop;
+ }
+ else
+ {
+ murphyProperties[propertyName] = prop;
+ m_re->updateSupported(supported(), PropertyList(), this);
+ }
+
+ m_re->updateProperty(prop, uuid());
+}
+
+bool MurphySource::hasProperty(string propertyName)
+{
+ PropertyList props = supported();
+ return contains(props,propertyName);
+}
+
+static void recvfrom_msg(mrp_transport_t *transp, mrp_msg_t *msg,
+ mrp_sockaddr_t *addr, socklen_t addrlen,
+ void *user_data)
+{
+ MurphySource *s = (MurphySource *) user_data;
+
+ void *cursor = NULL;
+ uint16_t tag = 0;
+ uint16_t type = 0;
+ mrp_msg_value_t value;
+ size_t size;
+
+ std::string property_name;
+
+ DebugOut()<<"Received a message from Murphy!"<<endl;
+
+ if (!mrp_msg_iterate(msg, &cursor, &tag, &type, &value, &size))
+ return;
+
+ if (tag == 1 && type == MRP_MSG_FIELD_STRING)
+ property_name = value.str;
+
+ if (!mrp_msg_iterate(msg, &cursor, &tag, &type, &value, &size))
+ return;
+
+ if (tag != 2)
+ return;
+
+ DebugOut() << "Property '" << property_name << "' with value: " <<endl;
+
+ bool hasProp = contains(VehicleProperty::capabilities(), property_name);
+
+ stringstream val;
+
+ switch (type)
+ {
+ case MRP_MSG_FIELD_STRING:
+ {
+ val << value.str;
+ if (!hasProp)
+ {
+ VehicleProperty::registerProperty(property_name,
+ [property_name](){return new StringPropertyType(property_name, "");});
+ }
+
+ DebugOut() << "string:" << value.str << std::endl;
+ break;
+ }
+ case MRP_MSG_FIELD_DOUBLE:
+ {
+ val << value.dbl;
+
+ if (!hasProp)
+ {
+ VehicleProperty::registerProperty(property_name,
+ [property_name](){return new BasicPropertyType<double>(property_name, 0);});
+ }
+
+ DebugOut() << "double:" << value.dbl << std::endl;
+ break;
+ }
+ case MRP_MSG_FIELD_BOOL:
+ {
+ val << value.bln;
+
+ if (!hasProp)
+ {
+ VehicleProperty::registerProperty(property_name,
+ [property_name](){return new BasicPropertyType<bool>(property_name, FALSE);});
+ }
+
+ DebugOut() << "boolean:" << value.bln << std::endl;
+ break;
+ }
+ case MRP_MSG_FIELD_UINT32:
+ {
+ val << value.u32;
+
+ if (!hasProp)
+ {
+ VehicleProperty::registerProperty(property_name,
+ [property_name](){return new BasicPropertyType<uint32_t>(property_name, 0);});
+ }
+
+ DebugOut() << "uint32:" << value.u32 << std::endl;
+ break;
+ }
+ case MRP_MSG_FIELD_UINT16:
+ {
+ val << value.u16;
+
+ if (!hasProp)
+ {
+ VehicleProperty::registerProperty(property_name,
+ [property_name](){return new BasicPropertyType<uint16_t>(property_name, 0);});
+ }
+
+ DebugOut() << "uint16:" << value.u16 << std::endl;
+
+ break;
+ }
+ case MRP_MSG_FIELD_INT32:
+ {
+ val << value.s32;
+
+ if (!hasProp)
+ {
+ VehicleProperty::registerProperty(property_name,
+ [property_name](){return new BasicPropertyType<int32_t>(property_name, 0);});
+ }
+
+ DebugOut() << "int32:" << value.s32 << std::endl;
+ break;
+ }
+ case MRP_MSG_FIELD_INT16:
+ {
+ val << value.s16;
+
+ if (!hasProp)
+ {
+ VehicleProperty::registerProperty(property_name,
+ [property_name](){return new BasicPropertyType<int16_t>(property_name, 0);});
+ }
+
+ DebugOut() << "int16:" << value.s16 << std::endl;
+ break;
+ }
+ default:
+ DebugOut()<<"Unknown type"<<endl;
+ }
+
+ AbstractPropertyType* prop = VehicleProperty::getPropertyTypeForPropertyNameValue(property_name);
+
+ prop->fromString(val.str());
+ s->processValue(property_name, prop);
+}
+
+static void recv_msg(mrp_transport_t *transp, mrp_msg_t *msg, void *user_data)
+{
+ return recvfrom_msg(transp, msg, NULL, 0, user_data);
+}
+
+static void closed_evt(mrp_transport_t *t, int error, void *user_data)
+{
+ /* TODO: should process the error somehow */
+
+ MurphySource *s = (MurphySource *) user_data;
+
+ s->setState(MRP_PROCESS_STATE_NOT_READY);
+ s->setConnected(FALSE);
+}
+
+
+void MurphySource::setConnected(bool connected)
+{
+ m_connected = connected;
+}
+
+
+int MurphySource::connectToMurphy()
+{
+ mrp_sockaddr_t addr;
+ socklen_t alen;
+ int flags = MRP_TRANSPORT_REUSEADDR | MRP_TRANSPORT_MODE_MSG;
+ static mrp_transport_evt_t evt;
+ const char *atype;
+
+ evt.recvmsg = recv_msg;
+ evt.recvmsgfrom = recvfrom_msg;
+ evt.closed = closed_evt;
+
+ if (m_ml == NULL || m_address.empty())
+ return -1;
+
+ if (m_connected == TRUE)
+ return -1;
+
+ alen = mrp_transport_resolve(NULL, m_address.c_str(), &addr, sizeof(addr), &atype);
+
+ if (alen <= 0)
+ {
+ debugOut("Failed to resolve address");
+ return -1;
+ }
+
+ m_tport = mrp_transport_create(m_ml, atype, &evt, this, flags);
+
+ if (!m_tport)
+ {
+ debugOut("Can't create a Murphy transport");
+ return -1;
+ }
+
+ if (mrp_transport_connect(m_tport, &addr, alen) == 0)
+ {
+ mrp_transport_destroy(m_tport);
+ m_tport = NULL;
+ debugOut("Failed to connect to Murphy");
+ return -1;
+ }
+
+ setConnected(true);
+
+ return 0;
+}
+
+PropertyInfo MurphySource::getPropertyInfo(const VehicleProperty::Property &property)
+{
+ Zone::ZoneList zones;
+ zones.push_back(murphyProperties[property]->zone);
+
+ return PropertyInfo(0, zones);
+}
+
+
+MurphySource::MurphySource(AbstractRoutingEngine *re, map<string, string> config) : AbstractSource(re, config)
+{
+ m_source = this;
+ m_re = re;
+ m_connected = false;
+
+ // main loop integration
+
+/*#ifdef USE_QT_CORE
+ m_ml = mrp_mainloop_qt_get();
+ debugOut("Murphy plugin initialized using QT mainloop!");
+#else*/
+ GMainLoop *g_ml = g_main_loop_new(NULL, TRUE);
+ m_ml = mrp_mainloop_glib_get(g_ml);
+ debugOut("Murphy plugin initialized using glib mainloop!");
+//#endif
+
+ setConfiguration(config);
+}
+
+MurphySource::~MurphySource()
+{
+ mrp_process_set_state("ambd", MRP_PROCESS_STATE_NOT_READY);
+ mrp_transport_destroy(m_tport);
+ mrp_mainloop_unregister(m_ml);
+
+ map<string, AbstractPropertyType *>::iterator i;
+
+ for (i = murphyProperties.begin(); i != murphyProperties.end(); i++)
+ {
+ // TODO: unregister VehicleProperty (*i).first
+
+ delete (*i).second;
+ }
+}
+
+void MurphySource::setState(mrp_process_state_t state)
+{
+ m_state = state;
+}
+
+mrp_process_state_t MurphySource::getState()
+{
+ return m_state;
+}
+
+static void murphy_watch(const char *id, mrp_process_state_t state, void *user_data)
+{
+ MurphySource *s = (MurphySource *) user_data;
+
+ debugOut("murphy process watch event");
+
+ if (strcmp(id, "murphy-amb") != 0)
+ return;
+
+ printf("murphyd state changed to %s\n",
+ state == MRP_PROCESS_STATE_READY ? "ready" : "not ready");
+
+ if (state == MRP_PROCESS_STATE_NOT_READY &&
+ s->getState() == MRP_PROCESS_STATE_READY)
+ {
+ DebugOut()<<"lost connection to murphyd"<<endl;
+ }
+
+ else if (state == MRP_PROCESS_STATE_READY)
+ {
+ /* start connecting if needed */
+ s->connectToMurphy();
+ }
+
+ s->setState(state);
+}
+
+void MurphySource::readyToConnect(mrp_mainloop_t *ml)
+{
+ /* set a watch to follow Murphy status */
+
+ if (mrp_process_set_watch("murphy-amb", ml, murphy_watch, this) < 0)
+ {
+ DebugOut()<<"failed to set a murphy process watch"<<endl;
+ return;
+ }
+
+ mrp_process_set_state("ambd", MRP_PROCESS_STATE_READY);
+
+ /* check if Murphy is running */
+ m_state = mrp_process_query_state("murphy-amb");
+
+ if (m_state == MRP_PROCESS_STATE_READY)
+ connectToMurphy();
+}
+
+
+void MurphySource::setConfiguration(map<string, string> config)
+{
+ string address;
+
+ for (map<string,string>::iterator i=configuration.begin();i!=configuration.end();i++)
+ {
+ if ((*i).first == "address")
+ {
+ address = (*i).second;
+ // cout << "address: " << address << endl;
+
+ // TODO: sanity check
+ m_address = address;
+ }
+ }
+
+ // TODO: read supported values from configuration?
+ m_re->updateSupported(supported(), PropertyList(), this);
+
+ // set up the connection with Murphy
+ if (!m_address.empty())
+ readyToConnect(m_ml);
+}
+
+
+PropertyList MurphySource::supported()
+{
+ // debugOut("> supported");
+
+ PropertyList properties;
+ map<string, AbstractPropertyType *>::iterator i;
+
+ for (i = murphyProperties.begin(); i != murphyProperties.end(); i++)
+ {
+ properties.push_back((*i).first);
+ }
+
+ return properties;
+}
+
+
+int MurphySource::supportedOperations()
+{
+ // debugOut("> supportedOperations");
+ return Get; // | Set;
+ //we really don't support Set
+}
+
+
+void MurphySource::subscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ // debugOut("> subscribeToPropertyChanges");
+}
+
+
+void MurphySource::unsubscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ // debugOut("> unsubscribeToPropertyChanges");
+}
+
+
+void MurphySource::getPropertyAsync(AsyncPropertyReply *reply)
+{
+ // debugOut("> getPropertyAsync");
+
+ if (murphyProperties.find(reply->property) != murphyProperties.end())
+ {
+ AbstractPropertyType *prop = murphyProperties[reply->property];
+ reply->value = prop;
+ reply->success = true;
+ reply->completed(reply);
+ }
+}
+
+
+void MurphySource::getRangePropertyAsync(AsyncRangePropertyReply *reply)
+{
+ // debugOut("> getRangePropertyAsync");
+}
+
+
+AsyncPropertyReply *MurphySource::setProperty(AsyncSetPropertyRequest request)
+{
+ // debugOut("> setProperty");
+
+ processValue(request.property, request.value);
+
+ AsyncPropertyReply* reply = new AsyncPropertyReply(request);
+ reply->success = true;
+ reply->completed(reply);
+ return reply;
+}
+
+#if 1
+extern "C" void create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ new MurphySource(routingengine, config);
+}
+#endif
diff --git a/plugins/murphyplugin/murphysource.h b/plugins/murphyplugin/murphysource.h
new file mode 100644
index 00000000..6ed5519f
--- /dev/null
+++ b/plugins/murphyplugin/murphysource.h
@@ -0,0 +1,90 @@
+
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef MURPHYSOURCE_H
+#define MURPHYSOURCE_H
+
+#include <murphy/common.h>
+#include <murphy/common/process.h>
+
+#include <abstractsource.h>
+#include <string>
+
+// #include <vehicleproperty.h>
+// #include <abstractpropertytype.h>
+
+using namespace std;
+
+class MurphySource : public AbstractSource
+{
+
+public:
+ MurphySource(AbstractRoutingEngine* re, map<string, string> config);
+ ~MurphySource();
+
+ const string uuid() { return "murphy"; }
+ void getPropertyAsync(AsyncPropertyReply *reply);
+ void getRangePropertyAsync(AsyncRangePropertyReply *reply);
+ AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request);
+ void subscribeToPropertyChanges(VehicleProperty::Property property);
+ void unsubscribeToPropertyChanges(VehicleProperty::Property property);
+ PropertyList supported();
+
+ int supportedOperations();
+
+ void supportedChanged(const PropertyList &) {}
+
+ void processValue(string propertyName, AbstractPropertyType *value);
+
+ bool hasProperty(string propertyName);
+
+ void setState(mrp_process_state_t state);
+ mrp_process_state_t getState();
+
+ void setConnected(bool connected);
+
+ int connectToMurphy();
+
+ PropertyInfo getPropertyInfo(const VehicleProperty::Property &property);
+
+private:
+ void checkSubscriptions();
+ void setConfiguration(map<string, string> config);
+ void readyToConnect(mrp_mainloop_t *ml);
+
+ PropertyList m_supportedProperties;
+
+ MurphySource *m_source;
+ AbstractRoutingEngine *m_re;
+
+ // known properties
+
+ map<string, AbstractPropertyType *> murphyProperties;
+
+ // murphy integration
+
+ mrp_mainloop_t *m_ml;
+ mrp_transport_t *m_tport;
+ string m_address; // transport address
+ mrp_process_state_t m_state;
+ bool m_connected;
+};
+
+#endif // MURPHYSOURCE_H
diff --git a/plugins/obd2plugin/CMakeLists.txt b/plugins/obd2plugin/CMakeLists.txt
new file mode 100644
index 00000000..807796b4
--- /dev/null
+++ b/plugins/obd2plugin/CMakeLists.txt
@@ -0,0 +1,25 @@
+if(obd2_plugin)
+
+include(CheckIncludeFiles)
+
+pkg_check_modules(gio REQUIRED gio-2.0)
+pkg_check_modules(gio-unix REQUIRED gio-unix-2.0)
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${gio_INCLUDE_DIRS} ${gio-unix_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/plugins/common)
+
+set(obd2sourceplugin_headers obd2source.h obdlib.h obdpid.h)
+set(obd2sourceplugin_sources obd2source.cpp obdlib.cpp obdpid.cpp)
+add_library(obd2sourceplugin MODULE ${obd2sourceplugin_sources})
+set_target_properties(obd2sourceplugin PROPERTIES PREFIX "")
+target_link_libraries(obd2sourceplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common ${link_libraries} ${gio_LIBRARIES} ${gio-unix_LIBRARIES} )
+
+install(TARGETS obd2sourceplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_BINARY_DIR}/obd2.README.md @ONLY)
+
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/obd2.README.md DESTINATION ${DOC_INSTALL_DIR}/plugins)
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/obd2.in.json ${CMAKE_CURRENT_BINARY_DIR}/obd2 @ONLY)
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/obd2 DESTINATION ${PLUGIN_SEGMENT_INSTALL_PATH})
+
+endif(obd2_plugin)
diff --git a/plugins/obd2plugin/README b/plugins/obd2plugin/README
new file mode 100644
index 00000000..c8bdf2ed
--- /dev/null
+++ b/plugins/obd2plugin/README
@@ -0,0 +1,56 @@
+# OBD-II Source Plugin {#obd2_plugin}
+Version: @PROJECT_VERSION@
+
+The OBD-II Source plugin uses ELM compatible scantools to get vehicle information.
+It is known to work with a number of commercial scantools including:
+
+OBDLink MX
+OBDLink S
+OBDPro USB
+
+To use the OBD-II Source plugin, add the following config to your /etc/ambd/config:
+
+~~~~~~~~~~~~~{.json}
+{
+ "name" : "OBD2Source",
+ "path" : "@PLUGIN_INSTALL_PATH@/obd2sourceplugin.so",
+ "device" : "/dev/ttyUSB0",
+ "baud" : "9600",
+ "bluetoothAdapter" : ""
+}
+~~~~~~~~~~~~~
+
+## Configuration Key Definitions:
+
+"name"
+name of plugin. This key is not used by the plugin at this moment.
+
+"path"
+path to plugin on the filesystem.
+
+"device"
+OBD-II Scantool device. This is usually a serial device. For bluetooth devices, use the bluetooth address for example:
+"00:00:11:aa:bb:cc".
+
+"baud"
+baud rate for OBD-II scantool. OBDLink *-style scantool usually default to 115200. Refer to your scantool
+docutmentation for the correct baud rate. Note also that some bluetooth scantools, like the OBDLink MX have automatic baud selection and will ignore this value.
+
+"bluetoothAdapter"
+Hardware address of the bluetooth adapter to use. If value is blank (ie "bluetoothAdapter" : ""), the system default
+adapter will be used. The bluetoothAdapter key is only used if the "device" key is also set to a bluetooth device address.
+
+
+## Performance
+
+Performance will vary with the scantool and the vehicle. Here are the current performance numbers per tested scantool
+using the ECUSim2000 from scantool.net:
+
+scantool - properties/second = (pids/s) - baud
+
+OBDLink MX - 120 pids/s - N/A (varies with bluetooth radio)
+OBDLink S - 100 pids/s - 115200
+OBDPro USB - 43 pids/s - 9600
+
+
+
diff --git a/plugins/obd2plugin/asyncqueuewatcher.cpp b/plugins/obd2plugin/asyncqueuewatcher.cpp
new file mode 100644
index 00000000..c4e43234
--- /dev/null
+++ b/plugins/obd2plugin/asyncqueuewatcher.cpp
@@ -0,0 +1,89 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "asyncqueuewatcher.h"
+
+#include <functional>
+
+struct Source: public GSource {
+ AsyncQueueWatcher* queueWatcher;
+};
+
+gboolean prepare(GSource* source, gint *timeout)
+{
+ *timeout = 0;
+ Source* s = static_cast<Source*>(source);
+ int size = g_async_queue_length (s->queueWatcher->queue);
+ return (size > 0);
+}
+
+gboolean check(GSource *source)
+{
+ Source* s = static_cast<Source*>(source);
+ int size = g_async_queue_length (s->queueWatcher->queue);
+ return (size > 0);
+}
+
+gboolean dispatch(GSource* source, GSourceFunc c, gpointer u)
+{
+ Source* s = static_cast<Source*>(source);
+ int size = g_async_queue_length (s->queueWatcher->queue);
+ gpointer item = g_async_queue_try_pop (s->queueWatcher->queue);
+
+ if (item == NULL)
+ {
+ return true;
+ }
+
+ if (s->queueWatcher->callback == NULL)
+ {
+ return false;
+ }
+
+ s->queueWatcher->callback(item, s->queueWatcher->userData);
+ return true;
+}
+
+void finalize(GSource *source)
+{
+
+}
+
+
+AsyncQueueWatcher::AsyncQueueWatcher(GAsyncQueue *q, AsyncQueueWatcherCallback cb, void *data)
+{
+ using namespace std::placeholders;
+
+ queue = g_async_queue_ref(q);
+ userData = data;
+ callback = cb;
+
+ auto foo1 = std::bind(prepare, _1, _2);
+
+ GSourceFuncs vtable;
+ vtable.prepare = prepare;
+ vtable.check = check;
+ vtable.dispatch = dispatch;
+ vtable.finalize = finalize;
+
+ Source* src = static_cast<Source*>(g_source_new(&vtable,sizeof(Source)));
+ src->queueWatcher = this;
+ g_source_attach(src,NULL);
+ g_source_set_can_recurse(src, TRUE);
+
+}
diff --git a/plugins/obd2plugin/asyncqueuewatcher.h b/plugins/obd2plugin/asyncqueuewatcher.h
new file mode 100644
index 00000000..326b9309
--- /dev/null
+++ b/plugins/obd2plugin/asyncqueuewatcher.h
@@ -0,0 +1,42 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef ASYNCQUEUEWATCHER_H_
+#define ASYNCQUEUEWATCHER_H_
+
+#include <glib.h>
+
+typedef void (*AsyncQueueWatcherCallback) (gpointer, void* data);
+
+class AsyncQueueWatcher
+{
+public:
+ AsyncQueueWatcher(GAsyncQueue* q, AsyncQueueWatcherCallback cb, void* data);
+
+ //static bool prepare(GSource *source, int *timeout, GAsyncQueue *queue);
+ //bool check(GSource *source);
+ //bool dispatch(GSource *source, GSourceFunc callback, gpointer user_data);
+ //void finalize(GSource* source);
+
+ int id;
+ GAsyncQueue* queue;
+ AsyncQueueWatcherCallback callback;
+ void* userData;
+};
+
+
+#endif
diff --git a/plugins/obd2plugin/obd2.in.json b/plugins/obd2plugin/obd2.in.json
new file mode 100644
index 00000000..06c84506
--- /dev/null
+++ b/plugins/obd2plugin/obd2.in.json
@@ -0,0 +1,7 @@
+{
+ "name" : "Obd2",
+ "path" : "@PLUGIN_INSTALL_PATH@/obd2sourceplugin.so",
+ "device" : "/dev/ttyUSB0",
+ "baud" : "115200",
+ "enabled" : false
+}
diff --git a/plugins/obd2plugin/obd2source.conf b/plugins/obd2plugin/obd2source.conf
new file mode 100644
index 00000000..284dd095
--- /dev/null
+++ b/plugins/obd2plugin/obd2source.conf
@@ -0,0 +1 @@
+{"sinks" : [ { "ip":"127.0.0.1","port":23000 } ] }
diff --git a/plugins/obd2plugin/obd2source.cpp b/plugins/obd2plugin/obd2source.cpp
new file mode 100644
index 00000000..35f9b38f
--- /dev/null
+++ b/plugins/obd2plugin/obd2source.cpp
@@ -0,0 +1,836 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "obd2source.h"
+#include <iostream>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <glib.h>
+#include <sstream>
+//#include <json-glib/json-glib.h>
+#include <listplusplus.h>
+#include "debugout.h"
+#include "bluetooth.hpp"
+#include "timestamp.h"
+#include "bluetooth5.h"
+#include "superptr.hpp"
+
+#ifdef USE_BLUEZ5
+Bluetooth5 bt;
+#endif
+
+#define __SMALLFILE__ std::string(__FILE__).substr(std::string(__FILE__).rfind("/")+1)
+AbstractRoutingEngine *m_re;
+
+//std::list<ObdPid*> Obd2Amb::supportedPidsList;
+Obd2Amb *obd2AmbInstance = new Obd2Amb;
+VehicleProperty::Property Obd2Connected = "Obd2Connected";
+int calledPersecond = 0;
+
+bool sendElmCommand(obdLib *obd,std::string command)
+{
+ std::vector<unsigned char> replyVector;
+ std::string reply;
+ obd->sendObdRequestString(command.append("\r").c_str(),command.length()+1,&replyVector,10,3);
+ for (unsigned int i=0;i<replyVector.size();i++)
+ {
+ reply += replyVector[i];
+ }
+ if (reply.find("OK") == -1)
+ {
+ //No OK reply found
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+
+}
+
+bool beginsWith(std::string a, std::string b)
+{
+ return (a.compare(0, b.length(), b) == 0);
+}
+
+bool connect(obdLib* obd, std::string device, std::string strbaud, int fd = -1)
+{
+ //printf("First: %s\nSecond: %s\n",req->arg.substr(0,req->arg.find(':')).c_str(),req->arg.substr(req->arg.find(':')+1).c_str());
+ std::string port = device;
+ DebugOut() << "Obd2Source::Connect()" << device << strbaud << endl;
+ int baud = boost::lexical_cast<int>(strbaud);
+
+ if(fd != -1)
+ {
+ if(obd->openPort(fd, baud) == -1)
+ return false;
+ }
+ else
+ {
+ if(obd->openPort(port.c_str(),baud) == -1)
+ return false;
+ }
+
+ ObdPid::ByteArray replyVector;
+ std::string reply;
+ obd->sendObdRequestString("ATZ\r",4,&replyVector,500,3);
+ for (unsigned int i=0;i<replyVector.size();i++)
+ {
+ reply += replyVector[i];
+ }
+ if (reply.find("ELM") == -1)
+ {
+ //No reply found
+ //printf("Error!\n");
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error resetting ELM"<<endl;
+ return false;
+ }
+ else
+ {
+ //printf("Reply to reset: %s\n",reply.c_str());
+ }
+ if (!sendElmCommand(obd,"ATSP0"))
+ {
+ //printf("Error sending echo\n");
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error setting auto protocol"<<endl;
+ return false;
+ }
+ if (!sendElmCommand(obd,"ATE0"))
+ {
+ //printf("Error sending echo\n");
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error turning off echo"<<endl;
+ return false;
+ }
+ if (!sendElmCommand(obd,"ATH0"))
+ {
+ //printf("Error sending headers off\n");
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error turning off headers"<<endl;
+ return false;
+ }
+ if (!sendElmCommand(obd,"ATL0"))
+ {
+ //printf("Error turning linefeeds off\n");
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error turning off linefeeds"<<endl;
+ return false;
+ }
+ obd->sendObdRequestString("010C1\r", 6, &replyVector, 500, 5);
+
+ return true;
+}
+
+void threadLoop(gpointer data)
+{
+ GAsyncQueue *privCommandQueue = g_async_queue_ref(((OBD2Source*)data)->commandQueue);
+ GAsyncQueue *privResponseQueue = g_async_queue_ref(((OBD2Source*)data)->responseQueue);
+ GAsyncQueue *privSingleShotQueue = g_async_queue_ref(((OBD2Source*)data)->singleShotQueue);
+ GAsyncQueue *privSubscriptionAddQueue = g_async_queue_ref(((OBD2Source*)data)->subscriptionAddQueue);
+ GAsyncQueue *privSubscriptionRemoveQueue = g_async_queue_ref(((OBD2Source*)data)->subscriptionRemoveQueue);
+ GAsyncQueue *privStatusQueue = g_async_queue_ref(((OBD2Source*)data)->statusQueue);
+
+ obdLib *obd = new obdLib();
+ OBD2Source *source = (OBD2Source*)data;
+
+ obd->setCommsCallback([](const char* mssg, void* data) { DebugOut(6)<<mssg<<endl; },NULL);
+ obd->setDebugCallback([](const char* mssg, void* data, obdLib::DebugLevel debugLevel) { DebugOut(debugLevel)<<mssg<<endl; },NULL);
+
+ std::list<ObdPid*> reqList;
+ std::list<ObdPid*> repeatReqList;
+ ObdPid::ByteArray replyVector;
+ std::string port;
+ std::string baud;
+ bool connected=false;
+ int emptycount = 0;
+ int timeoutCount = 0;
+ while (source->m_threadLive)
+ {
+ gpointer query = g_async_queue_try_pop(privSingleShotQueue);
+ if (query != nullptr)
+ {
+ //printf("Got request!\n");
+
+ ObdPid *req = (ObdPid*)query;
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Got single shot request: " << req->pid.substr(0,req->pid.length()-1) << ":" << req->property <<endl;
+ repeatReqList.push_back(req);
+ }
+ query = g_async_queue_try_pop(privSubscriptionAddQueue);
+ if (query != nullptr)
+ {
+
+ ObdPid *req = (ObdPid*)query;
+ //DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Got subscription request for "<<req->req<<endl;
+ reqList.push_back(req);
+ }
+ query = g_async_queue_try_pop(privCommandQueue);
+ if (query != nullptr)
+ {
+ //ObdPid *req = (ObdPid*)query;
+ CommandRequest *req = (CommandRequest*)query;
+ //commandMap[req->req] = req->arg;
+ //printf("Command: %s\n",req->req.c_str());
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Command:" << req->req << endl;
+ if (req->req == "connectifnot")
+ {
+ if (!connected)
+ {
+ if (source->m_isBluetooth)
+ {
+#ifdef USE_BLUEZ5
+ bt.getDeviceForAddress(source->m_btDeviceAddress, [&obd, baud, &privStatusQueue, &connected](int fd)
+ {
+ connected = connect(obd, "", baud, fd);
+
+ if(connected)
+ {
+ StatusMessage *statusreq = new StatusMessage();
+ statusreq->statusStr = "connected";
+ g_async_queue_push(privStatusQueue, statusreq);
+ }
+ else
+ {
+ StatusMessage *statusreq = new StatusMessage();
+ statusreq->statusStr = "disconnected";
+ g_async_queue_push(privStatusQueue, statusreq);
+ }
+ });
+#else
+ BluetoothDevice bt;
+ std::string tempPort = bt.getDeviceForAddress(source->m_btDeviceAddress, source->m_btAdapterAddress);
+ if(tempPort != "")
+ {
+ DebugOut(3) << "Using bluetooth device \"" << source->m_btDeviceAddress << "\" bound to: " << tempPort << endl;
+ port = tempPort;
+ }
+ else
+ {
+ DebugOut(DebugOut::Error) << "Error creating bluetooth device" << endl;
+ continue;
+ }
+
+ connected = connect(obd, port, baud);
+
+ if(connected)
+ {
+ StatusMessage *statusreq = new StatusMessage();
+ statusreq->statusStr = "connected";
+ g_async_queue_push(privStatusQueue, statusreq);
+ }
+ else
+ {
+ StatusMessage *statusreq = new StatusMessage();
+ statusreq->statusStr = "disconnected";
+ g_async_queue_push(privStatusQueue, statusreq);
+ }
+
+#endif
+ }
+ else
+ {
+
+ connected = connect(obd, port, baud);
+
+ if(connected)
+ {
+ StatusMessage *statusreq = new StatusMessage();
+ statusreq->statusStr = "connected";
+ g_async_queue_push(privStatusQueue, statusreq);
+ }
+ else
+ {
+ StatusMessage *statusreq = new StatusMessage();
+ statusreq->statusStr = "disconnected";
+ g_async_queue_push(privStatusQueue, statusreq);
+ }
+ }
+ }
+ }
+ else if (req->req == "setportandbaud")
+ {
+ port = req->arglist[0];
+ baud = req->arglist[1];
+ }
+ else if (req->req == "disconnect")
+ {
+ DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "Using queued disconnect" << (ulong)req << endl;
+ obd->closePort();
+#ifdef USE_BLUEZ5
+ bt.disconnect();
+#else
+ BluetoothDevice bt;
+ bt.disconnect(source->m_btDeviceAddress, source->m_btAdapterAddress);
+#endif
+ connected = false;
+ StatusMessage *statusreq = new StatusMessage();
+ statusreq->statusStr = "disconnected";
+ g_async_queue_push(privStatusQueue, statusreq);
+ }
+ delete req;
+ }
+ query = g_async_queue_try_pop(privSubscriptionRemoveQueue);
+ if (query != nullptr)
+ {
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Got unsubscription request"<<endl;
+ ObdPid *req = (ObdPid*)query;
+ for (std::list<ObdPid*>::iterator i=reqList.begin();i!= reqList.end();i++)
+ {
+ if ((*i)->property == req->property)
+ {
+ reqList.erase(i);
+ delete (*i);
+ i--;
+ if (reqList.size() == 0)
+ {
+ break;
+ }
+ }
+ }
+ //reqList.push_back(req->req);
+ delete req;
+ }
+ if (reqList.size() > 0 && !connected)
+ {
+ /*CommandRequest *req = new CommandRequest();
+ req->req = "connect";
+ req->arglist.push_back(port);
+ req->arglist.push_back(baud);
+ g_async_queue_push(privCommandQueue,req);
+ continue;*/
+ }
+ else if (reqList.size() == 0 && connected)
+ {
+ emptycount++;
+ if (emptycount < 1000)
+ {
+ usleep(10000);
+ continue;
+ }
+ emptycount = 0;
+ CommandRequest *req = new CommandRequest();
+ req->req = "disconnect";
+ g_async_queue_push(privCommandQueue,req);
+ continue;
+ }
+ if (!connected)
+ {
+ usleep(10000);
+ continue;
+ }
+ for (std::list<ObdPid*>::iterator i=reqList.begin();i!= reqList.end();i++)
+ {
+ repeatReqList.push_back(*i);
+ }
+ int badloop = 0;
+ for (std::list<ObdPid*>::iterator i=repeatReqList.begin();i!= repeatReqList.end();i++)
+ {
+ DebugOut(10) << __SMALLFILE__ << ":" << __LINE__ << "Requesting pid: " << (*i)->pid.substr(0,(*i)->pid.length()-1) << (*i)->property << endl;
+ if (source->m_blacklistPidCountMap.find((*i)->pid) != source->m_blacklistPidCountMap.end())
+ {
+ //Don't erase the pid, just skip over it.
+ int count = (*source->m_blacklistPidCountMap.find((*i)->pid)).second;
+ if (count > 10)
+ {
+ continue;
+ }
+ }
+ badloop++;
+
+ bool result = false;
+
+ if(beginsWith((*i)->pid,"AT") || beginsWith((*i)->pid, "ST"))
+ {
+ result = obd->sendObdRequestString((*i)->pid.c_str(),(*i)->pid.length(),&replyVector);
+ }
+ else result = obd->sendObdRequestString((*i)->pid.c_str(),(*i)->pid.length(),&replyVector,5,3);
+
+ if (!result)
+ {
+ //This only happens during a error with the com port. Close it and re-open it later.
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Unable to send request:" << (*i)->pid.substr(0,(*i)->pid.length()-1) << endl;
+ if (obd->lastError() == obdLib::NODATA)
+ {
+ DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "OBDLib::NODATA for pid" << (*i)->pid.substr(0,(*i)->pid.length()-1) << " expected property: " << (*i)->property << endl;
+ if (source->m_blacklistPidCountMap.find((*i)->pid) != source->m_blacklistPidCountMap.end())
+ {
+ //pid value i not yet in the list.
+ int count = (*source->m_blacklistPidCountMap.find((*i)->pid)).second;
+ if (count > 10)
+ {
+
+ }
+ source->m_blacklistPidCountMap.erase(source->m_blacklistPidCountMap.find((*i)->pid));
+ source->m_blacklistPidCountMap.insert(pair<std::string,int>((*i)->pid,count));
+ }
+ else
+ {
+ source->m_blacklistPidCountMap.insert(pair<std::string,int>((*i)->pid,1));
+ }
+ StatusMessage *statusreq = new StatusMessage();
+ statusreq->statusStr = "error:nodata";
+ statusreq->property = (*i)->property;
+ g_async_queue_push(privStatusQueue,statusreq);
+ continue;
+ }
+ else if (obd->lastError() == obdLib::TIMEOUT)
+ {
+ timeoutCount++;
+ if (timeoutCount < 2)
+ {
+ DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "OBDLib::TIMEOUT for pid" << (*i)->pid << endl;
+ StatusMessage *statusreq = new StatusMessage();
+ statusreq->statusStr = "error:timeout";
+ g_async_queue_push(privStatusQueue,statusreq);
+ continue;
+ }
+ }
+ else
+ {
+ DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "OBD Other error:" << obd->lastError() << endl;
+ }
+
+ CommandRequest *req = new CommandRequest();
+ DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "Queuing up a disconnect" << (ulong)req << endl;
+ req->req = "disconnect";
+ g_async_queue_push(privCommandQueue,req);
+ i = repeatReqList.end();
+ i--;
+ continue;
+ }
+ if (source->m_blacklistPidCountMap.find((*i)->pid) != source->m_blacklistPidCountMap.end())
+ {
+ //If we get the pid response, then we want to clear out the blacklist list.
+ source->m_blacklistPidCountMap.erase(source->m_blacklistPidCountMap.find((*i)->pid));
+ }
+ timeoutCount = 0;
+ //ObdPid *pid = ObdPid::pidFromReply(replyVector);
+ ObdPid *pid = obd2AmbInstance->createPidFromReply(replyVector);
+ if (!pid)
+ {
+ //Invalid reply
+ DebugOut() << "Invalid reply"<<endl;
+ continue;
+ }
+ else
+ {
+ DebugOut(11) << __SMALLFILE__ <<":"<< __LINE__ << "Reply recieved and queued for:" << (*i)->pid.substr(0,(*i)->pid.length()-1) << endl;
+ std::string repstr;
+ for (int i=0;i<replyVector.size();i++)
+ {
+ if (replyVector[i] != 13)
+ {
+ repstr += (char)replyVector[i];
+ }
+ //DebugOut(11) << replyVector[i];
+ }
+ DebugOut(11) << "Reply:" << repstr << endl;
+ }
+ g_async_queue_push(privResponseQueue,pid);
+ }
+ if (badloop == 0)
+ {
+ //We had zero non-blacklisted events. Pause for a moment here to keep from burning CPU.
+ //usleep(10000);
+ }
+ repeatReqList.clear();
+
+ }
+ if (connected)
+ {
+ obd->closePort();
+ }
+}
+static int updateProperties( gpointer data)
+{
+
+ OBD2Source* src = (OBD2Source*)data;
+
+ while (gpointer retval = g_async_queue_try_pop(src->statusQueue))
+ {
+ StatusMessage *reply = (StatusMessage*)retval;
+ if (reply->statusStr == "disconnected")
+ {
+ src->obd2Connected.setValue(false);
+ src->updateProperty(&src->obd2Connected);
+ }
+ else if (reply->statusStr == "connected")
+ {
+ src->obd2Connected.setValue(true);
+ src->updateProperty(&src->obd2Connected);
+ }
+ else if (reply->statusStr == "error:nodata" || reply->statusStr == "error:timeout")
+ {
+ AsyncPropertyReply* srcReply = nullptr;
+
+ for(auto i : src->propertyReplyList)
+ {
+ if(i->property == reply->property)
+ {
+ srcReply = i;
+ break;
+ }
+ }
+
+ if (srcReply)
+ {
+ DebugOut(5) << __SMALLFILE__ <<":"<< __LINE__ << reply->statusStr << " on property:" << reply->property << endl;
+ srcReply->success = false;
+ srcReply->error = AsyncPropertyReply::InvalidOperation;
+ srcReply->completed(srcReply);
+ removeOne(&src->propertyReplyList, srcReply);
+
+ /// Remove support for this pid:
+ PropertyList list = src->supported();
+ removeOne(&list, reply->property);
+ src->setSupported(list);
+ }
+ else
+ {
+ DebugOut(5) << __SMALLFILE__ <<":"<< __LINE__ << reply->statusStr << " on unrequested property:" << reply->property << endl;
+ }
+ }
+ delete reply;
+ }
+ while(gpointer retval = g_async_queue_try_pop(src->responseQueue))
+ {
+ ObdPid *reply = (ObdPid*)retval;
+
+ auto value = amb::make_unique(VehicleProperty::getPropertyTypeForPropertyNameValue(reply->property, reply->value));
+ value->priority = AbstractPropertyType::Instant;
+ src->updateProperty(value.get());
+ }
+
+ return true;
+}
+
+void OBD2Source::updateProperty(AbstractPropertyType* value)
+{
+ VehicleProperty::Property property = value->name;
+ AsyncPropertyReply* reply = nullptr;
+
+ DebugOut() << "updateProperty for: " << property << "value: " << value->toString() << endl;
+
+ for(auto i : propertyReplyList)
+ {
+ if(i->property == property)
+ {
+ reply = i;
+ break;
+ }
+ }
+
+ if (reply)
+ {
+
+ reply->value = value;
+ reply->success = true;
+ try {
+ reply->completed(reply);
+ }catch(...)
+ {
+ DebugOut(DebugOut::Error)<<"failed to call reply completed callback"<<endl;
+ }
+
+ removeOne(&propertyReplyList, reply);
+ }
+
+ if(oldValueMap.find(property) != oldValueMap.end())
+ {
+ AbstractPropertyType* old = oldValueMap[property];
+
+ if((*old) == (*value))
+ {
+ DebugOut() << "old value is same as new for: " << value->name << endl;
+ return;
+ }
+
+ delete old;
+ oldValueMap.erase(property);
+ }
+ else
+ {
+ oldValueMap[property] = value->copy();
+ }
+
+ DebugOut() << "updateProperty for: " << property << "value: " << value->toString() << endl;
+ m_re->updateProperty(value, uuid());
+
+}
+
+void OBD2Source::setSupported(PropertyList list)
+{
+ m_supportedProperties = list;
+ m_re->updateSupported(list,PropertyList(),this);
+}
+/*void OBD2Source::propertySignal(VehicleProperty::Property property,boost::any value)
+{
+}
+void OBD2Source::checkProperty()
+{
+}*/
+void OBD2Source::setConfiguration(map<string, string> config)
+{
+ // //Config has been passed, let's start stuff up.
+ configuration = config;
+
+ //Default values
+ std::string port = "/dev/ttyUSB0";
+ std::string baud = "115200";
+ std::string btadapter = "";
+ m_isBluetooth = false;
+
+ //Try to load config
+ //printf("OBD2Source::setConfiguration\n");
+ for (map<string,string>::iterator i=configuration.begin();i!=configuration.end();i++)
+ {
+ //printf("Incoming setting: %s:%s\n",(*i).first.c_str(),(*i).second.c_str());
+ DebugOut(5) << __SMALLFILE__ <<":"<< __LINE__ << "Incoming setting:" << (*i).first << ":" << (*i).second << endl;
+ if ((*i).first == "device")
+ {
+ port = (*i).second;
+ }
+ else if ((*i).first == "baud")
+ {
+ if((*i).second != "")
+ baud = (*i).second;
+ }
+
+ else if ((*i).first == "bluetoothAdapter")
+ {
+ btadapter = (*i).second;
+ }
+ }
+
+ if(port.find(":") != string::npos)
+ {
+ m_btDeviceAddress = port;
+ m_btAdapterAddress = btadapter;
+ m_isBluetooth = true;
+ }
+
+ //connect(obd, port, baud);
+ CommandRequest *req = new CommandRequest();
+ req->req = "setportandbaud";
+ req->arglist.push_back(port);
+ req->arglist.push_back(baud);
+ g_async_queue_push(commandQueue, req);
+
+ m_port = port;
+ m_baud = baud;
+ m_gThread = g_thread_new("mythread", (GThreadFunc)&threadLoop, this);
+ g_timeout_add(5, updateProperties, this);
+}
+
+OBD2Source::OBD2Source(AbstractRoutingEngine *re, map<string, string> config)
+ : AbstractSource(re, config), obd2Connected(Obd2Connected,false)
+{
+ bool success = VehicleProperty::registerProperty(Obd2Connected, [](){ return new Obd2ConnectType(Obd2Connected, false); });
+
+ if(!success)
+ {
+ ///ERROR!
+ }
+
+ clientConnected = false;
+ m_re = re;
+
+ m_threadLive = true;
+ Obd2Amb obd2amb;
+ obd = new obdLib();
+
+ for(auto itr = obd2amb.supportedPidsList.begin(); itr != obd2amb.supportedPidsList.end(); itr++)
+ {
+ m_supportedProperties.push_back((*itr)->property);
+ }
+
+ m_supportedProperties.push_back(Obd2Connected);
+
+ re->updateSupported(supported(), PropertyList(), this);
+
+ statusQueue = g_async_queue_new();
+ commandQueue = g_async_queue_new();
+ subscriptionAddQueue = g_async_queue_new();
+ subscriptionRemoveQueue = g_async_queue_new();
+ responseQueue = g_async_queue_new();
+ singleShotQueue = g_async_queue_new();
+
+ setConfiguration(config);
+}
+OBD2Source::~OBD2Source()
+{
+ DebugOut() << "OBD2Source Destructor called!!!"<<endl;
+ m_threadLive = false;
+ g_thread_join(m_gThread);
+}
+
+PropertyList OBD2Source::supported()
+{
+ return m_supportedProperties;
+}
+
+PropertyInfo OBD2Source::getPropertyInfo(const VehicleProperty::Property &)
+{
+ Zone::ZoneList zones;
+ zones.push_back(0);
+
+ return PropertyInfo(0, zones);
+}
+
+int OBD2Source::supportedOperations()
+{
+ return Get | Set;
+}
+
+extern "C" void create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ new OBD2Source(routingengine, config);
+}
+
+const string OBD2Source::uuid()
+{
+ return "f77af740-f1f8-11e1-aff1-0800200c9a66";
+}
+
+void OBD2Source::subscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ if (property == VehicleProperty::VIN)
+ {
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "VIN subscription requested... but there's no point!"<<endl;
+ }
+ else if (property == VehicleProperty::WMI)
+ {
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "WMI subscription requested... but there's no point!"<<endl;
+ }
+ else
+ {
+ if(!contains(m_supportedProperties, property))
+ {
+ DebugOut(0)<<"obd plugin does not support: "<<property<<endl;
+ return;
+ }
+
+
+ ObdPid *pid = obd2AmbInstance->createPidforProperty(property);
+
+ if(!pid)
+ {
+ DebugOut(DebugOut::Warning) << "We don't support this property: " << property <<endl;
+ return;
+ }
+
+ //If the pid is currently in the blacklist map, erase it. This allows for applications
+ //to "un-blacklist" a pid by re-subscribing to it.
+ if (m_blacklistPidCountMap.find(pid->pid) != m_blacklistPidCountMap.end())
+ {
+ m_blacklistPidCountMap.erase(m_blacklistPidCountMap.find(pid->pid));
+ }
+
+
+ g_async_queue_push(subscriptionAddQueue, pid);
+ CommandRequest *req = new CommandRequest();
+ req->req = "connectifnot";
+ g_async_queue_push(commandQueue, req);
+ }
+}
+
+
+void OBD2Source::unsubscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ if(!contains(m_supportedProperties, property))
+ {
+ DebugOut(0)<<"obd plugin does not support: "<<property<<endl;
+ return;
+ }
+
+ ObdPid *pid = obd2AmbInstance->createPidforProperty(property);
+ g_async_queue_push(subscriptionRemoveQueue,pid);
+}
+
+
+void OBD2Source::getPropertyAsync(AsyncPropertyReply *reply)
+{
+ DebugOut(5) << __SMALLFILE__ <<":"<< __LINE__ << "getPropertyAsync requested for " << reply->property << endl;
+
+ VehicleProperty::Property property = reply->property;
+
+
+ if(!contains(m_supportedProperties, property))
+ {
+ DebugOut(0)<<"obd plugin does not support: "<<property<<endl;
+ return;
+ }
+
+ if(reply->property == Obd2Connected)
+ {
+ reply->success = true;
+ reply->value = &obd2Connected;
+ reply->completed(reply);
+ return;
+ }
+
+ propertyReplyList.push_back(reply);
+ reply->timedout = [this](AsyncPropertyReply* reply)
+ {
+ DebugOut() << "removing "<< reply->property << " from propertyReplyList" << endl;
+ removeOne(&propertyReplyList, reply);
+ };
+
+ ObdPid* requ = obd2AmbInstance->createPidforProperty(property);
+ g_async_queue_push(singleShotQueue,requ);
+ CommandRequest *req = new CommandRequest();
+ req->req = "connectifnot";
+ g_async_queue_push(commandQueue,req);
+}
+
+AsyncPropertyReply *OBD2Source::setProperty(AsyncSetPropertyRequest request )
+{
+ AsyncPropertyReply* reply = new AsyncPropertyReply (request);
+
+ if(request.property == Obd2Connected)
+ {
+ propertyReplyList.push_back(reply);
+ reply->success = true;
+
+ if(request.value->value<bool>() == true)
+ {
+ CommandRequest *req = new CommandRequest();
+ req->req = "connectifnot";
+ g_async_queue_push(commandQueue, req);
+ }
+ else
+ {
+ CommandRequest *req = new CommandRequest();
+ req->req = "disconnect";
+ g_async_queue_push(commandQueue, req);
+ }
+
+ }
+ else
+ {
+ reply->success = false;
+ try
+ {
+ reply->completed(reply);
+ }
+ catch (...)
+ {
+
+ }
+ }
+
+
+ return reply;
+}
diff --git a/plugins/obd2plugin/obd2source.h b/plugins/obd2plugin/obd2source.h
new file mode 100644
index 00000000..8ca4ed45
--- /dev/null
+++ b/plugins/obd2plugin/obd2source.h
@@ -0,0 +1,202 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef OBD2SOURCE_H
+#define OBD2SOURCE_H
+
+
+
+#include <abstractsource.h>
+#include <string>
+#include <sstream>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <termios.h>
+#include "obdlib.h"
+#include <glib.h>
+
+#include "obdpid.h"
+
+class ObdRequest
+{
+public:
+ VehicleProperty::Property property;
+ std::string req;
+ std::string arg;
+};
+
+
+class CommandRequest
+{
+public:
+ std::string req;
+ std::vector<std::string> arglist;
+};
+class StatusMessage
+{
+public:
+ std::string statusStr;
+ VehicleProperty::Property property;
+};
+class ObdReply
+{
+public:
+ VehicleProperty::Property property;
+ std::string req;
+ std::string reply;
+};
+
+
+
+class Obd2Amb
+{
+public:
+
+ typedef function<std::string (std::string)> ConversionFunction;
+
+ typedef std::vector<unsigned char> ByteArray;
+ Obd2Amb()
+ {
+ supportedPidsList.push_back(new VehicleSpeedPid());
+ supportedPidsList.push_back(new EngineSpeedPid());
+ supportedPidsList.push_back(new MassAirFlowPid());
+ supportedPidsList.push_back(new VinPid());
+ supportedPidsList.push_back(new WmiPid());
+ supportedPidsList.push_back(new FuelConsumptionPid());
+ supportedPidsList.push_back(new EngineCoolantPid());
+ supportedPidsList.push_back(new AirIntakeTemperaturePid());
+ supportedPidsList.push_back(new EngineLoadPid());
+ supportedPidsList.push_back(new ThrottlePositionPid());
+ supportedPidsList.push_back(new BatteryVoltagePid());
+ }
+
+ ~Obd2Amb()
+ {
+ for(auto itr = supportedPidsList.begin(); itr != supportedPidsList.end(); itr++)
+ {
+ delete *itr;
+ }
+ }
+
+ ObdPid* createPidFromReply(ByteArray replyVector)
+ {
+ ByteArray replyVectorClean = ObdPid::cleanup(replyVector);
+ ByteArray replyVectorCompressed = ObdPid::compress(replyVectorClean);
+
+ for(auto itr = supportedPidsList.begin(); itr != supportedPidsList.end(); itr++)
+ {
+ ObdPid* p = *itr;
+
+ if(p->needsCompress())
+ {
+ replyVector = replyVectorCompressed;
+ }
+ else replyVector = replyVectorClean;
+
+ if (!p->tryParse(replyVector))
+ {
+ continue;
+ }
+
+ ObdPid* pid = (*itr)->create();
+ return pid;
+ }
+ return 0;
+ }
+ ObdPid* createPidforProperty(VehicleProperty::Property property)
+ {
+ for(auto itr = supportedPidsList.begin(); itr != supportedPidsList.end(); itr++)
+ {
+ VehicleProperty::Property p = (*itr)->property;
+ if(p == property)
+ {
+ ObdPid* obj = *itr;
+ return obj->create();
+ }
+ }
+ return NULL;
+ }
+
+ std::list<ObdPid*> supportedPidsList;
+};
+
+class OBD2Source : public AbstractSource
+{
+
+public:
+ OBD2Source(AbstractRoutingEngine* re, map<string, string> config);
+ ~OBD2Source();
+ const string uuid();
+ int portHandle;
+ void getPropertyAsync(AsyncPropertyReply *reply);
+ void getRangePropertyAsync(AsyncRangePropertyReply *reply){}
+ AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request);
+ void subscribeToPropertyChanges(VehicleProperty::Property property);
+ void unsubscribeToPropertyChanges(VehicleProperty::Property property);
+ PropertyList supported();
+
+ PropertyInfo getPropertyInfo(const VehicleProperty::Property &property);
+
+ int supportedOperations();
+
+ PropertyList queuedRequests;
+ bool clientConnected;
+ PropertyList activeRequests;
+ void engineSpeed(double speed);
+ void vehicleSpeed(int speed);
+ void mafValue(double maf);
+ void engineCoolantTemp(int temp);
+ PropertyList removeRequests;
+ void setSupported(PropertyList list);
+
+ void supportedChanged(const PropertyList &) {}
+ GAsyncQueue* commandQueue;
+ GAsyncQueue* statusQueue;
+ GAsyncQueue* subscriptionAddQueue;
+ GAsyncQueue* subscriptionRemoveQueue;
+ GAsyncQueue* singleShotQueue;
+ GAsyncQueue* responseQueue;
+ std::list<std::string> m_blacklistPidList;
+ std::map<std::string,int> m_blacklistPidCountMap;
+ void setConfiguration(map<string, string> config);
+ //void randomizeProperties();
+ std::string m_port;
+ std::string m_baud;
+ bool m_isBluetooth;
+ std::string m_btDeviceAddress;
+ std::string m_btAdapterAddress;
+ std::vector<AsyncPropertyReply*> propertyReplyList;
+ void updateProperty(AbstractPropertyType *value);
+ obdLib * obd;
+ bool m_threadLive;
+ GThread *m_gThread;
+
+ typedef BasicPropertyType<bool> Obd2ConnectType;
+ Obd2ConnectType obd2Connected;
+
+private:
+ PropertyList m_supportedProperties;
+ std::map<VehicleProperty::Property, AbstractPropertyType*> oldValueMap;
+ GMutex *threadQueueMutex;
+
+
+};
+
+#endif // OBD2SOURCE_H
diff --git a/plugins/obd2plugin/obdlib.cpp b/plugins/obd2plugin/obdlib.cpp
new file mode 100644
index 00000000..e223ea10
--- /dev/null
+++ b/plugins/obd2plugin/obdlib.cpp
@@ -0,0 +1,606 @@
+/*
+Copyright (C) 2010 by Michael Carpenter (malcom2073) malcom2073@gmail.com
+
+This file is a part of libobd
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "obdlib.h"
+#include <time.h>
+#include <iostream>
+#include <fstream>
+#include <string.h>
+#include <cstdarg>
+#include <unistd.h>
+
+
+void (*debugCallback)(const char *,void*,obdLib::DebugLevel) = NULL;
+void (*commsCallback)(const char *,void*) = NULL;
+void *debugUserData = NULL;
+void *commsUserData = NULL;
+obdLib::obdLib()
+{
+ m_lastError = NONE;
+ debugCallback = 0;
+ commsCallback = 0;
+}
+
+int obdLib::openPort(const char *portName)
+{
+ return openPort(portName,-1);
+}
+
+int obdLib::openPort(const int fd, int baudrate)
+{
+ portHandle = fd;
+ if (portHandle < 0)
+ {
+ debug(obdLib::DEBUG_ERROR, "Error opening device %s", strerror( errno ));
+
+ return -1;
+ }
+
+ debug(obdLib::DEBUG_VERBOSE,"Com Port Opened %i",portHandle);
+ fcntl(portHandle, F_SETFL, 0); //Set it to blocking.
+ //struct termios oldtio;
+ struct termios newtio;
+ //bzero(&newtio,sizeof(newtio));
+ tcgetattr(portHandle, &newtio);
+ long BAUD = B9600;
+ switch (baudrate)
+ {
+ case 38400:
+ BAUD = B38400;
+ break;
+ case 115200:
+ BAUD = B115200;
+ break;
+ case 19200:
+ BAUD = B19200;
+ break;
+ case 9600:
+ BAUD = B9600;
+ break;
+ case 4800:
+ BAUD = B4800;
+ break;
+ default:
+ BAUD = B38400;
+ break;
+ } //end of switch baud_rate
+
+ newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8;
+ newtio.c_cflag |= CLOCAL | CREAD;
+ newtio.c_cflag &= ~CRTSCTS;
+ newtio.c_cflag &= ~CSTOPB;
+ newtio.c_iflag=IGNBRK;
+ newtio.c_iflag &= ~(IXON|IXOFF|IXANY);
+ newtio.c_lflag=0;
+ newtio.c_oflag=0;
+ newtio.c_cc[VTIME]=1; //1/10th second timeout, reduces CPU usage but still allows for timeouts
+ newtio.c_cc[VMIN]=1; //We want a pure timer timeout
+
+ if (baudrate != -1)
+ {
+ if(cfsetispeed(&newtio, BAUD))
+ {
+ perror("cfsetispeed");
+ }
+
+ if(cfsetospeed(&newtio, BAUD))
+ {
+ perror("cfsetospeed");
+ }
+ debug(obdLib::DEBUG_VERBOSE,"Setting baud rate to %i\n",baudrate);
+ }
+ fcntl(portHandle, F_SETFL, 0); //Set to blocking
+ tcsetattr(portHandle, TCSANOW, &newtio);
+
+ return 0;
+}
+
+void obdLib::setDebugCallback(void (*callbackptr)(const char*,void*,obdLib::DebugLevel),void *usrdata)
+{
+ //printf("Calling setDebugCallback: %i\n",debugCallback);
+ debugCallback = callbackptr;
+ debugUserData = usrdata;
+ //printf("Calling setDebugCallback: %i\n",debugCallback);
+}
+void obdLib::setCommsCallback(void (*callbackptr)(const char*,void*),void* usrdata)
+{
+ commsCallback = callbackptr;
+ commsUserData = usrdata;
+}
+void obdLib::debug(DebugLevel lvl,const char* msg,...)
+{
+ char fmsg[4096];
+ va_list vl;
+ va_start(vl,msg);
+ vsnprintf(fmsg,sizeof(fmsg),msg,vl);
+ if (debugCallback != 0)
+ {
+ debugCallback(fmsg,debugUserData,lvl);
+ }
+ va_end(vl);
+}
+void obdLib::commsDebug(const char *msg)
+{
+ if (commsCallback != 0)
+ {
+ commsCallback(msg,commsUserData);
+ }
+}
+
+int obdLib::openPort(const char *portName,int baudrate)
+{
+ debug(obdLib::DEBUG_VERBOSE,"Attempting to open com port %s",portName);
+ portHandle = open(portName,O_RDWR | O_NOCTTY | O_NDELAY);
+
+ return openPort(portHandle, baudrate);
+}
+
+void obdLib::setPortHandle(HANDLE hdnl)
+{
+ portHandle = hdnl;
+}
+
+int obdLib::closePort()
+{
+ debug(obdLib::DEBUG_VERBOSE,"Closing port...");
+ #ifdef WINVER
+ CloseHandle(portHandle);
+ #else
+// tcsetattr(portHandle,TCSANOW,&oldtio);
+ close(portHandle);
+ #endif
+ return 0;
+}
+
+bool obdLib::connected()
+{
+
+}
+
+int obdLib::initPort()
+{
+ debug(obdLib::DEBUG_VERY_VERBOSE,"Init OBD2 port...");
+ sendObdRequest("atz\r",4);
+ sendObdRequest("ati\r",4);
+ sendObdRequest("ate0\r",5);
+#ifdef WINVER
+ Sleep(3000);
+#else
+ usleep(3000000);
+ tcflush(portHandle,TCIFLUSH);
+#endif
+ sendObdRequest("atl0\r",5);
+ sendObdRequest("ath0\r",5);
+ sendObdRequest("010C\r",5);
+ return 1;
+}
+byte obdLib::byteArrayToByte(byte b1, byte b2)
+{
+ byte newB1 = 0;
+ byte newB2 = 0;
+ if ((b1 >= 48) && (b1 <= 57))
+ {
+ newB1 = ((b1 - 48) * 16);
+ }
+ else if ((b1 >=65) && (b1 <= 90))
+ {
+ newB1 = ((b1 - 55) * 16);
+ }
+ else
+ {
+ newB1 = ((b1 - 87) * 16);
+ }
+ if ((b2 >= 48) && (b2 <= 57))
+ {
+ newB2 = (b2 - 48);
+ }
+ else if ((b2 >= 65) && (b2 <= 90))
+ {
+ newB2 = (b2 - 55);
+ }
+ else
+ {
+ newB2 = (b2 - 87);
+ }
+ byte retVal = (newB1 + newB2);
+ return retVal;
+}
+
+bool obdLib::sendObdRequest(const char *req,int len)
+{
+ //Blind request
+ std::vector<byte> reply;
+ return sendObdRequestString(req,len,&reply,-1,-1);
+}
+bool obdLib::sendObdRequest(const char *req,int len,int sleeptime)
+{
+ std::vector<byte> reply;
+ return sendObdRequestString(req,len,&reply,sleeptime,-1);
+}
+
+bool obdLib::sendObdRequestString(const char *req,int length,std::vector<byte> *reply)
+{
+ return sendObdRequestString(req,length,reply,20,3);
+}
+bool obdLib::sendObdRequestString(const char *req,int length,std::vector<byte> *reply,int sleeptime)
+{
+ return sendObdRequestString(req,length,reply,sleeptime,3);
+}
+
+void obdLib::flush()
+{
+#ifdef WINVER
+
+#else
+ tcflush(portHandle,TCIFLUSH);
+#endif
+}
+std::string obdLib::monitorModeReadLine()
+{
+ std::string retval;
+ int len=0;
+ char *tmp = new char[1024];
+ bool breakit = false;
+ while (!breakit)
+ {
+#ifndef WINHACK
+ len = read(portHandle,tmp,1024);
+#else
+ if (!ReadFile(portHandle,(LPVOID)tmp,1024,(LPDWORD)&len,NULL))
+ {
+ delete[] tmp;
+ m_lastError = SERIALREADERROR;
+ debug(obdLib::DEBUG_ERROR,"Serial read error");
+ return "";
+ }
+
+#endif
+
+ if (len < 0)
+ {
+ printf("No Read\n");
+ perror("Error");
+ delete[] tmp;
+ m_lastError = SERIALREADERROR;
+ debug(obdLib::DEBUG_ERROR,"Serial read error");
+ return std::string();
+ }
+ else if (len == 0)
+ {
+ #ifdef WINVER
+ Sleep(10);
+ #else
+ usleep(10000);
+ #endif
+ }
+ else
+ {
+ for (int i=0;i<len;i++)
+ {
+ if (tmp[i] == '\n')
+ {
+ breakit = true;
+ }
+ else
+ {
+ retval.append(1,tmp[i]);
+ }
+ }
+ }
+ }
+ return retval;
+
+}
+bool obdLib::sendObdRequestString(const char *req,int length,std::vector<byte> *reply,int sleeptime, int timeout)
+{
+ reply->clear();
+ //std::vector<byte> tmpReply;
+ char *tmp = new char[1024];
+ char *totalReply = new char[1024];
+ int loc = 0;
+ int len = 0;
+ time_t seconds = time(NULL);
+ commsDebug(req);
+#ifdef WINVER
+ if (!::WriteFile(portHandle, (void*)req, (DWORD)length, (LPDWORD)&len, NULL)) {
+ //DWORD error = GetLastError();
+ //int i = 2;
+ //An error happened, I should probably handle this sometime.
+ delete[] totalReply;
+ delete[] tmp;
+ m_lastError = SERIALWRITEERROR;
+ debug(obdLib::DEBUG_ERROR,"Serial write error");
+ return false;
+ }
+#else
+ len = write(portHandle,req,length);
+#endif
+ if (len < 0)
+ {
+ debug(obdLib::DEBUG_ERROR,"Serial write error: %s", strerror(errno));
+
+ return false;
+ }
+ if (sleeptime == -1)
+ {
+ //Not expecting a reply.
+ delete[] totalReply;
+ delete[] tmp;
+ return true;
+
+ }
+#ifdef WINVER
+ Sleep(sleeptime);
+#else
+ usleep(sleeptime * 1000);
+#endif
+ bool continueLoop = true;
+ while (continueLoop)
+ {
+#ifdef WINVER
+ if (!ReadFile(portHandle,(LPVOID)tmp,1024,(LPDWORD)&len,NULL))
+ {
+ delete[] tmp;
+ delete[] totalReply;
+ m_lastError = SERIALREADERROR;
+ debug(obdLib::DEBUG_ERROR,"Serial read error");
+ return false;
+ }
+#else
+ len = read(portHandle,tmp,1024);
+#endif
+
+ if (len < 0)
+ {
+ //printf("No Read\n");
+ perror("Error");
+ delete[] tmp;
+ delete[] totalReply;
+ m_lastError = SERIALREADERROR;
+ debug(obdLib::DEBUG_ERROR,"Serial read error");
+ return false;
+ }
+ else if (len == 0)
+ {
+ #ifdef WINVER
+ Sleep(10);
+ #else
+ //printf("Timeout\n");
+ usleep(10000);
+ #endif
+ }
+ else
+ {
+ for (int i=0;i<len;i++)
+ {
+ if (/*(tmp[i] != 0x20) && (tmp[i] != '\r') && (tmp[i] != '\n') && */(tmp[i] != '>'))
+ {
+ //printf("Byte: %c %i ",tmp[i],tmp[i]);
+ totalReply[loc++] = tmp[i];
+ }
+ if (tmp[i] == '>')
+ {
+ /*printf("\n> returned. Current: %i, Len: %i\n",i,len);
+ printf("\n\nResponse: ");
+ for (int j=i;j<len;j++)
+ {
+ printf("%c",tmp[j]);
+ }
+ printf(" :End\n\n");
+ */
+ continueLoop = false;
+ }
+ }
+ }
+ if (timeout > 0)
+ {
+ if ((time(NULL) - seconds)-(sleeptime / 1000.0) > timeout)
+ {
+ //printf("Time:%i:%i:%i\n",time(NULL) - seconds,(time(NULL) - seconds) - (sleeptime/1000.0),time(NULL));
+ continueLoop = false;
+
+ m_lastError = TIMEOUT;
+ printf("Timeout, current reply state:");
+ for (int i=0;i<loc;i++)
+ {
+ printf("%c",totalReply[i]);
+ }
+
+ printf(":\n");
+ printf("Current reply length: %i\n",loc);
+ delete[] tmp;
+ delete[] totalReply;
+ debug(obdLib::DEBUG_ERROR,"Timeout");
+ return false;
+ }
+ }
+ if (timeout == -1)
+ {
+ //Not waiting for a reply.
+ delete[] tmp;
+ delete[] totalReply;
+ debug(obdLib::DEBUG_ERROR,"Timeout, not waiting for a reply");
+ return true;
+ }
+ }
+
+ //Perform checking on totalReply
+ for (int i=0;i<loc;i++)
+ {
+ reply->push_back(totalReply[i]);
+ }
+ //printf("Total Reply Size: %i\n",loc);
+ totalReply[loc] = '\0';
+ commsDebug(totalReply);
+ int errorlen = strspn("NODATA",totalReply);
+ if (errorlen == 6)
+ {
+ //Error
+ //printf("Error\n");
+ //Nodata here
+ m_lastError = NODATA;
+ delete[] tmp;
+ delete[] totalReply;
+ debug(obdLib::DEBUG_ERROR,"nodata");
+ return false;
+ }
+ delete[] totalReply;
+ delete[] tmp;
+ //tcflush(portHandle,TCIFLUSH);
+ //debug(obdLib::DEBUG_ERROR,"Hunkydory");
+ return true;
+}
+obdLib::ObdError obdLib::lastError()
+{
+ return m_lastError;
+}
+bool obdLib::sendObdRequest(const char *req,int length,std::vector<byte> *reply)
+{
+ return sendObdRequest(req,length,reply,10,5);
+}
+
+
+bool obdLib::sendObdRequest(const char *req,int length,std::vector<byte> *reply,int sleep, int timeout)
+{
+ reply->clear();
+ std::vector<byte> tmpReply;
+ if (!sendObdRequestString(req,length,&tmpReply,sleep,timeout))
+ {
+ debug(obdLib::DEBUG_ERROR,"sendObdRequestString returned false!!");
+ return false;
+ }
+ if (tmpReply.size() == 0)
+ {
+ debug(obdLib::DEBUG_ERROR,"sendObdRequestString returned true with a tmpReply size of 0!");
+ return false;
+ }
+ for (unsigned int i=0;i<tmpReply.size()-1;i++)
+ {
+ if ((tmpReply[i] != 0x20) && (tmpReply[i] != '\r') && (tmpReply[i] != '\n'))
+ {
+ reply->push_back(byteArrayToByte(tmpReply[i],tmpReply[i+1]));
+ i++;
+ }
+ }
+ return true;
+}
+
+
+extern "C" {
+ STDCALL void *obdLibNew()
+ {
+ return new obdLib();
+ }
+ STDCALL int obdLibOpenPort(void *ptr,const char *portname,int baudrate)
+ {
+ obdLib *lib = ((obdLib*)ptr);
+ return lib->openPort(portname,baudrate);
+ }
+ STDCALL int obdLibClosePort(void *ptr)
+ {
+ obdLib *lib = ((obdLib*)ptr);
+ return lib->closePort();
+ }
+ STDCALL int obdLibInitPort(void *ptr)
+ {
+ obdLib *lib = ((obdLib*)ptr);
+ return lib->initPort();
+ }
+ STDCALL void obdLibDelete(void *ptr)
+ {
+ obdLib *lib = ((obdLib*)ptr);
+ delete lib;
+ }
+
+ //bool sendObdRequestString(const char *req,int length,std::vector<byte> *reply,int sleeptime, int timeout);
+ //bool sendObdRequest(const char *req,int length,std::vector<byte> *reply,int sleep, int timeout);
+ //bool sendObdRequest(const char *req,int length,std::vector<byte> *reply,int sleep, int timeout);
+ STDCALL bool obdLibSendObdRequest(void *ptr,const char *req,int length, char *reply,unsigned int replylength,int sleeptime, int timeout)
+ {
+ obdLib *lib = ((obdLib*)ptr);
+ std::vector<byte> replyvect;
+ if (!lib->sendObdRequest(req,length,&replyvect,sleeptime,timeout))
+ {
+ return false;
+ }
+ if (replyvect.size() > replylength)
+ {
+ //Not enough room in the buffer
+ return false;
+ }
+ for (unsigned int i=0;i<replyvect.size();i++)
+ {
+ reply[i] = replyvect.at(i);
+ }
+ reply[replyvect.size()] = '.';
+ return true;
+ }
+ STDCALL void setEcho(void *ptr,bool on)
+ {
+ obdLib *lib = ((obdLib*)ptr);
+ if (on)
+ {
+ lib->sendObdRequest("ate1\r",5,250);
+ }
+ else
+ {
+ lib->sendObdRequest("ate0\r",5,250);
+ }
+
+ }
+ STDCALL bool obdLibSendObdRequestString(void *ptr,const char *req,int length, char *reply,unsigned int replylength,int *replylengthptr,int sleeptime, int timeout)
+ {
+ obdLib *lib = ((obdLib*)ptr);
+ std::vector<byte> replyvect;
+ if (!lib->sendObdRequestString(req,length,&replyvect,sleeptime,timeout))
+ {
+ reply[0] = -1;
+ reply[1] = 1;
+ reply[2] = lib->lastError();
+ return false;
+ }
+ //char *tmp = new char(1024);
+ //sprintf(tmp,"ObdRequest returned! Size: %i",replyvect.size());
+ //OutputDebugString(tmp);
+ //fprintf(stderr,"ObdRequest returned! Size %i\n",replyvect.size());
+ if (replyvect.size() > replylength)
+ {
+ //Not enough room in the buffer
+ reply[0] = -1;
+ reply[1] = 2;
+ return false;
+ }
+ for (unsigned int i=0;i<replyvect.size();i++)
+ {
+ reply[i] = replyvect.at(i);
+ }
+ //reply[replyvect.size()]='.';
+ *replylengthptr = replyvect.size();
+ if (replyvect.size() == 0)
+ {
+ reply[0] = lib->lastError();
+ }
+ else
+ {
+ //reply[0] = replyvect.size();
+ }
+ return true;
+ }
+}
diff --git a/plugins/obd2plugin/obdlib.h b/plugins/obd2plugin/obdlib.h
new file mode 100644
index 00000000..50762cf1
--- /dev/null
+++ b/plugins/obd2plugin/obdlib.h
@@ -0,0 +1,141 @@
+/*
+Copyright (C) 2010 by Michael Carpenter (malcom2073) malcom2073@gmail.com
+
+This file is a part of libobd
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef OBDLIB_H
+#define OBDLIB_H
+#include <stdio.h>
+
+#include <string>
+//#define WINHACK
+
+#ifdef WINHACK
+#define M_SleepSec(x) Sleep(1000 * x);
+#include <windows.h>
+//#ifdef WIN32
+//#define STDCALL __sttribute__((__stdcall__))
+//#define STDCALL __stdcall
+#define STDCALL __declspec(dllexport)
+#else
+#define M_SleepSec(x) usleep(x * 1000000);
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <termios.h>
+#define STDCALL
+# define byte unsigned char
+# define HANDLE int
+# define DWORD long
+
+#endif // WIN32
+#include <vector>
+
+
+
+struct variantStruct
+{
+ int intVar;
+ double doubleVarOne;
+ double doubleVarTwo;
+ byte byteVar;
+ std::vector<byte> vectorBytes;
+ byte typeVar;
+ byte btMode;
+ byte btPID;
+};
+struct obdInfoStruct
+{
+ DWORD dwItemType;
+ std::string strItemDesc;
+ byte btMode;
+ byte btPID;
+ byte btItemSizeBytes;
+ DWORD dwOperation;
+ double dFactor;
+ double dOffset;
+ int iRangeLow;
+ int iRangeHigh;
+ std::string strUnitLabel;
+ int iBitLookupTable;
+};
+
+class obdLib
+{
+public:
+
+ enum ObdError
+ {
+ NODATA=0,
+ NOTCONNECTED,
+ OTHER,
+ SERIALWRITEERROR,
+ SERIALREADERROR,
+ TIMEOUT,
+ NONE
+ };
+ enum DebugLevel
+ {
+ DEBUG_VERY_VERBOSE=0,
+ DEBUG_VERBOSE=1,
+ DEBUG_INFO=2,
+ DEBUG_WARN=3,
+ DEBUG_ERROR=4,
+ DEBUG_FATAL=5
+ };
+ obdLib();
+ int openPort(const char *portName,int baudrate);
+ int openPort(const int fd, int baudrate);
+ int openPort(const char *portName);
+ void setPortHandle(HANDLE hdnl);
+ int initPort();
+ int closePort();
+ bool connected();
+ void flush();
+ void setDebugCallback(void (*callbackptr)(const char*,void*,obdLib::DebugLevel),void *);
+ void setCommsCallback(void (*callbackptr)(const char*,void*),void*);
+ std::string monitorModeReadLine();
+ //byte* sendRequest(byte *reqString,int length);
+// byte* sendRequest(char *asciiReqString, int length);
+ static byte byteArrayToByte(byte b1, byte b2);
+ std::string getVersion() { return versionString; }
+ bool sendObdRequest(const char *req,int len,std::vector<byte> *reply);
+ bool sendObdRequest(const char *req,int length,std::vector<byte> *reply,int sleep, int timeout);
+ bool sendObdRequestString(const char *req,int len,std::vector<byte> *reply,int sleeptime);
+ bool sendObdRequestString(const char *req,int length,std::vector<byte> *reply,int sleeptime, int timeout);
+ bool sendObdRequestString(const char *req,int len,std::vector<byte> *reply);
+ bool sendObdRequest(const char *req,int len);
+ bool sendObdRequest(const char *req,int len,int timeout);
+ ObdError lastError();
+
+
+private:
+ void debug(DebugLevel lvl,const char* msg,...);
+ void commsDebug(const char *msg);
+ ObdError m_lastError;
+ std::vector<std::vector<int> > *modeByteCount;
+ std::string versionString;
+ HANDLE portHandle;
+ byte* readBytes(int* bytesRead,int numBytesToRead);
+ void writeBytes(byte *sendBuffer,int bufferSize,int *bytesWritten);
+ byte *sendBuffer;
+ byte *rcvdBuffer;
+};
+#endif //OBDLIB_H
+
diff --git a/plugins/obd2plugin/obdpid.cpp b/plugins/obd2plugin/obdpid.cpp
new file mode 100644
index 00000000..81f12c4e
--- /dev/null
+++ b/plugins/obd2plugin/obdpid.cpp
@@ -0,0 +1,4 @@
+#include "obdpid.h"
+
+
+double FuelConsumptionPid::oldTime=0;
diff --git a/plugins/obd2plugin/obdpid.h b/plugins/obd2plugin/obdpid.h
new file mode 100644
index 00000000..20db314a
--- /dev/null
+++ b/plugins/obd2plugin/obdpid.h
@@ -0,0 +1,447 @@
+#ifndef _OBDPID_H__H_H_
+#define _OBDPID_H__H_H_
+
+#include <vector>
+#include <string>
+#include <vehicleproperty.h>
+#include "obdlib.h"
+#include <time.h>
+
+class ObdPid
+{
+public:
+ typedef std::vector<unsigned char> ByteArray;
+
+ ObdPid(VehicleProperty::Property prop, std::string p, int i)
+ :property(prop), pid(p), id(i), type(0x41)
+ {
+ isValidVal = false;
+ }
+ static ByteArray cleanup(ByteArray replyVector)
+ {
+ ByteArray tmp;
+
+ for (int i=0;i<replyVector.size();i++)
+ {
+ if ((replyVector[i] != 0x20) && (replyVector[i] != '\r') && (replyVector[i] != '\n'))
+ {
+ tmp.push_back(replyVector[i]);
+ }
+ }
+ return tmp;
+ }
+ static ByteArray compress(ByteArray replyVector)
+ {
+ ByteArray tmp;
+ for (int i=0;i<replyVector.size()-1;i++)
+ {
+ tmp.push_back(obdLib::byteArrayToByte(replyVector[i], replyVector[i+1]));
+ i++;
+ }
+ return tmp;
+ }
+ virtual ObdPid* create() = 0;
+
+ bool tryParse(ByteArray replyVector)
+ {
+ if (!isValid(replyVector))
+ {
+ return false;
+ }
+ parse(replyVector);
+ return true;
+ }
+ virtual void parse(const ByteArray &replyVector) = 0;
+ virtual bool isValid(const ByteArray &replyVector) = 0;
+ virtual bool needsCompress() { return true; }
+
+ VehicleProperty::Property property;
+ std::string pid;
+ int id;
+ int type;
+ std::string value;
+ bool isValidVal;
+};
+
+template <class T>
+class CopyMe: public ObdPid
+{
+public:
+
+ CopyMe(VehicleProperty::Property prop, std::string p, int i)
+ :ObdPid(prop, p, i)
+ {
+ }
+
+ ObdPid* create()
+ {
+ T* t = new T();
+ t->value = value;
+ t->isValidVal = isValidVal;
+ return t;
+ }
+};
+
+
+class VehicleSpeedPid: public CopyMe<VehicleSpeedPid>
+{
+public:
+
+ VehicleSpeedPid()
+ :CopyMe(VehicleProperty::VehicleSpeed, "010D1\r", 0x0D)
+ {
+
+ }
+ bool isValid(const ByteArray &replyVector)
+ {
+ isValidVal = true;
+ if (replyVector[1] != id)
+ {
+ return isValidVal = false;
+ }
+
+ return isValidVal;
+ }
+ void parse(const ByteArray &replyVector)
+ {
+ if (!isValidVal)
+ {
+ //TODO: Determine if we should throw an exception here, rather than just returning without a value?
+ return;
+ }
+
+ int mph = replyVector[2];
+ value = boost::lexical_cast<std::string>(mph);
+ }
+};
+
+class EngineSpeedPid: public CopyMe<EngineSpeedPid>
+{
+public:
+
+ EngineSpeedPid()
+ :CopyMe(VehicleProperty::EngineSpeed,"010C1\r",0x0C)
+ {
+
+ }
+ bool isValid(const ByteArray &replyVector)
+ {
+ if (replyVector[1] != id)
+ {
+ isValidVal = false;
+ return false;
+ }
+ isValidVal = true;
+ return true;
+ }
+ void parse(const ByteArray &replyVector)
+ {
+ if (!isValidVal)
+ {
+ //TODO: Determine if we should throw an exception here, rather than just returning without a value?
+ return;
+ }
+ double rpm = ((replyVector[2] << 8) + replyVector[3]) / 4.0;
+ value = boost::lexical_cast<std::string>(rpm);
+ }
+};
+
+class EngineCoolantPid: public CopyMe<EngineCoolantPid>
+{
+public:
+
+ EngineCoolantPid()
+ :CopyMe(VehicleProperty::EngineCoolantTemperature,"01051\r",0x05)
+ {
+
+ }
+ bool isValid(const ByteArray &replyVector)
+ {
+ if (replyVector[1] != id)
+ {
+ isValidVal = false;
+ return false;
+ }
+ isValidVal = true;
+ return true;
+ }
+ void parse(const ByteArray &replyVector)
+ {
+ if (!isValidVal)
+ {
+ //TODO: Determine if we should throw an exception here, rather than just returning without a value?
+ return;
+ }
+ int temp = replyVector[2] - 40;
+ value = boost::lexical_cast<std::string>(temp);
+ }
+};
+
+class MassAirFlowPid: public CopyMe<MassAirFlowPid>
+{
+public:
+
+ MassAirFlowPid()
+ :CopyMe(VehicleProperty::MassAirFlow,"01101\r", 0x10)
+ {
+
+ }
+ bool isValid(const ByteArray &replyVector)
+ {
+ if (replyVector[1] != id)
+ {
+ isValidVal = false;
+ return false;
+ }
+ isValidVal = true;
+ return true;
+ }
+ void parse(const ByteArray &replyVector)
+ {
+ if (!isValidVal)
+ {
+ //TODO: Determine if we should throw an exception here, rather than just returning without a value?
+ return;
+ }
+
+ maf = ((replyVector[2] << 8) + replyVector[3]) / 100.0;
+ value = boost::lexical_cast<std::string>(maf);
+ }
+
+protected:
+ double maf;
+};
+
+
+class FuelConsumptionPid: public MassAirFlowPid
+{
+public:
+ FuelConsumptionPid()
+
+ {
+
+ }
+ bool isValid(const ByteArray &replyVector)
+ {
+ return isValidVal = MassAirFlowPid::isValid(replyVector);
+ }
+ void parse(const ByteArray & replyVector)
+ {
+ if (!isValidVal)
+ {
+ //TODO: Determine if we should throw an exception here, rather than just returning without a value?
+ return;
+ }
+
+ timespec t;
+ clock_gettime(CLOCK_REALTIME, &t);
+
+ double currentTime = t.tv_sec + t.tv_nsec / 1000000;
+
+ double diffTime = currentTime - oldTime;
+ oldTime = currentTime;
+
+ double consumption = 1 / (14.75 * 6.26) * maf * diffTime/60;
+
+ value = boost::lexical_cast<std::string>(consumption);
+ }
+
+private:
+
+ static double oldTime;
+};
+
+
+class VinPid: public CopyMe<VinPid>
+{
+public:
+
+ VinPid()
+ :CopyMe(VehicleProperty::VIN,"0902\r",0x02)
+ {
+ type = 0x49;
+ }
+ bool isValid(const ByteArray & replyVector)
+ {
+ isValidVal = true;
+
+ if (replyVector[0] != 0x49 || replyVector[1] != 0x02)
+ {
+ isValidVal = false;
+
+ }
+ return isValidVal;
+ }
+ void parse(const ByteArray & replyVector)
+ {
+ if (!isValidVal)
+ {
+ //TODO: Determine if we should throw an exception here, rather than just returning without a value?
+ return;
+ }
+ std::string vinstring;
+ for (int j=0;j<replyVector.size();j++)
+ {
+ if(replyVector[j] == 0x49 && replyVector[j+1] == 0x02)
+ {
+ //We're at a reply header
+ j+=3;
+ }
+ if (replyVector[j] != 0x00)
+ {
+ vinstring += (char)replyVector[j];
+ //printf("VIN: %i %c\n",replyVector[j],replyVector[j]);
+ }
+ }
+
+ value = vinstring;
+ }
+};
+
+class WmiPid: public VinPid
+{
+public:
+
+ WmiPid()
+ :VinPid()
+ {
+ property = VehicleProperty::WMI;
+ }
+ bool isValid(const ByteArray & replyVector)
+ {
+ return isValidVal = VinPid::isValid(replyVector);
+ }
+ void parse(const ByteArray &replyVector)
+ {
+ if (!isValidVal)
+ {
+ //TODO: Determine if we should throw an exception here, rather than just returning without a value?
+ return;
+ }
+ VinPid::parse(replyVector);
+ value = value.substr(0,3);
+ }
+};
+
+class AirIntakeTemperaturePid: public CopyMe<AirIntakeTemperaturePid>
+{
+public:
+ AirIntakeTemperaturePid()
+ :CopyMe(VehicleProperty::AirIntakeTemperature,"010F1\r",0x0F)
+ {
+
+ }
+ bool isValid(const ByteArray & replyVector)
+ {
+ if (replyVector[1] != id)
+ {
+ isValidVal = false;
+ return false;
+ }
+ isValidVal = true;
+ return true;
+ }
+ void parse(const ByteArray & replyVector)
+ {
+ if (!isValidVal)
+ {
+ //TODO: Determine if we should throw an exception here, rather than just returning without a value?
+ return;
+ }
+ int temp = replyVector[2] - 40;
+ value = boost::lexical_cast<std::string>(temp);
+ }
+};
+
+class EngineLoadPid: public CopyMe<EngineCoolantPid>
+{
+public:
+ EngineLoadPid()
+ :CopyMe(VehicleProperty::EngineLoad,"01041\r",0x04)
+ {
+
+ }
+ bool isValid(const ByteArray & replyVector)
+ {
+ if (replyVector[1] != id)
+ {
+ isValidVal = false;
+ return false;
+ }
+ isValidVal = true;
+ return true;
+ }
+ void parse(const ByteArray &replyVector)
+ {
+ if (!isValidVal)
+ {
+ //TODO: Determine if we should throw an exception here, rather than just returning without a value?
+ return;
+ }
+ int load = replyVector[2]*100.0/255.0;
+ value = boost::lexical_cast<std::string>(load);
+ }
+};
+
+class ThrottlePositionPid: public CopyMe<ThrottlePositionPid>
+{
+public:
+ ThrottlePositionPid()
+ :CopyMe(VehicleProperty::ThrottlePosition,"01111\r",0x11)
+ {
+
+ }
+ bool isValid(const ByteArray & replyVector)
+ {
+ if (replyVector[1] != id)
+ {
+ isValidVal = false;
+ return false;
+ }
+ isValidVal = true;
+ return true;
+ }
+ void parse(const ByteArray & replyVector)
+ {
+ if (!isValidVal)
+ {
+ //TODO: Determine if we should throw an exception here, rather than just returning without a value?
+ return;
+ }
+ int temp = replyVector[2]*100.0/255.0;
+ value = boost::lexical_cast<std::string>(temp);
+ }
+};
+
+class BatteryVoltagePid: public CopyMe<BatteryVoltagePid>
+{
+public:
+ BatteryVoltagePid()
+ :CopyMe(VehicleProperty::BatteryVoltage,"ATRV\r",0)
+ {
+
+ }
+
+ bool needsCompress() { return false; }
+
+ bool isValid(const ByteArray & replyVector)
+ {
+ if(replyVector[replyVector.size() - 1] == 'V')
+ {
+ return isValidVal = true;
+ }
+ return false;
+ }
+
+ void parse(const ByteArray & replyVector)
+ {
+ value = "";
+ for(int i=0; i<replyVector.size() - 1; i++)
+ {
+ value += replyVector[i];
+ }
+ }
+
+};
+
+#endif
diff --git a/plugins/opencvlux/CMakeLists.txt b/plugins/opencvlux/CMakeLists.txt
new file mode 100644
index 00000000..902ad2f8
--- /dev/null
+++ b/plugins/opencvlux/CMakeLists.txt
@@ -0,0 +1,61 @@
+if(opencvlux_plugin)
+
+find_package(OpenCV REQUIRED)
+
+if(OpenCV_LIBS)
+ message(STATUS "opencv found: ${OpenCV_INCLUDE_DIRS}")
+else(OpenCV_LIBS)
+ message(FATAL_ERROR "opencv missing. please install opencv")
+endif(OpenCV_LIBS)
+
+set(qtmainloop ON CACHE INTERNAL "")
+
+add_definitions(-DCV_DATA="${OpenCV_CONFIG_PATH}")
+
+if(ocl)
+ message(STATUS "found opencv ocl headers. enabling opencl support. ${ocl}")
+ add_definitions(-DOPENCL)
+else(ocl)
+ message(STATUS "no opencl support")
+endif(ocl)
+
+option(cuda "enable cuda" OFF)
+
+if(cuda)
+ message(STATUS "found opencv cuda headers. enabling cuda support. ${cuda}")
+ add_definitions(-DCUDA)
+else(cuda)
+ message(STATUS "no opencv cuda headers found. no cuda support")
+ remove_definitions(-DCUDA)
+endif(cuda)
+
+find_package(Qt5Core REQUIRED)
+
+if(Qt5Core_FOUND)
+ 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)
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${OpenCV_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${QT_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/plugins/common)
+
+set(opencvluxplugin_headers opencvluxplugin.h)
+set(opencvluxplugin_sources opencvluxplugin.cpp)
+
+add_library(opencvluxplugin MODULE ${opencvluxplugin_sources})
+set_target_properties(opencvluxplugin PROPERTIES PREFIX "")
+target_link_libraries(opencvluxplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${OpenCV_LIBS} ${Boost_LIBRARIES} ${QT_LIBRARIES} amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common)
+
+install(TARGETS opencvluxplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_BINARY_DIR}/opencvlux.README.md @ONLY)
+set(opencvlux_doc_files ${CMAKE_CURRENT_BINARY_DIR}/opencvlux.README.md)
+install (FILES ${opencvlux_doc_files} DESTINATION ${DOC_INSTALL_DIR}/plugins)
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/opencvlux.in.json ${CMAKE_CURRENT_BINARY_DIR}/opencvlux @ONLY)
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/opencvlux DESTINATION ${PLUGIN_SEGMENT_INSTALL_PATH})
+
+endif(opencvlux_plugin)
diff --git a/plugins/opencvlux/README b/plugins/opencvlux/README
new file mode 100644
index 00000000..d89004c4
--- /dev/null
+++ b/plugins/opencvlux/README
@@ -0,0 +1,61 @@
+# OpenCV plugin {#opencvlux_plugin}
+
+[TOC]
+# OpenCV "lux" plugin
+Version: @PROJECT_VERSION@
+
+
+# Introduction {#opencv_intro}
+
+This plugin simulates the ExteriorBrigtness property using a traditional webcamera. It works
+by taking the mean pixel intensity of the web camera image and estimating lux. The particular
+can be calibrated using the "pixelUpperBound" and "pixelLowerBound" variables.
+
+
+# Setup {#opencv_setup}
+
+To enable the OpenCV "lux" plugin, run cmake and enable the opencvlux_plugin option:
+
+cmake -Dopencvlux_plugin=On ..
+
+Currently, this plugin has been tested with OpenCV 2.4.4.
+
+To use the OpenCV plugin, add the following to the "sources" array in /etc/ambd/config:
+~~~~~~~~~~~~~{.js}
+{
+ "name" : "OpenCV LUX",
+ "path" : "@PLUGIN_INSTALL_PATH@/opencvluxplugin.so",
+ "threaded" : "true",
+ "pixelLowerBound" : "0",
+ "pixelUpperBound" : "255",
+ "fps" : "30",
+ "opencl" : "false",
+ "device" : "0"
+}
+~~~~~~~~~~~~~
+
+**NOTE:** some features require the qtmainloop to be running. see the main README for details.
+
+# Configuration Key Definitions: {#opencv_config_keys}
+
+| Key | Definition | Default Value |
+| :---------------- | :---------------------------------------------------------------------- | :----------------- |
+| "name" | Name of plugin. This key is not used by the plugin at this moment | |
+| "path" | Path to plugin on the filesystem | |
+| "device" | Camera to use. The string "0" corrisponds to /dev/video0 | "0" |
+| "threaded" | Compute pixel intensity in another thread. Set to "true" or "false" | "false" |
+| "fps" | How many times per second to poll image data from the camera. | "30" |
+| "opencl" | (experimental) Use a specialized CPU/GPU device to help with processing | "false" |
+| "logging" | Turn on video logging. | "false" |
+| "logfile" | File to encode video to. | "/tmp/video.avi" |
+| "codec" | Fourcc name of codec. See <http://www.fourcc.org/codecs.php> | "mjpg" |
+| "ddd" | (experimental) Driver Drowsiness Detection with a driver facing camera detect whether or not eyes are open or closed. If closed for a period </br> of time, DriverDrowsiness will change to "true". | "false" |
+
+
+# AMB Properties: {#opencv_amb_properties}
+
+| Property Name | Description | Type | Access |
+| :---------------- | :---------------------------------------------------------------------- | :------: | :-------- |
+| VideoLogging | Turn on and off video logging | bool | readwrite |
+| DriverDrowsiness | True if the driver has been detected drowsy. | bool | readonly |
+| OpenCL | True if OpenCL acceleration is enabled. | bool | readwrite |
diff --git a/plugins/opencvlux/opencvlux.in.json b/plugins/opencvlux/opencvlux.in.json
new file mode 100644
index 00000000..d72b71f9
--- /dev/null
+++ b/plugins/opencvlux/opencvlux.in.json
@@ -0,0 +1,17 @@
+{
+ "name" : "OpenCV",
+ "path" : "@PLUGIN_INSTALL_PATH@/opencvluxplugin.so",
+ "enabled" : false,
+ "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"
+}
diff --git a/plugins/opencvlux/opencvluxplugin.cpp b/plugins/opencvlux/opencvluxplugin.cpp
new file mode 100644
index 00000000..2ee49482
--- /dev/null
+++ b/plugins/opencvlux/opencvluxplugin.cpp
@@ -0,0 +1,588 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "opencvluxplugin.h"
+#include "timestamp.h"
+#include <listplusplus.h>
+#include <superptr.hpp>
+#include <ambplugin.h>
+
+#include <iostream>
+#include <thread>
+#include <opencv2/opencv.hpp>
+#include <opencv2/core/ocl.hpp>
+
+#include <QFuture>
+#include <QFutureWatcher>
+#include <QtConcurrent/QtConcurrent>
+
+
+#include <opencv2/core/ocl.hpp>
+
+using namespace std;
+
+const std::string VideoLogging = "VideoLogging";
+const std::string DriverDrowsiness = "DriverDrowsiness";
+const std::string OpenCL = "OpenCL";
+
+#include "debugout.h"
+
+extern "C" void create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ auto plugin = new AmbPlugin<OpenCvLuxPlugin>(routingengine, config);
+ plugin->init();
+}
+
+OpenCvLuxPlugin::OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string> config, AbstractSource &parent)
+ :AmbPluginImpl(re, config, parent), lastLux(0), speed(0), latitude(0), longitude(0)
+{
+ videoLogging = addPropertySupport(Zone::None, [](){
+ return new BasicPropertyType<bool>(VideoLogging, false);
+ });
+
+ driverDrowsiness = addPropertySupport(Zone::None, [](){
+ return new OpenCvLuxPlugin::DriverDrowsinessType(DriverDrowsiness, false);
+ });
+
+ openCl = addPropertySupport(Zone::None, [](){
+ return new BasicPropertyType<bool>(OpenCL, false);
+ });
+
+ extBrightness = addPropertySupport<VehicleProperty::ExteriorBrightnessType>(Zone::None);
+
+ shared = amb::make_unique(new Shared);
+ shared->parent = this;
+
+ shared->m_capture = NULL;
+ shared->mWriter = nullptr;
+
+ shared->threaded = false;
+ shared->kinect = false;
+ shared->useCuda = false;
+ shared->loggingOn = false;
+ shared->ddd = false;
+
+ shared->fps=30;
+ device="0";
+ shared->pixelLowerBound = 0;
+ shared->pixelUpperBound = 255;
+
+
+ if(config.find("threaded") != config.end())
+ {
+ shared->threaded = config["threaded"] == "true";
+ }
+
+ if(config.find("kinect") != config.end())
+ {
+ shared->kinect = config["kinect"] == "true";
+ }
+
+ if(config.find("fps") != config.end())
+ {
+ shared->fps = boost::lexical_cast<int>(config["fps"]);
+ }
+
+ if(config.find("device") != config.end())
+ {
+ device = config["device"].c_str();
+ }
+
+ if(config.find("pixelLowerBound") != config.end())
+ {
+ shared->pixelLowerBound = boost::lexical_cast<int>(config["pixelLowerBound"]);
+
+ if(shared->pixelLowerBound < 0)
+ {
+ shared->pixelLowerBound = 0;
+ }
+ }
+
+ if(config.find("pixelUpperBound") != config.end())
+ {
+ shared->pixelUpperBound = boost::lexical_cast<int>(config["pixelUpperBound"]);
+
+ if(shared->pixelUpperBound > 255)
+ shared->pixelUpperBound = 255;
+ }
+
+ if(config.find("opencl") != config.end())
+ {
+ if(cv::ocl::haveOpenCL())
+ {
+ bool useOcl = config["opencl"] == "true";
+ cv::ocl::setUseOpenCL(useOcl);
+ openCl->setValue(cv::ocl::useOpenCL());
+ }
+ else
+ {
+ DebugOut(DebugOut::Warning) << "You really don't have openCL support." << endl;
+ }
+ }
+
+ if(config.find("ddd") != config.end())
+ {
+ shared->ddd = config["ddd"] == "true";
+ }
+
+ if(config.find("logging") != config.end())
+ {
+ shared->loggingOn = config["logging"] == "true";
+ }
+
+ if(shared->ddd)
+ {
+ faceCascade = amb::make_unique(new cv::CascadeClassifier());
+ eyeCascade = amb::make_unique(new cv::CascadeClassifier());
+
+ std::string faceFile = config["faceCascade"];
+
+ if(!faceCascade->load(faceFile))
+ {
+ DebugOut(DebugOut::Warning) << "Could not load face cascade: " << faceFile <<". Disabling ddd" << endl;
+ shared->ddd = false;
+ }
+
+ std::string eyeFile = config["eyeCascade"];
+
+ if(!eyeCascade->load(eyeFile))
+ {
+ DebugOut(DebugOut::Warning) << "Could not load eye cascade: " << eyeFile <<". Disabling ddd" << endl;
+ shared->ddd = false;
+ }
+
+ }
+
+ routingEngine->subscribeToProperty(VehicleProperty::VehicleSpeed, &parent);
+ routingEngine->subscribeToProperty(VehicleProperty::Latitude, &parent);
+ routingEngine->subscribeToProperty(VehicleProperty::Longitude, &parent);
+}
+
+OpenCvLuxPlugin::~OpenCvLuxPlugin()
+{
+
+}
+
+const string OpenCvLuxPlugin::uuid() const
+{
+ return "3c7a1ea0-7d2e-11e2-9e96-0800200c9a66";
+}
+
+void OpenCvLuxPlugin::getPropertyAsync(AsyncPropertyReply *reply)
+{
+ reply->timedout = [this](AsyncPropertyReply* reply) {
+ removeOne(&replyQueue, reply);
+ };
+
+ if(!shared->m_capture || !shared->m_capture->isOpened())
+ {
+ /// we want to turn on the camera for one shot to get an image and determine the intensity
+
+ init();
+ grabImage(shared.get());
+ }
+
+ AmbPluginImpl::getPropertyAsync(reply);
+}
+
+void OpenCvLuxPlugin::getRangePropertyAsync(AsyncRangePropertyReply *reply)
+{
+ throw std::runtime_error("OpenCVLuxPlugin does not support this operation. We should never hit this method.");
+}
+
+AsyncPropertyReply *OpenCvLuxPlugin::setProperty(AsyncSetPropertyRequest request )
+{
+ if(request.property == VideoLogging)
+ {
+ shared->loggingOn = request.value->value<bool>();
+ }
+ if(request.property == OpenCL)
+ {
+ QMutexLocker lock(&mutex);
+ cv::ocl::setUseOpenCL(request.value->value<bool>());
+ }
+
+ return AmbPluginImpl::setProperty(request);;
+}
+
+void OpenCvLuxPlugin::subscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ if(!shared->mRequests.size())
+ {
+ init();
+ g_timeout_add(1000 / shared->fps, grabImage, shared.get());
+ }
+
+ shared->mRequests.push_back(property);
+}
+
+void OpenCvLuxPlugin::unsubscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ removeOne(&shared->mRequests,property);
+}
+
+void OpenCvLuxPlugin::propertyChanged(AbstractPropertyType *value)
+{
+ QMutexLocker lock(&mutex);
+ if(value->name == VehicleProperty::VehicleSpeed)
+ {
+ speed = value->value<uint16_t>();
+ }
+ else if(value->name == VehicleProperty::Latitude)
+ {
+ latitude = value->value<double>();
+ }
+ else if(value->name == VehicleProperty::Longitude)
+ {
+ longitude = value->value<double>();
+ }
+}
+
+void OpenCvLuxPlugin::supportedChanged(const PropertyList &)
+{
+ DebugOut()<<"OpenCvLuxPlugin::supported changed."<<endl;
+}
+
+static int grabImage(void *data)
+{
+ OpenCvLuxPlugin::Shared* shared = static_cast<OpenCvLuxPlugin::Shared*>(data);
+
+ shared->frameCount++;
+
+ if(shared->frameCount >= shared->fps)
+ shared->frameCount = 0;
+
+ if(shared->frameCount % 4 != 0)
+ {
+ return true;
+ }
+
+ if(!shared->m_capture->isOpened())
+ return false;
+
+ cv::UMat m_image;
+
+ *(shared->m_capture.get()) >> m_image;
+
+ if(shared->ddd)
+ {
+ try
+ {
+ shared->parent->detectEyes(m_image);
+ }
+ catch(...)
+ {
+ DebugOut(DebugOut::Warning) << "DDD detection exception: "<< endl;
+ }
+ }
+
+ if(shared->threaded)
+ {
+ QFutureWatcher<uint> *watcher = new QFutureWatcher<uint>();
+ QObject::connect(watcher, &QFutureWatcher<uint>::finished, shared->parent, &OpenCvLuxPlugin::imgProcResult);
+
+ QFuture<uint> future = QtConcurrent::run(evalImage, m_image, shared);
+ watcher->setFuture(future);
+
+ QtConcurrent::run(shared->parent, &OpenCvLuxPlugin::writeVideoFrame, m_image);
+ }
+ else
+ {
+ if(shared->parent->videoLogging->value<bool>())
+ shared->parent->writeVideoFrame(m_image);
+ try
+ {
+ uint16_t lux = evalImage(m_image, shared);
+ shared->parent->updateProperty(lux);
+ }
+ catch(...)
+ {
+ DebugOut(DebugOut::Warning) << "Exception caught "<< __FUNCTION__ << endl;
+ }
+
+ //detectLight(m_image,shared);
+ }
+
+ if(shared->mRequests.size())
+ {
+ return true;
+ }
+
+ return false;
+}
+
+static uint evalImage(cv::UMat qImg, OpenCvLuxPlugin::Shared *shared)
+{
+ if(qImg.empty())
+ {
+ DebugOut(DebugOut::Warning)<<"Empty image frame."<<endl;
+ return 0;
+ }
+
+ cv::Scalar avgPixelIntensity;
+
+ avgPixelIntensity = cv::mean(qImg);
+
+ double val = avgPixelIntensity.val[0];
+
+ double qualifiedPixel = (val - shared->pixelLowerBound);
+
+ if(qualifiedPixel < 0) qualifiedPixel = 0;
+
+ uint lux = qualifiedPixel * (130000.0 / shared->pixelUpperBound);
+
+ DebugOut(7)<<"average pixel value: "<<qualifiedPixel<<" lux: "<<lux<<endl;
+
+ return lux;
+}
+
+
+void OpenCvLuxPlugin::init()
+{
+ if(!shared->m_capture)
+ {
+ if(device == "")
+ shared->m_capture = amb::make_unique(new cv::VideoCapture(0));
+ else
+ shared->m_capture = amb::make_unique(new cv::VideoCapture(atoi(device.c_str())));
+ }
+
+ if(!shared->m_capture->isOpened())
+ {
+ DebugOut() << "we failed to open camera device (" << device << ") or no camera found" << endl;
+ return;
+ }
+
+ if(!shared->mWriter || !shared->mWriter->isOpened())
+ {
+ cv::Size s = cv::Size((int) shared->m_capture->get(cv::CAP_PROP_FRAME_WIDTH),
+ (int) shared->m_capture->get(cv::CAP_PROP_FRAME_HEIGHT));
+
+ std::string codec = configuration["codec"];
+
+ if(codec.empty() || codec.size() != 4)
+ {
+ DebugOut(DebugOut::Warning)<<"Invalid codec: "<<codec <<". Using default: MJPG"<<endl;
+ codec = "MJPG";
+ }
+
+ std::string filename = configuration["logfile"];
+
+ if(filename.empty()) filename = "/tmp/video.avi";
+
+ boost::algorithm::to_upper(codec);
+
+ shared->mWriter = amb::make_unique(new cv::VideoWriter(filename, cv::VideoWriter::fourcc(codec.at(0), codec.at(1), codec.at(2), codec.at(3)),30,s));
+ }
+
+ DebugOut()<<"camera frame width: "<<shared->m_capture->get(cv::CAP_PROP_FRAME_WIDTH)<<endl;
+ DebugOut()<<"camera frame height: "<<shared->m_capture->get(cv::CAP_PROP_FRAME_HEIGHT)<<endl;
+ DebugOut()<<"camera frame fps: "<<shared->m_capture->get(cv::CAP_PROP_FPS)<<endl;
+
+ return;
+}
+
+
+
+void OpenCvLuxPlugin::writeVideoFrame(cv::UMat f)
+{
+ QMutexLocker locker(&mutex);
+
+ if(shared->loggingOn && speed > 0)
+ {
+ cv::Mat frame;
+ f.copyTo(frame);
+
+ std::stringstream str;
+ str<<"Speed: "<<speed<<" kph, Lat/Lon: "<<latitude<<"/"<<longitude;
+
+ std::stringstream datestr;
+ datestr<<QDateTime::currentDateTime().toString().toStdString();
+
+ locker.unlock();
+
+ std::string text = str.str();
+
+ int fontFace = cv::FONT_HERSHEY_SIMPLEX;
+ double fontScale = 1;
+ int thickness = 3;
+
+ int baseline=0;
+ cv::Size textSize = cv::getTextSize(text, fontFace,
+ fontScale, thickness, &baseline);
+
+ cv::Size dateTextSize = cv::getTextSize(datestr.str(), fontFace,
+ fontScale, thickness, &baseline);
+
+ baseline += thickness;
+
+ // center the text
+ cv::Point textOrg((frame.cols - textSize.width)/2,
+ (frame.rows - textSize.height));
+
+ cv::Point dateOrg((frame.cols - dateTextSize.width)/2, dateTextSize.height);
+
+ // then put the text itself
+ cv::putText(frame, text, textOrg, fontFace, fontScale,
+ cv::Scalar::all(255), thickness, 8);
+
+ cv::putText(frame, datestr.str(), dateOrg, fontFace, fontScale,
+ cv::Scalar::all(255), thickness, 8);
+
+ (*shared->mWriter) << frame;
+ (*shared->mWriter) << frame;
+ }
+}
+
+void OpenCvLuxPlugin::updateProperty(uint16_t lux)
+{
+ extBrightness->setValue(lux);
+
+ if(lux != lastLux && shared->mRequests.size())
+ {
+ lastLux = lux;
+ routingEngine->updateProperty(extBrightness.get(), uuid());
+ }
+}
+
+void OpenCvLuxPlugin::imgProcResult()
+{
+ try
+ {
+ QFutureWatcher<uint> *watcher = dynamic_cast<QFutureWatcher<uint>*>(sender());
+
+ uint lux = watcher->result();
+ shared->parent->updateProperty(lux);
+
+ watcher->deleteLater();
+ }
+ catch(...)
+ {
+ DebugOut(DebugOut::Warning) << "exception caught getting img processing result" << endl;
+ }
+}
+
+TrafficLight::Color detectLight(cv::UMat img, OpenCvLuxPlugin::Shared *shared)
+{
+
+ cv::UMat gray;
+
+ cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
+ cv::GaussianBlur(gray, gray, cv::Size(9,9), 2, 2);
+
+ std::vector<cv::Vec3f> circles;
+
+ //cv::HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 1, gray.rows/8, 200, 100, 0, 0);
+
+ cv::HoughCircles( gray, circles, cv::HOUGH_GRADIENT, 2, 30, 231, 50, 0, 0 );
+
+ for(auto i = 0; i < circles.size(); i++)
+ {
+ cv::Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
+ int radius = cvRound(circles[i][2]);
+
+ cv::Rect rect(center.x - radius / 2, center.y - radius / 2, radius, radius);
+
+ try {
+
+ cv::UMat light(img, rect);
+
+ cv::circle(img, center, radius, cv::Scalar(0,0,255), 3, 8, 0 );
+
+ cv::rectangle(img, rect.tl(), rect.br(), cv::Scalar(255,0,0));
+
+ cv::Scalar avgPixel = cv::mean(light);
+
+ if(avgPixel[2] > 128 && avgPixel[0] < 128 && avgPixel[1] < 128)
+ {
+ DebugOut(1)<<"Red Light!!!"<<endl;
+ return TrafficLight::Red;
+ }
+ else if(avgPixel[1] > 128 && avgPixel[0] < 128 && avgPixel[2] < 128)
+ {
+ DebugOut(1)<<"Green Light!!!"<<endl;
+ return TrafficLight::Green;
+ }
+ else if(avgPixel[0] > 128 && avgPixel[1] < 128 && avgPixel[2] < 128)
+ {
+ DebugOut(1)<<"Yellow Light!!!"<<endl;
+ return TrafficLight::Yellow;
+ }
+ }
+ catch(...)
+ {
+
+ }
+
+ }
+}
+
+
+void OpenCvLuxPlugin::detectEyes(cv::UMat frame)
+{
+ if(frame.empty())
+ return;
+
+ bool hasEyes = false;
+ std::vector<cv::Rect> faces;
+ cv::UMat frameGray;
+
+
+ cv::cvtColor(frame, frameGray, cv::COLOR_BGR2GRAY);
+ cv::equalizeHist(frameGray, frameGray);
+ faceCascade->detectMultiScale(frameGray, faces, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));
+
+ for( size_t i = 0; i < faces.size(); i++ )
+ {
+ cv::Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );
+ cv::ellipse( frame, center, cv::Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, cv::Scalar( 255, 0, 255 ), 4, 8, 0 );
+
+ std::vector<cv::Rect> eyes;
+
+
+ cv::UMat faceROI(frameGray(faces[i]));
+ eyeCascade->detectMultiScale( faceROI, eyes, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30) );
+
+ for( size_t j = 0; j < eyes.size(); j++ )
+ {
+ cv::Point center( faces[i].x + eyes[j].x + eyes[j].width*0.5, faces[i].y + eyes[j].y + eyes[j].height*0.5 );
+ int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
+ cv::circle( frame, center, radius, cv::Scalar( 255, 0, 0 ), 4, 8, 0 );
+ }
+
+ if(eyes.size())
+ {
+ hasEyes = true;
+ DebugOut() << "Number of eyes: " << eyes.size() << endl;
+
+ if(driverDrowsiness->value<bool>())
+ {
+ driverDrowsiness->setValue(false);
+ routingEngine->updateProperty(driverDrowsiness.get(), this->uuid());
+ }
+ }
+ else
+ {
+ if(!driverDrowsiness->value<bool>())
+ {
+ driverDrowsiness->setValue(true);
+ routingEngine->updateProperty(driverDrowsiness.get(), this->uuid());
+ }
+ }
+ }
+}
diff --git a/plugins/opencvlux/opencvluxplugin.h b/plugins/opencvlux/opencvluxplugin.h
new file mode 100644
index 00000000..aecd08e2
--- /dev/null
+++ b/plugins/opencvlux/opencvluxplugin.h
@@ -0,0 +1,127 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef OPENCVLUXPLUGIN_H
+#define OPENCVLUXPLUGIN_H
+
+#include <abstractsource.h>
+#include <ambpluginimpl.h>
+#include <string>
+#include <memory>
+
+#include <opencv2/objdetect.hpp>
+#include <opencv2/highgui/highgui.hpp>
+
+#include <QObject>
+#include <QMutex>
+
+using namespace std;
+
+class OpenCvLuxPlugin: public QObject, public AmbPluginImpl
+{
+Q_OBJECT
+public:
+
+ typedef BasicPropertyType<bool> DriverDrowsinessType;
+
+ struct Shared
+ {
+ Shared(): frameCount(0) { }
+ std::unique_ptr<cv::VideoCapture> m_capture;
+ std::unique_ptr<cv::VideoWriter> mWriter;
+ PropertyList mRequests;
+ OpenCvLuxPlugin* parent;
+
+ int fps;
+ bool threaded;
+ bool kinect;
+ bool useCuda;
+ int pixelLowerBound;
+ int pixelUpperBound;
+ bool loggingOn;
+ bool ddd;
+ int frameCount;
+ };
+
+ OpenCvLuxPlugin(AbstractRoutingEngine* re, map<string, string> config, AbstractSource& parent);
+
+ ~OpenCvLuxPlugin();
+
+ const string uuid() const;
+ void getPropertyAsync(AsyncPropertyReply *reply);
+ void getRangePropertyAsync(AsyncRangePropertyReply *reply);
+ AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request);
+ void subscribeToPropertyChanges(VehicleProperty::Property property);
+ void unsubscribeToPropertyChanges(VehicleProperty::Property property);
+
+ void propertyChanged(AbstractPropertyType* value);
+
+ void supportedChanged(const PropertyList &);
+
+ void updateProperty(uint16_t lux);
+
+ void writeVideoFrame(cv::UMat frame);
+
+ void detectEyes(cv::UMat frame);
+
+ void init();
+
+ std::shared_ptr<AbstractPropertyType> videoLogging;
+
+public Q_SLOTS:
+ void imgProcResult();
+
+private:
+ uint speed;
+ uint latitude;
+ uint longitude;
+
+ uint lastLux;
+ std::string device;
+ std::list<AsyncPropertyReply*> replyQueue;
+
+ std::shared_ptr<AbstractPropertyType> extBrightness;
+
+ std::unique_ptr<Shared> shared;
+ QMutex mutex;
+
+ std::unique_ptr<cv::CascadeClassifier> faceCascade;
+ std::unique_ptr<cv::CascadeClassifier> eyeCascade;
+
+ std::shared_ptr<AbstractPropertyType> driverDrowsiness;
+ std::shared_ptr<AbstractPropertyType> openCl;
+};
+
+static int grabImage(void *data);
+static uint evalImage(cv::UMat qImg, OpenCvLuxPlugin::Shared *shared);
+
+namespace TrafficLight
+{
+enum Color
+{
+ Unknown = -1,
+ Red = 0,
+ Yellow,
+ Green
+};
+}
+
+TrafficLight::Color detectLight(cv::UMat img, OpenCvLuxPlugin::Shared* shared);
+
+
+#endif // EXAMPLEPLUGIN_H
diff --git a/plugins/openxc/CMakeLists.txt b/plugins/openxc/CMakeLists.txt
new file mode 100644
index 00000000..5c4cc1e0
--- /dev/null
+++ b/plugins/openxc/CMakeLists.txt
@@ -0,0 +1,19 @@
+if(openxc_plugin)
+
+
+message(STATUS "openxc protocol plugin enabled")
+
+pkg_check_modules(json REQUIRED json)
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${json_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/plugins/common)
+
+set(openxcplugin_headers openxcplugin.h)
+set(openxcplugin_sources openxcplugin.cpp)
+
+add_library(openxcplugin MODULE ${openxcplugin_sources})
+set_target_properties(openxcplugin PROPERTIES PREFIX "")
+target_link_libraries(openxcplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib amb-plugins-common -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common ${link_libraries} ${json_LIBRARIES})
+
+install(TARGETS openxcplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+
+endif(openxc_plugin)
diff --git a/plugins/openxc/README b/plugins/openxc/README
new file mode 100644
index 00000000..57db1e40
--- /dev/null
+++ b/plugins/openxc/README
@@ -0,0 +1,40 @@
+OpenXC plugin
+
+This plugin uses the OpenXC protocol supported devices to provide information to AMB.
+
+To enable the OpenXC plugin, run cmake and enable the openxc_plugin option:
+
+cmake -Dopenxc_plugin=On ..
+
+To use the Database plugin, add the following to the "sources" array in /etc/ambd/config:
+
+{
+ "name" : "openxc",
+ "path" : "/usr/lib/automotive-message-broker/openxcplugin.so",
+ "device" : "/dev/ttyUSB0",
+ "bluetoothAdapter" : "00:00:00:00:00:00",
+ "test" : "false"
+}
+
+Configuration Key Definitions:
+
+"name"
+name of plugin. This key is not used by the plugin at this moment.
+
+"path"
+path to plugin on the filesystem.
+
+"device"
+openXC device. This must be a serial device. It can also be a bluetooth address.
+
+Default: none
+
+"bluetoothAdapter"
+Bluetooth adapter to use. This is only used if "device" is also a bluetooth device.
+Leave blank to use system default adapter.
+
+Default: none
+
+AMB Properties:
+
+none
diff --git a/plugins/openxc/openxcplugin.cpp b/plugins/openxc/openxcplugin.cpp
new file mode 100644
index 00000000..75c75487
--- /dev/null
+++ b/plugins/openxc/openxcplugin.cpp
@@ -0,0 +1,498 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "openxcplugin.h"
+#include "timestamp.h"
+
+#include <iostream>
+#include <boost/assert.hpp>
+#include <glib.h>
+
+#include "bluetooth.hpp"
+
+using namespace std;
+
+#include "debugout.h"
+
+bool gioPollingFunc(GIOChannel *source,GIOCondition condition,gpointer data)
+{
+ if (condition == G_IO_HUP)
+ {
+ //Hang up. Returning false closes out the GIOChannel.
+ //printf("Callback on G_IO_HUP\n");
+ return false;
+ }
+
+ OpenXCPlugin* plugin = static_cast<OpenXCPlugin*>(data);
+
+ if(!plugin)
+ {
+ throw std::runtime_error("Bad cast to OpenXCPlugin*");
+ }
+
+ plugin->processData();
+
+ return true;
+}
+
+OpenXCPlugin::OpenXCPlugin(AbstractRoutingEngine* re, map<string, string> config)
+:AbstractSource(re, config)
+{
+ re->setSupported(supported(), this);
+
+ /// populate the openxc to amb map:
+
+ openXC2AmbMap["steering_wheel_angle"] = VehicleProperty::SteeringWheelAngle;
+ //openXC2AmbMap["torque_at_transmission"] = VehicleProperty::Engine;
+ openXC2AmbMap["engine_speed"] = VehicleProperty::EngineSpeed;
+ openXC2AmbMap["vehicle_speed"] = VehicleProperty::VehicleSpeed;
+ openXC2AmbMap["accelerator_pedal_position"] = VehicleProperty::ThrottlePosition;
+ openXC2AmbMap["parking_brake_status"] = VehicleProperty::ParkingBrakeStatus;
+ openXC2AmbMap["brake_pedal_status"] = VehicleProperty::LightBrake;
+ openXC2AmbMap["transmission_gear_position"] = VehicleProperty::TransmissionGearPosition;
+ openXC2AmbMap["odometer"] = VehicleProperty::Odometer;
+ openXC2AmbMap["ignition_status"] = VehicleProperty::VehiclePowerMode;
+ openXC2AmbMap["fuel_level"] = VehicleProperty::FuelLevel;
+ openXC2AmbMap["fuel_consumed_since_restart"] = VehicleProperty::FuelConsumption;
+ openXC2AmbMap["headlamp_status"] = VehicleProperty::LightHead;
+ openXC2AmbMap["high_beam_status"] = VehicleProperty::LightHighBeam;
+ openXC2AmbMap["windshield_wiper_status"] = VehicleProperty::WindshieldWiper;
+ openXC2AmbMap["latitude"] = VehicleProperty::Latitude;
+ openXC2AmbMap["longitude"] = VehicleProperty::Longitude;
+ openXC2AmbMap["button_event"] = VehicleProperty::ButtonEvent;
+
+ bool test = false;
+ if(config.find("test") != config.end())
+ {
+ test = config["test"] == "true";
+ }
+
+ if(test)
+ {
+ testParseEngine();
+ }
+
+ std::string bluetoothAddy = config["device"];
+ std::string bluetoothAdapter = config["bluetoothAdapter"];
+ std::string serialDevice;
+
+ if(bluetoothAddy != "")
+ {
+ BluetoothDevice btDevice;
+
+ serialDevice = btDevice.getDeviceForAddress(bluetoothAddy, bluetoothAdapter);
+ }
+
+ device = new SerialPort(serialDevice);
+ if(!device->open())
+ {
+ throw std::runtime_error("unable to open serial device " + serialDevice);
+ }
+
+ GIOChannel *chan = g_io_channel_unix_new(device->fileDescriptor());
+ g_io_add_watch(chan, G_IO_IN,(GIOFunc)gioPollingFunc, this);
+ g_io_add_watch(chan,G_IO_HUP,(GIOFunc)gioPollingFunc,this);
+ g_io_add_watch(chan,G_IO_ERR,(GIOFunc)gioPollingFunc,this);
+ g_io_channel_unref(chan); //Pass ownership of the GIOChannel to the watch.
+
+
+}
+
+
+
+extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ return new OpenXCPlugin(routingengine, config);
+
+}
+
+const string OpenXCPlugin::uuid()
+{
+ return "openxc";
+}
+
+
+void OpenXCPlugin::getPropertyAsync(AsyncPropertyReply *reply)
+{
+
+}
+
+void OpenXCPlugin::getRangePropertyAsync(AsyncRangePropertyReply *reply)
+{
+
+}
+
+AsyncPropertyReply *OpenXCPlugin::setProperty(AsyncSetPropertyRequest request )
+{
+
+}
+
+void OpenXCPlugin::subscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ mRequests.push_back(property);
+}
+
+PropertyList OpenXCPlugin::supported()
+{
+ PropertyList props;
+
+ return props;
+}
+
+int OpenXCPlugin::supportedOperations()
+{
+ return Get;
+}
+
+void OpenXCPlugin::unsubscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ mRequests.remove(property);
+}
+
+
+
+bool OpenXCPlugin::translateOpenXCEvent(string json)
+{
+ /// signal:
+ /// {"name": "steering_wheel_angle", "value": 45}
+
+ /// event:
+ /// {"name": "button_event", "value": "up", "event": "pressed"}
+
+ json_object *rootobject;
+ json_tokener *tokener = json_tokener_new();
+
+
+ ///TODO: we have several json leaks here
+
+ enum json_tokener_error err;
+ do
+ {
+ rootobject = json_tokener_parse_ex(tokener, json.c_str(),json.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.
+ }
+ if (tokener->char_offset < json.length()) // XXX shouldn't access internal fields
+ {
+ // Handle extra characters after parsed object as desired.
+ // e.g. issue an error, parse another object from that point, etc...
+ }
+
+ VehicleProperty::Property property;
+
+ json_object *name = json_object_object_get(rootobject,"name");
+ if (name)
+ {
+ string namestr = string(json_object_get_string(name));
+
+ property = openXC2AmbMap[namestr];
+ }
+
+ json_object *value = json_object_object_get(rootobject, "value");
+ if(value)
+ {
+ if (property == VehicleProperty::SteeringWheelAngle)
+ {
+ int val = json_object_get_int(value);
+ VehicleProperty::SteeringWheelAngleType ambVal(val);
+
+ routingEngine->updateProperty(property, &ambVal,uuid());
+
+ return true;
+ }
+
+ else if (property == VehicleProperty::EngineSpeed)
+ {
+ int val = json_object_get_int(value);
+ VehicleProperty::EngineSpeedType ambVal(val);
+
+ routingEngine->updateProperty(property, &ambVal,uuid());
+ return true;
+ }
+
+ else if (property == VehicleProperty::VehicleSpeed)
+ {
+ int val = json_object_get_int(value);
+ VehicleProperty::VehicleSpeedType ambVal(val);
+
+ routingEngine->updateProperty(property, &ambVal,uuid());
+ return true;
+ }
+
+ else if (property == VehicleProperty::ThrottlePosition)
+ {
+ int val = json_object_get_int(value);
+ VehicleProperty::ThrottlePositionType ambVal(val);
+
+ routingEngine->updateProperty(property, &ambVal,uuid());
+
+ return true;
+ }
+
+ else if (property == VehicleProperty::LightBrake)
+ {
+ bool val = json_object_get_boolean(value);
+ VehicleProperty::LightBrakeType ambVal(val);
+
+ routingEngine->updateProperty(property, &ambVal,uuid());
+
+ return true;
+ }
+
+ else if (property == VehicleProperty::ParkingBrakeStatus)
+ {
+ bool val = json_object_get_boolean(value);
+ VehicleProperty::ParkingBrakeStatusType ambVal(val);
+
+ routingEngine->updateProperty(property, &ambVal,uuid());
+
+ return true;
+ }
+
+ else if (property == VehicleProperty::TransmissionGearPosition)
+ {
+ /// TODO: implement
+ return false;
+ }
+
+ else if (property == VehicleProperty::Odometer)
+ {
+ int val = json_object_get_int(value);
+ VehicleProperty::OdometerType ambVal(val);
+
+ routingEngine->updateProperty(property, &ambVal,uuid());
+
+ return true;
+ }
+
+ else if (property == VehicleProperty::VehiclePowerMode)
+ {
+ /// TODO: implement
+ return false;
+ }
+
+ else if (property == VehicleProperty::FuelLevel)
+ {
+ int val = json_object_get_int(value);
+ VehicleProperty::FuelLevelType ambVal(val);
+
+ routingEngine->updateProperty(property, &ambVal,uuid());
+
+ return true;
+ }
+
+ else if (property == VehicleProperty::FuelConsumption)
+ {
+ /// This is a different concept than our 'instant' fuel consumption.
+ /// TODO: we should probably do a CumulativeFuelConsuption
+ }
+
+ else if (property == VehicleProperty::DoorStatus)
+ {
+
+ }
+
+ else if (property == VehicleProperty::LightHead)
+ {
+ bool val = json_object_get_boolean(value);
+ VehicleProperty::LightHeadType ambVal(val);
+
+ routingEngine->updateProperty(property, &ambVal,uuid());
+
+ return true;
+ }
+
+ else if (property == VehicleProperty::LightHighBeam)
+ {
+ bool val = json_object_get_boolean(value);
+ VehicleProperty::LightHighBeamType ambVal(val);
+
+ routingEngine->updateProperty(property, &ambVal, uuid());
+
+ return true;
+ }
+
+ else if (property == VehicleProperty::WindshieldWiper)
+ {
+ bool val = json_object_get_boolean(value);
+ if(val)
+ {
+ Window::WiperSpeed speed = Window::Auto;
+
+ VehicleProperty::WindshieldWiperType ambVal(speed);
+ routingEngine->updateProperty(property, &ambVal, uuid());
+
+ return true;
+ }
+ else
+ {
+ Window::WiperSpeed speed = Window::Off;
+
+ VehicleProperty::WindshieldWiperType ambVal(speed);
+ routingEngine->updateProperty(property, &ambVal, uuid());
+
+ return true;
+ }
+
+ }
+
+ else if (property == VehicleProperty::Latitude)
+ {
+ double val = json_object_get_double(value);
+ VehicleProperty::LatitudeType ambVal(val);
+
+ routingEngine->updateProperty(property, &ambVal, uuid());
+
+ return true;
+ }
+
+ else if (property == VehicleProperty::Longitude)
+ {
+ double val = json_object_get_double(value);
+ VehicleProperty::LongitudeType ambVal(val);
+
+ routingEngine->updateProperty(property, &ambVal, uuid());
+
+ return true;
+ }
+
+ else if (property == VehicleProperty::ButtonEvent)
+ {
+ /// TODO: implement
+ DebugOut(DebugOut::Error)<<"OpenXC button event not implemented"<<endl;
+ return false;
+ }
+ }
+
+ return false;
+
+}
+
+void OpenXCPlugin::testParseEngine()
+{
+ bool passed = true;
+
+ if(!translateOpenXCEvent("{\"name\": \"steering_wheel_angle\", \"value\": 45}"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (steering_wheel_angle): \tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (steering_wheel_angle): \tPassed"<<endl;
+
+ if(!translateOpenXCEvent("{\"name\": \"engine_speed\", \"value\": 5000}"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (engine_speed): \t\tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (engine_speed): \t\tPassed"<<endl;
+ if(!translateOpenXCEvent("{\"name\": \"vehicle_speed\", \"value\": 100}"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (vehicle_speed): \t\tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (vehicle_speed): \t\tPassed"<<endl;
+ if(!translateOpenXCEvent("{\"name\": \"accelerator_pedal_position\", \"value\": 90}"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (accelerator_pedal_position): tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (accelerator_pedal_position):\tPassed"<<endl;
+ if(!translateOpenXCEvent("{\"name\": \"parking_brake_status\", \"value\": \"false\" }"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (parking_brake_status):\tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (parking_brake_status):\tPassed"<<endl;
+ if(!translateOpenXCEvent("{\"name\": \"brake_pedal_status\", \"value\": \"false\" }"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (brake_pedal_status):\tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (brake_pedal_status):\tPassed"<<endl;
+ if(!translateOpenXCEvent("{\"name\": \"transmission_gear_position\", \"value\": \"fourth\"}"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (transmission_gear_position):\tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (transmission_gear_position):\tPassed"<<endl;
+ if(!translateOpenXCEvent("{\"name\": \"odometer\", \"value\": 1000}"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (odometer): \t\tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (odometer): \t\tPassed"<<endl;
+ if(!translateOpenXCEvent("{\"name\": \"ignition_status\", \"value\": \"run\"}"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (ignition_status): \t\tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (ignition_status): \t\tPassed"<<endl;
+ if(!translateOpenXCEvent("{\"name\": \"fuel_level\", \"value\": 30}"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (fuel_level): \t\tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (fuel_level): \t\tPassed"<<endl;
+ if(!translateOpenXCEvent("{\"name\": \"fuel_consumed_since_restart\", \"value\": 45}"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (fuel_consumed_since_restart):\tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (fuel_consumed_since_restart):\tPassed"<<endl;
+ if(!translateOpenXCEvent("{\"name\": \"headlamp_status\", \"value\": \"true\"}"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (headlamp_status): \t\tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (headlamp_status): \t\tPassed"<<endl;
+ if(!translateOpenXCEvent("{\"name\": \"latitude\", \"value\": 88.12125}"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (latitude): \t\tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (latitude): \t\tPassed"<<endl;
+ if(!translateOpenXCEvent("{\"name\": \"longitude\", \"value\": 108.12125}"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (longitude): \t\tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (longitude): \t\tPassed"<<endl;
+ if(!translateOpenXCEvent("{\"name\": \"button_event\", \"value\": \"up\", \"event\": \"pressed\"}"))
+ {
+ DebugOut(0)<<"OpenXC Parse Test (button_event): \t\tFailed"<<endl;
+ passed = false;
+ }
+ else DebugOut(0)<<"OpenXC Parse Test (button_event): \t\tPassed"<<endl;
+
+ if(!passed)
+ {
+ DebugOut(0)<<"Some OpenXC Parse Tests failed. Aborting";
+ throw std::runtime_error("OpenXC Parse tests failed.");
+ }
+}
+
+
+void OpenXCPlugin::processData()
+{
+ std::string data = device->read();
+
+ translateOpenXCEvent(data);
+}
diff --git a/plugins/openxc/openxcplugin.h b/plugins/openxc/openxcplugin.h
new file mode 100644
index 00000000..86dc9aea
--- /dev/null
+++ b/plugins/openxc/openxcplugin.h
@@ -0,0 +1,61 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef OPENXCPLUGIN_H
+#define OPENXCPLUGIN_H
+
+#include <abstractsource.h>
+#include <string>
+
+#include "serialport.hpp"
+
+using namespace std;
+
+class OpenXCPlugin: public AbstractSource
+{
+public:
+ OpenXCPlugin(AbstractRoutingEngine* re, map<string, string> config);
+
+ const string uuid();
+ void getPropertyAsync(AsyncPropertyReply *reply);
+ void getRangePropertyAsync(AsyncRangePropertyReply *reply);
+ AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request);
+ void subscribeToPropertyChanges(VehicleProperty::Property property);
+ void unsubscribeToPropertyChanges(VehicleProperty::Property property);
+ PropertyList supported();
+
+ int supportedOperations();
+
+ void propertyChanged(VehicleProperty::Property property, AbstractPropertyType* value, string uuid) {}
+ void supportedChanged(PropertyList) {}
+
+ void processData();
+
+private:
+ PropertyList mRequests;
+
+ bool translateOpenXCEvent(std::string json);
+
+ void testParseEngine();
+ std::map<std::string, std::string> openXC2AmbMap;
+
+ SerialPort* device;
+
+};
+
+#endif // EXAMPLEPLUGIN_H
diff --git a/plugins/plugins.in.idl b/plugins/plugins.in.idl
new file mode 100644
index 00000000..79698215
--- /dev/null
+++ b/plugins/plugins.in.idl
@@ -0,0 +1,21 @@
+/*!
+ * \file plugins.idl
+ * \section plugins AMB Plugin documentation
+ *
+ * \section intro Introduction
+ * AMB plugins each have their own usage documentation including any special AMB Properties or DBus interfaces they define. Below is a description
+ * of several AMB plugins and their documenation:
+ * - \ref bluemonkey_plugin - Extensible javascript engine plugin for defining plugin behavior in javascript
+ * - \ref database_plugin - Plugin that logs data in a sqlite database and can play back logs
+ * - \ref dbus_plugin - Exposes AMB Properties on DBus
+ * - \ref gpsnmea_plugin - GPS Plugin that provides location position data from NMEA compatible devices
+ * - \ref obd2_plugin - Plugin that provides data from OBD-II compatible vehicles
+ * - \ref opencvlux_plugin - Plugin that uses OpenCV to produce ADAS data and perform video logging
+ * - \ref websocket_plugin - Both source and sink plugin that uses a websocket protocol to communicate
+ * - \ref wheel_plugin - Plugin that generates data using the Logitech G27 racing wheel
+ *
+ * \section plugins_docs Additional Plugin Documentation
+ * In addition to the plugin documentation listed above, some plugins have additional information. Here are some links:
+ * - \ref bluemonkey
+ * - \ref websocket
+ */
diff --git a/plugins/testplugin/CMakeLists.txt b/plugins/testplugin/CMakeLists.txt
new file mode 100644
index 00000000..f66d52bb
--- /dev/null
+++ b/plugins/testplugin/CMakeLists.txt
@@ -0,0 +1,16 @@
+if(test_plugin)
+
+include(CheckIncludeFiles)
+
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs})
+
+set(testplugin_headers testplugin.h)
+set(testplugin_sources testplugin.cpp)
+add_library(testplugin MODULE ${testplugin_sources})
+set_target_properties(testplugin PROPERTIES PREFIX "")
+target_link_libraries(testplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib)
+
+install(TARGETS testplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+
+endif(test_plugin)
diff --git a/plugins/testplugin/README b/plugins/testplugin/README
new file mode 100644
index 00000000..6215a9c4
--- /dev/null
+++ b/plugins/testplugin/README
@@ -0,0 +1,18 @@
+Test Source Plugin
+
+The test source plugin tests the internal routing engine of AMB. If there is an error, the test plugin will cause ambd to abort.
+This plugin is useful when testing changes in AMB's core routing engine.
+
+To use the Test Source plugin, add the following config to your /etc/ambd/config:
+
+
+"sources" : [
+ {
+ "name" : "test",
+ "path" : "/usr/lib/automotive-message-broker/testsourceplugin.so"
+ }
+ ]
+
+
+
+
diff --git a/plugins/testplugin/testplugin.cpp b/plugins/testplugin/testplugin.cpp
new file mode 100644
index 00000000..9b76732e
--- /dev/null
+++ b/plugins/testplugin/testplugin.cpp
@@ -0,0 +1,446 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include <iostream>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <glib.h>
+#include <sstream>
+//#include <json-glib/json-glib.h>
+#include <listplusplus.h>
+#include <vehicleproperty.h>
+#include <abstractpropertytype.h>
+#include "debugout.h"
+#include "timestamp.h"
+#include "testplugin.h"
+#define __SMALLFILE__ std::string(__FILE__).substr(std::string(__FILE__).rfind("/")+1)
+AbstractRoutingEngine *m_re;
+
+#define TEST(success) g_assert((success));
+const std::string TestProptertyName1 = "TestPropertyName1";
+const std::string TestProptertyName2 = "TestPropertyName2";
+
+//std::list<ObdPid*> Obd2Amb::supportedPidsList;
+
+void testBooleanToStringFromString()
+{
+ BasicPropertyType<bool> boolean(true);
+ std::string isTrue = boolean.toString();
+ boolean.fromString(boolean.toString());
+ std::string isTrue2 = boolean.toString();
+
+ TEST(isTrue == isTrue2);
+}
+
+bool beginsWith(std::string a, std::string b)
+{
+ return (a.compare(0, b.length(), b) == 0);
+}
+
+/**
+ * Tests Core's methods:
+ * * setSupported
+ * * supported
+ * * sourcesForProperty
+ * * getPropertyInfo
+ */
+
+bool TestPlugin::testCoreSetSupported()
+{
+ PropertyList supported(routingEngine->supported());
+ TEST(contains(supported, TestProptertyName1) == false);
+
+ //
+ // CALL setSupported
+ //
+
+ // valid call
+ routingEngine->updateSupported(m_supportedProperties, PropertyList(), this);
+
+ TEST(routingEngine->getPropertyInfo(TestProptertyName1, uuid()).isValid() == true);
+ Zone::ZoneList zones(routingEngine->getPropertyInfo(TestProptertyName1, uuid()).zones());
+ TEST(contains(zones, Zone::LeftSide) == true);
+
+ supported = routingEngine->supported();
+ TEST(contains(supported, TestProptertyName1) == true);
+ TEST(contains(supported, TestProptertyName2) == true);
+ TEST(contains(supported, VehicleProperty::ClutchStatus) == false);
+
+ std::vector<std::string> sources = routingEngine->sourcesForProperty(TestProptertyName1);
+ TEST(contains(sources,uuid()) == true);
+
+ TEST(routingEngine->getPropertyInfo(TestProptertyName2, uuid()).isValid() == true);
+ zones = routingEngine->getPropertyInfo(TestProptertyName2, uuid()).zones();
+ TEST(contains(zones, Zone::FrontSide) == true);
+
+ return true;
+}
+
+/**
+ * Tests Core's methods:
+ * * unregisterSink
+ * * registerSink
+ * * sourcesForProperty
+ * * subscribeToProperty - 2 versions
+ * * unsubscribeToProperty
+ */
+
+bool TestPlugin::testSubscription()
+{
+ int oldSubscriptionsToSupportedCounter = subscriptionsToSupportedCounter;
+ int oldSubscriptionsToUnsupportedCounter = subscriptionsToUnsupportedCounter;
+ int oldUnsubscriptionsToSupportedCounter= unsubscriptionsToSupportedCounter;
+ int oldUnsubscriptionsToUnsupportedCounter = unsubscriptionsToUnsupportedCounter;
+
+ // ! subscription works without having sink registered ! so there is no need to test
+ // routingEngine->registerSink(this) and routingEngine->unregisterSink(this)
+ routingEngine->unregisterSink(this);
+ routingEngine->registerSink(this);
+
+ // VehicleProperty::ClutchStatus doesn't exist
+ TEST(routingEngine->subscribeToProperty(VehicleProperty::ClutchStatus, uuid(), this) == false);
+ TEST(oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
+ TEST(oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
+
+ // TestProptertyName1 exists in our testplugin
+ TEST(routingEngine->subscribeToProperty(TestProptertyName1, uuid(), this) == true);
+ TEST(++oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
+ TEST(oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
+
+ TEST(routingEngine->subscribeToProperty(TestProptertyName1, "", this) == false);
+ TEST(oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
+ TEST(oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
+
+ // "other" source means no subscription callback in our plugin
+ TEST(routingEngine->subscribeToProperty(TestProptertyName1, "other", this) == false);
+ TEST(oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
+ TEST(oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
+
+ // we have subscribed TestProptertyName1 and not subscribed TestProptertyName2
+ int oldSupportedPropertyChanges = supportedPropertyChanges;
+ int oldPropertyChanges = propertyChanges;
+
+ AbstractPropertyType* value = new BasicPropertyType<int>(TestProptertyName1, 22);
+ value->priority = AbstractPropertyType::Instant;
+ routingEngine->updateProperty(value, "");
+ TEST(oldSupportedPropertyChanges == supportedPropertyChanges);
+ TEST(oldPropertyChanges == propertyChanges);
+ routingEngine->updateProperty(value, uuid());
+ TEST(++oldSupportedPropertyChanges == supportedPropertyChanges);
+ TEST(++oldPropertyChanges == propertyChanges);
+ delete value;
+
+ value = new BasicPropertyType<short>(TestProptertyName2, 255);
+ value->priority = AbstractPropertyType::Instant;
+ routingEngine->updateProperty(value, "");
+ TEST(oldSupportedPropertyChanges == supportedPropertyChanges);
+ TEST(oldPropertyChanges == propertyChanges);
+ routingEngine->updateProperty(value, uuid());
+ TEST(oldSupportedPropertyChanges == supportedPropertyChanges);
+ TEST(oldPropertyChanges == propertyChanges);
+ delete value;
+
+ value = new BasicPropertyType<bool>(VehicleProperty::ClutchStatus, true);
+ value->priority = AbstractPropertyType::Instant;
+ routingEngine->updateSupported({VehicleProperty::ClutchStatus},PropertyList(), this);
+
+ class TestSink : public AbstractSink
+ {
+ public:
+ TestSink(AbstractRoutingEngine* engine, map<string, string> config) : AbstractSink(engine, config) {}
+ virtual const string uuid() { return "other"; }
+ virtual void propertyChanged(AbstractPropertyType *value){ ++propertyChanges; }
+ virtual void supportedChanged(const PropertyList & supportedProperties){};
+
+ int propertyChanges = 0;
+ };
+
+ //some other sink is subscribed, not this plug-in!
+ TestSink anotherSink(routingEngine, {});
+ TEST(routingEngine->subscribeToProperty(VehicleProperty::ClutchStatus, &anotherSink) == true);
+ TEST(oldSubscriptionsToSupportedCounter == subscriptionsToSupportedCounter);
+ TEST(++oldSubscriptionsToUnsupportedCounter == subscriptionsToUnsupportedCounter);
+ routingEngine->updateProperty(value, uuid());// uuid() != "other" no sink notified
+ TEST(anotherSink.propertyChanges == 1);// one update
+ TEST(oldSupportedPropertyChanges == supportedPropertyChanges);// no updates
+ TEST(oldPropertyChanges == propertyChanges);// no updates
+ TEST(routingEngine->unsubscribeToProperty(VehicleProperty::ClutchStatus, &anotherSink) == true);
+ routingEngine->updateSupported(PropertyList(),{VehicleProperty::ClutchStatus}, this);
+ TEST(oldUnsubscriptionsToSupportedCounter == unsubscriptionsToSupportedCounter);
+ TEST(++oldUnsubscriptionsToUnsupportedCounter == unsubscriptionsToUnsupportedCounter);
+
+
+ /// test lamba subscription:
+
+ TEST (routingEngine->subscribeToProperty(VehicleProperty::VehicleSpeed,[](AbstractPropertyType* value)
+ {
+ DebugOut(0)<<"lamba subscriptions work!"<<endl;
+ TEST(value);
+ }) > 0);
+
+ /// change vehiclespeed to trigger subscribe above
+
+ PropertyList s;
+ s.push_back(VehicleProperty::VehicleSpeed);
+
+ routingEngine->updateSupported(s, PropertyList(), this);
+ VehicleProperty::VehicleSpeedType speed(10);
+ speed.priority = AbstractPropertyType::Instant;
+
+ routingEngine->updateProperty(&speed,uuid());
+ routingEngine->updateSupported(PropertyList(), s, this);
+
+ delete value;
+
+ // unsubscription
+
+ // VehicleProperty::ClutchStatus doesn't exist
+ TEST(routingEngine->unsubscribeToProperty(VehicleProperty::ClutchStatus, this) == false);
+ TEST(oldUnsubscriptionsToSupportedCounter == unsubscriptionsToSupportedCounter);
+ TEST(oldUnsubscriptionsToUnsupportedCounter == unsubscriptionsToUnsupportedCounter);
+
+ // TestProptertyName1 exists in our testplugin
+ // subscribed 2x, lets try to unsubscribe 3x
+ // we should get only one unsubscription callback
+ TEST(routingEngine->unsubscribeToProperty(TestProptertyName1, this) == true);
+ TEST(routingEngine->unsubscribeToProperty(TestProptertyName1, this) == false);
+ TEST(routingEngine->unsubscribeToProperty(TestProptertyName1, this) == false);
+ TEST(++oldUnsubscriptionsToSupportedCounter == unsubscriptionsToSupportedCounter);
+ TEST(oldUnsubscriptionsToUnsupportedCounter == unsubscriptionsToUnsupportedCounter);
+
+ // TestProptertyName2 not subscribed
+ TEST(routingEngine->unsubscribeToProperty(TestProptertyName2, this) == false);;
+ TEST(oldUnsubscriptionsToSupportedCounter == unsubscriptionsToSupportedCounter);
+ TEST(oldUnsubscriptionsToUnsupportedCounter == unsubscriptionsToUnsupportedCounter);
+
+ return true;
+}
+
+bool TestPlugin::testSetAndGet()
+{
+ bool replySuccess(false);
+ int replyError(-1);
+ std::string replySignalName("");
+
+ // Invalid request test
+ AsyncSetPropertyRequest requestInvalid;
+ requestInvalid.timeout = 0;
+ AsyncPropertyReply* reply = routingEngine->setProperty(requestInvalid);
+ TEST(reply == nullptr);
+
+ requestInvalid.property = "NotExists";
+ requestInvalid.completed = [&](AsyncPropertyReply* reply)
+ {
+ replySuccess = reply->success;
+ replyError = reply->error;
+ delete reply;
+ };
+
+ reply = routingEngine->setProperty(requestInvalid);
+
+ TEST(replySuccess == false);
+ TEST(replyError == -1);
+
+ AsyncSetPropertyRequest request;
+ request.timeout = 0;
+ request.property = TestProptertyName1;
+ request.zoneFilter = Zone::LeftSide;
+ request.value = VehicleProperty::getPropertyTypeForPropertyNameValue(request.property, "1");
+ request.completed = requestInvalid.completed;
+
+ reply = routingEngine->setProperty(request);
+ delete request.value;
+ request.value = nullptr;
+
+ TEST(replySuccess == true);
+ TEST(replyError == AsyncPropertyReply::NoError);
+}
+
+bool TestPlugin::testCoreUpdateSupported()
+{
+ bool success = false;
+
+ PropertyList toAdd;
+ toAdd.push_back(VehicleProperty::ClutchStatus);
+
+ routingEngine->updateSupported(toAdd,PropertyList(), this);
+
+ PropertyList supported = routingEngine->supported();
+
+ success = contains(supported,VehicleProperty::ClutchStatus);
+
+ PropertyList toRemove = toAdd;
+
+ routingEngine->updateSupported(PropertyList(),toRemove, this);
+
+ supported = routingEngine->supported();
+
+ success &= !contains(supported,VehicleProperty::ClutchStatus);
+
+ return success;
+}
+
+void TestPlugin::setConfiguration(map<string, string> config)
+{
+ // //Config has been passed, let's start stuff up.
+}
+
+TestPlugin::TestPlugin(AbstractRoutingEngine *re, map<string, string> config)
+ : AbstractSource(re, config),
+ m_supportedProperties({TestProptertyName1, TestProptertyName2}),
+ subscriptionsToSupportedCounter(0),
+ subscriptionsToUnsupportedCounter(0),
+ unsubscriptionsToSupportedCounter(0),
+ unsubscriptionsToUnsupportedCounter(0),
+ propertyChanges(0),
+ supportedPropertyChanges(0)
+{
+
+ DebugOut(0) << "Capabilities: " << endl;
+
+ for(auto prop : VehicleProperty::capabilities())
+ {
+ DebugOut(0) << prop << endl;
+ }
+
+ DebugOut() << "Testing Core::setSupported... " << endl;
+ testCoreSetSupported();
+
+ DebugOut() << "Testing MapPropertyType... " << endl;
+ MapPropertyType<BasicPropertyType<Door::Status>> propmap("Something");
+ MapPropertyType<BasicPropertyType<Door::Status>> propmaptwo("SomethingElse");
+ propmap.append("hi", Door::Ajar);
+ GVariant *var = propmap.toVariant();
+ gsize dictsize = g_variant_n_children(var);
+ //DebugOut() << var << endl;
+ propmaptwo.fromVariant(var);
+
+ g_assert(propmaptwo.toString() == propmap.toString());
+
+ ///test fromString:
+ propmap.fromString(propmaptwo.toString());
+
+ DebugOut() << "Testing map string equivalency: " << propmaptwo.toString() << "==" << propmap.toString() << endl;
+
+ g_assert(propmaptwo.toString() == propmap.toString());
+
+ DebugOut() << "Testing ListPropertyType... " << endl;
+ VehicleProperty::TripMetersType* tfirst = new VehicleProperty::TripMetersType();
+ VehicleProperty::TripMetersType* tsecond = new VehicleProperty::TripMetersType();
+ BasicPropertyType<uint16_t> v1(0);
+ BasicPropertyType<uint16_t> v2(5);
+ BasicPropertyType<uint16_t> v3(10);
+ tfirst->append(v1);
+ tfirst->append(v2);
+ tfirst->append(v3);
+ tsecond->fromVariant(tfirst->toVariant());
+
+ GVariant* testGVSVariant = g_variant_new("i", 9);
+ TEST(GVS<int>::value(testGVSVariant) == 9);
+
+ TEST (tfirst->toString() == tsecond->toString());
+
+ testBooleanToStringFromString();
+
+ TEST (testCoreUpdateSupported());
+
+ testSubscription();
+
+ testSetAndGet();
+}
+
+TestPlugin::~TestPlugin()
+{
+ DebugOut() << "TestPlugin Destructor called!!!"<<endl;
+}
+
+PropertyList TestPlugin::supported()
+{
+ return m_supportedProperties;
+}
+
+int TestPlugin::supportedOperations()
+{
+ return Get | Set;
+}
+
+extern "C" void create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ new TestPlugin(routingengine, config);
+}
+const string TestPlugin::uuid()
+{
+ return "f77af740-f1f8-11e1-aff1-0800200c9a66";
+}
+void TestPlugin::subscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ if(contains(m_supportedProperties, property))
+ ++subscriptionsToSupportedCounter;
+ else
+ ++subscriptionsToUnsupportedCounter;
+}
+
+
+void TestPlugin::unsubscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ if(contains(m_supportedProperties, property))
+ ++unsubscriptionsToSupportedCounter;
+ else
+ ++unsubscriptionsToUnsupportedCounter;
+}
+
+
+void TestPlugin::getPropertyAsync(AsyncPropertyReply *reply)
+{
+
+}
+
+AsyncPropertyReply *TestPlugin::setProperty(AsyncSetPropertyRequest request )
+{
+ AsyncPropertyReply* reply = new AsyncPropertyReply (request);
+ reply->success = true;
+ reply->error = AsyncPropertyReply::NoError;
+ if(reply->completed)
+ reply->completed(reply);
+ return reply;
+}
+
+PropertyInfo TestPlugin::getPropertyInfo(const VehicleProperty::Property &property)
+{
+ if(!contains(m_supportedProperties, property))
+ return PropertyInfo::invalid();
+
+ if(property == TestProptertyName1){
+ return PropertyInfo(10, {Zone::LeftSide});
+ }
+ else if(property == TestProptertyName2){
+ return PropertyInfo(30, {Zone::FrontSide});
+ }
+ else{
+ return PropertyInfo(60, {Zone::None});
+ }
+}
+
+void TestPlugin::propertyChanged(AbstractPropertyType *value)
+{
+ ++propertyChanges;
+ if(value && contains(m_supportedProperties, value->name))
+ supportedPropertyChanges++;
+
+}
diff --git a/plugins/testplugin/testplugin.h b/plugins/testplugin/testplugin.h
new file mode 100644
index 00000000..1b91efae
--- /dev/null
+++ b/plugins/testplugin/testplugin.h
@@ -0,0 +1,78 @@
+
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef OBD2SOURCE_H
+#define OBD2SOURCE_H
+
+
+
+#include <abstractsource.h>
+#include <string>
+#include <sstream>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <glib.h>
+
+
+
+
+class TestPlugin : public AbstractSource
+{
+
+public:
+ TestPlugin(AbstractRoutingEngine* re, map<string, string> config);
+ ~TestPlugin();
+ const string uuid();
+ int portHandle;
+ void getPropertyAsync(AsyncPropertyReply *reply);
+ void getRangePropertyAsync(AsyncRangePropertyReply *reply){}
+ AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request);
+ void subscribeToPropertyChanges(VehicleProperty::Property property);
+ void unsubscribeToPropertyChanges(VehicleProperty::Property property);
+ PropertyList supported();
+
+ int supportedOperations();
+
+ void supportedChanged(const PropertyList &) {}
+ void setConfiguration(map<string, string> config);
+ //void randomizeProperties();
+ void updateProperty(VehicleProperty::Property property, AbstractPropertyType *value);
+
+ PropertyInfo getPropertyInfo(const VehicleProperty::Property & property);
+ void propertyChanged(AbstractPropertyType *value);
+
+private:
+ bool testCoreSetSupported();
+ bool testCoreUpdateSupported();
+ bool testSetAndGet();
+ bool testSubscription();
+
+ PropertyList m_supportedProperties;
+ int subscriptionsToSupportedCounter;
+ int subscriptionsToUnsupportedCounter;
+ int unsubscriptionsToSupportedCounter;
+ int unsubscriptionsToUnsupportedCounter;
+ int propertyChanges;
+ int supportedPropertyChanges;
+};
+
+#endif // OBD2SOURCE_H
diff --git a/plugins/websocket/CMakeLists.txt b/plugins/websocket/CMakeLists.txt
new file mode 100644
index 00000000..9745e675
--- /dev/null
+++ b/plugins/websocket/CMakeLists.txt
@@ -0,0 +1,52 @@
+if(websocket_plugin)
+
+add_definitions(-Dwebsocket_plugin)
+
+include(CheckIncludeFiles)
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs})
+
+find_package(Qt5Core REQUIRED)
+
+if(Qt5Core_FOUND)
+ 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} -DQTBINARY_DATA)
+ add_definitions(-DQT_NO_KEYWORDS)
+ set(CMAKE_AUTOMOC ON)
+endif(Qt5Core_FOUND)
+
+pkg_check_modules(websockets REQUIRED libwebsockets)
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${QT_INCLUDE_DIRS})
+
+set(websocketsink_headers websocketsink.h websocketmanager.h common.h)
+set(websocketsink_sources websocketsinkmanager.cpp websocketsink.cpp common.cpp)
+add_library(websocketsink MODULE ${websocketsink_sources})
+set_target_properties(websocketsink PROPERTIES PREFIX "")
+target_link_libraries(websocketsink amb ${websockets_LIBRARIES} -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${QT_LIBRARIES})
+
+install(TARGETS websocketsink LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+
+
+set(websocketsource_headers websocketsource.h common.h)
+set(websocketsource_sources websocketsource.cpp common.cpp)
+add_library(websocketsource MODULE ${websocketsource_sources})
+set_target_properties(websocketsource PROPERTIES PREFIX "")
+target_link_libraries(websocketsource amb ${websockets_LIBRARIES} -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries} ${QT_LIBRARIES})
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test/vehicle.js ${CMAKE_CURRENT_SOURCE_DIR}/test/vehicle.js)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test/test.js ${CMAKE_CURRENT_SOURCE_DIR}/test/test.js)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test/events.js ${CMAKE_CURRENT_SOURCE_DIR}/test/events.js)
+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.md @ONLY)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/protocol.idl ${CMAKE_CURRENT_BINARY_DIR}/protocol.idl @ONLY)
+
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/websocket.README.md DESTINATION ${DOC_INSTALL_DIR}/plugins)
+install (DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test DESTINATION ${DOC_INSTALL_DIR}/plugins/websocket COMPONENT Docs)
+
+
+endif(websocket_plugin)
diff --git a/plugins/websocket/README b/plugins/websocket/README
new file mode 100644
index 00000000..3f8ba05c
--- /dev/null
+++ b/plugins/websocket/README
@@ -0,0 +1,75 @@
+# Websocket plugins {#websocket_plugin}
+Version: @PROJECT_VERSION@
+
+The websocket sink and source plugins are designed to relay data between devices and
+potentially to web pages.
+
+To enable the websocket plugins, run cmake and enable the websocket_plugin option:
+
+cmake -Dwebsocket_plugin=On ..
+
+To use the websocket sink plugin, add the following to the "sinks" array in /etc/ambd/config:
+
+~~~~~~~~~~~~~{.json}
+{
+ "name" : "websocket sink",
+ "path" : "@PLUGIN_INSTALL_PATH@/websocketsink.so",
+ "interface" : "lo",
+ "useExtensions" : "true",
+ "binaryProtocol" : "false",
+ "ssl" : "false".
+ "cert" : "libwebsockets-test-server.pem",
+ "key" : "libwebsockets-test-server.key.pem"
+}
+~~~~~~~~~~~~~
+
+To use the websocket source plugin, add the following to the "sources" array in /etc/ambd/config:
+
+~~~~~~~~~~~~~{.json}
+{
+ "name" : "WebsocketSource",
+ "path" : "@PLUGIN_INSTALL_PATH@/websocketsource.so",
+ "port" : "23000",
+ "ssl" : "false",
+ "ip" : "192.168.1.40",
+ "binaryProtocol" : "true",
+ "useExtensions" : "true"
+}
+~~~~~~~~~~~~~
+
+## Configuration Key Definitions:
+
+"name"
+name of plugin.
+
+"path"
+path to plugin on the filesystem.
+
+"interface" (sink only)
+interface device. Usually "lo" for loopback or "eth0".
+
+default: lo
+
+"useExtensions"
+Use built in libwebsocket extensions like zlib compression of frames
+
+default: false
+
+"binaryProtocol"
+Use fast and efficient binary protocol instead of JSON.
+
+default: false
+
+"ssl"
+Use ssl secure socket
+
+default: false
+
+"cert" (sink only)
+
+path to ssl certificate
+
+"key" (sink only)
+
+path to ssl key
+
diff --git a/plugins/websocket/common.cpp b/plugins/websocket/common.cpp
new file mode 100644
index 00000000..5088620e
--- /dev/null
+++ b/plugins/websocket/common.cpp
@@ -0,0 +1,136 @@
+#include "common.h"
+#include "debugout.h"
+#include <math.h>
+#include <glib.h>
+
+#include <QVariantMap>
+
+bool doBinary = false;
+
+const char * amb::BasicTypes::UInt16Str = "UInt16";
+const char * amb::BasicTypes::UInt32Str = "UInt32";
+const char * amb::BasicTypes::Int16Str = "Int16";
+const char * amb::BasicTypes::Int32Str = "Int32";
+const char * amb::BasicTypes::StringStr = "String";
+const char * amb::BasicTypes::DoubleStr = "Double";
+const char * amb::BasicTypes::BooleanStr = "Boolean";
+
+int lwsWrite(libwebsocket *lws, QByteArray d)
+{
+ if(!lws)
+ {
+ DebugOut(DebugOut::Error)<<__FUNCTION__<<": libwebsockets is not valid. Perhaps it has not been initialized?" << endl;
+ return -1;
+ }
+
+ DebugOut() << "Writing to websocket: " << d.constData() << endl;
+
+ int retval = -1;
+
+ QByteArray temp = d;
+
+ int numframes = 1;
+ int framesize = 5012;
+
+ if(d.length() > framesize)
+ {
+ numframes = ceil((double)d.length() / double(framesize));
+ QVariantMap multiFrameMessage;
+ multiFrameMessage["type"] = "multiframe";
+ multiFrameMessage["frames"] = numframes;
+
+ lwsWriteVariant(lws, multiFrameMessage);
+ }
+
+ while(numframes--)
+ {
+ int range = 0;
+ if(temp.length() > framesize)
+ range = framesize;
+ else range = temp.length();
+
+ QByteArray toWrite = temp.mid(0,range);
+ const char* strToWrite = toWrite.data();
+
+ temp = temp.mid(range);
+
+ if(doBinary)
+ {
+ retval = libwebsocket_write(lws, (unsigned char*)strToWrite, toWrite.length(), LWS_WRITE_BINARY);
+ }
+ else
+ {
+ std::unique_ptr<char[]> buffer(new char[LWS_SEND_BUFFER_PRE_PADDING + toWrite.length() + LWS_SEND_BUFFER_POST_PADDING]);
+ char *buf = buffer.get() + LWS_SEND_BUFFER_PRE_PADDING;
+ memcpy(buf, strToWrite, toWrite.length());
+
+ retval = libwebsocket_write(lws, (unsigned char*)strToWrite, toWrite.length(), LWS_WRITE_TEXT);
+ }
+ }
+ return retval;
+}
+
+int lwsWriteVariant(libwebsocket *lws, QVariant d)
+{
+ QByteArray replystr;
+ if(doBinary)
+ replystr = QJsonDocument::fromVariant(d).toBinaryData();
+ else
+ {
+ replystr = QJsonDocument::fromVariant(d).toJson();
+ cleanJson(replystr);
+ }
+
+ lwsWrite(lws, replystr);
+}
+
+void cleanJson(QByteArray &json)
+{
+ json.replace(" ", "");
+ json.replace("\n", "");
+ json.replace("\t", "");
+}
+
+const std::string amb::BasicTypes::fromSignature(const string &sig)
+{
+ if(sig.empty()) return "";
+
+ char c = sig[0];
+
+ if(c == G_VARIANT_CLASS_BOOLEAN)
+ return BooleanStr;
+
+ else if(c == G_VARIANT_CLASS_BYTE)
+ return "";
+
+ else if(c == G_VARIANT_CLASS_INT16)
+ return Int16Str;
+
+ else if(c == G_VARIANT_CLASS_UINT16)
+ return UInt16Str;
+
+ else if(c == G_VARIANT_CLASS_INT32)
+ return Int32Str;
+
+ else if(c == G_VARIANT_CLASS_UINT32)
+ return UInt32Str;
+
+ else if(c == G_VARIANT_CLASS_INT64)
+ return "";
+
+ else if(c == G_VARIANT_CLASS_UINT64)
+ return "";
+
+ else if(c == G_VARIANT_CLASS_DOUBLE)
+ return DoubleStr;
+
+ else if(c == G_VARIANT_CLASS_STRING)
+ return StringStr;
+
+ else if(c == G_VARIANT_CLASS_ARRAY)
+ {
+ ///TODO support array and map
+ return "";
+ }
+ return "";
+}
diff --git a/plugins/websocket/common.h b/plugins/websocket/common.h
new file mode 100644
index 00000000..b246e1bb
--- /dev/null
+++ b/plugins/websocket/common.h
@@ -0,0 +1,44 @@
+#ifndef COMMON_WEBSOCKET_H_
+#define COMMON_WEBSOCKET_H_
+
+#include <QJsonDocument>
+#include <libwebsockets.h>
+#include <memory>
+
+extern bool doBinary;
+
+void cleanJson(QByteArray &json);
+
+// libwebsocket_write helper function
+int lwsWrite(struct libwebsocket *lws, QByteArray d);
+int lwsWriteVariant(struct libwebsocket *lws, QVariant d);
+
+namespace amb
+{
+namespace BasicTypes
+{
+enum BasicTypeEnum
+{
+ UInt16,
+ UInt32,
+ Int16,
+ Int32,
+ String,
+ Double,
+ Boolean
+};
+
+extern const char * UInt16Str;
+extern const char * UInt32Str;
+extern const char * Int16Str;
+extern const char * Int32Str;
+extern const char * StringStr;
+extern const char * DoubleStr;
+extern const char * BooleanStr;
+
+const std::string fromSignature(std::string const & sig);
+
+} // BasicTypes
+} // amb
+
+#endif
diff --git a/plugins/websocket/common.hpp b/plugins/websocket/common.hpp
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/plugins/websocket/common.hpp
diff --git a/plugins/websocket/protocol.idl b/plugins/websocket/protocol.idl
new file mode 100644
index 00000000..e812456d
--- /dev/null
+++ b/plugins/websocket/protocol.idl
@@ -0,0 +1,446 @@
+/*!
+ * \file protocol.idl
+ * \section websocket Websocket Plugin Protocol Documentation
+ * \version @PROJECT_VERSION@
+ *
+ * <a href="../../../html/index.html">Back to AMB Documentation Main</a>
+ * \section websocket_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 websocket_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 systemTime of the other system. Used to synchronize time
+ */
+ attribute double systemTime;
+
+ /*!
+ * \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/events.js b/plugins/websocket/test/events.js
new file mode 100644
index 00000000..18fa6e12
--- /dev/null
+++ b/plugins/websocket/test/events.js
@@ -0,0 +1,129 @@
+/*
+ * 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
+ *
+ */
+
+/* ---------------------- vehicle event typedef --------------------------- */
+
+function VehicleEventType()
+{
+ this.event = [
+"Randomize",
+"AirConditioning",
+"AirRecirculation",
+"AirflowDirection",
+"AvgKW",
+"BatteryVoltage",
+"ChildLock",
+"Defrost",
+"ExteriorBrightness",
+"ExteriorTemperature",
+"FanSpeed",
+"FrontWheelRadius",
+"InteriorTemperature",
+"LightHazard",
+"LightHead",
+"LightParking",
+"NightMode",
+"Odometer",
+"SeatHeater",
+"TargetTemperature",
+"TransmissionShiftPosition",
+"VehicleSpeed",
+"Weather"
+ ];
+ this.value = [];
+
+ /* set random initial values for all the props */
+ for(i in this.event)
+ {
+ var prop = this.event[i];
+ this.value[prop] = Math.floor(Math.random() * 1000000);
+ }
+}
+
+VehicleEventType.prototype.getSupportedEventList = function(val)
+{
+ /* for undefined just assume everything */
+ if((val === undefined)||(val === ""))
+ return this.event;
+
+ /* grab every event with case insensitive prefix of val */
+ var value = val.toLowerCase();
+ var list = [];
+ for(i in this.event)
+ {
+ var prop = this.event[i].toLowerCase();
+ if(prop.indexOf(value) === 0)
+ {
+ list[list.length] = prop;
+ }
+ }
+
+ /* if the target val isn't alone, remove it, it's a grouping */
+ var idx = list.indexOf(value);
+ if((idx >= 0)&&(list.length > 1))
+ {
+ list.splice(idx, 1);
+ }
+ return list;
+}
+
+VehicleEventType.prototype.getValueEventList = function(val)
+{
+ var i, j, list = this.getSupportedEventList(val);
+ for(i = 0; i < list.length; i++)
+ {
+ for(j = i + 1; j < list.length; j++)
+ {
+ if(list[j].indexOf(list[i]) === 0)
+ {
+ list.splice(i, 1);
+ i--;
+ }
+ }
+ }
+ return list;
+}
+
+VehicleEventType.prototype.getValuesEventList = function(vals)
+{
+ var i, j, list = [];
+ for(i = 0; i < vals.length; i++)
+ {
+ var sublist = this.getValueEventList(vals[i]);
+ for(j = 0; j < sublist.length; j++)
+ {
+ if(list.indexOf(sublist[j]) < 0)
+ {
+ list[list.length] = sublist[j];
+ }
+ }
+ }
+ return list;
+}
+
+VehicleEventType.prototype.isValueEvent = function(val)
+{
+ var list = this.getValueEventList(val);
+ return(list.length === 1);
+}
+
+VehicleEventType.prototype.getValue = function(prop)
+{
+ return this.value[prop];
+}
+
+VehicleEventType.prototype.isValid = function(prop)
+{
+ return (this.event.indexOf(prop) >= 0);
+}
+
+VehicleEventType.prototype.setValue = function(prop, newval)
+{
+ this.value[prop] = newval;
+}
diff --git a/plugins/websocket/test/index.html b/plugins/websocket/test/index.html
new file mode 100644
index 00000000..9a5daef4
--- /dev/null
+++ b/plugins/websocket/test/index.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <title>IVI API Tester</title>
+ <meta charset="utf-8">
+ <link rel="stylesheet" href="style.css"/>
+ <script src="vehicle.js"></script>
+</head>
+<body onload="init()">
+ <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/style.css b/plugins/websocket/test/style.css
new file mode 100644
index 00000000..8456fd1e
--- /dev/null
+++ b/plugins/websocket/test/style.css
@@ -0,0 +1,182 @@
+.PassClass {
+ font: bold 16px Arial;
+ color: green;
+}
+
+.FailClass {
+ font: bold 16px Arial;
+ color: red;
+}
+
+.LogClass {
+ font: 16px Arial;
+ color: black;
+}
+
+#tester {
+ position: absolute;
+ -webkit-user-select: none;
+ top: 0px;
+ left: 0%;
+ height: 100%;
+ width: 620px;
+ overflow-y: auto;
+}
+
+#result {
+ position: absolute;
+ top: 0px;
+ left: 620px;
+ height: 98%;
+ width: 1380px;
+ padding-top: 1%;
+ background-color: #eeeeee;
+ padding-left: 1%;
+ word-wrap:break-word;
+ overflow-y: auto;
+}
+
+.proptest {
+ position: relative;
+ left: 0px;
+ height: 67px;
+ width: 700px;
+ overflow: hidden;
+}
+
+.proptest .buttons {
+ position: absolute;
+ top: 32px;
+ left: 0px;
+ height: 35px;
+ width: 630px;
+}
+
+.smallText {
+ text-align: left;
+ color: #FFFFFF;
+ font: 18px Arial;
+ display: inline;
+}
+.propinfo {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ height: 67px;
+ width: 600px;
+ text-align: left;
+ color: #FFFFFF;
+ font: 18px Arial;
+ line-height: 30px;
+ padding-left: 5px;
+ background: -webkit-gradient(linear, left top, left bottom, from(#444), to(#000));
+ cursor: pointer;
+}
+
+.propinfo.select {
+ background: -webkit-gradient(linear, left top, left bottom, from(#444), to(#aaa));
+}
+
+.propinfo.unselectable {
+ cursor: auto;
+ background: #000000;
+ border-bottom: solid 1px #444;
+}
+
+input[type='text'] {
+ margin-top: 5px;
+ color: black;
+ font: bold 18px Arial;
+ height: 19px;
+ width: 100px;
+ background: -webkit-gradient(linear, left top, left bottom, from(#aaa), to(#fff));
+ -webkit-transition: all 2s linear;
+}
+
+input[type='text'].change {
+ -webkit-transition: all 0.1s linear;
+ color: red;
+}
+
+.testbutton {
+ position: relative;
+ float: left;
+ color: #d7d7d7;
+ border: solid 1px #333;
+ text-align: center;
+ text-decoration: none;
+ font: 16px/100% Arial, Helvetica, sans-serif;
+ text-shadow: 0 1px 1px rgba(0,0,0,.3);
+ -webkit-border-radius: 12px;
+ border-radius: 12px;
+ background: -webkit-gradient(linear, left top, left bottom, from(#666), to(#000));
+ height: 25px;
+ line-height: 24px;
+ cursor: pointer;
+ box-shadow: 2px 2px 14px #000;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ margin-right: 2px;
+}
+
+.testbutton.types {
+ width: 50px;
+ background: -webkit-gradient(linear, left top, left bottom, from(blue), to(#000));
+}
+
+.testbutton.types:after {
+ content: 'types';
+}
+
+.testbutton.get {
+ width: 35px;
+ background: -webkit-gradient(linear, left top, left bottom, from(green), to(#000));
+}
+
+.testbutton.get:after {
+ content: 'get';
+}
+
+.testbutton.set {
+ width: 35px;
+ background: -webkit-gradient(linear, left top, left bottom, from(green), to(#000));
+}
+
+.testbutton.set:after {
+ content: 'set';
+}
+
+.testbutton.subscribe {
+ width: 80px;
+ background: -webkit-gradient(linear, left top, left bottom, from(purple), to(#000));
+}
+
+.testbutton.subscribe.disable {
+ pointer-events: none;
+ color: #999999;
+ background: -webkit-gradient(linear, left top, left bottom, from(#000), to(#111));
+}
+
+.testbutton.subscribe:after {
+ content: 'subscribe';
+}
+
+.testbutton.unsubscribe {
+ width: 100px;
+ background: -webkit-gradient(linear, left top, left bottom, from(purple), to(#000));
+}
+
+.testbutton.unsubscribe.disable {
+ pointer-events: none;
+ color: #999999;
+ background: -webkit-gradient(linear, left top, left bottom, from(#000), to(#111));
+}
+
+.testbutton.unsubscribe:after {
+ content: 'unsubscribe';
+}
+
+.testbutton:active {
+ color: #666;
+ background: -webkit-gradient(linear, left top, left bottom, from(#000), to(#444));
+}
diff --git a/plugins/websocket/test/test.js b/plugins/websocket/test/test.js
new file mode 100644
index 00000000..db4befee
--- /dev/null
+++ b/plugins/websocket/test/test.js
@@ -0,0 +1,267 @@
+/*
+ * 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;
+ },
+
+ clear: function() {
+ this.logElement.innerHTML = "";
+ },
+
+ pass: function(msg) {
+ this.logElement.innerHTML += "<div class='PassClass'>PASS: " + msg + "</div>";
+ this.scrollToBottom();
+ },
+
+ fail: function(msg) {
+ this.logElement.innerHTML += "<div class='FailClass'>FAIL: " + msg + "</div>";
+ this.scrollToBottom();
+ },
+
+ log: function(msg) {
+ this.logElement.innerHTML += "<div class='LogClass'> " + msg + "</div>";
+ this.scrollToBottom();
+ },
+}
+
+/* ----------------------------- test code --------------------------------- */
+
+var vehicleEventType = new VehicleEventType();
+var selected = [];
+
+function getTypes(event) {
+ var types = window.vehicle.getSupportedEventTypes(event, false,
+ function(data) {
+ if (data && data.length > 1) {
+ PRINT.pass(event + " is a set of " + data.length + " objects:");
+ for (i in data) {
+ PRINT.log(JSON.stringify(data[i]));
+ }
+ } else {
+ PRINT.fail(event + " unexcepted empty data field");
+ }
+ },
+ function(msg) {
+ PRINT.fail(((event === "") ? "all events" : event) + ":<br>" + msg);
+ }
+ );
+}
+
+function updateInput(input, value) {
+ input.value = value;
+ input.className = "change";
+ input.addEventListener('webkitTransitionEnd', function callback(e) {
+ e.target.removeEventListener('webkitTransitionEnd', callback, false);
+ e.target.className = "";
+ }, false);
+}
+
+function getValue(event) {
+ var zone = getZone(event);
+ var types = window.vehicle.get(event, zone,
+ function(propertyValue) {
+ if (propertyValue) {
+ PRINT.pass("values received:");
+ PRINT.log(propertyValue.data.property + ": " + propertyValue.data.value + ", zone: " + propertyValue.data.zone);
+
+ var elements = document.getElementsByClassName('proptest');
+ for (var i = 0; i < elements.length; i++) {
+ var propinfo = elements[i].getElementsByClassName('propinfo')[0];
+ var name = propinfo.innerHTML;
+ var zone = elements[i].getElementsByTagName('input')[1];
+ if(zone)
+ updateInput(zone, zone.value);
+ var input = elements[i].getElementsByTagName('input')[0];
+ if(input)
+ updateInput(input, propertyValue.value);
+ }
+ } else {
+ PRINT.fail("no values retrieved for " + eventlist);
+ }
+ },
+ function(msg) {
+ PRINT.fail(msg);
+ }
+ );
+}
+
+function setValue(eventlist) {
+ var zoneList = getZone(eventlist);
+ var elements = document.getElementsByClassName('proptest');
+ var i, valuelist = [] ;
+
+ /* initialize the value list */
+ for (i = 0; i < eventlist.length; i++) {
+ valuelist[i] = 0;
+ }
+
+ for (var i = 0; i < elements.length; i++) {
+ var propinfo = elements[i].getElementsByClassName('propinfo')[0];
+ var name = propinfo.innerHTML;
+ var idx = eventlist.indexOf(name);
+ if (idx >= 0) {
+
+ var input = elements[i].getElementsByTagName('input')[0];
+ valuelist[idx] = input.value;
+ }
+ }
+
+ var types = window.vehicle.set(eventlist, valuelist, zoneList,
+ function(msg) {
+ PRINT.pass("Set success for: " + JSON.stringify(msg));
+ },
+ function(msg) {
+ PRINT.fail("Set error: " + JSON.stringify(msg));
+ }
+ );
+}
+
+function eventListener(e) {
+ PRINT.log(e.name + " update: " + JSON.stringify(e.value));
+ var elements = document.getElementsByClassName('proptest');
+ for (var i = 0; i < elements.length; i++) {
+ var propinfo = elements[i].getElementsByClassName('propinfo')[0];
+ var name = propinfo.innerHTML;
+ if (name === e.name) {
+ var input = elements[i].getElementsByTagName('input')[0];
+ updateInput(input, e.value.value);
+ var zone = elements[i].getElementsByTagName('input')[1];
+ updateInput(zone, e.value.zone);
+ }
+ }
+}
+
+function subscribe(event) {
+ var zoneList = getZone(event);
+ window.vehicle.subscribe(event, zoneList,
+ function(data) {
+ PRINT.pass("Subscribe success for: " + data.property);
+ document.addEventListener(data.property, eventListener, false);
+ },
+ function(msg) {
+ PRINT.fail("Subscribe failed for: " + msg);
+ }
+ );
+}
+
+function unsubscribe(event, zone) {
+ zone = getZone(event);
+ /* kill the handers first, so even if the service fails to acknowledge */
+ /* we've stopped listening */
+ document.removeEventListener(event, eventListener, false);
+
+ window.vehicle.unsubscribe(event, zone,
+ function(data) {
+ PRINT.pass("Unsubscribe success for: " + data);
+ },
+ function(msg) {
+ PRINT.fail("Unsubscribe failed for: " + msg);
+ }
+ );
+}
+
+function getZone(eventlist) {
+
+ var elements = document.getElementsByClassName('proptest');
+ for (var i = 0; i < elements.length; i++) {
+ var propinfo = elements[i].getElementsByClassName('propinfo')[0];
+ if (event == propinfo.innerHTML) {
+ var zone = elements[i].getElementsByTagName('input')[1];
+ return zone.value;
+ }
+ }
+}
+
+function select(elem) {
+ var name = elem.innerHTML;
+ if (!vehicleEventType.isValid(name))
+ return;
+
+ var idx = selected.indexOf(name);
+ if (elem.className === "propinfo") {
+ if (idx < 0) {
+ selected[selected.length] = name;
+ }
+ elem.className = "propinfo select";
+ } else if (elem.className === "propinfo select") {
+ if (idx >= 0) {
+ selected.splice(idx, 1);
+ }
+ elem.className = "propinfo";
+ }
+}
+
+function start(msg) {
+ if (window.vehicle && window.vehicle.getSupportedEventTypes) {
+ PRINT.pass("vehicle interface online " + msg);
+ } else {
+ PRINT.fail("vehicle interface not found");
+ return;
+ }
+
+ var tester = document.getElementById("tester");
+ var part = ['<div class="proptest"><div class="propinfo" onclick=select(this)>',
+ '</div><div class="buttons"><div class="testbutton types" onclick=getTypes("',
+ '")></div><div id="',
+ '_subscribe" class="testbutton subscribe" onclick=subscribe("',
+ '")></div><div id="',
+ '_unsubscribe" class="testbutton unsubscribe" onclick=unsubscribe("',
+ '")></div><div class="testbutton get" onclick=getValue("',
+ '")></div><div class="testbutton set" onclick=setValue("',
+ '")></div><input class = "Textvalue" type="text" value="0" placeholder="Value" /><div class = "smallText"> Zone: </div><input class = "zone" type="text" value="0" placeholder="Zone"/></div></div>'
+ ];
+ var events = vehicleEventType.event;
+
+ /* apply on all selected events */
+ var html = '<div class="proptest"><div class="propinfo unselectable">apply on all selected events' +
+ '</div><div class="buttons">' +
+ '<div class="testbutton subscribe" onclick=subscribe(selected)></div>' +
+ '<div class="testbutton unsubscribe" onclick=unsubscribe(selected)></div>' +
+ '<div class="testbutton get" onclick=getValue(selected)></div>' +
+ '<div class="testbutton set" onclick=setValue(selected)></div></div></div>';
+
+ /* all events */
+ html += '<div class="proptest"><div class="propinfo unselectable">all events';
+ html += '</div><div class="buttons"><div class="testbutton types" onclick=getTypes("' ;
+ html += '")></div><div class="testbutton subscribe" onclick=\"subscribe([\'' ;
+ html += events.join("','") ;
+ html += '\'])\"></div><div class="testbutton unsubscribe" onclick= \"unsubscribe([\'' ;
+ html += events.join("','");
+ html += '\'])\"></div><div class="testbutton get" onclick=\"getValue([\'' ;
+ html += events.join("','");
+ html += '\'])\"></div></div></div>';
+
+ /* events */
+ for (var i = 0; i < events.length; i++) {
+ var piece = "";
+ for (var j = 0; j < part.length - 1; j++) {
+ piece += part[j] + events[i];
+ }
+ html += piece + part[j];
+ }
+ tester.innerHTML = html;
+}
+
+function error(msg) {
+ PRINT.fail(msg);
+}
+
+function init(url, protocol) {
+ PRINT.init("result");
+ window.vehicle = new Vehicle(start, error, url, protocol);
+}
diff --git a/plugins/websocket/test/vehicle.js b/plugins/websocket/test/vehicle.js
new file mode 100644
index 00000000..706fb698
--- /dev/null
+++ b/plugins/websocket/test/vehicle.js
@@ -0,0 +1,367 @@
+/*
+ * 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
+ *
+ */
+
+/*****************************************************************************
+* Class name: Vehicle
+* Description:
+* A javascript implementation of the IVI vehicle API that communicates
+* to the automotive message broker through a websocket
+* Optional constructor arguments:
+* sCB: success callback, called when socket is connected, argument is
+* success message string
+* eCB: error callback, called on socket close or error, argument is error
+* message string
+* url: the URL to use for the websocket, in the form "ws://host:port/script"
+* protocol: the protocol to use for the websocket, default is "http-only"
+*
+* [Public Member functions]
+* Function name: getSupportedEventTypes(type, writeable, successCB, errorCB)
+* Description:
+* Retrieves a list of vehicle events for the requested type
+* Required arguments:
+* type: target event or group to query (use empty string for all events)
+* writeable: if true, return only writeable events, otherwise get all
+* successCB: success callback, gets called with a string list of names
+* for all the events and event groups that are children of the
+* target. e.g. "vehicle_info" returns all events/groups with the
+* vehicle_info prefix. If the target is an event group, it's
+* omitted from the returned list
+* errorCB: error callback, called with error message string
+*
+* Function name: get(eventlist, successCB, errorCB)
+* Description:
+* Retrieves a list of event/value pairs for a target list of event names
+* Required arguments:
+* eventlist[]: list of events to read (use empty string for all events)
+* successCB: success callback, gets called with the event/value pair list
+* for all requested events. The list is the in the
+* form of data[n].name/data[n].value
+* errorCB: error callback, called with error message string
+*
+* Function name: getHistory(event, startTime, endTime, successCB, errorCB)
+* Description:
+* Retrieves a list of event/value pairs for a target list of event names
+* Required arguments:
+* event: event to read
+* startTime: start date/time
+* endTime: end date/time
+* successCB: success callback, gets called with the event/value pair list
+* for all requested events. The list is the in the
+* form of data[n].name/data[n].value
+* errorCB: error callback, called with error message string
+*
+*
+* Function name: set(eventlist, valuelist, successCB, errorCB)
+* Description:
+* Sets a gourp of event's values (triggers error on read-only events)
+* Required arguments:
+* eventlist: target events to set
+* valuelist: target event values
+* successCB: success callback, gets called with the eventlist
+* that was successfully set
+* errorCB: error callback, called with error message string
+*
+* Function name: subscribe(eventlist, successCB, errorCB)
+* Description:
+* Subscribe to a list of events so you can listen to value changes, they
+* can be monitored with document.addEventListener(eventname, callback, false);
+* The Event object passed to the callback has two parameters, e.name and
+* e.value. Events are sent to the handler individually.
+* Required arguments:
+* eventlist: target events to listen to
+* successCB: success callback, gets called with the eventlist
+* that was successfully subscribed
+* errorCB: error callback, called with the eventlist that failed to subscribe
+*
+* Function name: unsubscribe(eventlist, successCB, errorCB)
+* Description:
+* Unsubscribe to a list of events to let the server know you're not listening,
+* they should stop being sent from the server if no other clients are using them,
+* but will at least stop being triggered in your app.
+* Required arguments:
+* eventlist: target events to stop listening to
+* successCB: success callback, gets called with the eventlist
+* that was successfully unsubscribed
+* errorCB: error callback, called with the eventlist that failed to unsubscribe
+*
+******************************************************************************/
+/*
+(function () {
+*/
+function Vehicle(sCB, eCB, url, protocol)
+{
+ /* store a copy of Vehicle this for reference in callbacks */
+ var self = this;
+
+ this.iSuccessCB = sCB;
+ this.iErrorCB = eCB;
+
+ /* variables for call management, supports up to 100 simultaneously */
+ this.methodIdx = 0;
+ this.methodCalls = [];
+ for(var i = 0; i < 100; i++)
+ {
+ this.methodCalls[i] = null;
+ }
+
+ /* number of connection retries to attempt if the socket closes */
+ this.retries = 5;
+ this.connected = false;
+
+ /* timeout for method calls in milliseconds */
+ this.timeouttime = 5000;
+
+ /* default values for WebSocket */
+ this.socketUrl = "ws://localhost:23000/vehicle";
+ this.socketProtocol = "http-only";
+
+ /* override the websocket address if parameters are given */
+ if(url !== undefined) this.socketUrl = url;
+ if(protocol !== undefined) this.socketProtocol = protocol;
+
+ this.VehicleMethodCall = function(id, name, successCB, errorCB)
+ {
+ var me = this;
+ this.successCB = successCB;
+ this.errorCB = errorCB;
+ this.transactionid = id;
+ this.name = name;
+ this.done = false;
+ this.start = function()
+ {
+ me.timeout = setTimeout(function(){
+ if(me.errorCB !== undefined)
+ {
+ me.errorCB("\""+me.name+"\" method timed out after "+self.timeouttime+"ms");
+ }
+ me.finish();
+ }, self.timeouttime);
+ }
+ this.finish = function()
+ {
+ if(me.timeout !== undefined)
+ {
+ clearTimeout(me.timeout);
+ }
+ me.done = true;
+ }
+ }
+
+ function init() {
+ if ("WebSocket" in window)
+ {
+ if(self.socketProtocol.length > 0)
+ {
+ self.socket = new WebSocket(self.socketUrl, self.socketProtocol);
+ }
+ else
+ {
+ self.socket = new WebSocket(self.socketUrl);
+ }
+ self.socket.onopen = function()
+ {
+ self.connected = true;
+ self.iSuccessCB((self.retries < 5)?"(RECONNECTED)":"");
+ self.retries = 5;
+ };
+ self.socket.onclose = function()
+ {
+ self.connected = false;
+ self.iErrorCB("socket closed "+((self.retries > 0)?"retrying in 5 seconds ...":""));
+ if(self.retries > 0)
+ {
+ setTimeout(function(){
+ self.retries--;
+ init();
+ }, 5000);
+ }
+ };
+ self.socket.onerror = function(e)
+ {
+ self.iErrorCB(e.data);
+ };
+ self.socket.onmessage = function (e)
+ {
+ self.receive(e.data);
+ };
+ }
+ else
+ {
+ console.log("This browser doesn't appear to support websockets!");
+ }
+ }
+ init();
+}
+
+Vehicle.prototype.generateTransactionId = function()
+{
+ var i, val = [];
+ for(i = 0; i < 8; i++)
+ {
+ var num = Math.floor((Math.random()+1)*65536);
+ val[i] = num.toString(16).substring(1);
+ }
+ var uuid = val[0]+val[1]+"-"+
+ val[2]+"-"+val[3]+"-"+val[4]+"-"+
+ val[5]+val[6]+val[7];
+ return uuid;
+}
+
+Vehicle.prototype.send = function(obj, successCB, errorCB)
+{
+ if(!this.connected)
+ {
+ if(errorCB !== undefined)
+ {
+ errorCB("\""+obj.name+"\" method failed because socket is closed");
+ }
+ return;
+ }
+ var i = this.methodIdx;
+ this.methodIdx = (this.methodIdx + 1)%100;
+ this.methodCalls[i] = new this.VehicleMethodCall(obj.transactionid,
+ obj.name, successCB, errorCB);
+ this.socket.send(JSON.stringify(obj));
+ this.methodCalls[i].start();
+}
+
+
+Vehicle.prototype.getSupportedEventTypes = function(type, writeable, successCB, errorCB)
+{
+ var obj = {
+ "type" : "method",
+ "name" : "getSupported",
+ "writeable" : writeable,
+ "transactionid" : this.generateTransactionId(),
+ "data" : type
+ };
+ this.send(obj, successCB, errorCB);
+}
+
+Vehicle.prototype.get = function(name, zone, successCB, errorCB)
+{
+ property = {"property" : name, "zone" : zone};
+
+ var obj = {
+ "type" : "method",
+ "name": "get",
+ "transactionid" : this.generateTransactionId(),
+ "data" : property
+ };
+ this.send(obj, successCB, errorCB);
+}
+
+Vehicle.prototype.getHistory = function(event, startTime, endTime, successCB, errorCB)
+{
+ var obj = {
+ "type" : "method",
+ "name": "getHistory",
+ "transactionid" : this.generateTransactionId(),
+ "data" : [event, (startTime.getTime()/1000).toString(), (endTime.getTime()/1000).toString()]
+ };
+
+ this.send(obj, successCB, errorCB);
+
+}
+
+Vehicle.prototype.set = function(name, value, zone, successCB, errorCB)
+{
+ var obj = {
+ "type" : "method",
+ "name": "set",
+ "transactionid" : this.generateTransactionId(),
+ "data" : { "property" : name, "value" : value, "zone" : zone }
+ };
+
+ this.send(obj, successCB, errorCB);
+}
+
+Vehicle.prototype.subscribe = function(name, zone, successCB, errorCB)
+{
+ var obj = {
+ "type" : "method",
+ "name": "subscribe",
+ "transactionid" : this.generateTransactionId(),
+ "property" : name
+ };
+
+ this.send(obj, successCB, errorCB);
+}
+
+Vehicle.prototype.unsubscribe = function(name, zone, successCB, errorCB)
+{
+ var obj = {
+ "type" : "method",
+ "name": "unsubscribe",
+ "transactionid" : this.generateTransactionId(),
+ "property" : name
+ };
+
+ this.send(obj, successCB, errorCB);
+}
+
+Vehicle.prototype.sendEvent = function(name, value)
+{
+ var evt = document.createEvent("Event");
+ evt.initEvent(name, true, true);
+ evt.name = name;
+ evt.value = value;
+ document.dispatchEvent(evt);
+ console.log(evt);
+}
+
+Vehicle.prototype.receive = function(msg)
+{
+ var self = this;
+ var event;
+ try {
+ event = JSON.parse(msg);
+ }
+ catch(e) {
+ self.iErrorCB("GARBAGE MESSAGE: "+msg);
+ return;
+ }
+
+ if((event === undefined)||(event.type === undefined)||
+ (event.name === undefined))
+ {
+ self.iErrorCB("BADLY FORMED MESSAGE: "+msg);
+ return;
+ }
+ else
+ {
+ if(event.type === "methodReply")
+ {
+ var calls = this.methodCalls;
+ for(var i = 0; i < calls.length; i++)
+ {
+ var call = calls[i];
+ if(call && (!call.done) && (call.transactionid === event.transactionid))
+ {
+ call.finish();
+ if(event.error !== undefined)
+ {
+ call.errorCB(event.error);
+ }
+ else if(call.successCB !== undefined)
+ {
+ call.successCB(event);
+ }
+ return;
+ }
+ }
+ }
+ else if(event.type === "valuechanged")
+ {
+ self.sendEvent(event.name, event.data);
+ }
+ }
+}
+
+
diff --git a/plugins/websocket/websocketsink.cpp b/plugins/websocket/websocketsink.cpp
new file mode 100644
index 00000000..5cdfb72b
--- /dev/null
+++ b/plugins/websocket/websocketsink.cpp
@@ -0,0 +1,84 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "websocketsink.h"
+#include <glib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sstream>
+#include "debugout.h"
+#include "common.h"
+
+#include <QJsonDocument>
+#include <QVariantMap>
+
+WebSocketSink::WebSocketSink(AbstractRoutingEngine* re, libwebsocket *wsi, string uuid, VehicleProperty::Property property, std::string ambdproperty)
+ : AbstractSink(re,map<string, string> ())
+{
+ m_amdbproperty = ambdproperty;
+ m_uuid = uuid;
+ m_wsi = wsi;
+ m_property = property;
+ m_re = re;
+ re->subscribeToProperty(ambdproperty, this);
+}
+const string WebSocketSink::uuid()
+{
+ return m_uuid;
+}
+void WebSocketSink::propertyChanged(AbstractPropertyType *value)
+{
+ VehicleProperty::Property property = value->name;
+
+ QVariantMap data;
+ QVariantMap reply;
+
+ data["value"] = value->toString().c_str();
+ data["zone"] = value->zone;
+ data["timestamp"]=value->timestamp;
+ data["sequence"]=value->sequence;
+ data["type"] = amb::BasicTypes::fromSignature(amb::make_unique(VehicleProperty::getPropertyTypeForPropertyNameValue(property))->signature()).c_str();
+
+ reply["data"]=data;
+ reply["type"]="valuechanged";
+ reply["name"]=property.c_str();
+ reply["transactionid"]=m_uuid.c_str();
+
+ lwsWriteVariant(m_wsi, reply);
+}
+WebSocketSink::~WebSocketSink()
+{
+ m_re->unsubscribeToProperty(m_amdbproperty, this);
+}
+void WebSocketSink::supportedChanged(const PropertyList &supportedProperties)
+{
+}
+PropertyList WebSocketSink::subscriptions()
+{
+ return PropertyList();
+}
+
+/// 6% and 4% cpu with json
+/// 5% and 4% with binary
diff --git a/plugins/websocket/websocketsink.h b/plugins/websocket/websocketsink.h
new file mode 100644
index 00000000..1ddd73b2
--- /dev/null
+++ b/plugins/websocket/websocketsink.h
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef WEBSOCKETSINK_H
+#define WEBSOCKETSINK_H
+
+#include <glib.h>
+#include <abstractroutingengine.h>
+#include "abstractsink.h"
+#include <libwebsockets.h>
+
+class WebSocketSink : public AbstractSink
+{
+
+public:
+ WebSocketSink(AbstractRoutingEngine* re, libwebsocket *wsi, string uuid, VehicleProperty::Property property, std::string ambdproperty);
+ ~WebSocketSink();
+ const string uuid() ;
+ void propertyChanged(AbstractPropertyType *value);
+ void supportedChanged(const PropertyList & supportedProperties);
+ PropertyList subscriptions();
+ libwebsocket *socket() { return m_wsi; }
+
+private:
+ char *webSocketBuffer;
+ string m_amdbproperty;
+ AbstractRoutingEngine *m_re;
+ libwebsocket *m_wsi;
+ string m_uuid;
+ string m_property;
+};
+
+#endif // WEBSOCKETSINK_H
diff --git a/plugins/websocket/websocketsinkmanager.cpp b/plugins/websocket/websocketsinkmanager.cpp
new file mode 100644
index 00000000..6003af9b
--- /dev/null
+++ b/plugins/websocket/websocketsinkmanager.cpp
@@ -0,0 +1,641 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "websocketsinkmanager.h"
+#include "websocketsink.h"
+#include "common.h"
+
+#include <sstream>
+#include <json/json.h>
+#include <json/json_object.h>
+#include <json/json_tokener.h>
+#include <listplusplus.h>
+#include <memory>
+
+#include <QVariantMap>
+#include <QJsonDocument>
+#include <QStringList>
+#include <QByteArray>
+
+#define __SMALLFILE__ std::string(__FILE__).substr(std::string(__FILE__).rfind("/")+1)
+
+//Global variables, these will be moved into the class
+struct pollfd pollfds[100];
+int count_pollfds = 0;
+libwebsocket_context *context;
+WebSocketSinkManager *sinkManager;
+static int websocket_callback(struct libwebsocket_context *context,struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason, void *user,void *in, size_t len);
+bool gioPollingFunc(GIOChannel *source,GIOCondition condition,gpointer data);
+
+WebSocketSinkManager::WebSocketSinkManager(AbstractRoutingEngine* engine, map<string, string> config)
+ :routingEngine(engine), configuration(config), partialMessageIndex(0), expectedMessageFrames(0)
+{
+ if(config.find("binaryProtocol") != config.end())
+ {
+ doBinary = config["binaryProtocol"] == "true";
+ }
+
+ //Create a listening socket on port 23000 on localhost.
+
+
+}
+
+void WebSocketSinkManager::init()
+{
+ //Protocol list for libwebsockets.
+ protocollist[0] = { "http-only", websocket_callback, 0 };
+ protocollist[1] = { NULL, NULL, 0 };
+
+
+ setConfiguration(configuration);
+}
+
+PropertyList WebSocketSinkManager::getSupportedProperties()
+{
+ return m_engine->supported();
+}
+
+void WebSocketSinkManager::setConfiguration(map<string, string> config)
+{
+// //Config has been passed, let's start stuff up.
+ configuration = config;
+ struct lws_context_creation_info info;
+ memset(&info, 0, sizeof info);
+
+ //Default values
+ int port = 23000;
+ std::string interface = "lo";
+ std::string ssl_cert_path;
+ std::string ssl_key_path;
+ int options = 0;
+ bool ssl = false;
+ info.extensions = nullptr;
+
+ //Try to load config
+ for (map<string,string>::iterator i=configuration.begin();i!=configuration.end();i++)
+ {
+ //printf("Incoming setting: %s:%s\n",(*i).first.c_str(),(*i).second.c_str());
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Incoming setting:" << (*i).first << ":" << (*i).second << "\n";
+ if ((*i).first == "interface")
+ {
+ interface = (*i).second;
+ }
+ if ((*i).first == "port")
+ {
+ port = boost::lexical_cast<int>((*i).second);
+ }
+ if ((*i).first == "cert")
+ {
+ ssl_cert_path = (*i).second;
+ }
+ if ((*i).first == "key")
+ {
+ ssl_key_path = (*i).second;
+ }
+ if ((*i).first == "ssl")
+ {
+ if ((*i).second == "true")
+ {
+ ssl = true;
+ }
+ else
+ {
+ ssl = false;
+ }
+ }
+ if ((*i).first == "useExtensions")
+ {
+ {
+ if((*i).second == "true")
+ {
+ info.extensions = libwebsocket_get_internal_extensions();
+ }
+ else info.extensions = nullptr;
+ }
+ }
+ }
+ info.iface = interface.c_str();
+ info.protocols = protocollist;
+ info.gid = -1;
+ info.uid = -1;
+ info.options = options;
+ info.port = port;
+ info.user = this;
+ if (ssl)
+ {
+ info.ssl_cert_filepath = ssl_cert_path.c_str();
+ info.ssl_private_key_filepath = ssl_key_path.c_str();
+ }
+ context = libwebsocket_create_context(&info);
+
+}
+
+void WebSocketSinkManager::addSingleShotSink(libwebsocket* socket, VehicleProperty::Property property, Zone::Type zone, string id)
+{
+ AsyncPropertyRequest request;
+
+ request.property = property;
+ request.zoneFilter = zone;
+ request.completed = [socket,id,property](AsyncPropertyReply* reply)
+ {
+ DebugOut()<<"Got property: "<<reply->property.c_str()<<endl;
+ if(!reply->success || !reply->value)
+ {
+ DebugOut()<<"Property value is null"<<endl;
+ delete reply;
+ return;
+ }
+
+ QVariantMap data;
+ data["property"] = property.c_str();
+ data["zone"] = reply->value->zone;
+ data["value"] = reply->value->toString().c_str();
+ data["timestamp"] = reply->value->timestamp;
+ data["sequence"] = reply->value->sequence;
+
+ QVariantMap replyvar;
+
+ replyvar["type"]="methodReply";
+ replyvar["name"]="get";
+ replyvar["data"]= data;
+ replyvar["transactionid"]=id.c_str();
+
+ lwsWriteVariant(socket, replyvar);
+
+ delete reply;
+ };
+
+ AsyncPropertyReply* reply = routingEngine->getPropertyAsync(request);
+}
+
+void WebSocketSinkManager::addSingleShotRangedSink(libwebsocket* socket, PropertyList properties, double start, double end, double seqstart,double seqend, string id)
+{
+ AsyncRangePropertyRequest rangedRequest;
+
+ rangedRequest.timeBegin = start;
+ rangedRequest.timeEnd = end;
+ rangedRequest.sequenceBegin = seqstart;
+ rangedRequest.sequenceEnd = seqend;
+ rangedRequest.properties = properties;
+
+ rangedRequest.completed = [socket, id](AsyncRangePropertyReply* reply)
+ {
+ QVariantMap replyvar;
+ QVariantList list;
+
+ std::list<AbstractPropertyType*> values = reply->values;
+ for(auto value : values)
+ {
+ QVariantMap obj;
+ 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);
+ }
+
+ replyvar["type"]="methodReply";
+ replyvar["name"]="getRanged";
+ replyvar["data"]=list;
+ replyvar["transactionid"]=id.c_str();
+
+ lwsWriteVariant(socket, replyvar);
+
+ delete reply;
+ };
+
+ routingEngine->getRangePropertyAsync(rangedRequest);
+}
+
+void WebSocketSinkManager::removeSink(libwebsocket* socket,VehicleProperty::Property property, string uuid)
+{
+ if (m_sinkMap.find(property) != m_sinkMap.end())
+ {
+ list<WebSocketSink*> sinks = m_sinkMap[property];
+
+ for(auto i : sinks)
+ {
+ m_sinkMap[property].remove(i);
+ delete i;
+ }
+
+ QVariantMap reply;
+ reply["type"]="methodReply";
+ reply["name"]="unsubscribe";
+ reply["property"]=property.c_str();
+ reply["transactionid"]= uuid.c_str();
+
+ lwsWriteVariant(socket, reply);
+ }
+}
+void WebSocketSinkManager::setValue(libwebsocket* socket, VehicleProperty::Property property, string value,Zone::Type zone, string uuid)
+{
+ AbstractPropertyType* type = VehicleProperty::getPropertyTypeForPropertyNameValue(property, value);
+
+ AsyncSetPropertyRequest request;
+ request.property = property;
+
+ request.value = type;
+ request.zoneFilter = zone;
+ request.completed = [&](AsyncPropertyReply* reply)
+ {
+ QVariantMap data;
+ 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);
+
+ delete reply;
+ };
+
+ m_engine->setProperty(request);
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "AbstractRoutingEngine::setProperty called with arguments:" << property << value << "\n";
+ delete type;
+
+}
+void WebSocketSinkManager::addSink(libwebsocket* socket, VehicleProperty::Property property, string uuid)
+{
+ QVariantMap reply;
+
+ reply["type"] = "methodReply";
+ reply["name"] = "subscribe";
+ reply["property"] = property.c_str();
+ reply["transactionid"] = uuid.c_str();
+
+ lwsWriteVariant(socket, reply);
+
+ WebSocketSink *sink = new WebSocketSink(m_engine, socket, uuid, property, property);
+ m_sinkMap[property].push_back(sink);
+}
+extern "C" void create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ sinkManager = new WebSocketSinkManager(routingengine, config);
+ sinkManager->init();
+}
+void WebSocketSinkManager::disconnectAll(libwebsocket* socket)
+{
+ std::list<WebSocketSink*> toDeleteList;
+
+ for (auto i=m_sinkMap.begin(); i != m_sinkMap.end();i++)
+ {
+ std::list<WebSocketSink*> *sinks = & (*i).second;
+ for (auto sinkItr = sinks->begin(); sinkItr != sinks->end(); sinkItr++)
+ {
+ if ((*sinkItr)->socket() == socket)
+ {
+ //This is the sink in question.
+ WebSocketSink* sink = (*sinkItr);
+ if(!contains(toDeleteList, sink))
+ {
+ toDeleteList.push_back(sink);
+ }
+
+ sinks->erase(sinkItr);
+ sinkItr = sinks->begin();
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Sink removed"<<endl;
+ }
+ }
+ }
+
+ for(auto i=toDeleteList.begin();i!=toDeleteList.end();i++)
+ {
+ delete *i;
+ }
+}
+void WebSocketSinkManager::addPoll(int fd)
+{
+ GIOChannel *chan = g_io_channel_unix_new(fd);
+ guint sourceid = g_io_add_watch(chan, GIOCondition(G_IO_IN | G_IO_HUP | G_IO_ERR),(GIOFunc)gioPollingFunc,chan);
+ g_io_channel_set_close_on_unref(chan,true);
+ g_io_channel_unref(chan); //Pass ownership of the GIOChannel to the watch.
+ m_ioChannelMap[fd] = chan;
+ m_ioSourceMap[fd] = sourceid;
+}
+void WebSocketSinkManager::removePoll(int fd)
+{
+ g_io_channel_shutdown(m_ioChannelMap[fd],false,0);
+ //printf("Shutting down IO Channel\n");
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Shutting down IO Channel\n";
+ g_source_remove(m_ioSourceMap[fd]); //Since the watch owns the GIOChannel, this should unref it enough to dissapear.
+
+ //for (map<int,guint>::const_iterator i=m_ioSourceMap.cbegin();i!=m_ioSourceMap.cend();i++)
+ for (map<int,guint>::iterator i=m_ioSourceMap.begin();i!=m_ioSourceMap.end();i++)
+ {
+ if((*i).first == fd)
+ {
+ //printf("Erasing source\n");
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Erasing source\n";
+ m_ioSourceMap.erase(i);
+ i--;
+ if (m_ioSourceMap.size() == 0)
+ {
+ break;
+ }
+ }
+ }
+ //for (map<int,GIOChannel*>::const_iterator i=m_ioChannelMap.cbegin();i!=m_ioChannelMap.cend();i++)
+ for (map<int,GIOChannel*>::iterator i=m_ioChannelMap.begin();i!=m_ioChannelMap.end();i++)
+ {
+ if((*i).first == fd)
+ {
+ //printf("Erasing channel\n");
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Erasing channel\n";
+ m_ioChannelMap.erase(i);
+ i--;
+ if (m_ioChannelMap.size() == 0)
+ {
+ break;
+ }
+ }
+ }
+}
+
+static int websocket_callback(struct libwebsocket_context *context,struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason, void *user,void *in, size_t len)
+{
+ //printf("Switch: %i\n",reason);
+ DebugOut(5) << __SMALLFILE__ << ":" << __LINE__ << "websocket_callback:" << reason << endl;
+
+
+ switch (reason)
+ {
+ case LWS_CALLBACK_CLIENT_WRITEABLE:
+ {
+ break;
+ }
+ case LWS_CALLBACK_CLOSED:
+ {
+ sinkManager->disconnectAll(wsi);
+ break;
+ }
+ case LWS_CALLBACK_CLIENT_RECEIVE:
+ {
+ break;
+ }
+ case LWS_CALLBACK_SERVER_WRITEABLE:
+ {
+ break;
+ }
+
+ case LWS_CALLBACK_RECEIVE:
+ {
+
+ }
+ case LWS_CALLBACK_HTTP:
+ {
+ //TODO: Verify that ALL requests get sent via LWS_CALLBACK_HTTP, so we can use that instead of LWS_CALLBACK_RECIEVE
+ //TODO: Do we want exceptions, or just to return an invalid json reply? Probably an invalid json reply.
+ DebugOut() << __SMALLFILE__ << ":" << __LINE__ << " Requested: " << (char*)in << "\n";
+
+ QByteArray d((char*)in,len);
+
+ WebSocketSinkManager * manager = sinkManager;
+
+ if(manager->expectedMessageFrames && manager->partialMessageIndex < manager->expectedMessageFrames)
+ {
+ manager->incompleteMessage += d;
+ manager->partialMessageIndex++;
+ break;
+ }
+ else if(manager->expectedMessageFrames && manager->partialMessageIndex == manager->expectedMessageFrames)
+ {
+ d = manager->incompleteMessage + d;
+ manager->expectedMessageFrames = 0;
+ }
+
+ QJsonDocument doc;
+ if(doBinary)
+ doc = QJsonDocument::fromBinaryData(d);
+ else
+ doc = QJsonDocument::fromJson(d);
+
+ if(doc.isNull())
+ {
+ DebugOut(DebugOut::Error)<<"Invalid message"<<endl;
+ return 0;
+ }
+
+ QVariantMap call = doc.toVariant().toMap();
+
+ string type = call["type"].toString().toStdString();
+ string name = call["name"].toString().toStdString();
+ string id = call["transactionid"].toString().toStdString();
+
+ if (type == "multiframe")
+ {
+
+ manager->expectedMessageFrames = call["frames"].toInt();
+ manager->partialMessageIndex = 1;
+ manager->incompleteMessage = "";
+ }
+ else if (type == "method")
+ {
+ if(name == "getRanged")
+ {
+ QVariant dataVariant = call["data"];
+
+ QVariantList data = dataVariant.toList();
+
+ PropertyList propertyList;
+
+ Q_FOREACH(QVariant v, data)
+ {
+ propertyList.push_back(v.toString().toStdString());
+ }
+
+ 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))
+ {
+ DebugOut(DebugOut::Warning)<<"Invalid time begin/end pair"<<endl;
+ }
+ else if ((sequenceBegin < 0 && sequenceEnd > 0) || (sequenceBegin > 0 && sequenceEnd < 0))
+ {
+ DebugOut(DebugOut::Warning)<<"Invalid sequence begin/end pair"<<endl;
+ }
+ else
+ {
+ sinkManager->addSingleShotRangedSink(wsi, propertyList, timeBegin, timeEnd, sequenceBegin, sequenceEnd, id);
+ }
+ }
+ else if (name == "get")
+ {
+ QVariantMap data = call["data"].toMap();
+ Zone::Type zone = Zone::None;
+ if(data.contains("zone"))
+ {
+ zone = data["zone"].toInt();
+ }
+ sinkManager->addSingleShotSink(wsi,data["property"].toString().toStdString(),zone,id);
+
+ }
+ else if (name == "set")
+ {
+ QVariantMap data = call["data"].toMap();
+ Zone::Type zone(Zone::None);
+ if(data.contains("zone"))
+ {
+ zone = data["zone"].toInt();
+ }
+ sinkManager->setValue(wsi, data["property"].toString().toStdString(), data["value"].toString().toStdString(), zone, id);
+ }
+ else if (name == "subscribe")
+ {
+ std::string property = call["property"].toString().toStdString();
+ sinkManager->addSink(wsi, property, id);
+ }
+ else if (name == "unsubscribe")
+ {
+ sinkManager->removeSink(wsi, call["property"].toString().toStdString(), id);
+ }
+ else if (name == "getSupportedEventTypes" || name == "getSupported")
+ {
+ QVariantMap reply;
+ QVariantList list;
+
+ PropertyList supported = sinkManager->getSupportedProperties();
+ DebugOut() << "we support " << supported.size() << " properties" << endl;
+ for(VehicleProperty::Property i : supported)
+ {
+ std::vector<std::string> sources = sinkManager->router()->sourcesForProperty(i);
+ for(auto source : sources)
+ {
+ PropertyInfo info = sinkManager->router()->getPropertyInfo(i, source);
+
+ for(auto zone : info.zones())
+ {
+ auto property = amb::make_unique(VehicleProperty::getPropertyTypeForPropertyNameValue(i));
+
+ std::string signature = property->signature();
+ const std::string basicType = amb::BasicTypes::fromSignature(signature);
+
+ QVariantMap map;
+ map["zone"] = zone;
+ map["name"] = i.c_str();
+ map["property"] = i.c_str();
+ map["type"] = basicType.c_str();
+ map["source"] = source.c_str();
+
+ list.append(map);
+ }
+ }
+ }
+
+ reply["type"] = "methodReply";
+ reply["name"] = "getSupported";
+ reply["transactionid"] = id.c_str();
+ reply["data"] = list;
+ reply["systemTime"] = amb::Timestamp::instance()->epochTime();
+
+ lwsWriteVariant(wsi, reply);
+ }
+ else
+ {
+ DebugOut(0)<<"Unknown method called."<<endl;
+ }
+ }
+ break;
+ }
+ case LWS_CALLBACK_ADD_POLL_FD:
+ {
+ //printf("Adding poll %i\n",sinkManager);
+ DebugOut(5) << __SMALLFILE__ <<":"<< __LINE__ << "Adding poll" << endl;
+ if (sinkManager != 0)
+ {
+ //sinkManager->addPoll((int)(long)user);
+ sinkManager->addPoll(libwebsocket_get_socket_fd(wsi));
+ }
+ else
+ {
+ DebugOut(5) << "Error, invalid sink manager!!" << endl;
+ }
+ break;
+ }
+ case LWS_CALLBACK_DEL_POLL_FD:
+ {
+ sinkManager->removePoll(libwebsocket_get_socket_fd(wsi));
+ break;
+ }
+ case LWS_CALLBACK_SET_MODE_POLL_FD:
+ {
+ //Set the poll mode
+ break;
+ }
+ case LWS_CALLBACK_CLEAR_MODE_POLL_FD:
+ {
+ //Don't handle this yet.
+ break;
+ }
+ default:
+ {
+ //printf("Unhandled callback: %i\n",reason);
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Unhandled callback:" << reason << "\n";
+ break;
+ }
+ }
+ return 0;
+}
+
+bool gioPollingFunc(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+ DebugOut(5) << "Polling..." << condition << endl;
+
+ if(condition & G_IO_ERR)
+ {
+ DebugOut(0)<< __SMALLFILE__ <<":"<< __LINE__ <<" websocketsink polling error."<<endl;
+ }
+
+ if (condition & G_IO_HUP)
+ {
+ //Hang up. Returning false closes out the GIOChannel.
+ //printf("Callback on G_IO_HUP\n");
+ DebugOut(0)<<"socket hangup event..."<<endl;
+ return false;
+ }
+
+ //This is the polling function. If it return false, glib will stop polling this FD.
+ //printf("Polling...%i\n",condition);
+
+ lws_tokens token;
+ struct pollfd pollstruct;
+ int newfd = g_io_channel_unix_get_fd(source);
+ pollstruct.fd = newfd;
+ pollstruct.events = condition;
+ pollstruct.revents = condition;
+ libwebsocket_service_fd(context,&pollstruct);
+
+ return true;
+}
diff --git a/plugins/websocket/websocketsinkmanager.h b/plugins/websocket/websocketsinkmanager.h
new file mode 100644
index 00000000..1b2fba64
--- /dev/null
+++ b/plugins/websocket/websocketsinkmanager.h
@@ -0,0 +1,68 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef WEBSOCKETSINKMANAGER_H
+#define WEBSOCKETSINKMANAGER_H
+
+#include <abstractroutingengine.h>
+#include <abstractsink.h>
+#include "websocketsink.h"
+#include <gio/gio.h>
+#include <map>
+#include <libwebsockets.h>
+#include "debugout.h"
+#include <stdexcept>
+#include "sys/types.h"
+#include <stdlib.h>
+#include <QByteArray>
+
+class WebSocketSinkManager
+{
+public:
+ WebSocketSinkManager(AbstractRoutingEngine* engine, map<string, string> config);
+ void addSingleShotSink(libwebsocket* socket, VehicleProperty::Property property, Zone::Type zone, string id);
+ void addSingleShotRangedSink(libwebsocket* socket, PropertyList properties,double start, double end, double seqstart,double seqend, string id);
+ void addSink(libwebsocket* socket, VehicleProperty::Property property, string uuid);
+ void disconnectAll(libwebsocket* socket);
+ void removeSink(libwebsocket* socket, VehicleProperty::Property property, string uuid);
+ void addPoll(int fd);
+ void removePoll(int fd);
+ 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);
+ PropertyList getSupportedProperties();
+
+ AbstractRoutingEngine * router() { return routingEngine; }
+
+ int partialMessageIndex;
+ QByteArray incompleteMessage;
+ int expectedMessageFrames;
+
+private:
+ std::map<int, GIOChannel*> m_ioChannelMap;
+ std::map<int, guint> m_ioSourceMap;
+ AbstractRoutingEngine *m_engine;
+ struct libwebsocket_protocols protocollist[2];
+
+ AbstractRoutingEngine * routingEngine;
+ std::map<std::string, std::string> configuration;
+
+};
+
+#endif // WEBSOCKETSINKMANAGER_H
diff --git a/plugins/websocket/websocketsource.cpp b/plugins/websocket/websocketsource.cpp
new file mode 100644
index 00000000..a52cdb18
--- /dev/null
+++ b/plugins/websocket/websocketsource.cpp
@@ -0,0 +1,817 @@
+/*
+ Copyright (C) 2012 Intel Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#include "websocketsource.h"
+#include <iostream>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <glib.h>
+#include <sstream>
+#include <listplusplus.h>
+#include <memory>
+#include <timestamp.h>
+#include "uuidhelper.h"
+
+#include <QVariantMap>
+#include <QJsonDocument>
+#include <QStringList>
+
+#include "debugout.h"
+#include "common.h"
+#include "superptr.hpp"
+
+#define __SMALLFILE__ std::string(__FILE__).substr(std::string(__FILE__).rfind("/")+1)
+libwebsocket_context *context = NULL;
+WebSocketSource *source;
+AbstractRoutingEngine *m_re;
+
+double oldTimestamp=0;
+double totalTime=0;
+double numUpdates=0;
+double averageLatency=0;
+
+class UniquePropertyCache
+{
+public:
+ bool hasProperty(std::string name, std::string source, Zone::Type zone)
+ {
+ for(auto i : mProperties)
+ {
+ if(i->name == name &&
+ i->sourceUuid == source &&
+ i->zone == zone)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ std::shared_ptr<AbstractPropertyType> append(std::string name, std::string source, Zone::Type zone, std::string type)
+ {
+ for(auto i : mProperties)
+ {
+ if(i->name == name &&
+ i->sourceUuid == source &&
+ i->zone == zone)
+ {
+ return i;
+ }
+ }
+
+ auto t = VehicleProperty::getPropertyTypeForPropertyNameValue(name);
+
+ if(!t)
+ {
+ VehicleProperty::registerProperty(name, [name, type]() -> AbstractPropertyType* {
+ if(type == amb::BasicTypes::UInt16Str)
+ {
+ return new BasicPropertyType<uint16_t>(name, 0);
+ }
+ else if(type == amb::BasicTypes::Int16Str)
+ {
+ return new BasicPropertyType<int16_t>(name, 0);
+ }
+ else if(type == amb::BasicTypes::UInt32Str)
+ {
+ return new BasicPropertyType<uint32_t>(name, 0);
+ }
+ else if(type == amb::BasicTypes::Int32Str)
+ {
+ return new BasicPropertyType<int32_t>(name, 0);
+ }
+ else if(type == amb::BasicTypes::StringStr)
+ {
+ return new StringPropertyType(name);
+ }
+ else if(type == amb::BasicTypes::DoubleStr)
+ {
+ return new BasicPropertyType<double>(name, 0);
+ }
+ else if(type == amb::BasicTypes::BooleanStr)
+ {
+ return new BasicPropertyType<bool>(name, false);
+ }
+ DebugOut(DebugOut::Warning) << "Unknown or unsupported type: " << type << endl;
+ return nullptr;
+ });
+ t = VehicleProperty::getPropertyTypeForPropertyNameValue(name);
+ }
+
+ if(t)/// check again to see if registration succeeded
+ {
+ t->sourceUuid = source;
+ t->zone = zone;
+
+ mProperties.emplace_back(t);
+ }
+
+ return property(name, source, zone); /// will return nullptr if t didn't register
+ }
+
+ std::shared_ptr<AbstractPropertyType> property(std::string name, std::string source, Zone::Type zone)
+ {
+ for(auto i : mProperties)
+ {
+ if(i->name == name &&
+ i->sourceUuid == source &&
+ i->zone == zone)
+ {
+ return i;
+ }
+ }
+
+ return nullptr;
+ }
+
+ std::vector<std::shared_ptr<AbstractPropertyType>> properties() { return mProperties; }
+
+private:
+ std::vector<std::shared_ptr<AbstractPropertyType>> mProperties;
+};
+
+UniquePropertyCache properties;
+
+static int callback_http_only(libwebsocket_context *context,struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason,void *user, void *in, size_t len);
+static struct libwebsocket_protocols protocols[] = {
+{
+ "http-only",
+ callback_http_only,
+ 0,
+ 128,
+},
+{ /* end of list */
+ NULL,
+ NULL,
+ 0,
+ 0
+}
+};
+
+//Called when a client connects, subscribes, or unsubscribes.
+void WebSocketSource::checkSubscriptions()
+{
+ while (queuedRequests.size() > 0)
+ {
+ VehicleProperty::Property prop = queuedRequests.front();
+ removeOne(&queuedRequests,prop);
+ if (contains(activeRequests,prop))
+ {
+ return;
+ }
+ activeRequests.push_back(prop);
+
+ QVariantMap reply;
+
+ reply["type"] = "method";
+ reply["name"] = "subscribe";
+ reply["property"] = prop.c_str();
+ reply["transactionid"] = "d293f670-f0b3-11e1-aff1-0800200c9a66";
+
+ lwsWriteVariant(clientsocket, reply);
+ }
+}
+void WebSocketSource::setConfiguration(map<string, string> config)
+{
+ //printf("WebSocketSource::setConfiguration has been called\n");
+ std::string ip;
+ int port;
+ configuration = config;
+
+ if(config.find("binaryProtocol") != config.end())
+ {
+ doBinary = config["binaryProtocol"] == "true";
+ }
+
+ for (map<string,string>::iterator i=configuration.begin();i!=configuration.end();i++)
+ {
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Incoming setting for WebSocketSource:" << (*i).first << ":" << (*i).second << "\n";
+ //printf("Incoming setting: %s:%s\n",(*i).first.c_str(),(*i).second.c_str());
+ if ((*i).first == "ip")
+ {
+ ip = (*i).second;
+ }
+ if ((*i).first == "port")
+ {
+ port = boost::lexical_cast<int>((*i).second);
+ }
+ if ((*i).first == "ssl")
+ {
+ if ((*i).second == "true")
+ {
+ m_sslEnabled = true;
+ }
+ else
+ {
+ m_sslEnabled = false;
+ }
+ }
+ }
+ //printf("Connecting to websocket server at %s port %i\n",ip.c_str(),port);
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Connecting to websocket server at" << ip << ":" << port << "\n";
+ int sslval = 0;
+ if (m_sslEnabled)
+ {
+ DebugOut(5) << "SSL ENABLED" << endl;
+ sslval = 2;
+ }
+
+ clientsocket = libwebsocket_client_connect(context, ip.c_str(), port, sslval,"/", "localhost", "websocket", protocols[0].name, -1);
+}
+
+PropertyInfo WebSocketSource::getPropertyInfo(const VehicleProperty::Property &property)
+{
+ Zone::ZoneList zones;
+ for(auto i : properties.properties())
+ {
+ if(i->name == property)
+ {
+ zones.push_back(i->zone);
+ }
+ }
+
+ return PropertyInfo(0, zones);
+}
+
+bool gioPollingFunc(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+ //This is the polling function. If it return false, glib will stop polling this FD.
+
+ oldTimestamp = amb::currentTime();
+
+ struct pollfd pollstruct;
+ int newfd = g_io_channel_unix_get_fd(source);
+ pollstruct.fd = newfd;
+ pollstruct.events = condition;
+ pollstruct.revents = condition;
+ libwebsocket_service_fd(context,&pollstruct);
+ if (condition & G_IO_HUP)
+ {
+ //Hang up. Returning false closes out the GIOChannel.
+ //printf("Callback on G_IO_HUP\n");
+ return false;
+ }
+ if (condition & G_IO_IN)
+ {
+
+ }
+ DebugOut() << "gioPollingFunc" << condition << endl;
+
+ return true;
+}
+
+static int checkTimeouts(gpointer data)
+{
+ WebSocketSource *src = (WebSocketSource*)data;
+ for (auto i=src->uuidTimeoutMap.begin();i!= src->uuidTimeoutMap.end();i++)
+ {
+ if (src->uuidRangedReplyMap.find((*i).first) != src->uuidRangedReplyMap.end())
+ {
+ //A source exists!
+ if (amb::currentTime() > (*i).second)
+ {
+ //We've reached timeout
+ DebugOut() << "Timeout reached for request ID:" << (*i).first << "\n";
+ src->uuidRangedReplyMap[(*i).first]->success = false;
+ src->uuidRangedReplyMap[(*i).first]->completed(src->uuidRangedReplyMap[(*i).first]);
+ src->uuidRangedReplyMap.erase((*i).first);
+ src->uuidTimeoutMap.erase((*i).first);
+ i--;
+
+ if (src->uuidTimeoutMap.size() == 0)
+ {
+ return 0;
+ }
+
+ }
+ else
+ {
+ //No timeout yet, keep waiting.
+ }
+ }
+ else
+ {
+ //Reply has already come back, ignore and erase from list.
+ src->uuidTimeoutMap.erase((*i).first);
+ i--;
+
+ if (src->uuidTimeoutMap.size() == 0)
+ {
+ return 0;
+ }
+ }
+
+ }
+ return 0;
+}
+
+static int callback_http_only(libwebsocket_context *context, struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len)
+{
+ unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 4096 + LWS_SEND_BUFFER_POST_PADDING];
+ DebugOut() << __SMALLFILE__ << ":" << __LINE__ << reason << "callback_http_only" << endl;
+ switch (reason)
+ {
+ case LWS_CALLBACK_CLOSED:
+ //fprintf(stderr, "mirror: LWS_CALLBACK_CLOSED\n");
+ //wsi_mirror = NULL;
+ //printf("Connection closed!\n");
+ break;
+
+ //case LWS_CALLBACK_PROTOCOL_INIT:
+ case LWS_CALLBACK_CLIENT_ESTABLISHED:
+ {
+ //This happens when a client initally connects. We need to request the support event types.
+ source->clientConnected = true;
+ source->checkSubscriptions();
+ //printf("Incoming connection!\n");
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Incoming connection" << endl;
+
+ QVariantMap toSend;
+ toSend["type"] = "method";
+ toSend["name"] = "getSupported";
+ toSend["transactionid"] = amb::createUuid().c_str();
+
+ lwsWriteVariant(wsi, toSend);
+
+ break;
+ }
+ case LWS_CALLBACK_CLIENT_RECEIVE:
+ {
+ QByteArray d((char*)in, len);
+
+ WebSocketSource * manager = source;
+
+ if(manager->expectedMessageFrames && manager->partialMessageIndex < manager->expectedMessageFrames)
+ {
+ manager->incompleteMessage += d;
+ manager->partialMessageIndex++;
+ break;
+ }
+ else if(manager->expectedMessageFrames && manager->partialMessageIndex == manager->expectedMessageFrames)
+ {
+ d = manager->incompleteMessage + d;
+ manager->expectedMessageFrames = 0;
+ }
+
+ DebugOut(7) << "data received: " << d.data() << endl;
+
+ int start = d.indexOf("{");
+
+ if(manager->incompleteMessage.isEmpty() && start > 0)
+ {
+ DebugOut(7)<< "We have an incomplete message at the beginning. Toss it away." << endl;
+ d = d.right(start-1);
+ }
+
+
+ int end = d.lastIndexOf("}");
+
+ if(end == -1)
+ {
+ manager->incompleteMessage += d;
+ break;
+ }
+
+ QByteArray tryMessage = manager->incompleteMessage + d.left(end+1);
+
+ DebugOut(6) << "Trying to parse message: " << tryMessage.data() << endl;
+
+ QJsonDocument doc;
+
+ QJsonParseError parseError;
+
+ doc = QJsonDocument::fromJson(tryMessage, &parseError);
+
+ if(doc.isNull())
+ {
+ DebugOut(7) << "Invalid or incomplete message" << endl;
+ DebugOut(7) << parseError.errorString().toStdString() << ": " << parseError.offset << endl;
+ manager->incompleteMessage += d;
+ break;
+ }
+
+ manager->incompleteMessage = end == d.length()-1 ? "" : d.right(end);
+
+ QVariantMap call = doc.toVariant().toMap();
+
+ string type = call["type"].toString().toStdString();
+ string name = call["name"].toString().toStdString();
+ string id = call["transactionid"].toString().toStdString();
+
+ if(type == "multiframe")
+ {
+ manager->expectedMessageFrames = call["frames"].toInt();
+ manager->partialMessageIndex = 1;
+ manager->incompleteMessage = "";
+
+ }
+ else if (type == "valuechanged")
+ {
+ QVariantMap data = call["data"].toMap();
+
+ string value = data["value"].toString().toStdString();
+ double timestamp = data["timestamp"].toDouble();
+ int sequence = data["sequence"].toInt();
+ Zone::Type zone = data["zone"].toInt();
+ string type = data["type"].toString().toStdString();
+
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Value changed:" << name << value << endl;
+
+ try
+ {
+ auto property = properties.append(name, source->uuid(), zone, type);
+
+ if(!property)
+ {
+ DebugOut(DebugOut::Warning) << "We either don't have this or don't support it ("
+ << name << "," << zone << "," << type << ")" << endl;
+ }
+
+ property->timestamp = timestamp;
+ property->sequence = sequence;
+ property->fromString(value);
+
+ m_re->updateProperty(property.get(), source->uuid());
+
+ double currenttime = amb::currentTime();
+
+ /** This is now the latency between when something is available to read on the socket, until
+ * a property is about to be updated in AMB. This includes libwebsockets parsing and the
+ * JSON parsing in this section.
+ */
+
+ DebugOut()<<"websocket network + parse latency: "<<(currenttime - property->timestamp)*1000<<"ms"<<endl;
+ totalTime += (currenttime - oldTimestamp)*1000;
+ numUpdates ++;
+ averageLatency = totalTime / numUpdates;
+
+ DebugOut()<<"Average parse latency: "<<averageLatency<<endl;
+ }
+ catch (exception ex)
+ {
+ //printf("Exception %s\n",ex.what());
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Exception:" << ex.what() << "\n";
+ }
+ }
+ else if (type == "methodReply")
+ {
+ if (name == "getSupported" || name == "supportedChanged")
+ {
+
+ QVariant data = call["data"];
+
+ QVariantList supported = data.toList();
+
+ DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Got getSupported request"<<endl;
+
+ double serverTime = call["systemTime"].toDouble();
+
+ DebugOut() << "Server time is: " << serverTime << endl;
+
+ if(serverTime)
+ source->serverTimeOffset = amb::Timestamp::instance()->epochTime() - serverTime;
+
+ Q_FOREACH(QVariant p, supported)
+ {
+ QVariantMap d = p.toMap();
+ Zone::Type zone = d["zone"].toInt();
+ std::string name = d["property"].toString().toStdString();
+ std::string proptype = d["type"].toString().toStdString();
+ std::string source = d["source"].toString().toStdString();
+
+ properties.append(name, source, zone, proptype);
+ }
+
+ source->updateSupported();
+
+ }
+ else if (name == "getRanged")
+ {
+ QVariantList data = call["data"].toList();
+
+ std::list<AbstractPropertyType*> propertylist;
+
+ Q_FOREACH(QVariant d, data)
+ {
+ QVariantMap obj = d.toMap();
+
+ std::string name = obj["property"].toString().toStdString();
+ std::string value = obj["value"].toString().toStdString();
+ double timestamp = obj["timestamp"].toDouble() + source->serverTimeOffset;
+ 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;
+
+ propertylist.push_back(type);
+ }
+
+ if (source->uuidRangedReplyMap.find(id) != source->uuidRangedReplyMap.end())
+ {
+ source->uuidRangedReplyMap[id]->values = propertylist;
+ source->uuidRangedReplyMap[id]->success = true;
+ source->uuidRangedReplyMap[id]->completed(source->uuidRangedReplyMap[id]);
+ source->uuidRangedReplyMap.erase(id);
+ }
+ else
+ {
+ DebugOut() << "getRanged methodReply has been recieved, without a request being in!. This is likely due to a request coming in after the timeout has elapsed.\n";
+ }
+ }
+ else if (name == "get")
+ {
+
+ DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "Got \"GET\" reply" << endl;
+ if (source->uuidReplyMap.find(id) != source->uuidReplyMap.end())
+ {
+ 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));
+
+ 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.get();
+ source->uuidReplyMap[id]->success = true;
+ source->uuidReplyMap[id]->completed(source->uuidReplyMap[id]);
+ source->uuidReplyMap.erase(id);
+
+ }
+ else
+ {
+ 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";
+ }
+ }
+ else
+ {
+ DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "GET Method Reply INVALID! Multiple properties detected, only single are supported!!!" << "\n";
+ }
+
+
+ }
+ 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;
+ }
+
+ }
+
+ break;
+
+ }
+ case LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED:
+ {
+ //printf("Requested extension: %s\n",(char*)in);
+ return 0;
+ break;
+ }
+ case LWS_CALLBACK_ADD_POLL_FD:
+ {
+ DebugOut(5) << __SMALLFILE__ << ":" << __LINE__ << "Adding poll for websocket IO channel" << endl;
+ //Add a FD to the poll list.
+ GIOChannel *chan = g_io_channel_unix_new(libwebsocket_get_socket_fd(wsi));
+
+ /// TODO: I changed this to be more consistent with the websocket sink end. it may not be correct. TEST
+
+ g_io_add_watch(chan,GIOCondition(G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP),(GIOFunc)gioPollingFunc,0);
+ g_io_channel_set_close_on_unref(chan,true);
+ g_io_channel_unref(chan); //Pass ownership of the GIOChannel to the watch.
+
+ break;
+ }
+ return 0;
+ }
+}
+void WebSocketSource::updateSupported()
+{
+ PropertyList list;
+ for(auto i : properties.properties())
+ {
+ if(!contains(list, i->name))
+ list.push_back(i->name);
+ }
+
+ m_re->updateSupported(list, PropertyList(), this);
+}
+
+WebSocketSource::WebSocketSource(AbstractRoutingEngine *re, map<string, string> config) : AbstractSource(re, config), partialMessageIndex(0),expectedMessageFrames(0),
+ serverTimeOffset(0)
+{
+ m_sslEnabled = false;
+ clientConnected = false;
+ source = this;
+ m_re = re;
+ struct lws_context_creation_info info;
+ memset(&info, 0, sizeof info);
+ info.protocols = protocols;
+ info.extensions = nullptr;
+
+ if(config.find("useExtensions") != config.end() && config["useExtensions"] == "true")
+ {
+ info.extensions = libwebsocket_get_internal_extensions();
+ }
+
+ info.gid = -1;
+ info.uid = -1;
+ info.port = CONTEXT_PORT_NO_LISTEN;
+ info.user = this;
+
+ context = libwebsocket_create_context(&info);
+
+ setConfiguration(config);
+
+ //printf("websocketsource loaded!!!\n");
+ g_timeout_add(1000,checkTimeouts,this); //Do this once per second, check for functions that have timed out and reply with success = false;
+
+}
+PropertyList WebSocketSource::supported()
+{
+ PropertyList list;
+ for(auto i : properties.properties())
+ {
+ list.push_back(i->name);
+ }
+ return list;
+}
+
+int WebSocketSource::supportedOperations()
+{
+ /// TODO: need to do this correctly based on what the host supports.
+ return Get | Set | GetRanged;
+}
+
+const string WebSocketSource::uuid()
+{
+ return "d293f670-f0b3-11e1-aff1-0800200c9a66";
+}
+
+void WebSocketSource::subscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ //printf("Subscribed to property: %s\n",property.c_str());
+ queuedRequests.push_back(property);
+ if (clientConnected)
+ {
+ checkSubscriptions();
+ }
+}
+
+
+void WebSocketSource::unsubscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ removeRequests.push_back(property);
+ if (clientConnected)
+ {
+ checkSubscriptions();
+ }
+}
+
+
+void WebSocketSource::getPropertyAsync(AsyncPropertyReply *reply)
+{
+ std::string uuid = amb::createUuid();
+ uuidReplyMap[uuid] = reply;
+ uuidTimeoutMap[uuid] = amb::currentTime() + 10.0; ///TODO: 10 second timeout, make this configurable?
+
+ QVariantMap data;
+ data["property"] = reply->property.c_str();
+ data["zone"] = reply->zoneFilter;
+
+ QVariantMap replyvar;
+ replyvar["type"] = "method";
+ replyvar["name"] = "get";
+ replyvar["data"] = data;
+ replyvar["transactionid"] = uuid.c_str();
+
+ lwsWriteVariant(clientsocket, replyvar);
+}
+
+void WebSocketSource::getRangePropertyAsync(AsyncRangePropertyReply *reply)
+{
+ std::string uuid = amb::createUuid();
+ uuidRangedReplyMap[uuid] = reply;
+ uuidTimeoutMap[uuid] = amb::currentTime() + 60; ///TODO: 60 second timeout, make this configurable?
+ stringstream s;
+ s.precision(15);
+ s << "{\"type\":\"method\",\"name\":\"getRanged\",\"data\": {";
+
+ QVariantMap replyvar;
+ replyvar["type"] = "method";
+ replyvar["name"] = "getRanged";
+ replyvar["transactionid"] = uuid.c_str();
+ replyvar["timeBegin"] = reply->timeBegin - serverTimeOffset;
+ replyvar["timeEnd"] = reply->timeEnd - serverTimeOffset;
+ replyvar["sequenceBegin"] = reply->sequenceBegin;
+ replyvar["sequenceEnd"] = reply->sequenceEnd;
+
+ QStringList properties;
+
+ for (auto itr = reply->properties.begin(); itr != reply->properties.end(); itr++)
+ {
+ VehicleProperty::Property p = *itr;
+ properties.append(p.c_str());
+ }
+
+ replyvar["data"] = properties;
+
+ lwsWriteVariant(clientsocket, replyvar);
+}
+
+AsyncPropertyReply * WebSocketSource::setProperty( AsyncSetPropertyRequest request )
+{
+ 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"] = uuid.c_str();
+
+ lwsWriteVariant(clientsocket, replyvar);
+
+ setReplyMap[uuid] = reply;
+
+ return reply;
+}
+
+extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ return new WebSocketSource(routingengine, config);
+
+}
diff --git a/plugins/websocket/websocketsource.h b/plugins/websocket/websocketsource.h
new file mode 100644
index 00000000..966fee3d
--- /dev/null
+++ b/plugins/websocket/websocketsource.h
@@ -0,0 +1,73 @@
+
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+#ifndef WEBSOCKETSOURCE_H
+#define WEBSOCKETSOURCE_H
+
+#include <abstractsource.h>
+#include <string>
+#include <libwebsockets.h>
+#include <QByteArray>
+
+class WebSocketSource : public AbstractSource
+{
+
+public:
+ WebSocketSource(AbstractRoutingEngine* re, std::map<std::string, std::string> config);
+ const std::string uuid();
+ void getPropertyAsync(AsyncPropertyReply *reply);
+ void getRangePropertyAsync(AsyncRangePropertyReply *reply);
+ AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request);
+ bool m_sslEnabled;
+ void subscribeToPropertyChanges(VehicleProperty::Property property);
+ void unsubscribeToPropertyChanges(VehicleProperty::Property property);
+ PropertyList supported();
+
+ int supportedOperations();
+
+ libwebsocket *clientsocket;
+ PropertyList queuedRequests;
+ bool clientConnected;
+ void checkSubscriptions();
+ PropertyList activeRequests;
+ PropertyList removeRequests;
+ void updateSupported();
+ void supportedChanged(const PropertyList &) {}
+ void setConfiguration(std::map<std::string, std::string> config);
+
+ 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;
+ int expectedMessageFrames;
+
+ PropertyInfo getPropertyInfo(const VehicleProperty::Property & property);
+
+ /*!
+ * \brief serverTimeOffset offset between server time and local time
+ */
+ double serverTimeOffset;
+private:
+};
+
+#endif // WEBSOCKETSOURCE_H
diff --git a/plugins/wheel/CMakeLists.txt b/plugins/wheel/CMakeLists.txt
new file mode 100644
index 00000000..ad348e30
--- /dev/null
+++ b/plugins/wheel/CMakeLists.txt
@@ -0,0 +1,20 @@
+
+include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs})
+
+pkg_check_modules(giounix REQUIRED gio-unix-2.0)
+set(link_libraries ${link_libraries} ${giounix_LIBRARIES})
+#set(include_dirs ${include_dirs} ${giounix_INCLUDE_DIRS})
+include_directories(${giounix_INCLUDE_DIRS})
+
+set(wheelsourceplugin_headers wheelplugin.h)
+set(wheelsourceplugin_sources wheelplugin.cpp)
+
+add_library(wheelsourceplugin MODULE ${wheelsourceplugin_sources})
+set_target_properties(wheelsourceplugin PROPERTIES PREFIX "")
+target_link_libraries(wheelsourceplugin amb -L${CMAKE_CURRENT_BINARY_DIR}/lib ${link_libraries})
+
+install(TARGETS wheelsourceplugin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH})
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_BINARY_DIR}/wheel.README.md @ONLY)
+
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/wheel.README.md DESTINATION ${DOC_INSTALL_DIR}/plugins)
diff --git a/plugins/wheel/README b/plugins/wheel/README
new file mode 100644
index 00000000..6424250e
--- /dev/null
+++ b/plugins/wheel/README
@@ -0,0 +1,31 @@
+# Wheel source plugin {#wheel_plugin}
+Version: @PROJECT_VERSION@
+
+The wheel source plugin uses the Logitech G27 (or similar) racing wheel for data.
+
+The wheel source plugin is enabled by default.
+
+
+To use the wheel source plugin, add the following to the "sources" array in /etc/ambd/config:
+
+~~~~~~~~~~~~~{.json}
+{
+ "name" : "WheelSource",
+ "path" : "@PLUGIN_INSTALL_PATH@/wheelsourceplugin.so",
+ "device" : "/dev/input/js0"
+}
+~~~~~~~~~~~~~
+
+## Configuration Key Definitions:
+
+"name"
+name of plugin. This key is not used by the plugin at this moment.
+
+"path"
+path to plugin on the filesystem.
+
+"device"
+Path to the racing wheel device
+
+default: "/dev/input/js0"
+
diff --git a/plugins/wheel/wheelplugin.cpp b/plugins/wheel/wheelplugin.cpp
new file mode 100644
index 00000000..0cbdf017
--- /dev/null
+++ b/plugins/wheel/wheelplugin.cpp
@@ -0,0 +1,629 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "wheelplugin.h"
+
+#include <iostream>
+#include <stdexcept>
+#include <boost/assert.hpp>
+#include <glib.h>
+
+#include <gio/gunixinputstream.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/input.h>
+#include <linux/joystick.h>
+
+using namespace std;
+
+#include "debugout.h"
+#include "timestamp.h"
+
+#define JSNAMELEN 128
+#define LG27 "G27 Racing Wheel"
+#define MAX_GEARS 6
+
+double gearRatio[8] = {
+ 0.0, //Neutral
+ 1.0/4.12, //First
+ 1.0/2.84, //Second
+ 1.0/2.28, //Third
+ 1.0/1.45, //Fourth
+ 1.0/1.0, //Fifth
+ 1.0/0.69, //Sixth
+ 1.0/3.21 //Reverse
+};
+
+
+class WheelPrivate
+{
+
+public:
+ WheelPrivate(WheelSourcePlugin *parent, AbstractRoutingEngine *route);
+ ~WheelPrivate();
+
+ AbstractPropertyType *getProperty(VehicleProperty::Property propType);
+
+ friend void readCallback(GObject *srcObj, GAsyncResult *res, gpointer userData);
+
+
+private:
+ void gotData(GAsyncResult *res);
+ void newButtonValue(char number, bool val);
+ void newAxisValue(char number, int val);
+
+ void changeMachineGuns(bool val);
+ void changeTurnSignal(TurnSignals::TurnSignalType dir, bool val);
+ void changeGear(int gear);
+ void changeOilPressure(bool increase);
+ void changeCoolantTemp(bool increase);
+
+ void changeSteeringAngle(int val);
+ void changeClutch(int val);
+ void changeThrottle(int val);
+ void changeBrake(int val);
+
+ uint16_t calcCarSpeed();
+ uint16_t calcRPM();
+ void checkButtonEvents();
+
+ AbstractRoutingEngine *re;
+ GInputStream *gis;
+ struct js_event jsEvent;
+ VehicleProperty::Property btnMap[16];
+ int *axis;
+ char *button;
+
+ VehicleProperty::MachineGunTurretStatusType* machineGuns;
+ VehicleProperty::VehicleSpeedType *vehicleSpeed;
+ VehicleProperty::EngineSpeedType *engineSpeed;
+ VehicleProperty::TurnSignalType *turnSignal;
+ VehicleProperty::TransmissionShiftPositionType *shiftPosition;
+ VehicleProperty::TransmissionGearPositionType *gearPosition;
+ VehicleProperty::EngineOilPressureType *oilPSI;
+ VehicleProperty::EngineCoolantTemperatureType *coolantTemp;
+ VehicleProperty::SteeringWheelAngleType *steeringAngle;
+ VehicleProperty::SteeringWheelAngleW3CType *steeringAngleW3C;
+ VehicleProperty::ThrottlePositionType *throttle;
+ VehicleProperty::ClutchStatusType *clutch;
+ VehicleProperty::WheelBrakeType *brake;
+
+ AbstractSource* mParent;
+
+ VehicleProperty::ButtonEventType *tempButton;
+};
+
+
+WheelSourcePlugin::WheelSourcePlugin(AbstractRoutingEngine* re, map<string, string> config)
+:AbstractSource(re, config)
+{
+ this->mWheel = new WheelPrivate(this, re);
+}
+
+WheelSourcePlugin::~WheelSourcePlugin()
+{
+ delete this->mWheel;
+}
+
+
+
+extern "C" void create(AbstractRoutingEngine* routingengine, map<string, string> config)
+{
+ new WheelSourcePlugin(routingengine, config);
+}
+
+const string WheelSourcePlugin::uuid()
+{
+ return "c0ffee8a-c605-4a06-9034-59c1deadbeef";
+}
+
+void WheelSourcePlugin::getPropertyAsync(AsyncPropertyReply *reply)
+{
+ reply->value = this->mWheel->getProperty(reply->property);
+
+ if(reply->value)
+ reply->success = true;
+
+ reply->completed(reply);
+}
+
+AsyncPropertyReply *WheelSourcePlugin::setProperty(AsyncSetPropertyRequest request )
+{
+
+}
+
+void WheelSourcePlugin::subscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ mRequests.insert(property);
+}
+
+PropertyList WheelSourcePlugin::supported()
+{
+ PropertyList props;
+ props.push_back(VehicleProperty::EngineSpeed);
+ props.push_back(VehicleProperty::VehicleSpeed);
+ props.push_back(VehicleProperty::TransmissionShiftPosition);
+ props.push_back(VehicleProperty::TransmissionGearPosition);
+ props.push_back(VehicleProperty::ThrottlePosition);
+ props.push_back(VehicleProperty::WheelBrake);
+ props.push_back(VehicleProperty::SteeringWheelAngle);
+ props.push_back(VehicleProperty::SteeringWheelAngleW3C);
+ props.push_back(VehicleProperty::TurnSignal);
+ props.push_back(VehicleProperty::ClutchStatus);
+ props.push_back(VehicleProperty::EngineOilPressure);
+ props.push_back(VehicleProperty::EngineCoolantTemperature);
+ props.push_back(VehicleProperty::MachineGunTurretStatus);
+ props.push_back(VehicleProperty::ButtonEvent);
+
+ return props;
+}
+
+int WheelSourcePlugin::supportedOperations()
+{
+ return Get | Set;
+}
+
+PropertyInfo WheelSourcePlugin::getPropertyInfo(const VehicleProperty::Property &property)
+{
+ Zone::ZoneList zones;
+ zones.push_back(0);
+ return PropertyInfo(0, zones);
+}
+
+void WheelSourcePlugin::unsubscribeToPropertyChanges(VehicleProperty::Property property)
+{
+ mRequests.erase(property);
+}
+
+//PIMPL:
+
+
+void readCallback(GObject *srcObj, GAsyncResult *res, gpointer userData)
+{
+ if (!userData) {
+ throw std::runtime_error("Got a null WheelPrivate in the Read Callback!");
+ }
+
+ WheelPrivate *wp = (WheelPrivate *)userData;
+ wp->gotData(res);
+
+}
+
+WheelPrivate::WheelPrivate(WheelSourcePlugin *parent, AbstractRoutingEngine *route)
+ :re(route), gis(nullptr), axis(nullptr), button(nullptr),
+ oilPSI(new VehicleProperty::EngineOilPressureType(10)),
+ coolantTemp(new VehicleProperty::EngineCoolantTemperatureType(100)),
+ turnSignal(new VehicleProperty::TurnSignalType(TurnSignals::Off)),
+ throttle(new VehicleProperty::ThrottlePositionType(0)),
+ machineGuns(new VehicleProperty::MachineGunTurretStatusType(false)),
+ gearPosition(new VehicleProperty::TransmissionGearPositionType(Transmission::Neutral)),
+ shiftPosition(new VehicleProperty::TransmissionShiftPositionType(Transmission::Neutral)),
+ engineSpeed(new VehicleProperty::EngineSpeedType(0)),
+ vehicleSpeed(new VehicleProperty::VehicleSpeedType(0)),
+ steeringAngle(new VehicleProperty::SteeringWheelAngleType(0)),
+ steeringAngleW3C(new VehicleProperty::SteeringWheelAngleW3CType(0)),
+ clutch(new VehicleProperty::ClutchStatusType(false)),
+ brake(new VehicleProperty::WheelBrakeType(false)),
+ tempButton(new VehicleProperty::ButtonEventType(ButtonEvents::NoButton)),
+ mParent(parent)
+{
+
+ unsigned char numAxes = 0;
+ unsigned char numButtons = 0;
+ int version = 0;
+ int fd;
+ char name[JSNAMELEN] = "Unknown";
+ struct js_corr cal[6];
+ int i, j;
+ //FIXME: Ugly as all get-out, but gets the job done quick...
+ unsigned int calData[36] = {
+ 1, 0, 8191, 8192, 65542, 65534,
+ 1, 0, 127, 128, 4227201, 4194176,
+ 1, 0, 127, 128, 4227201, 4194176,
+ 1, 0, 127, 128, 4227201, 4194176,
+ 1, 0, 0, 0, 536854528, 536854528,
+ 1, 0, 0, 0, 536854528, 536854528
+ };
+
+
+ //FIXME: Support config file with joystick device mapping, button/axis mappings, etc.
+ std::string jsdev = parent->getConfiguration()["device"];
+
+ DebugOut(0)<<"JSDev: "<<jsdev<<endl;
+
+ if(jsdev == "")
+ jsdev = "/dev/input/js0";
+
+ if ((fd = open(jsdev.c_str(), O_RDONLY)) < 0) {
+ throw std::runtime_error("Could not find a joystick class device!"); //FIXME: Later, don't throw, watch input devices, and jump on to any JS devices that appear
+ return;
+ }
+
+ ioctl(fd, JSIOCGVERSION, &version);
+ ioctl(fd, JSIOCGAXES, &numAxes);
+ ioctl(fd, JSIOCGBUTTONS, &numButtons);
+ ioctl(fd, JSIOCGNAME(JSNAMELEN), name);
+
+ for (i = 0; i < 6; i++) {
+ int k = 0;
+
+ cal[i].type = calData[(i*6)+k];
+ k++;
+ cal[i].prec = calData[(i*6)+k];
+ k++;
+
+ for(j = 0; j < 4; j++) {
+ cal[i].coef[j] = calData[(i*6)+k];
+ k++;
+ }
+ }
+ if (ioctl(fd, JSIOCSCORR, &cal) < 0) {
+ throw std::runtime_error("Could not set calibration data!");
+ return;
+ }
+
+ DebugOut() << "Driver version: " << (version >> 16) << "." << ((version >> 8) & 0xFF) << "." << (version & 0xFF) << endl;
+ DebugOut() << "JS Name: " << name << endl;
+ DebugOut() << "JS Axes/Buttons: " << (int)numAxes << "/" << (int)numButtons << endl;
+ DebugOut() << "Converting FD to GIO Input Stream..." << endl;
+ this->axis = (int *)calloc(numAxes, sizeof(int));
+ this->button = (char *)calloc(numButtons, sizeof(char));
+ this->gis = g_unix_input_stream_new(fd, TRUE);
+ g_input_stream_read_async(this->gis, &this->jsEvent, sizeof(struct js_event), G_PRIORITY_DEFAULT, nullptr, &readCallback, this);
+
+}
+
+WheelPrivate::~WheelPrivate()
+{
+ if (this->gis)
+ g_input_stream_close_async(this->gis, G_PRIORITY_DEFAULT, NULL, NULL, NULL);
+}
+
+
+AbstractPropertyType *WheelPrivate::getProperty(VehicleProperty::Property propType)
+{
+ if (propType == VehicleProperty::VehicleSpeed)
+ {
+ vehicleSpeed->setValue(this->calcCarSpeed());
+ return vehicleSpeed;
+ }
+ else if (propType == VehicleProperty::EngineSpeed)
+ {
+ engineSpeed->setValue(this->calcRPM());
+ return engineSpeed;
+ }
+ else if (propType == VehicleProperty::TransmissionShiftPosition)
+ return this->shiftPosition;
+ else if (propType == VehicleProperty::TransmissionGearPosition)
+ return this->gearPosition;
+ else if (propType == VehicleProperty::ThrottlePosition)
+ return this->throttle;
+ else if (propType == VehicleProperty::WheelBrake)
+ return this->brake;
+ else if (propType == VehicleProperty::SteeringWheelAngle)
+ return this->steeringAngle;
+ else if (propType == VehicleProperty::SteeringWheelAngleW3C)
+ return this->steeringAngleW3C;
+ else if (propType == VehicleProperty::TurnSignal)
+ return this->turnSignal;
+ else if (propType == VehicleProperty::ClutchStatus)
+ return this->clutch;
+ else if (propType == VehicleProperty::EngineOilPressure)
+ return this->oilPSI;
+ else if (propType == VehicleProperty::EngineCoolantTemperature)
+ return this->coolantTemp;
+ else if (propType == VehicleProperty::MachineGunTurretStatus)
+ return this->machineGuns;
+ else if (propType == VehicleProperty::ButtonEvent)
+ return tempButton;
+ else
+ cout << "Unhandled getProperty type: " << propType << endl;
+
+ return nullptr;
+}
+
+void WheelPrivate::newButtonValue(char number, bool val)
+{
+ switch (number) {
+ case 0: //Gear attach diamond down
+ checkButtonEvents();
+ break;
+ case 1: //Gear attach diamond left
+ checkButtonEvents();
+ break;
+ case 2: //Gear attach diamond right
+ checkButtonEvents();
+ break;
+ case 3: //Gear attach diamond up
+ checkButtonEvents();
+ break;
+ case 11://Gear attach red button row, left button
+ checkButtonEvents();
+ break;
+ case 8: //Gear attach red button row, 2nd btn from left
+ checkButtonEvents();
+ break;
+ case 9: //Gear attach red button row, 3rd btn from left
+ checkButtonEvents();
+ break;
+ case 10://Gear attach red button row, 4th btn from left (right button)
+ checkButtonEvents();
+ break;
+ case 4: //Right paddle shifter
+ if(val && this->gearPosition->basicValue() < MAX_GEARS)
+ {
+ this->changeGear(Transmission::TransmissionPositions(this->gearPosition->basicValue()+1));
+ changeMachineGuns(val);
+ }
+ break;
+ case 5: //Left paddle shifter
+ if(val && this->gearPosition->basicValue() > 0)
+ this->changeGear(Transmission::TransmissionPositions(this->gearPosition->basicValue()-1));
+ break;
+ case 6: //Right upper wheel button
+ this->changeTurnSignal(TurnSignals::Right, val);
+ break;
+ case 18://Right middle wheel button
+ //Oil pressure up
+ if (val)
+ this->changeOilPressure(true);
+ break;
+ case 19://Right lower wheel button
+ //Coolant temperature up
+ if (val)
+ this->changeCoolantTemp(true);
+ break;
+ case 7: //Left upper wheel button
+ this->changeTurnSignal(TurnSignals::Left, val);
+ break;
+ case 20://Left middle wheel button
+ //Oil pressure down
+ if (val)
+ this->changeOilPressure(false);
+ break;
+ case 21://Left lower wheel button
+ //Coolant temperature down
+ if (val)
+ this->changeCoolantTemp(false);
+ break;
+ case 12://1st gear
+ this->changeGear((val ? 1 : 0));
+ break;
+ case 13://2nd gear
+ this->changeGear((val ? 2 : 0));
+ break;
+ case 14://3rd gear
+ this->changeGear((val ? 3 : 0));
+ break;
+ case 15://4th gear
+ this->changeGear((val ? 4 : 0));
+ break;
+ case 16://5th gear
+ this->changeGear((val ? 5 : 0));
+ break;
+ case 17://6th gear
+ this->changeGear((val ? 6 : 0));
+ break;
+ case 22://Reverse gear
+ this->changeGear((val ? 128 : 0));
+ break;
+ default:
+ DebugOut() << "Got unknown button number: " << (int)number << endl;
+ break;
+ }
+}
+
+void WheelPrivate::newAxisValue(char number, int val)
+{
+ switch (number) {
+ case 0: //Wheel angle, -32767 - 32767
+ //VehicleProperty::SteeringWheelAngle
+ this->changeSteeringAngle(val);
+ break;
+ case 1: //Clutch, -32767 (depressed) - 32767 (undepressed)
+ this->changeClutch(val);
+ break;
+ case 2: //Throttle, -32767 (depressed) - 32767 (undepressed)
+ //VehicleProperty::VehicleSpeed
+ //VehicleProperty::EngineSpeed
+ this->changeThrottle(val);
+ break;
+ case 3: //Brake, -32767 (depressed) - 32767 (undepressed)
+ this->changeBrake(val);
+ break;
+ case 4: //D-Pad L/R, -32767 (L), 0 (Released), 32767 (R)
+ break;
+ case 5: //D-Pad U/D, -32767 (U), 0 (Released), 32767 (D)
+ break;
+ default:
+ cout << "Got unknown axis number: " << (int)number << endl;
+ break;
+ }
+}
+
+void WheelPrivate::gotData(GAsyncResult *res)
+{
+ GError *gerror = NULL;
+ int size = g_input_stream_read_finish(this->gis, res, &gerror);
+
+ if (res < 0) {
+ throw std::runtime_error(gerror->message);
+ g_error_free(gerror);
+ }
+ if (size != sizeof(struct js_event)) {
+ cout << "Only read " << size << " bytes from js device - should have been " << sizeof(struct js_event) << " bytes!";
+ throw std::runtime_error("Bad read from JS device!");
+ return;
+
+ } else {
+ switch (this->jsEvent.type & ~JS_EVENT_INIT) {
+ case JS_EVENT_BUTTON:
+ this->button[this->jsEvent.number] = this->jsEvent.value;
+// cout << "Got button event, btn# " << (int)this->jsEvent.number << ", val " << this->jsEvent.value << endl;
+ this->newButtonValue(this->jsEvent.number, this->jsEvent.value);
+ break;
+ case JS_EVENT_AXIS:
+ this->axis[this->jsEvent.number] = this->jsEvent.value;
+// cout << "Got axis event, axis# " << (int)this->jsEvent.number << ", val " << this->jsEvent.value << endl;
+ this->newAxisValue(this->jsEvent.number, this->jsEvent.value);
+ break;
+ default:
+ cout << "Got JS event that wasn't button or axis!" << endl;
+ break;
+ }
+ }
+
+ g_input_stream_read_async(this->gis, &this->jsEvent, sizeof(struct js_event), G_PRIORITY_DEFAULT, nullptr, &readCallback, this);
+}
+
+
+//Data handling functions
+
+
+void WheelPrivate::changeMachineGuns(bool val)
+{
+ *(this->machineGuns) = val;
+ this->re->updateProperty(this->machineGuns, mParent->uuid());
+}
+
+void WheelPrivate::changeTurnSignal(TurnSignals::TurnSignalType dir, bool val)
+{
+ TurnSignals::TurnSignalType tsVal= TurnSignals::Off;
+ if (val) {
+ if (dir == TurnSignals::Left)
+ tsVal = TurnSignals::Left;
+ else
+ tsVal = TurnSignals::Right;
+ }
+ *(this->turnSignal) = tsVal;
+ this->re->updateProperty(this->turnSignal, mParent->uuid());
+}
+
+void WheelPrivate::changeGear(int gear)
+{
+ gearPosition->setValue((Transmission::TransmissionPositions)gear);
+ shiftPosition->setValue((Transmission::TransmissionPositions)gear);
+
+ vehicleSpeed->setValue(this->calcCarSpeed());
+
+ this->re->updateProperty(gearPosition, mParent->uuid());
+ this->re->updateProperty(shiftPosition, mParent->uuid());
+ this->re->updateProperty(vehicleSpeed, mParent->uuid());
+}
+
+void WheelPrivate::changeOilPressure(bool increase)
+{
+ if(increase)
+ oilPSI->setValue(oilPSI->basicValue()+1);
+ else if(oilPSI->basicValue() > 0)
+ oilPSI->setValue(oilPSI->basicValue()-1);
+
+ this->re->updateProperty(oilPSI, mParent->uuid());
+}
+
+void WheelPrivate::changeCoolantTemp(bool increase)
+{
+ (increase ? ++(*coolantTemp) : --(*coolantTemp));
+
+ this->re->updateProperty(coolantTemp, mParent->uuid());
+}
+
+
+void WheelPrivate::changeSteeringAngle(int val)
+{
+ *steeringAngle = (((double)val/(double)32767.0) + (double)1.0) * (double)180.0;
+ *steeringAngleW3C = (((double)val/(double)32767.0) + (double)1.0) * (double)180.0;
+ this->re->updateProperty(steeringAngle, mParent->uuid());
+ this->re->updateProperty(steeringAngleW3C, mParent->uuid());
+}
+
+void WheelPrivate::changeClutch(int val)
+{
+
+ *clutch = (val < 20000);
+ this->re->updateProperty(clutch, mParent->uuid());
+
+}
+
+void WheelPrivate::changeThrottle(int val)
+{
+ *throttle = ((double)(val - 32767)/(double)-65534.0)*(double)100.0;
+ *vehicleSpeed = calcCarSpeed();
+ *engineSpeed = calcRPM();
+
+ this->re->updateProperty(throttle, mParent->uuid());
+ this->re->updateProperty(engineSpeed, mParent->uuid());
+ this->re->updateProperty(vehicleSpeed, mParent->uuid());
+}
+
+void WheelPrivate::changeBrake(int val)
+{
+ *brake = (val < 20000);
+ this->re->updateProperty(brake, mParent->uuid());
+}
+
+
+uint16_t WheelPrivate::calcCarSpeed()
+{
+// cout << "Calc Car Speed, rpm: " << this->calcRPM() << ", gearRatio: " << gearRatio[this->currentGear == 128 ? 7 : this->currentGear] << " current gear: " << this->currentGear << endl;
+ return (this->calcRPM() * gearRatio[this->gearPosition->basicValue() == 128 ? 7 : this->gearPosition->basicValue()])/100;
+
+}
+
+uint16_t WheelPrivate::calcRPM()
+{
+// cout << "Calc rpm, throttle: " << this->throttle << endl;
+ return throttle->basicValue() * 100;
+}
+
+void WheelPrivate::checkButtonEvents()
+{
+ if (this->button[0]) {
+ // cout << "Inside button 11!" << endl;
+ *tempButton = ButtonEvents::StopButton;
+
+ }
+ if (this->button[1]) {
+ // cout << "Inside button 11!" << endl;
+ *tempButton = (ButtonEvents::PrevButton);
+ }
+ if (this->button[2]) {
+ *tempButton = (ButtonEvents::SkipButton);
+
+ }
+ if (this->button[3]) {
+ *tempButton = ButtonEvents::PlayButton;
+
+ }
+ if (this->button[11]) {
+ *tempButton = (ButtonEvents::Preset1Button);
+ }
+ if (this->button[8]) {
+ *tempButton = (ButtonEvents::Preset2Button);
+ }
+ if (this->button[9]) {
+ *tempButton = (ButtonEvents::Preset3Button);
+
+ }
+ if (this->button[10]) {
+ *tempButton = (ButtonEvents::Preset4Button);
+ }
+
+ this->re->updateProperty(tempButton, mParent->uuid());
+}
diff --git a/plugins/wheel/wheelplugin.h b/plugins/wheel/wheelplugin.h
new file mode 100644
index 00000000..4bfa11a7
--- /dev/null
+++ b/plugins/wheel/wheelplugin.h
@@ -0,0 +1,60 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef WHEELPLUGIN_H
+#define WHEELPLUGIN_H
+
+#include <abstractsource.h>
+#include <string>
+
+using namespace std;
+
+class WheelPrivate;
+
+class WheelSourcePlugin: public AbstractSource
+{
+
+public:
+ WheelSourcePlugin(AbstractRoutingEngine* re, map<string, string> config);
+ ~WheelSourcePlugin();
+
+ const string uuid();
+ void getPropertyAsync(AsyncPropertyReply *reply);
+ void getRangePropertyAsync(AsyncRangePropertyReply *reply){}
+ AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request);
+ void subscribeToPropertyChanges(VehicleProperty::Property property);
+ void unsubscribeToPropertyChanges(VehicleProperty::Property property);
+ PropertyList supported();
+
+ int supportedOperations();
+
+ void supportedChanged(const PropertyList &) {}
+
+ map<string, string> getConfiguration() { return configuration; }
+
+ PropertyInfo getPropertyInfo(const VehicleProperty::Property &property);
+
+ friend class WheelPrivate;
+
+private:
+
+ WheelPrivate *mWheel;
+ PropertySet mRequests;
+};
+
+#endif // WHEELPLUGIN_H
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 00000000..ab924e20
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,13 @@
+set(amb_tests ${CMAKE_CURRENT_BINARY_DIR}/amb-get ${CMAKE_CURRENT_BINARY_DIR}/amb-set
+ ${CMAKE_CURRENT_BINARY_DIR}/amb-get-history ${CMAKE_CURRENT_BINARY_DIR}/amb-listen
+ ${CMAKE_CURRENT_BINARY_DIR}/gen-set)
+
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/amb-get.py ${CMAKE_CURRENT_BINARY_DIR}/amb-get @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/amb-set.py ${CMAKE_CURRENT_BINARY_DIR}/amb-set @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/amb-get-history.py ${CMAKE_CURRENT_BINARY_DIR}/amb-get-history @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/amb-listen.py ${CMAKE_CURRENT_BINARY_DIR}/amb-listen @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/gen-set.py ${CMAKE_CURRENT_BINARY_DIR}/gen-set @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/gendb.sh ${CMAKE_CURRENT_SOURCE_DIR}/gendb @ONLY)
+
+install (PROGRAMS ${amb_tests} DESTINATION bin)
+
diff --git a/tests/amb-get-history.py b/tests/amb-get-history.py
new file mode 100755
index 00000000..637e7d2b
--- /dev/null
+++ b/tests/amb-get-history.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+
+import dbus
+import sys
+import argparse
+import json
+
+print "This application is deprecated. It will disappear in the future. Use ambctl"
+
+parser = argparse.ArgumentParser()
+parser.add_argument("get", help="{objectName}")
+parser.add_argument("start", help="{startTime}")
+parser.add_argument("end", help="{endTime}")
+parser.add_argument("zone", help="{zone}")
+
+args = parser.parse_args()
+
+objectName = args.get
+start = float(args.start)
+end = float(args.end)
+zone = int(args.zone)
+
+bus = dbus.SystemBus()
+managerObject = bus.get_object("org.automotive.message.broker", "/");
+managerInterface = dbus.Interface(managerObject, "org.automotive.Manager")
+
+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)
diff --git a/tests/amb-get.py b/tests/amb-get.py
new file mode 100755
index 00000000..352961b9
--- /dev/null
+++ b/tests/amb-get.py
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+
+import dbus
+import sys
+import argparse
+import json
+
+print "This application is deprecated. It will disappear in the future. Use ambctl"
+
+parser = argparse.ArgumentParser()
+parser.add_argument("get", help="get {objectName}")
+args = parser.parse_args()
+
+objectName = args.get
+
+bus = dbus.SystemBus()
+managerObject = bus.get_object("org.automotive.message.broker", "/");
+managerInterface = dbus.Interface(managerObject, "org.automotive.Manager")
+
+objects = managerInterface.FindObject(objectName);
+
+for o in objects:
+ propertiesInterface = dbus.Interface(bus.get_object("org.automotive.message.broker", o),"org.freedesktop.DBus.Properties")
+ print json.dumps(propertiesInterface.GetAll("org.automotive."+objectName), indent=2)
diff --git a/tests/amb-listen.py b/tests/amb-listen.py
new file mode 100755
index 00000000..1b28996a
--- /dev/null
+++ b/tests/amb-listen.py
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+
+import dbus
+import sys
+import argparse
+import gobject
+import json
+from dbus.mainloop.glib import DBusGMainLoop
+
+print "This application is deprecated. It will disappear in the future. Use ambctl"
+
+def print_data(interface, properties, invalidated):
+ print json.dumps(properties, indent=2)
+
+parser = argparse.ArgumentParser()
+parser.add_argument("get", help="get {objectName}")
+args = parser.parse_args()
+
+objectName = args.get
+
+dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+bus = dbus.SystemBus()
+managerObject = bus.get_object("org.automotive.message.broker", "/");
+managerInterface = dbus.Interface(managerObject, "org.automotive.Manager")
+
+objects = managerInterface.FindObject(objectName);
+
+for o in objects:
+ bus.add_signal_receiver(print_data,
+ dbus_interface="org.freedesktop.DBus.Properties",
+ signal_name="PropertiesChanged",
+ path=o)
+
+loop = gobject.MainLoop()
+loop.run()
diff --git a/tests/amb-set.py b/tests/amb-set.py
new file mode 100755
index 00000000..bbdbc48d
--- /dev/null
+++ b/tests/amb-set.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python
+
+import dbus
+import sys
+import argparse
+
+print "This application is deprecated. It will disappear in the future. Use ambctl"
+
+parser = argparse.ArgumentParser()
+parser.add_argument("objectName", help="{objectName}")
+parser.add_argument("property", help="{propertyToSet}")
+parser.add_argument("value", help="{value}")
+parser.add_argument("valueType", help="{valueType}")
+parser.add_argument("zone", help="{zone}")
+
+args = parser.parse_args()
+
+objectName = args.objectName
+propertyToSet = args.property
+value = args.value
+valueType = args.valueType.lower()
+zone = int(args.zone)
+
+realValue = 0
+
+if valueType == "boolean":
+ realValue = value == "true"
+elif valueType == "integer":
+ realValue = dbus.Int32(value)
+elif valueType == "string":
+ realValue = value
+elif valueType == "double":
+ realValue = double(value)
+elif valueType == "UInt16":
+ realValue = dbus.UInt16(value)
+else:
+ raise Exception("Unknown type: " + valueType)
+
+bus = dbus.SystemBus()
+managerObject = bus.get_object("org.automotive.message.broker", "/");
+managerInterface = dbus.Interface(managerObject, "org.automotive.Manager")
+
+object = managerInterface.FindObjectForZone(objectName, zone)
+
+propertiesInterface = dbus.Interface(bus.get_object("org.automotive.message.broker", object),"org.freedesktop.DBus.Properties")
+propertiesInterface.Set("org.automotive."+objectName, propertyToSet, realValue)
+print "Success!"
diff --git a/tests/gen-set.py b/tests/gen-set.py
new file mode 100755
index 00000000..82f999c3
--- /dev/null
+++ b/tests/gen-set.py
@@ -0,0 +1,27 @@
+#!/usr/bin/python
+
+import dbus
+import sys
+import argparse
+
+parser = argparse.ArgumentParser()
+parser.add_argument("property", help="{propertyToSet}")
+parser.add_argument("value", help="{value}")
+parser.add_argument("zone", help="{zone}")
+
+args = parser.parse_args()
+
+# "{'type' : 'method', 'name' : 'set', 'transactionid' : 'meh',
+# 'data' : [{'interface' : 'vcan0', 'property' : 'VehicleSpeed', 'value' : '33', 'zone' : '0' }]}"
+
+realValue = "{'type' : 'method', 'name' : 'set', 'transactionid' : 'meh', 'data' : [{'interface' : 'vcan0', 'property' : '" + args.property + "', 'value' : '" + args.value + "', 'zone' : " + args.zone + " }]}"
+
+bus = dbus.SystemBus()
+managerObject = bus.get_object("org.automotive.message.broker", "/");
+managerInterface = dbus.Interface(managerObject, "org.automotive.Manager")
+
+object = managerInterface.FindObjectForZone("SimCommand", 0)
+
+propertiesInterface = dbus.Interface(bus.get_object("org.automotive.message.broker", object),"org.freedesktop.DBus.Properties")
+propertiesInterface.Set("org.automotive.SimCommand", "SimCommand", realValue)
+print "Success!"
diff --git a/tests/gendb.sh b/tests/gendb.sh
new file mode 100755
index 00000000..9830d82d
--- /dev/null
+++ b/tests/gendb.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+TABLE="@database_table_create@;"
+
+if [ -f generated.db ];
+ then
+ rm generated.db
+fi
+
+echo $TABLE > generated.db.sql
+echo "BEGIN IMMEDIATE TRANSACTION;" >> generated.db.sql
+
+for (( i=0; i<130; i++ ))
+do
+T=$(echo 1385571956 + $i)
+ for (( n=1; n<1000; n++ ))
+ do
+ MS=$(echo $n \* 0.001 | bc)
+ TIME=$(echo $T + $MS | bc)
+ echo "insert into data values('VehicleSpeed', $(( ( RANDOM % 300 ) + 1 )),'test', 0, $TIME, -1, 'alskejroanpnfansadfasdfa');" >> generated.db.sql
+ done
+done
+
+echo "END TRANSACTION;" >> generated.db.sql
+
+sqlite3 generated.db < generated.db.sql
+
+exit
diff --git a/tests/testing b/tests/testing
new file mode 100644
index 00000000..55c04fd7
--- /dev/null
+++ b/tests/testing
@@ -0,0 +1,94 @@
+Automotive Message Broker testing
+
+Abstract:
+
+This document outlines steps that should be taken in order to test Automotive Message Broker (AMB) functionality.
+
+Contents:
+
+I. Internal testing
+II. DBus API testing
+III. Performance testing
+
+
+Internal testing
+
+AMB performs internal testing of core functionality via the "test" plugin[1]. This plugin tests
+AbstractRoutingEngine methods. If a test failes, ambd will abort. This plugins also prints out the total
+property capabilities of AMB. This is useful for verifying the addition of core properties to AMB's capabilities.
+To run the test plugin, simply run ambd with the following example configuration[2]:
+
+ambd -c testsourceconfig -d5
+
+Debug level 5 is usually enough to get most debug or log information from ambd.
+
+References:
+[1] - Test plugin: https://github.com/otcshare/automotive-message-broker/blob/master/plugins/testplugin/README
+[2] - Test plugin config: https://github.com/otcshare/automotive-message-broker/blob/master/examples/testsourceconfig
+
+DBus API testing
+
+AMB exposes a complex API over DBus[1]. This document will only lightly touch on the organization of the API for
+testing purposes. For a information, please refer to the AMB DBus API documentation. The API has two general
+interfaces: "Manager", and "DataType". DataType refers to a particular type of vehicle data such as "VehicleSpeed".
+The easiest way to test the AMB DBus API is to run the example dbus config[3]:
+
+ambd -c dbusconfig -d5
+
+Manager testing
+
+The Manager interfaces[2] is located in "/" with the interface "org.automotive.Manager". Manager is used to create
+and find DataTypes. It has the following methods:
+
+List
+FindObject
+ZonesForObjectName
+FindObjectForSourceZone
+FindObjectForZone
+SourcesForObjectName
+
+Please refer to the Manager documentation for specific explaination on what these methods do.
+
+To test these methods, dbus-send, which comes with most linux distros can be used. The following is the general
+pattern:
+
+dbus-send --system --print-reply --dest=org.automotive.message.broker / org.automotive.Manager.{METHOD_NAME} ...
+
+To test the "List" method:
+
+dbus-send --system --print-reply --dest=org.automotive.message.broker / org.automotive.Manager.List
+
+This should return a list of supported DataTypes that can be used to create and find object paths representing that
+type.
+
+To test the "FindObject" method:
+
+dbus-send --system --print-reply --dest=org.automotive.message.broker / org.automotive.Manager.FindObject string:VehicleSpeed
+
+This should return a list of objects that provide the data type "VehicleSpeed"
+
+The other methods follow the same pattern. See the documentation for the arguments and return values.
+
+Because of the dynamic nature of the API (objects may not exist until Manager creates them), simple tools like dbus-send, gdbus or qdbus will not suffice for most operations. To compensate for these lack of tools, AMB includes several helper scripts:
+
+amb-get
+amb-set
+amb-get-history
+amb-listen
+
+These scripts can be used to get values of objects, set properties on objects, get historic/logged data and listen
+for changes to objects. For usage, please see [command] -h. For example: "amb-get -h".
+
+References:
+[1] - DBus API documentation: https://github.com/otcshare/automotive-message-broker/blob/master/docs/README
+[2] - Manager interface documentation: https://github.com/otcshare/automotive-message-broker/blob/master/docs/manager.txt
+[3] - DBus config: https://github.com/otcshare/automotive-message-broker/blob/master/examples/dbusconfig
+
+Performance Testing
+
+In addition to general profiling tools, AMB comes with a few ways you can measure performance. When running ambd
+with the -d1 option, you can see how many property updates are being generated per second and how many are actually
+being fired because a plugin is subscribed to that property. Coupling this with CPU usage measuring tools can help
+with measuring performance.
+
+
diff --git a/tools/AmbSignalMapper/.gitignore b/tools/AmbSignalMapper/.gitignore
new file mode 100644
index 00000000..2133cf46
--- /dev/null
+++ b/tools/AmbSignalMapper/.gitignore
@@ -0,0 +1,18 @@
+Makefile
+Makefile.old
+Build
+Build.bat
+META.*
+MYMETA.*
+.build/
+_build/
+cover_db/
+blib/
+inc/
+.lwpcookies
+.last_cover_stats
+nytprof.out
+pod2htm*.tmp
+pm_to_blib
+AmbSignalMapper-*
+AmbSignalMapper-*.tar.gz
diff --git a/tools/AmbSignalMapper/Changes b/tools/AmbSignalMapper/Changes
new file mode 100644
index 00000000..e514979c
--- /dev/null
+++ b/tools/AmbSignalMapper/Changes
@@ -0,0 +1,5 @@
+Revision history for AmbSignalMapper
+
+0.01 Date/time
+ First version, released on an unsuspecting world.
+
diff --git a/tools/AmbSignalMapper/MANIFEST b/tools/AmbSignalMapper/MANIFEST
new file mode 100644
index 00000000..02a5ad59
--- /dev/null
+++ b/tools/AmbSignalMapper/MANIFEST
@@ -0,0 +1,23 @@
+Changes
+Makefile.PL
+MANIFEST This list of files
+README
+bin/dbc2json
+bin/json2amb
+lib/Intel/IviPoc/DbcGrammar
+lib/Intel/IviPoc/DbcGrammar.pod
+lib/Intel/IviPoc/AmbPluginGenerator.pm
+lib/Intel/IviPoc/AmbCommon.pm
+lib/Intel/IviPoc/templates/ambtmpl_plugin.h
+lib/Intel/IviPoc/templates/ambtmpl_plugin.cpp
+lib/Intel/IviPoc/templates/ambtmpl_plugin.idl
+lib/Intel/IviPoc/templates/ambtmpl_cansignal.h
+lib/Intel/IviPoc/templates/ambtmpl_cansignal.cpp
+lib/Intel/IviPoc/templates/ambtmpl_cansignals.h
+lib/Intel/IviPoc/templates/CMakeLists.txt
+t/00-load.t
+t/ambsignalmapper.t
+t/manifest.t
+t/pod-coverage.t
+t/pod.t
+t/boilerplate.t
diff --git a/tools/AmbSignalMapper/Makefile.PL b/tools/AmbSignalMapper/Makefile.PL
new file mode 100644
index 00000000..bae450ee
--- /dev/null
+++ b/tools/AmbSignalMapper/Makefile.PL
@@ -0,0 +1,72 @@
+use 5.006;
+use strict;
+use warnings FATAL => 'all';
+use ExtUtils::MakeMaker;
+
+our @EXCLUSIONS=();
+our $MORE_MAKERULES='';
+
+compile_DbcGrammar();
+
+WriteMakefile(
+ NAME => 'Intel::IviPoc::AmbPluginGenerator',
+ AUTHOR => q{Intel IVI PoC <ivipoc@intel.com>},
+ VERSION_FROM => 'lib/Intel/IviPoc/AmbPluginGenerator.pm',
+ ABSTRACT_FROM => 'lib/Intel/IviPoc/AmbPluginGenerator.pm',
+ LICENSE => 'LGPL2.1',
+ PL_FILES => {},
+ MIN_PERL_VERSION => 5.006,
+ CONFIGURE_REQUIRES => {
+ 'ExtUtils::MakeMaker' => 0,
+ },
+ BUILD_REQUIRES => {
+ 'Test::More' => 0,
+ 'Parse::RecDescent' => 0,
+ },
+ PREREQ_PM => {
+ 'Exporter'=>0,
+ 'JSON'=>0,
+ 'Data::UUID'=>0,
+ 'File::Basename'=>0,
+ 'File::Spec'=>0,
+ 'Cwd'=>0,
+ 'Digest::SHA1'=>0,
+ #'Config::General'=>0,
+ },
+ EXE_FILES => [ 'bin/dbc2json','bin/json2amb'],
+ dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
+ clean => { FILES => 'AmbSignalMapper-*' },
+);
+
+# Overriding ExtUtils::MM methods
+# --------------------------------------------------------------------
+# Exclude the sources used to generate others from the build (See below).
+sub MY::libscan {
+my($self,$path)=@_;
+ if(($path =~ /~$/) || grep($path eq $_, @EXCLUSIONS)){
+ return ""; }
+ $self->MY::SUPER::libscan($path); }
+
+# Append any additional Makefile rules added by the following.
+sub MY::postamble {
+ shift->MY::SUPER::postamble(@_) . $MORE_MAKERULES; }
+
+# Compile the RecDescent grammar during make;
+sub compile_DbcGrammar {
+ push(@EXCLUSIONS,'blib/lib/Intel/IviPoc/DbcGrammar');
+ $MORE_MAKERULES .= <<'MakeGrammar';
+
+# Precompile the (Recursive Descent) DbcGrammar
+pure_all :: $(INST_LIBDIR)/Intel/IviPoc/DbcGrammar.pm
+
+$(INST_LIBDIR)/Intel/IviPoc/DbcGrammar.pm: lib/Intel/IviPoc/DbcGrammar
+ $(PERLRUN) -MParse::RecDescent - lib/Intel/IviPoc/DbcGrammar Intel::IviPoc::DbcGrammar
+ $(NOECHO) $(MKPATH) $(INST_LIBDIR)/Intel/IviPoc
+ $(MV) -f DbcGrammar.pm blib/lib/Intel/IviPoc/DbcGrammar.pm
+ $(CHMOD) $(PERM_RWX) bin/dbc2json
+ $(CHMOD) $(PERM_RWX) bin/json2amb
+
+MakeGrammar
+}
+
+
diff --git a/tools/AmbSignalMapper/README b/tools/AmbSignalMapper/README
new file mode 100644
index 00000000..42907f5c
--- /dev/null
+++ b/tools/AmbSignalMapper/README
@@ -0,0 +1,77 @@
+AmbSignalMapper
+
+ABSTRACT:
+
+The AmbSignalMapper tool serves basic utilities for AMB signal mapping process.
+It should take place in three steps:
+
+1. Vector CANdb++ conversion into intermediate file (First phase)
+2. Manual annotation of intermediate file (Second phase)
+3. Processing of intermediate file and AMB plugin and WebIDL creation (Third phase)
+
+The First phase is achieved by software utolity called dbc2json.
+The second phase needs to be done by humans manually.
+The third phase is again covered by software utolity called json2amb.
+
+PREREQUISITES:
+
+Perl version 5.006 or higher.
+
+The following modules are needed to succesfuly build and run the AmbSignalMapper tool:
+ 'ExtUtils::MakeMaker'
+ 'Test::More',
+ 'Parse::RecDescent',
+ 'Exporter',
+ 'JSON',
+ 'Data::UUID',
+ 'File::Basename',
+ 'File::Spec',
+ 'Cwd',
+ 'Digest::SHA1'.
+
+These modules are optional for executing moodule tests:
+ 'Test::Pod',
+ 'Test::Pod::Coverage',
+
+The following command is an example of Data::UUID module instalation.
+Note that sudo credentials might be needed on users linux box.
+
+ cpan install Data::UUID
+
+INSTALLATION
+
+To install this module, run the following commands:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+SUPPORT AND DOCUMENTATION
+
+After installing, you can find documentation for this module with the
+perldoc command.
+
+ perldoc dbc2json
+
+ perldoc json2amb
+
+LICENSE AND COPYRIGHT
+
+Copyright (C) 2014 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
diff --git a/tools/AmbSignalMapper/bin/dbc2json b/tools/AmbSignalMapper/bin/dbc2json
new file mode 100755
index 00000000..e96f8679
--- /dev/null
+++ b/tools/AmbSignalMapper/bin/dbc2json
@@ -0,0 +1,204 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2014 Intel Corporation
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+use strict;
+use warnings;
+
+use Intel::IviPoc::DbcGrammar;
+use Intel::IviPoc::AmbCommon;
+use File::Basename;
+use File::Spec;
+use Cwd;
+use JSON;
+
+
+=head1 NAME
+
+dbc2json - Vector CANdb++ to JSON file format converter.
+
+=head1 SYNOPSIS
+
+B<dbc2json> I<infile> [ I<outfile> ]
+
+=head1 DESCRIPTION
+
+Part of Automotive Message Broker Signal Mapper tool.
+
+B<dbc2json> converts file in Vector CANdb++ format to intermediate JSON file.
+
+Intermediate file is used to format and annotate raw data from CANDb++ file into format suitable for AMB plugin creation.
+
+=head1 OPTIONS
+
+=over 4
+
+=item I<infile>
+
+Input I<infile> file in Vector CANdb++ (*.dbc) format.
+
+=item [ I<outfile> ]
+
+Target output I<outfile> file converted to JSON, otherwise created in current directory.
+
+=back
+
+=head1 FILES
+
+=over 4
+
+=back
+
+=head1 REQUIRES
+
+Perl 5.006, Intel::IviPoc::DbcGrammar, File::Basename, File::Spec, Cwd, JSON
+
+=head1 SEE ALSO
+
+perl(1), json2amb(1)
+
+=cut
+
+local $/;
+
+# get total arg passed to this script
+my $total = $#ARGV + 1;
+
+if ( $total < 1 or $total > 2) {
+ # get script name and print usage
+ my $scriptname = $0;
+ &printUsage($scriptname);
+ exit;
+ }
+
+# First parameter is input file
+my $inputfilename = $ARGV[0];
+my $text = &readFileContent($inputfilename);
+
+# Second optional parameter is output file
+my $outputfilename = '';
+if ( $total == 1 ) {
+ my ($infilename, $indirectories, $insuffix) = fileparse($inputfilename, qr/\.[^.]*/);
+ my $targetDir = getcwd;
+ $outputfilename = File::Spec->catfile( ($targetDir), $infilename . '.json' );
+} else {
+ $outputfilename = $ARGV[1];
+}
+
+# We add one space if there is something like ""ReceiverId to get "" ReceiverId
+$text =~ s/"(.*)"(\w*)/"$1" $2/g;
+
+#Create parser
+my $parser = new Intel::IviPoc::DbcGrammar;
+
+# Print wait info for user
+&printWait($inputfilename, $outputfilename);
+
+# Parse input file and generate json
+my $result;
+$result = $parser->DbcOutput($text);
+my %jsonroot = %{$result};
+
+# Get the filename without path and extension and set it as pluginName
+my ($outfilename, $outdirectories, $outsuffix) = fileparse($outputfilename, qr/\.[^.]*/);
+$jsonroot{'pluginName'} = $outfilename;
+
+# Now just spit the JSON out
+my $json = JSON->new;
+$json = $json->utf8;
+my $json_text = $json->pretty->encode( \%jsonroot );
+
+open (my $fho, '>', $outputfilename)
+ or die "Can't create filehandle: $!";
+
+binmode($fho, ":utf8");
+
+print { $fho } $json_text;
+
+if ( $total == 1 or $total == 2 ) {
+ # close current output file
+ close($fho);
+}
+
+# Finnish
+exit;
+
+=head2 printWait
+
+Prints out wait information
+
+=cut
+
+sub printWait {
+ print STDERR ("\n");
+ print STDERR ("Processing input file:\n");
+ print STDERR (" $_[0]\n");
+ print STDERR ("Generating output file:\n");
+ print STDERR (" $_[1]\n");
+ print STDERR ("\n");
+ print STDERR ("This operation may take some while. Please wait...\n");
+ print STDERR ("\n");
+ print STDERR ("\n");
+}
+
+=head2 printUsage
+
+Prints out basic usage help
+
+=cut
+
+sub printUsage {
+ my $scriptname=$_[0];
+ print STDERR ("$scriptname\n");
+ print STDERR ("Usage: dbc2json infile [outfile]\n");
+ print STDERR (" infile Input dbc file\n");
+ print STDERR (" outfile File (optional) converted to json,\n");
+ print STDERR (" otherwise created in current directory.\n");
+ print STDERR ("\n");
+}
+
+=head1 AUTHOR
+
+IntelIVIPoc, C<< <ivipoc at intel.com> >>
+
+=head1 SUPPORT
+
+You can find documentation for this module with the perldoc command.
+
+ perldoc dbc2json
+
+=head1 ACKNOWLEDGEMENTS
+
+=head1 LICENSE AND COPYRIGHT
+
+Copyright (C) 2014 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+=cut
diff --git a/tools/AmbSignalMapper/bin/json2amb b/tools/AmbSignalMapper/bin/json2amb
new file mode 100755
index 00000000..7e39e988
--- /dev/null
+++ b/tools/AmbSignalMapper/bin/json2amb
@@ -0,0 +1,164 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2014 Intel Corporation
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+use 5.006;
+use strict;
+use warnings FATAL => 'all';
+
+use Intel::IviPoc::AmbPluginGenerator qw(processPlugin);
+use Cwd;
+
+=head1 NAME
+
+json2amb - JSON to Automotive Message Broker plugin generator.
+
+=head1 SYNOPSIS
+
+B<json2amb> B<-e|-E> | B<-d|-D> I<infile> [ I<outdir> ]
+
+=head1 DESCRIPTION
+
+Part of Automotive Message Broker Signal Mapper tool.
+
+B<json2amb> converts intermediate JSON file to Automotive Message Broker plugin.
+
+B<json2amb> - The command line interface for Intel::IviPoc::AmbPluginGenerator.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-e|-E>
+
+Signal encryption enabled.
+
+=item B<-d|-D>
+
+Signal encryption disabled
+
+=item I<filename>
+
+Input json file.
+
+=item [ I<outdir> ]
+
+ This parameter is optional. Target directory where the plugin is generated to.
+ Otherwise current directory.
+
+=back
+
+=head1 FILES
+
+=over 4
+
+=back
+
+=head1 REQUIRES
+
+Perl 5.006, Cwd, Intel::IviPoc::AmbPluginGenerator, Intel::IviPoc::AmbCommon
+
+=head1 SEE ALSO
+
+perl(1), dbc2json(1)
+
+=cut
+
+local $/;
+
+# get total arg passed to this script
+my $total = $#ARGV + 1;
+my $scriptname = $0;
+if ( $total < 1) {
+ # get script name and print usage
+ &printUsage($scriptname);
+ exit;
+ }
+
+my $hashingAllowed = 'E';
+if ( $ARGV[0] eq '-e' or $ARGV[0] eq '-E' ) {
+ $hashingAllowed = 'E';
+} elsif ( $ARGV[0] eq '-d' or $ARGV[0] eq '-D' ) {
+ $hashingAllowed = 'D';
+} else {
+ print STDERR ("\nERROR: Invalid input option $ARGV[0]\n\n");
+ &printUsage($scriptname);
+ exit;
+}
+
+my $targetDir = ();
+if ($total == 2) {
+ $targetDir = getcwd;
+} else {
+ $targetDir = Cwd::abs_path($ARGV[2]);
+}
+
+# Generate the plaugin
+processPlugin ( $hashingAllowed, $ARGV[1], $targetDir );
+
+# Finnish
+exit;
+
+=head2 printUsage
+
+Prints out basic usage help
+
+=cut
+
+sub printUsage {
+ my $scriptname=$_[0];
+ print STDERR ("$scriptname\n");
+ print STDERR ("Usage: json2amb enc infile [outdir]\n");
+ print STDERR (" enc: mandatory signal encryption option\n");
+ print STDERR (" -e Signal encryption enabled\n");
+ print STDERR (" -d Signal encryption disabled\n");
+ print STDERR (" infile Input json file\n");
+ print STDERR (" outdir Target plugin directory (optional) generated to,\n");
+ print STDERR (" otherwise current directory.\n");
+}
+
+=head1 AUTHOR
+
+IntelIVIPoc, C<< <ivipoc at intel.com> >>
+
+=head1 SUPPORT
+
+You can find documentation for this module with the perldoc command.
+
+ perldoc json2amb
+
+=head1 ACKNOWLEDGEMENTS
+
+=head1 LICENSE AND COPYRIGHT
+
+Copyright (C) 2014 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+=cut
diff --git a/tools/AmbSignalMapper/dbc2json.html b/tools/AmbSignalMapper/dbc2json.html
new file mode 100644
index 00000000..e16cdf04
--- /dev/null
+++ b/tools/AmbSignalMapper/dbc2json.html
@@ -0,0 +1,144 @@
+<html><head><title>dbc2json</title>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" >
+</head>
+<body class='pod'>
+<!--
+ generated by Pod::Simple::HTML v3.22,
+ using Pod::Simple::PullParser v3.22,
+ under Perl v5.014002 at Tue Jan 7 15:04:44 2014 GMT.
+
+ If you want to change this HTML document, you probably shouldn't do that
+ by changing it directly. Instead, see about changing the calling options
+ to Pod::Simple::HTML, and/or subclassing Pod::Simple::HTML,
+ then reconverting this document from the Pod source.
+ When in doubt, email the author of Pod::Simple::HTML for advice.
+ See 'perldoc Pod::Simple::HTML' for more info.
+
+-->
+
+<!-- start doc -->
+<a name='___top' class='dummyTopAnchor' ></a>
+
+<h1><a class='u'
+name="NAME"
+>NAME</a></h1>
+
+<p>dbc2json - Vector CANdb++ to JSON file format converter.</p>
+
+<h1><a class='u'
+name="SYNOPSIS"
+>SYNOPSIS</a></h1>
+
+<p><b>dbc2json</b> <i>infile</i> [ <i>outfile</i> ]</p>
+
+<h1><a class='u'
+name="DESCRIPTION"
+>DESCRIPTION</a></h1>
+
+<p>Part of Automotive Message Broker Signal Mapper tool.</p>
+
+<p><b>dbc2json</b> converts file in Vector CANdb++ format to intermediate JSON file.</p>
+
+<p>Intermediate file is used to format and annotate raw data from CANDb++ file into format suitable for AMB plugin creation.</p>
+
+<h1><a class='u'
+name="OPTIONS"
+>OPTIONS</a></h1>
+
+<dl>
+<dt><a name="infile"
+><i>infile</i></a></dt>
+
+<dd>
+<p>Input <i>infile</i> file in Vector CANdb++ (*.dbc) format.</p>
+
+<dt><a name="[_outfile_]"
+>[ <i>outfile</i> ]</a></dt>
+
+<dd>
+<p>Target output <i>outfile</i> file converted to JSON,
+otherwise created in current directory.</p>
+</dd>
+</dl>
+
+<h1><a class='u'
+name="FILES"
+>FILES</a></h1>
+
+<h1><a class='u'
+name="REQUIRES"
+>REQUIRES</a></h1>
+
+<p>Perl 5.006,
+Intel::IviPoc::DbcGrammar,
+File::Basename,
+File::Spec,
+Cwd,
+JSON</p>
+
+<h1><a class='u'
+name="SEE_ALSO"
+>SEE ALSO</a></h1>
+
+<p>perl(1),
+json2amb(1)</p>
+
+<h2><a class='u'
+name="readFileContent"
+>readFileContent</a></h2>
+
+<p>Reads and returns the whole content of given file.</p>
+
+<h2><a class='u'
+name="printWait"
+>printWait</a></h2>
+
+<p>Prints out wait information</p>
+
+<h2><a class='u'
+name="printUsage"
+>printUsage</a></h2>
+
+<p>Prints out basic usage help</p>
+
+<h1><a class='u'
+name="AUTHOR"
+>AUTHOR</a></h1>
+
+<p>IntelIVIPoc,
+<code>&#60;ivipoc at intel.com&#62;</code></p>
+
+<h1><a class='u'
+name="SUPPORT"
+>SUPPORT</a></h1>
+
+<p>You can find documentation for this module with the perldoc command.</p>
+
+<pre> perldoc dbc2json</pre>
+
+<h1><a class='u'
+name="ACKNOWLEDGEMENTS"
+>ACKNOWLEDGEMENTS</a></h1>
+
+<h1><a class='u'
+name="LICENSE_AND_COPYRIGHT"
+>LICENSE AND COPYRIGHT</a></h1>
+
+<p>Copyright (C) 2014 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA</p>
+<!-- end doc -->
+
+</body></html>
diff --git a/tools/AmbSignalMapper/json2amb.html b/tools/AmbSignalMapper/json2amb.html
new file mode 100644
index 00000000..a0f26ee9
--- /dev/null
+++ b/tools/AmbSignalMapper/json2amb.html
@@ -0,0 +1,139 @@
+<html><head><title>json2amb</title>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" >
+</head>
+<body class='pod'>
+<!--
+ generated by Pod::Simple::HTML v3.22,
+ using Pod::Simple::PullParser v3.22,
+ under Perl v5.014002 at Tue Jan 7 15:05:00 2014 GMT.
+
+ If you want to change this HTML document, you probably shouldn't do that
+ by changing it directly. Instead, see about changing the calling options
+ to Pod::Simple::HTML, and/or subclassing Pod::Simple::HTML,
+ then reconverting this document from the Pod source.
+ When in doubt, email the author of Pod::Simple::HTML for advice.
+ See 'perldoc Pod::Simple::HTML' for more info.
+
+-->
+
+<!-- start doc -->
+<a name='___top' class='dummyTopAnchor' ></a>
+
+<h1><a class='u'
+name="NAME"
+>NAME</a></h1>
+
+<p>json2amb - JSON to Automotive Message Broker plugin generator.</p>
+
+<h1><a class='u'
+name="SYNOPSIS"
+>SYNOPSIS</a></h1>
+
+<p><b>json2amb</b> <b>-e|-E</b> | <b>-d|-D</b> <i>infile</i> [ <i>outdir</i> ]</p>
+
+<h1><a class='u'
+name="DESCRIPTION"
+>DESCRIPTION</a></h1>
+
+<p>Part of Automotive Message Broker Signal Mapper tool.</p>
+
+<p><b>json2amb</b> converts intermediate JSON file to Automotive Message Broker plugin.</p>
+
+<p><b>json2amb</b> - The command line interface for Intel::IviPoc::AmbPluginGenerator.</p>
+
+<h1><a class='u'
+name="OPTIONS"
+>OPTIONS</a></h1>
+
+<dl>
+<dt><a name="-e|-E"
+><b>-e|-E</b></a></dt>
+
+<dd>
+<p>Signal encryption enabled.</p>
+
+<dt><a name="-d|-D"
+><b>-d|-D</b></a></dt>
+
+<dd>
+<p>Signal encryption disabled</p>
+
+<dt><a name="filename"
+><i>filename</i></a></dt>
+
+<dd>
+<p>Input json file.</p>
+
+<dt><a name="[_outdir_]"
+>[ <i>outdir</i> ]</a></dt>
+
+<dd>
+<pre> This parameter is optional. Target directory where the plugin is generated to.
+ Otherwise current directory.</pre>
+</dd>
+</dl>
+
+<h1><a class='u'
+name="FILES"
+>FILES</a></h1>
+
+<h1><a class='u'
+name="REQUIRES"
+>REQUIRES</a></h1>
+
+<p>Perl 5.006, Cwd, Intel::IviPoc::AmbPluginGenerator</p>
+
+<h1><a class='u'
+name="SEE_ALSO"
+>SEE ALSO</a></h1>
+
+<p>perl(1), dbc2json(1)</p>
+
+<h2><a class='u'
+name="printUsage"
+>printUsage</a></h2>
+
+<p>Prints out basic usage help</p>
+
+<h1><a class='u'
+name="AUTHOR"
+>AUTHOR</a></h1>
+
+<p>IntelIVIPoc, <code>&#60;ivipoc at intel.com&#62;</code></p>
+
+<h1><a class='u'
+name="SUPPORT"
+>SUPPORT</a></h1>
+
+<p>You can find documentation for this module with the perldoc command.</p>
+
+<pre> perldoc json2amb</pre>
+
+<h1><a class='u'
+name="ACKNOWLEDGEMENTS"
+>ACKNOWLEDGEMENTS</a></h1>
+
+<h1><a class='u'
+name="LICENSE_AND_COPYRIGHT"
+>LICENSE AND COPYRIGHT</a></h1>
+
+
+<p>Copyright (C) 2014 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA</p>
+
+<!-- end doc -->
+
+</body></html>
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/AmbCommon.pm b/tools/AmbSignalMapper/lib/Intel/IviPoc/AmbCommon.pm
new file mode 100644
index 00000000..b2957a3c
--- /dev/null
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/AmbCommon.pm
@@ -0,0 +1,212 @@
+#Copyright (C) 2014 Intel Corporation
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU Lesser General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+#Lesser General Public License for more details.
+#
+#You should have received a copy of the GNU Lesser General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+package Intel::IviPoc::AmbCommon;
+our @ISA = qw(Exporter);
+our @EXPORT = qw(evaluateType readFileContent);
+
+use 5.006;
+use strict;
+use warnings FATAL => 'all';
+use Exporter;
+
+=head1 NAME
+
+Intel::IviPoc::AmbCommon - The great new Intel::IviPoc::AmbCommon!
+
+=head1 VERSION
+
+Version 0.01
+
+=cut
+
+our $VERSION = '0.01';
+
+
+=head1 SYNOPSIS
+
+Module provides subroutines for reading input JSON file and generating Automotive Message Broker
+plugin project.
+
+The following little code snippet shows the module usage.
+
+ use Intel::IviPoc::AmbCommon;
+
+ $signal->{'AMBPropertyType'} = &evaluateType($signal);
+ ...
+
+=head1 EXPORT
+
+The following convenience methods are provided by this module. They are
+exported by default:
+
+=over 4
+
+=item C<processPlugin $signal>
+
+For given signal file name generates the Automotive Message Broker plugin
+
+=back
+
+=head1 SUBROUTINES/METHODS
+
+=head2 evaluateType
+
+Copies all template files into target folder while replacing the name
+with newly generated plugin name. Then generates C++ and IDL definitions
+based on information comming from input JSON file.
+
+=cut
+
+sub evaluateType {
+ my $signal = $_[0];
+ my $type = undef;
+
+ if ($signal->{'factor'} == 1) {
+ if ($signal->{'length'} == 1) {
+ $type = 'bool';
+ } else {
+ my $count = -1;
+ if ( exists( $signal->{'values'} ) ) {
+ $count = @{$signal->{'values'}};
+ }
+ if ($count == (2**$signal->{'length'})) {
+ $type = 'enum';
+ } else {
+ $type = &evalIntType( $signal );
+ }
+ }
+ }
+ else {
+ if ( $signal->{'factor'} =~ /\.|[eE]/ ) {
+ $type = 'double';
+ } else {
+ $type = &evalIntType( $signal );
+ }
+ }
+
+return $type;
+}
+
+=head2 evalIntType
+
+Copies one template file into target folder while replacing the name
+with newly generated plugin name. Then generates definitions
+based on information comming from input JSON file.
+
+=cut
+
+sub evalIntType {
+ my $signal = $_[0];
+ my $type = '';
+
+ my $signedness = '';
+
+ my $min = 0;
+ my $max = 0;
+ if ($signal->{'signedness'} eq '+') {
+ # unsigned
+ $min = $signal->{'offset'} + $signal->{'factor'} * 0;
+ $max = $signal->{'offset'} + $signal->{'factor'} * ((2**$signal->{'length'} ) - 1);
+ } else {
+ # signed
+ $min = $signal->{'offset'} - $signal->{'factor'} * (2**$signal->{'length'} - 1);
+ $max = $signal->{'offset'} + $signal->{'factor'} * (2**$signal->{'length'} - 1);
+ }
+
+ if ( 0 <= $min && $max < (2**8) ) {
+ $type = "uint8_t";
+ } elsif ( -1*(2**7) <= $min && $max < (2**7) ) {
+ $type = "int8_t";
+ } elsif ( 0 <= $min && $max < (2**16) ) {
+ $type = "uint16_t";
+ } elsif ( -1*(2**15) <= $min && $max < (2**15) ) {
+ $type = "int16_t";
+ } elsif ( 0 <= $min && $max < (2**32) ) {
+ $type = "uint32_t";
+ } elsif ( -1*(2**31) <= $min && $max < (2**31) ) {
+ $type = "int32_t";
+ } elsif ( 0 <= $min && $max < (2**64) ) {
+ $type = "uint64_t";
+ } else {
+ $type = "int64_t";
+ }
+
+ return $type;
+}
+
+=head2 readFileContent
+
+Reads and returns the whole content of given file.
+
+=cut
+
+sub readFileContent {
+ my $fileName = $_[0];
+ open(my $tmpl, '<', $fileName)
+ or die "Could not open file '$fileName' $!";
+
+ # Copy data from one file to another.
+ my $fileContent = <$tmpl>;
+
+ close $tmpl;
+
+ return $fileContent;
+}
+
+##############################################################################
+
+=head1 AUTHOR
+
+IntelIVIPoc, C<< <ivipoc at intel.com> >>
+
+=head1 SUPPORT
+
+You can find documentation for this module with the perldoc command.
+
+ perldoc Intel::IVIPoc::AmbCommon
+
+
+=head1 ACKNOWLEDGEMENTS
+
+=head1 LICENSE AND COPYRIGHT
+
+INTEL CONFIDENTIAL
+Copyright 2011 - 2013 Intel Corporation All Rights Reserved.
+
+The source code contained or described herein and all documents related to the
+source code("Material") are owned by Intel Corporation or its suppliers or
+licensors.Title to the Material remains with Intel Corporation or its
+suppliers and licensors.The Material may contain trade secrets and proprietary
+and confidential information of Intel Corporation and its suppliers and
+licensors, and is protected by worldwide copyright and trade secret laws and
+treaty provisions.No part of the Material may be used, copied, reproduced,
+modified, published, uploaded, posted, transmitted, distributed, or disclosed
+in any way without Intels prior express written permission.
+No license under any patent, copyright, trade secret or other intellectual
+property right is granted to or conferred upon you by disclosure or delivery
+of the Materials, either expressly, by implication, inducement, estoppel or
+otherwise.Any license under such intellectual property rights must be
+express and approved by Intel in writing.
+
+Unless otherwise agreed by Intel in writing, you may not remove or alter this
+notice or any other notice embedded in Materials by Intel or Intels suppliers
+or licensors in any way.
+
+
+=cut
+
+1; # End of Intel::IviPoc::AmbCommon
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/AmbPluginGenerator.pm b/tools/AmbSignalMapper/lib/Intel/IviPoc/AmbPluginGenerator.pm
new file mode 100644
index 00000000..88fb7088
--- /dev/null
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/AmbPluginGenerator.pm
@@ -0,0 +1,718 @@
+#Copyright (C) 2014 Intel Corporation
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU Lesser General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+#Lesser General Public License for more details.
+#
+#You should have received a copy of the GNU Lesser General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+package Intel::IviPoc::AmbPluginGenerator;
+our @ISA = qw(Exporter);
+our @EXPORT = qw(processPlugin);
+
+use 5.006;
+use strict;
+use warnings FATAL => 'all';
+use Exporter;
+
+use JSON;
+use Data::UUID;
+use File::Spec;
+use Digest::SHA qw(sha1_hex);
+use Intel::IviPoc::AmbCommon qw(readFileContent);
+
+=head1 NAME
+
+Intel::IviPoc::AmbPluginGenerator - The great new Intel::IviPoc::AmbPluginGenerator!
+
+=head1 VERSION
+
+Version 0.01
+
+=cut
+
+our $VERSION = '0.01';
+
+
+=head1 SYNOPSIS
+
+Module provides subroutines for reading input JSON file and generating Automotive Message Broker
+plugin project.
+
+The following little code snippet shows the module usage.
+
+ use Intel::IviPoc::AmbPluginGenerator qw(processPlugin);
+
+ my $hashingAllowed = "E";
+ my $inputfile = "myfile.json";
+ my $targetDir = '/home/user/project/automotive-message-broker/plugins';
+ processPlugin ( $hashingAllowed, $inputfile, $targetDir );
+ ...
+
+=head1 EXPORT
+
+The following convenience methods are provided by this module. They are
+exported by default:
+
+=over 4
+
+=item C<processPlugin $json_filename>
+
+For given json file name generates the Automotive Message Broker plugin
+
+=back
+
+=head1 SUBROUTINES/METHODS
+
+=head2 processPlugin
+
+Copies all template files into target folder while replacing the name
+with newly generated plugin name. Then generates C++ and IDL definitions
+based on information comming from input JSON file.
+
+=cut
+
+my $hashingAllowed = 'E'; # Enabled by default
+
+sub processPlugin {
+ $hashingAllowed = $_[0];
+ my $jsonfile = $_[1];
+ my $targetDir = $_[2];
+
+ # Load the json
+ my $json_text = &readFileContent( $jsonfile );
+
+ my $json = JSON->new;
+ $json = $json->utf8;
+
+ my $dbcjson = $json->decode( $json_text );
+ if ($hashingAllowed eq 'E' ) {
+ &encryptAmbPropertyNames( $dbcjson );
+ }
+
+ my $pluginName = $dbcjson->{'pluginName'};
+
+ my $templatesDir = 'templates/';
+ my $pluginDir = File::Spec->catdir( ($targetDir, lc($pluginName). '_plugin/') );
+
+ # make new folder
+ &createDirectory( $pluginDir );
+
+ my @templatesFiles = ( "CMakeLists.txt"
+ , "ambtmpl_cansignal.h"
+ , "ambtmpl_cansignal.cpp"
+ , "ambtmpl_plugin.h"
+ , "ambtmpl_plugin.cpp"
+ , "ambtmpl_cansignals.h"
+ , "ambtmpl_plugin.idl"
+ );
+
+ my @pluginFiles = ( "CMakeLists.txt"
+ , lc ($pluginName) . "_cansignal.h"
+ , lc ($pluginName) . "_cansignal.cpp"
+ , lc ($pluginName) . "_plugin.h"
+ , lc ($pluginName) . "_plugin.cpp"
+ , lc ($pluginName) . "_cansignals.h"
+ , lc ($pluginName) . "_plugin.idl"
+ );
+
+ my @generationSubs = ( undef
+ , undef
+ , undef
+ , \&generateUuid
+ , \&generateCppImplTypes
+ , \&generateSignalsTypes
+ , \&generateIdlTypes
+ );
+
+ my $templateFile = '';
+ my $pluginFile = '';
+ my ($volume, $directory) = File::Spec->splitpath( $INC{'Intel/IviPoc/AmbPluginGenerator.pm'} );
+ for my $i (0..scalar(@pluginFiles)-1) {
+ # First join templates folder and filename
+ $templateFile = File::Spec->catfile( ($templatesDir), $templatesFiles[$i] );
+ # Now prepend the module full path
+ $templateFile = File::Spec->catpath( $volume, $directory, $templateFile );
+ # Join target directory with target filename
+ $pluginFile = File::Spec->catfile( ($pluginDir), $pluginFiles[$i] );
+ # Generate each plugin files
+ &generatePluginFile( $templateFile, $pluginFile, $dbcjson, $generationSubs[$i]);
+ }
+}
+
+=head2 generatePluginFile
+
+Copies one template file into target folder while replacing the name
+with newly generated plugin name. Then generates definitions
+based on information comming from input JSON file.
+
+=cut
+
+sub generatePluginFile {
+ my $srcFileName = $_[0];
+ my $dstFileName = $_[1];
+ my $dbcjson = $_[2];
+ my $generationSub = $_[3];
+
+ my $pluginName = $dbcjson->{'pluginName'};
+
+ # Open template file
+ my $content = &readFileContent( $srcFileName );
+ $content = &replaceTemplateStrings( $content, $pluginName );
+
+ if (defined $generationSub) {
+ my $generatedCode = $generationSub->( $dbcjson );
+ my $place = '\/\*GENERATED_CODE\*\/';
+ $content =~ s/$place/$generatedCode/g;
+ }
+
+ # Create new file
+ my $pluginFileHandle = &createFile( $dstFileName );
+
+ # Copy data from one file to another.
+ print $pluginFileHandle $content;
+
+ # close the file
+ close ($pluginFileHandle);
+}
+
+=head2 createDirectory
+
+Creates directory for plugin.
+
+=cut
+
+sub createDirectory {
+ my $dirName = $_[0];
+
+ unless(-e $dirName or mkdir $dirName) {
+ die "Unable to create directory '$dirName' $!";
+ }
+}
+
+=head2 createFile
+
+Creates file and returns a file handle to it.
+
+=cut
+
+sub createFile {
+ my $fileName = $_[0];
+
+ # Open file or die
+ open(my $fileHandle, '>', $fileName)
+ or die "Could not open file '$fileName' $!";
+
+ return $fileHandle;
+}
+
+=head2 replaceTemplateStrings
+
+Replaces all occurencies of template specific symbols with plugin name.
+
+=cut
+
+sub replaceTemplateStrings {
+ my $text = $_[0];
+ my $pluginName = $_[1];
+
+ $text =~ s/AmbTmpl/$pluginName/g;
+ $pluginName = lc ($pluginName);
+ $text =~ s/ambtmpl/$pluginName/g;
+ $pluginName = uc ($pluginName);
+ $text =~ s/AMBTMPL/$pluginName/g;
+ return $text;
+}
+
+=head2 generateUuid
+
+For all signals generates C++ property instantiation.
+Returns C++ code to be placed into the target plugin.
+
+=cut
+
+sub generateUuid {
+ my $dbcjson = $_[0];
+
+ my $ug = new Data::UUID;
+ my $uuidText = $ug->create_str();
+
+ return $uuidText;
+}
+
+=head2 generateCppImplTypes
+
+For all signals generates C++ property instantiation.
+Returns C++ code to be placed into the target plugin.
+
+=cut
+
+sub generateCppImplTypes {
+ my $dbcjson = $_[0];
+
+ my $registerMessageText = '';
+ my $hexValue = ();
+
+ my @engineControlUnits = @{$dbcjson->{'electronicControlUnits'}};
+ for my $ecui (0..scalar(@engineControlUnits)-1) {
+ if ( exists( $engineControlUnits[$ecui]{'messages'} ) ) {
+ my @messages = @{$engineControlUnits[$ecui]{'messages'}};
+ for my $msgi (0..scalar(@messages)-1) {
+ $hexValue = '0x' . uc ( sprintf( "%x", $messages[$msgi]{'canId'} ) );
+ $registerMessageText .= " registerMessage($hexValue, $messages[$msgi]{'canDlc'}";
+
+ my @signals = @{$messages[$msgi]{'signals'}};
+ foreach my $signal ( @signals ) {
+ my $type = $signal->{'AMBPropertyType'};
+ $registerMessageText .= &generateCppProperty( $signal, $type);
+ }
+
+ $registerMessageText .= "\n );\n";
+ }
+ }
+ }
+
+ return $registerMessageText;
+}
+
+=head2 generateCppProperty
+
+For given signal generates ADDPROPERTY calls and returns C++ property
+definitions.
+
+=cut
+
+sub generateCppProperty {
+ my $signal = $_[0];
+ my $type = $_[1];
+
+ my $generatedText = '';
+ my $zonesInUse = 0; # TODO this needs to be in config file
+
+ if ( exists( $signal->{'AMBPropertyName'} ) ) {
+ my $ambPropertyName = $signal->{'AMBPropertyName'};
+
+ # TODO CANSignal needs to take zone as argument
+ #my $zone = 'Zone::None';
+ #if ($zonesInUse) {
+ # $zone = &calculateZone( $ambPropertyName );
+ #}
+ $generatedText .= "\n , new ${ambPropertyName}Type()";
+ }
+ return $generatedText;
+}
+
+=head2 generateSignalsTypes
+
+For all signals generates C++ property definitions.
+Returns C++ code to be placed into the target plugin.
+
+=cut
+
+sub generateSignalsTypes {
+ my $dbcjson = $_[0];
+
+ my $enumsText = '';
+ my $propertiesText = '';
+
+ # First generate the c++ enums from signals with values
+ my @engineControlUnits = @{$dbcjson->{'electronicControlUnits'}};
+ for my $ecui (0..scalar(@engineControlUnits)-1) {
+ if ( exists( $engineControlUnits[$ecui]{'messages'} ) ) {
+ my @messages = @{$engineControlUnits[$ecui]{'messages'}};
+ for my $msgi (0..scalar(@messages)-1) {
+ my @signals = @{$messages[$msgi]{'signals'}};
+ foreach my $signal ( @signals ) {
+ my $type = $signal->{'AMBPropertyType'};
+ $enumsText .= &generateEnumOrValues( $signal, $type);
+ $propertiesText .= &generatePropertyClasses( $signal, $type );
+ }
+ }
+ }
+ }
+ return $enumsText . $propertiesText;
+}
+
+=head2 generateEnumOrValues
+
+For given signal generates enums or c++ constants and returns C++ types
+definitions.
+
+=cut
+
+sub generateEnumOrValues {
+ my $signal = $_[0];
+ my $type = $_[1];
+
+ my $generatedText = "";
+
+ my $ambPropertyName = $signal->{'canId'};
+ if ( exists( $signal->{'AMBPropertyName'} ) ) {
+ $ambPropertyName = $signal->{'AMBPropertyName'};
+ }
+
+ if ( exists( $signal->{'values'} ) ) {
+ my @dupvalues = @{$signal->{'values'}};
+ my @values = sort { $$a{'value'} <=> $$b{'value'} } (&removeDuplicates (\@dupvalues));
+ my $hexValue = ();
+
+ if ( $type eq 'enum' or $type =~ m/int/) {
+ # Start with comments
+ $generatedText .= "/**< $ambPropertyName\n";
+ for my $vali (0..scalar(@values) -1 ) {
+ $hexValue = '0x' . uc ( sprintf( "%x", $values[$vali]->{'value'} ) );
+ $generatedText .= " * $hexValue = $values[$vali]->{'description'}\n";
+ }
+ $generatedText .= " */\n";
+ }
+
+ if ( $type eq 'enum' ) {
+ # Enum definition
+ $generatedText .= "namespace ${ambPropertyName}s {\n";
+ $generatedText .= "enum ${ambPropertyName}Type {\n";
+
+ # Generate enum values
+ for my $vali (0..scalar(@values) -1 ) {
+ $hexValue = '0x' . uc ( sprintf( "%x", $values[$vali]->{'value'} ) );
+ $generatedText .= " $values[$vali]->{'name'} = $hexValue";
+ if ($vali != scalar(@values)-1 ) {
+ $generatedText .= ",";
+ }
+ $generatedText .= "\n";
+ }
+ $generatedText .= "};\n";
+ $generatedText .= "}\n\n";
+ } elsif ( $type =~ m/int/ ) {
+ $generatedText .= "namespace ${ambPropertyName}s {\n";
+ # Generate values
+ for my $vali (0..scalar(@values) -1 ) {
+ $hexValue = '0x' . uc ( sprintf( "%x", $values[$vali]->{'value'} ) );
+ $generatedText .= "static const $type $values[$vali]->{'name'} = $hexValue;";
+ $generatedText .= "\n";
+ }
+ $generatedText .= "}\n\n";
+ }
+ }
+
+ return $generatedText;
+}
+
+=head2 generatePropertyClasses
+
+For given signal generates documentation, VehicleProperty::Property
+properties with values of stringified properties names.
+lastly using CANSIGNAL macro generates C++ classes
+for given signal.
+
+Returns C++ definitions of one signal property.
+
+=cut
+
+sub generatePropertyClasses {
+ my $signal = $_[0];
+ my $type = $_[1];
+
+ my $generatedText = '';
+
+ my $ambPropertyName = $signal->{'canId'};
+ if ( exists( $signal->{'AMBPropertyName'} ) ) {
+ $ambPropertyName = $signal->{'AMBPropertyName'};
+ }
+
+ my $byteOrdering = "Endian::Intel"; # LittleEndian by default
+ if ( exists( $signal->{'byteOrdering'} ) and $signal->{'byteOrdering'} eq '0') {
+ $byteOrdering = "Endian::Motorola"; # BigEndian
+ }
+
+ my $signedness;
+ if ($signal->{'signedness'} eq '+') {
+ $signedness = "Signedness::Unsigned"; # Unsigned
+ } else {
+ $signedness = "Signedness::Signed"; # Signed
+ }
+
+ my $convertFromFunction = "nullptr";
+ if ( exists( $signal->{'AMBConversionFrom'} ) ) {
+ $convertFromFunction = $signal->{'AMBConversionFrom'};
+ }
+
+ my $convertToFunction = "nullptr";
+ if ( exists( $signal->{'AMBConversionTo'} ) ) {
+ $convertToFunction = $signal->{'AMBConversionTo'};
+ }
+
+ $generatedText .= "\n";
+ $generatedText .= "/**< $ambPropertyName.\n";
+
+ my $typeBasedText = '';
+ my $cppType;
+
+ if ( $type =~ m/enum/ ) {
+ if ( exists( $signal->{'values'} ) ) {
+ $generatedText .= " *\@see ${ambPropertyName}s::${ambPropertyName}Type\n";
+ $cppType = "${ambPropertyName}s::${ambPropertyName}Type";
+ }
+ } elsif ( $type =~ m/bool/ ) {
+ if ( exists( $signal->{'values'} ) ) {
+ my @dupvalues = @{$signal->{'values'}};
+ my @values = sort { $$a{'value'} <=> $$b{'value'} } (&removeDuplicates (\@dupvalues));
+ my $hexValue = ();
+ for my $vali (0..scalar(@values) -1 ) {
+ $hexValue = '0x' . uc ( sprintf( "%x", $values[$vali]->{'value'} ) );
+ $generatedText .= " * $hexValue = $values[$vali]->{'description'}\n";
+ }
+ }
+ $cppType = "$type";
+ } elsif ( $type =~ m/int8/ ) {
+ $cppType = "char";
+ } elsif ( $type =~ m/int32/ ) {
+ if ( $type eq 'uint32_t' ) {
+ $cppType = "$type";
+ } else {
+ $cppType = "int";
+ }
+ } else { # (u)int16, (u)int64
+ $cppType = "$type";
+ }
+
+ $typeBasedText .= "CANSIGNAL($ambPropertyName, $cppType, $signal->{'startBit'}, $signal->{'length'}, $byteOrdering, $signedness, $signal->{'factor'}, $signal->{'offset'}, static_cast<$cppType>($signal->{'minValue'}), static_cast<$cppType>($signal->{'maxValue'}), $convertFromFunction, $convertToFunction)\n";
+
+ $generatedText .= " */\n";
+ my $shownPropertyName = $ambPropertyName;
+ if ($hashingAllowed eq 'E' ) {
+ $shownPropertyName = $signal->{'AMBPropertyNameEnc'};
+ }
+ $generatedText .= "const VehicleProperty::Property $ambPropertyName = \"$shownPropertyName\";\n";
+ $generatedText .= $typeBasedText;
+
+ return $generatedText;
+}
+
+=head2 generateIdlTypes
+
+For all signals generates WebIDL property documentation.
+Returns IDL code to be placed into the target plugin.
+
+=cut
+
+sub generateIdlTypes {
+ my $dbcjson = $_[0];
+
+ my $generatedText = '';
+
+ my @engineControlUnits = @{$dbcjson->{'electronicControlUnits'}};
+ for my $ecui (0..scalar(@engineControlUnits)-1) {
+ if ( exists( $engineControlUnits[$ecui]{'messages'} ) ) {
+ my @messages = @{$engineControlUnits[$ecui]{'messages'}};
+ for my $msgi (0..scalar(@messages)-1) {
+ my @signals = @{$messages[$msgi]{'signals'}};
+ foreach my $signal ( @signals ) {
+ my $type = $signal->{'AMBPropertyType'};
+ $generatedText .= &generateIdlProperty( $signal, $type);
+ }
+ }
+ }
+ }
+ return $generatedText;
+}
+
+=head2 generateIdlProperty
+
+For given signal generates WebIDL documentation and returns WebIDL
+definitions of one signal property.
+
+=cut
+
+sub generateIdlProperty {
+ my $signal = $_[0];
+ my $type = $_[1];
+ my $generatedText = '';
+
+ my $ambPropertyName = $signal->{'canId'};
+ if ( exists( $signal->{'AMBPropertyName'} ) ) {
+ $ambPropertyName = $signal->{'AMBPropertyName'};
+ }
+
+ $generatedText .= "[NoInterfaceObject]\n";
+ $generatedText .= "interface org.automotive.${ambPropertyName} : VehiclePropertyType {\n";
+ if ( $type eq 'enum' ) {
+ if ( exists( $signal->{'values'} ) ) {
+ my @dupvalues = @{$signal->{'values'}};
+ my @values = sort { $$a{'value'} <=> $$b{'value'} } (&removeDuplicates (\@dupvalues));
+
+ my $hexValue = ();
+ for my $vali (0..scalar(@values) -1 ) {
+ # TODO const unsigned short migth be not enough, guess type based on values
+ $hexValue = '0x' . uc (sprintf( "%x", $values[$vali]->{'value'} ) );
+ $generatedText .= " const unsigned short " . uc($values[$vali]->{'name'}) . " = $hexValue;\n";
+ }
+ }
+ }
+
+ $generatedText .= "\n";
+ $generatedText .= " /** ${ambPropertyName}\n";
+ $generatedText .= " * \\brief Returns ${ambPropertyName}\n";
+ $generatedText .= " **/\n";
+
+ my $unsigned = '';
+ if ( $type =~ m/uint/ ) {
+ $unsigned = 'unsigned ';
+ }
+
+ if ( $type =~ m/enum/ ) {
+ # TODO const unsigned short migth be not enough, guess type based on values
+ $generatedText .= " readonly attribute octet ${ambPropertyName};\n";
+ } elsif ( $type =~ m/bool/ ) {
+ $generatedText .= " readonly attribute boolean ${ambPropertyName};\n";
+ } elsif ( $type =~ m/int8/ ) {
+ $generatedText .= " readonly attribute ${unsigned}octet ${ambPropertyName};\n";
+ } elsif ( $type =~ m/int16/ ) {
+ $generatedText .= " readonly attribute ${unsigned}short ${ambPropertyName};\n";
+ } elsif ( $type =~ m/int32/ ) {
+ $generatedText .= " readonly attribute ${unsigned}long ${ambPropertyName};\n";
+ } else {
+ $generatedText .= " readonly attribute double ${ambPropertyName};\n";
+ }
+ $generatedText .= "};\n\n";
+
+ return $generatedText;
+}
+
+=head2 encryptAmbPropertyNames
+
+Encrypt AmbPropertyNames.
+
+=cut
+
+sub encryptAmbPropertyNames {
+ my $dbcjson = $_[0];
+
+ my @engineControlUnits = @{$dbcjson->{'electronicControlUnits'}};
+ for my $ecui (0..scalar(@engineControlUnits)-1) {
+ if ( exists( $engineControlUnits[$ecui]{'messages'} ) ) {
+ my @messages = @{$engineControlUnits[$ecui]{'messages'}};
+ for my $msgi (0..scalar(@messages)-1) {
+ my @signals = @{$messages[$msgi]{'signals'}};
+ foreach my $signal ( @signals ) {
+ my $shownPropertyName = sha1_hex( $signal->{'AMBPropertyName'} );
+ $signal->{'AMBPropertyNameEnc'} = 'S' . sha1_hex( $shownPropertyName );
+ }
+ }
+ }
+ }
+}
+
+=head2 removeDuplicates
+
+Returns array of values witout duplicates.
+
+=cut
+
+sub removeDuplicates {
+ my @arr = sort { $a->{'name'} cmp $b->{'name'} } @{$_[0]};
+
+ my @duplicates;
+ my $prev = pop @arr;
+
+ while (defined(my $x = pop @arr)) {
+ if ($prev->{'name'} eq $x->{'name'}) {
+ push @duplicates, $x;
+ while (defined(my $y = pop @arr)) {
+ if ($y->{'name'} ne $x->{'name'}) {
+ $prev = $y;
+ last;
+ }
+ }
+ }
+ else {
+ $prev = $x;
+ }
+ }
+ # Typically very small arrays
+ @arr = sort @{$_[0]};
+ if (scalar @duplicates > 0) {
+ foreach my $x (@arr) {
+ foreach my $y (@duplicates) {
+ if ($x->{'name'} eq $y->{'name'}) {
+ $x->{'name'} .= '_' . $x->{'value'};
+ }
+ }
+ }
+ }
+
+ return @arr;
+}
+
+=head2 calculateZone
+
+Returns calculated Zone for given signal.
+
+=cut
+
+sub calculateZone {
+ my $ambPropertyName = $_[0];
+ my $zone = 'Zone::None';
+
+ if ( $ambPropertyName =~ m/FrL/) {
+ $zone = 'Zone::FrontLeft';
+ } elsif ( $ambPropertyName =~ m/FrR/) {
+ $zone = 'Zone::FrontRight';
+ } elsif ( $ambPropertyName =~ m/ReL/) {
+ $zone = 'Zone::RearLeft';
+ } elsif ( $ambPropertyName =~ m/ReR/) {
+ $zone = 'Zone::RearRight';
+ }
+ return $zone;
+}
+
+##############################################################################
+
+=head1 AUTHOR
+
+IntelIVIPoc, C<< <ivipoc at intel.com> >>
+
+=head1 SUPPORT
+
+You can find documentation for this module with the perldoc command.
+
+ perldoc Intel::IVIPoc::AMBPluginGenerator
+
+
+=head1 ACKNOWLEDGEMENTS
+
+=head1 LICENSE AND COPYRIGHT
+
+INTEL CONFIDENTIAL
+Copyright 2011 - 2013 Intel Corporation All Rights Reserved.
+
+The source code contained or described herein and all documents related to the
+source code("Material") are owned by Intel Corporation or its suppliers or
+licensors.Title to the Material remains with Intel Corporation or its
+suppliers and licensors.The Material may contain trade secrets and proprietary
+and confidential information of Intel Corporation and its suppliers and
+licensors, and is protected by worldwide copyright and trade secret laws and
+treaty provisions.No part of the Material may be used, copied, reproduced,
+modified, published, uploaded, posted, transmitted, distributed, or disclosed
+in any way without Intels prior express written permission.
+No license under any patent, copyright, trade secret or other intellectual
+property right is granted to or conferred upon you by disclosure or delivery
+of the Materials, either expressly, by implication, inducement, estoppel or
+otherwise.Any license under such intellectual property rights must be
+express and approved by Intel in writing.
+
+Unless otherwise agreed by Intel in writing, you may not remove or alter this
+notice or any other notice embedded in Materials by Intel or Intels suppliers
+or licensors in any way.
+
+
+=cut
+
+1; # End of Intel::IviPoc::AmbPluginGenerator
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/DbcGrammar b/tools/AmbSignalMapper/lib/Intel/IviPoc/DbcGrammar
new file mode 100644
index 00000000..80e6164e
--- /dev/null
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/DbcGrammar
@@ -0,0 +1,218 @@
+#Copyright (C) 2014 Intel Corporation
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU Lesser General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+#Lesser General Public License for more details.
+#
+#You should have received a copy of the GNU Lesser General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+{
+ my @networks = ();
+ my @ecuList = ();
+ my %ecuMessages = ();
+ my %ecuValues = ();
+}
+
+DbcOutput: Line(s?) eofile
+ {
+ my @electronicControlUnits = ();
+ for my $ecui (0..scalar(@ecuList)-1) {
+ my %ecuField = ();
+ $ecuField{'canId'} = $ecuList[$ecui];
+
+ if ( exists( $ecuMessages{$ecuList[$ecui]} ) ) {
+ my $messagesRef = $ecuMessages{$ecuList[$ecui]};
+ my @messages = @{$messagesRef};
+
+ $ecuField{'messages'} = \@messages;
+ for my $msgi (0..scalar(@messages)-1) {
+ my @signals = @{$messages[$msgi]{'signals'}};
+
+ for my $si (0..scalar(@signals)-1) {
+ my $signal = \%{$signals[$si]};
+ my $msgid = $messages[$msgi]{'canId'};
+
+ if ( exists( ${ecuValues{$msgid}} ) && defined ${$ecuValues{$msgid}{$signal->{'canId'}}} ) {
+ my $valueListRef=${$ecuValues{$msgid}->{$signal->{'canId'}}};
+ my @valueList = @$valueListRef;
+ $signal->{'values'} = \@valueList;
+
+ # Add AMBPropertyName prefix if valueName starts with number
+ foreach my $vali (@{$signal->{'values'}}) {
+ if ( $vali->{'name'} =~ m/^[0-9]/ ) {
+ $vali->{'name'} = $signal->{'AMBPropertyName'} . '_' . $vali->{'name'};
+ }
+ }
+ }
+ use Intel::IviPoc::AmbCommon;
+ $signal->{'AMBPropertyType'} = &evaluateType($signal);
+ }
+ }
+ }
+ push (@electronicControlUnits, \%ecuField);
+ }
+
+ my %jsonroot = ();
+ $jsonroot{'pluginName'} = "pluginName";
+ $jsonroot{'electronicControlUnits'} = \@electronicControlUnits;
+
+ # Now return the whole internal json structure
+ return \%jsonroot;
+ }
+
+
+eofile: /^\Z/
+
+Line: CommentPrefix /.*\n/
+ # Not needed to output anything yet
+ | 'VERSION' DoubleQuotedId
+ # Not needed to output anything yet
+ | 'NS_' ':' NSList(s?) ...'BS_'
+ {
+ # We just read the list of NSs
+ @networks = @{$item[3]};
+ }
+ | 'BS_' /.*\n/
+ # Not needed to output anything yet
+ | 'BU_' ':' EcuList(s?) ...'BO_'
+ {
+ @ecuList = @{$item[3]};
+ }
+ | 'BO_' Number Identifier ':' Identifier Identifier Signal(s?)
+ {
+ my %msg = ();
+ $msg{'canId'} = $item[2];
+ $msg{'canName'} = $item[3];
+ $msg{'canDlc'} = $item[5];
+ $msg{'canMessageId'} = $item[6];
+ $msg{'signals'} = $item[7];
+
+ push ( @{$ecuMessages{$item[6]}}, \%msg );
+ }
+ | 'VAL_' Number Identifier ValuePair(s?) ';'
+ {
+ ${$ecuValues{$item[2]}->{$item[3]}} = $item[4];
+ }
+ | <error: Invalid dbc format at $thisline!>
+
+Signal: 'SG_' Identifier ':' DataPlacement FactorOffset Range DoubleQuotedId Receiver(s /,/)
+ {
+ my %signal;
+ $signal{'canId'} = $item[2];
+
+ my %placement = %{$item[4]};
+ $signal{'startbit'} = $placement{'startbit'};
+ $signal{'length'} = $placement{'length'};
+ $signal{'byteOrdering'} = $placement{'byteOrdering'};
+ $signal{'signedness'} = $placement{'signedness'};
+
+ my %fo=%{$item[5]};
+ $signal{'factor'} = $fo{'factor'};
+ $signal{'offset'} = $fo{'offset'};
+
+ my %range=%{$item[6]};
+ $signal{'minValue'} = $range{'minValue'};
+ $signal{'maxValue'} = $range{'maxValue'};
+
+ $signal{'unit'} = $item[7];
+
+ $signal{'receivers'} = $item[8];
+
+ my $ambPropertyName = $item[2];
+ $ambPropertyName =~ s/\_[HM]S$//;
+ $signal{'AMBPropertyName'} = $ambPropertyName;
+
+ $return=\%signal;
+ }
+
+EcuList: ...!'BO_' Identifier
+ {
+ $return = $item[2];
+ }
+
+NSList: ...!'BS_' Identifier
+ {
+ $return = $item[2];
+ }
+
+Receiver: Identifier
+ {
+ my %rx;
+ $rx{'name'} = $item[1];
+ $return = \%rx;
+ }
+
+ValuePair: Number DoubleQuotedId
+ {
+ my %valuepair;
+ $valuepair{'value'} = $item[1];
+ $valuepair{'description'} = $item[2];
+
+ my $s = $item[2];
+ $s =~ s!(^|\s)(\w)!$1\U$2!g;
+ $s =~ s/ |-/_/g;
+ $s =~ s/[^_a-zA-Z0-9]//g;
+ $s =~ s/_(?=[_]*$)//;
+ $s =~ s/(_)\1+/$1/g;
+ $s =~ s/^\_//;
+ $s =~ s/\_$//;
+ $valuepair{'name'} = $s;
+
+ $return=\%valuepair;
+ }
+
+DataPlacement: Number '|' Number '@' Number Sign
+ {
+ my %placement;
+ $placement{'startbit'} = $item[1];
+ $placement{'length'} = $item[3];
+ $placement{'byteOrdering'} = $item[5];
+ $placement{'signedness'} = $item[6];
+ $return=\%placement;
+ }
+
+FactorOffset: '(' RealNumber ',' RealNumber ')'
+ {
+ my %fo;
+ $fo{'factor'} = $item[2];
+ $fo{'offset'} = $item[4];
+ $return=\%fo;
+ }
+
+Range: '[' RealNumber '|' RealNumber ']'
+ {
+ my %range;
+ $range{'minValue'} = $item[2];
+ $range{'maxValue'} = $item[4];
+ $return=\%range;
+ }
+
+DoubleQuotedId: DoubleQuotation /[A-Za-z0-9°\!@#\$%\^&\*()\-_=\+\[\]\{\};:\'|,\.\/<>\?`~\ ]+/ DoubleQuotation
+ {
+ $return = $item[2];
+ }
+ | DoubleQuotation DoubleQuotation
+ {
+ $return = "";
+ }
+
+Identifier: /[A-Za-z0-9_\-]+/
+ {
+ $return = $item[1];
+ }
+
+Number: /[-+]?[0-9]*/
+RealNumber: /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/
+Sign: /^[-+]?/
+
+CommentPrefix: /^\/\//
+
+DoubleQuotation: "\""
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/DbcGrammar.pod b/tools/AmbSignalMapper/lib/Intel/IviPoc/DbcGrammar.pod
new file mode 100644
index 00000000..b6d3e44b
--- /dev/null
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/DbcGrammar.pod
@@ -0,0 +1,90 @@
+#Copyright (C) 2014 Intel Corporation
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU Lesser General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+#Lesser General Public License for more details.
+#
+#You should have received a copy of the GNU Lesser General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+=head1 NAME
+
+Intel::IviPoc::DbcGrammar - Vector CANdb++ (*.dbc) file format parser
+
+=head1 SYNOPSIS
+
+ use Intel::IviPoc::DbcGrammar;
+
+ my $result;
+ $result = $parser->DbcOutput($text);
+ my %jsonroot = %{$result};
+
+=head1 REQUIRES
+
+Perl 5.006, Parse::RecDescent, Intel::IviPoc::AmbCommon
+
+=head1 EXPORTS
+
+new
+
+=head1 DESCRIPTION
+
+The Parse::RecDescent - Generate Recursive-Descent Parsers is Perl library for recursive top-down parsing(LL).
+
+=head1 METHODS
+
+=over 4
+
+=item DbcOutput $text
+
+Parses the provided string $text
+Returns the hash representing the entire $text.
+
+=item new
+
+Returns an instance of DbcParser.
+
+=back
+
+=head1 AUTHOR
+
+IntelIVIPoc, C<< <ivipoc at intel.com> >>
+
+=head1 SEE ALSO
+
+L<strict|http://search.cpan.org/~jtbraun/Parse-RecDescent-1.967009/lib/Parse/RecDescent.pm>
+
+=head1 ACKNOWLEDGEMENTS
+
+=head1 LICENSE AND COPYRIGHT
+
+INTEL CONFIDENTIAL
+Copyright 2011 - 2013 Intel Corporation All Rights Reserved.
+
+The source code contained or described herein and all documents related to the
+source code("Material") are owned by Intel Corporation or its suppliers or
+licensors.Title to the Material remains with Intel Corporation or its
+suppliers and licensors.The Material may contain trade secrets and proprietary
+and confidential information of Intel Corporation and its suppliers and
+licensors, and is protected by worldwide copyright and trade secret laws and
+treaty provisions.No part of the Material may be used, copied, reproduced,
+modified, published, uploaded, posted, transmitted, distributed, or disclosed
+in any way without Intels prior express written permission.
+No license under any patent, copyright, trade secret or other intellectual
+property right is granted to or conferred upon you by disclosure or delivery
+of the Materials, either expressly, by implication, inducement, estoppel or
+otherwise.Any license under such intellectual property rights must be
+express and approved by Intel in writing.
+
+Unless otherwise agreed by Intel in writing, you may not remove or alter this
+notice or any other notice embedded in Materials by Intel or Intels suppliers
+or licensors in any way.
+
+=cut
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/CMakeLists.txt b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/CMakeLists.txt
new file mode 100644
index 00000000..6d392eed
--- /dev/null
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/CMakeLists.txt
@@ -0,0 +1,68 @@
+cmake_minimum_required(VERSION 2.8)
+
+set( CMAKE_VERBOSE_MAKEFILE on )
+
+# to install plugin into /usr instead of /usr/local
+set (CMAKE_INSTALL_PREFIX /usr)
+
+IF(CMAKE_BUILD_TYPE MATCHES DEBUG)
+ message("debug mode")
+ENDIF(CMAKE_BUILD_TYPE MATCHES DEBUG)
+
+IF(CMAKE_BUILD_TYPE MATCHES RELEASE)
+ message("release mode")
+ add_definitions(-D_LOGGER_NO_LOG)
+ENDIF(CMAKE_BUILD_TYPE MATCHES RELEASE)
+
+include(FindPkgConfig)
+
+find_package(Boost REQUIRED)
+
+pkg_check_modules(glib REQUIRED glib-2.0)
+pkg_check_modules(json REQUIRED json)
+
+add_definitions(-std=gnu++0x -fPIC -fPIE)
+
+pkg_check_modules( amb REQUIRED automotive-message-broker )
+pkg_check_modules( amb-plugins-common REQUIRED amb-plugins-common )
+
+include_directories(${include_dirs} ${amb-plugins-common_INCLUDE_DIRS} ${amb_INCLUDE_DIRS} ${glib_INCLUDE_DIRS} ${gio_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${json_INCLUDE_DIRS} )
+
+set(ambtmpl_plugin_headers ambtmpl_plugin.h ambtmpl_cansignals.h ambtmpl_cansignal.h)
+set(ambtmpl_plugin_sources ambtmpl_plugin.cpp ambtmpl_cansignal.cpp)
+
+if(ivipoc_tests)
+#########################################
+# ivipoc_tests START
+#########################################
+
+#find CppUTest headers ( CppUTest/CommandLineTestRunner.h ):
+find_path(cpputest_INCLUDE_DIR CppUTest/CommandLineTestRunner.h PATHS $ENV{CPPUTEST_HOME}/include DOC "CppUTest headers")
+
+include_directories(${include_dirs} ${cpputest_INCLUDE_DIR})
+
+#find libCppUTestExt.a (and libCppUTest.a) library:
+find_library(CppUTest_LIBRARY CppUTest PATHS $ENV{CPPUTEST_HOME}/lib DOC "CppUTest library")
+find_library(CppUTestExt_LIBRARY CppUTestExt PATHS $ENV{CPPUTEST_HOME}/lib DOC "CppUTestExt library")
+
+# test definitions
+add_definitions(-DUNIT_TESTS -fprofile-arcs -ftest-coverage)
+
+# test link libs
+set(link_libraries gcov ${CppUTest_LIBRARY} ${CppUTestExt_LIBRARY})
+
+# test sources
+add_subdirectory(test)
+
+#########################################
+# ivipoc_tests END
+#########################################
+endif(ivipoc_tests)
+
+add_library(ambtmpl_plugin MODULE ${ambtmpl_plugin_sources} ${ambtmpl_plugin_headers})
+set_target_properties(ambtmpl_plugin PROPERTIES PREFIX "")
+target_link_libraries(ambtmpl_plugin ${link_libraries} ${libamb_LIBRARY} ${amb_LIBRARIES} ${amb-plugins-common_LIBRARIES})
+
+install(TARGETS ambtmpl_plugin LIBRARY DESTINATION lib/automotive-message-broker)
+
+############################################################################################################################################
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.cpp b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.cpp
new file mode 100644
index 00000000..b44f36ef
--- /dev/null
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.cpp
@@ -0,0 +1,188 @@
+/*****************************************************************
+Copyright (C) 2014 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ *****************************************************************/
+
+#include "ambtmpl_cansignal.h"
+
+template<>
+bool convert<bool>( double temp )
+{
+ return abs(temp) > std::numeric_limits<double>::epsilon();
+}
+
+double fromGVariant(GVariant *value)
+{
+ GVariantClass c = g_variant_classify(value);
+ if(c == G_VARIANT_CLASS_BOOLEAN)
+ return g_variant_get_boolean(value) ? 1.0 : 0.0;
+
+ else if(c == G_VARIANT_CLASS_BYTE)
+ return static_cast<double>(g_variant_get_byte(value));
+
+ else if(c == G_VARIANT_CLASS_INT16)
+ return static_cast<double>(g_variant_get_int16(value));
+
+ else if(c == G_VARIANT_CLASS_UINT16)
+ return static_cast<double>(g_variant_get_uint16(value));
+
+ else if(c == G_VARIANT_CLASS_INT32)
+ return static_cast<double>(g_variant_get_int32(value));
+
+ else if(c == G_VARIANT_CLASS_UINT32)
+ return static_cast<double>(g_variant_get_uint32(value));
+
+ else if(c == G_VARIANT_CLASS_INT64)
+ return static_cast<double>(g_variant_get_int64(value));
+
+ else if(c == G_VARIANT_CLASS_UINT64)
+ return static_cast<double>(g_variant_get_uint64(value));
+
+ else if(c == G_VARIANT_CLASS_DOUBLE)
+ return static_cast<double>(g_variant_get_double(value));
+
+ else
+ return 0.0;
+
+}
+
+CANSignal::CANSignal(std::function<AbstractPropertyType* ()> factoryFunction) :
+ ambProperty(nullptr),
+ signature(static_cast<GVariantClass>(0)),
+ factoryFunction(factoryFunction)
+{
+}
+
+CANSignal::~CANSignal()
+{
+}
+
+void CANSignal::onMessage(const can_frame& frame, std::function<void (AbstractPropertyType*)> changeCallback)
+{
+ std::unique_ptr<GVariant, decltype(&g_variant_unref)> variant(processSignal(frame), &g_variant_unref);
+ if(variant){
+ std::unique_ptr<GVariant, decltype(&g_variant_unref)> oldValue(ambProperty->toVariant(), &g_variant_unref);
+ if(!g_variant_equal(variant.get(), oldValue.get())) {
+ ambProperty->fromVariant( variant.get() );
+ if(changeCallback)
+ changeCallback(ambProperty.get());
+ }
+ }
+}
+
+void CANSignal::setAmbProperty(std::shared_ptr<AbstractPropertyType> ambProperty)
+{
+ this->ambProperty = ambProperty;
+ std::unique_ptr<GVariant, decltype(&g_variant_unref)> variant(ambProperty->toVariant(), &g_variant_unref);
+ if(variant)
+ signature = g_variant_classify(variant.get());
+}
+
+template <>
+GVariant* CANSignal::processFrameBits<bool>( const can_frame& frame )
+{
+ bool value = getSignalBits( frame ) != 0ull;
+ return toGVariant<bool>(value, signature);
+}
+
+bool CANSignal::updateFrame(can_frame* frame)
+{
+ if(/*!value ||*/ !frame)
+ return false;
+
+ std::unique_ptr<GVariant, decltype(&g_variant_unref)> variant(ambProperty->toVariant(), &g_variant_unref);
+ //ambProperty->fromVariant(variant.get());
+
+ double val(fromGVariant(variant.get()));
+ double temp = (val - signalInfo.m_offset)/signalInfo.m_factor;
+
+ int64_t bits = conversionFunctionTo(val, static_cast<int64_t>(temp));
+
+ *(reinterpret_cast<uint64_t*>(&frame->data[0])) |= toSignalBits(bits);
+}
+
+int64_t CANSignal::getSignalBits( const can_frame& frame )
+{
+ int64_t bits = *reinterpret_cast<const int64_t* >(frame.data);
+ int startbit = signalInfo.m_startbit;
+
+ if (signalInfo.m_byteOrdering == Motorola ) {
+ // Motorola
+ bits = __bswap_64(bits);
+ int rounded = signalInfo.m_startbit & (~0x07); //(signalInfo.m_startbit/8)*8;
+ int remainder = signalInfo.m_startbit & 0x07; //signalInfo.m_startbit % 8;
+ startbit = (CANFrameDataSize - ( (8 - remainder) + rounded) - (signalInfo.m_length - 1) );
+ }
+ else{
+ // Intel - do nothing
+ }
+
+ bits = bits >> startbit;
+ uint64_t mask = ~(0ull);
+ if(signalInfo.m_length < 64){
+ mask = (1ull << static_cast<uint64_t>(signalInfo.m_length)) - 1ull;
+ }
+
+ bits &= mask;
+ if(signalInfo.m_signedness){
+ if(signalInfo.m_length <= 8 ){
+ bits = static_cast<int8_t>(bits);
+ }
+ else if(signalInfo.m_length <= 16 ){
+ bits = static_cast<int16_t>(bits);
+ }
+ else if(signalInfo.m_length <= 32 ){
+ bits = static_cast<int32_t>(bits);
+ }
+ }
+
+ return bits;
+}
+
+uint64_t CANSignal::toSignalBits( int64_t bits )
+{
+ uint64_t signBit(0ull);
+ if(signalInfo.m_signedness && bits < 0ull){
+ signBit = (1ull << static_cast<uint64_t>(signalInfo.m_length-1));
+ }
+
+ uint64_t mask = ~(0ull);
+ if(signalInfo.m_length < 64){
+ mask = (1ull << static_cast<uint64_t>(signalInfo.m_length)) - 1ull;
+ }
+ bits &= mask;
+ bits |= signBit;
+
+ int startbit = signalInfo.m_startbit;
+ if (signalInfo.m_byteOrdering == Motorola ) {
+ // Motorola
+ int rounded = signalInfo.m_startbit & (~0x07); //(signalInfo.m_startbit/8)*8;
+ int remainder = signalInfo.m_startbit & 0x07; //signalInfo.m_startbit % 8;
+ startbit = (CANFrameDataSize - ( (8 - remainder) + rounded) - (signalInfo.m_length - 1) );
+ }
+ else{
+ // Intel - do nothing
+ }
+
+ bits = bits << startbit;
+
+ if (signalInfo.m_byteOrdering == Motorola ) {
+ bits = __bswap_64(bits);
+ }
+
+ return bits;
+}
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.h b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.h
new file mode 100644
index 00000000..2ea563fd
--- /dev/null
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.h
@@ -0,0 +1,231 @@
+/*****************************************************************
+Copyright (C) 2014 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *****************************************************************/
+
+#ifndef AMBTMPL_CANSIGNAL_H_
+#define AMBTMPL_CANSIGNAL_H_
+
+#include <map>
+#include <limits>
+#include <glib.h>
+#include <abstractpropertytype.h>
+#include <vehicleproperty.h>
+#include <byteswap.h>
+#include <boost/any.hpp>
+
+#include <canbus.h>
+#include <canobserver.h>
+
+enum Endian{
+ Motorola = 0x0, // BigEndian
+ Intel = 0x1 // LittleEndian
+};
+
+enum Signedness{
+ Unsigned = 0x0, // Unsigned
+ Signed = 0x1 // Signed
+};
+
+const int CANFrameDataSize = 8*sizeof(can_frame::data);
+
+template<typename T>
+T convert( double temp )
+{
+ return static_cast<T>(temp);
+}
+
+template<typename T>
+T convert( const boost::any& temp )
+{
+ return boost::any_cast<T>(temp);
+}
+
+template<typename T>
+GVariant* toGVariant(const T& value, const GVariantClass& c)
+{
+ if(c == G_VARIANT_CLASS_BOOLEAN)
+ return g_variant_new_boolean(static_cast<gboolean>(value));
+
+ else if(c == G_VARIANT_CLASS_BYTE)
+ return g_variant_new_byte(static_cast<guchar>(value));
+
+ else if(c == G_VARIANT_CLASS_INT16)
+ return g_variant_new_int16(static_cast<gshort>(value));
+
+ else if(c == G_VARIANT_CLASS_UINT16)
+ return g_variant_new_uint16(static_cast<gushort>(value));
+
+ else if(c == G_VARIANT_CLASS_INT32)
+ return g_variant_new_int32(static_cast<gint>(value));
+
+ else if(c == G_VARIANT_CLASS_UINT32)
+ return g_variant_new_uint32(static_cast<guint>(value));
+
+ else if(c == G_VARIANT_CLASS_INT64)
+ return g_variant_new_int64(static_cast<gint64>(value));
+
+ else if(c == G_VARIANT_CLASS_UINT64)
+ return g_variant_new_int64(static_cast<guint64>(value));
+
+ else if(c == G_VARIANT_CLASS_DOUBLE)
+ return g_variant_new_double(static_cast<gdouble>(value));
+
+ else
+ return nullptr;
+}
+
+class CANSignal {
+
+public:
+ explicit CANSignal(std::function<AbstractPropertyType* ()> factoryFunction);
+ virtual ~CANSignal();
+
+ virtual GVariant *processSignal( const can_frame& frame ) = 0;
+
+ virtual void onMessage( const can_frame& frame, std::function<void (AbstractPropertyType*)> changeCallback );
+
+ virtual bool updateFrame( can_frame* frame );
+
+ template <typename T>
+ GVariant* processFrameBits( const can_frame& frame )
+ {
+ int64_t bits = getSignalBits( frame );
+ double temp = static_cast<double>(bits)*signalInfo.m_factor + signalInfo.m_offset;
+ T value(convert<T>(conversionFunctionFrom(temp, bits)));
+ return toGVariant<T>(value, signature);
+ }
+
+ virtual boost::any conversionFunctionFrom(double value, int64_t bits) = 0;
+
+ virtual uint64_t conversionFunctionTo(double value, uint64_t bits) = 0;
+
+ void setAmbProperty(std::shared_ptr<AbstractPropertyType> ambProperty);
+
+ inline std::function<AbstractPropertyType* ()> factory()
+ {
+ return factoryFunction;
+ }
+
+protected:
+ int64_t getSignalBits( const can_frame& frame );
+ uint64_t toSignalBits( int64_t bits );
+
+protected:
+ struct SignalInfo {
+ uint8_t m_startbit;
+ uint8_t m_length;
+ Endian m_byteOrdering;
+ Signedness m_signedness;
+ double m_factor;
+ double m_offset;
+ };
+
+ SignalInfo signalInfo;
+ std::shared_ptr<AbstractPropertyType> ambProperty;
+ GVariantClass signature;
+ std::function<AbstractPropertyType* ()> factoryFunction;
+};
+
+class CANMessage
+{
+public:
+ CANMessage() = delete;
+
+ CANMessage(canid_t canId, __u8 canDlc) :
+ canId(canId),
+ canDlc(canDlc)
+ {
+ }
+
+ void addSignal(const VehicleProperty::Property& name, std::shared_ptr<CANSignal> signal)
+ {
+ if(signal)
+ canSignals[name] = signal;
+ }
+
+ void onMessage(const can_frame& frame, std::function<void (AbstractPropertyType*)> changeCallback)
+ {
+ if(frame.can_dlc != canDlc || frame.can_id != canId)
+ return;
+
+ for ( auto it = canSignals.begin(); it != canSignals.end(); ++it ) {
+ std::shared_ptr<CANSignal> signal(it->second);
+
+ if ( signal ) {
+ signal->onMessage(frame, changeCallback);
+ }
+ }
+ }
+
+ void setupFrame(can_frame* frame)
+ {
+ if(!frame)
+ return;
+
+ memset(frame, 0, sizeof(can_frame));
+ frame->can_id = canId;
+ frame->can_dlc = canDlc;
+
+ for ( auto it = canSignals.begin(); it != canSignals.end(); ++it ) {
+ it->second->updateFrame(frame);
+ }
+ }
+
+private:
+ canid_t canId;
+ __u8 canDlc;
+ std::map< VehicleProperty::Property , std::shared_ptr<CANSignal> > canSignals;
+};
+
+#define CANSIGNAL(property, valueType, startbit, length, byteOrdering, signedness, factor, offset, minValue, maxValue, convertFrom, convertTo) \
+ class property ## Type : public CANSignal { \
+ public: property ## Type() : \
+ CANSignal([](){ return new BasicPropertyType<valueType>(property); } ) \
+ , convertFromFunction(convertFrom) \
+ , convertToFunction(convertTo) \
+ {\
+ signalInfo.m_startbit = startbit; \
+ signalInfo.m_length = length; \
+ signalInfo.m_byteOrdering = byteOrdering; \
+ signalInfo.m_signedness = signedness; \
+ signalInfo.m_factor = factor; \
+ signalInfo.m_offset = offset; \
+ m_minValue = minValue; \
+ m_maxValue = maxValue; \
+ } \
+ GVariant *processSignal( const can_frame& frame ) { \
+ return processFrameBits<valueType>( frame ); \
+ } \
+ boost::any conversionFunctionFrom(double value, int64_t bits) { \
+ valueType targetValue(convert<valueType>(value)); \
+ if(convertFromFunction) \
+ return convertFromFunction(targetValue, bits); \
+ else return targetValue; \
+ } \
+ uint64_t conversionFunctionTo(double value, uint64_t bits) { \
+ if(convertToFunction) \
+ convertToFunction(convert<valueType>(value), bits); \
+ else return bits; \
+ } \
+ valueType m_minValue; \
+ valueType m_maxValue; \
+ std::function<valueType(valueType, int64_t)> convertFromFunction; \
+ std::function<uint64_t(valueType, uint64_t)> convertToFunction; \
+ typedef valueType value_type; \
+ };
+
+#endif /* AMBTMPL_CANSIGNAL_H_ */
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignals.h b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignals.h
new file mode 100644
index 00000000..e41e9e22
--- /dev/null
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignals.h
@@ -0,0 +1,30 @@
+/*****************************************************************
+Copyright (C) 2014 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *****************************************************************/
+
+#ifndef AMBTMPL_CANSIGNALS_H_
+#define AMBTMPL_CANSIGNALS_H_
+
+#include "ambtmpl_plugin.h"
+#include "ambtmpl_cansignal.h"
+
+#include <glib.h>
+#include <vehicleproperty.h>
+
+/*GENERATED_CODE*/
+
+#endif /* AMBTMPL_CANSIGNALS_H_ */
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.cpp b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.cpp
new file mode 100644
index 00000000..6f412742
--- /dev/null
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.cpp
@@ -0,0 +1,289 @@
+/*****************************************************************
+Copyright (C) 2014 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *****************************************************************/
+
+#include <boost/assert.hpp>
+#include <glib.h>
+#include <cstdarg>
+
+#include <vehicleproperty.h>
+#include <listplusplus.h>
+
+#include <logger.h>
+
+#include "ambtmpl_plugin.h"
+#include "ambtmpl_cansignals.h"
+
+//using namespace AmbTmplPlugin;
+
+static const char* DEFAULT_CAN_IF_NAME = "vcan0";
+
+// library exported function for plugin loader
+extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, std::map<std::string, std::string> config)
+{
+#ifndef UNIT_TESTS
+ DEBUG_CONF("AmbTmplPlugin",
+ CUtil::Logger::file_off|CUtil::Logger::screen_on,
+ CUtil::Logger::EInfo, CUtil::Logger::EInfo
+ );
+#endif
+
+ std::unique_ptr< AmbPlugin<AmbTmplPlugin> > plugin(new AmbPlugin<AmbTmplPlugin>(routingengine, config));
+ plugin->init();
+ return plugin.release();
+}
+
+void AmbTmplPlugin::timerDestroyNotify(gpointer data)
+{
+ TimerData* timerData = reinterpret_cast<TimerData*>(data);
+ if(timerData){
+ AmbTmplPlugin* plugin = std::get<0>(*timerData);
+ const can_frame& frame = std::get<3>(*timerData);
+ plugin->eraseTimer(frame.can_id);
+ delete timerData;
+ }
+
+}
+
+gboolean AmbTmplPlugin::timeoutCallback(gpointer data)
+{
+ TimerData* timerData = reinterpret_cast<TimerData*>(data);
+ if(!timerData)
+ return false;
+
+ CANBus* bus = std::get<1>(*timerData);
+ int retries = --std::get<2>(*timerData);
+ const can_frame& frame = std::get<3>(*timerData);
+
+ if(retries > 0){
+ if(bus)
+ bus->sendStandardFrame(frame);
+ return true;
+ }
+ else return false;
+}
+
+//----------------------------------------------------------------------------
+// AmbTmplPlugin
+//----------------------------------------------------------------------------
+
+AmbTmplPlugin::AmbTmplPlugin(AbstractRoutingEngine* re, const map<string, string>& config, AbstractSink& parent) :
+ AmbPluginImpl(re, config, parent),
+ interface(DEFAULT_CAN_IF_NAME),
+ canBus(new CANBus(*static_cast<CANObserver*>(this))),
+ announcementIntervalTimer(1000),
+ announcementCount(20)
+{
+ auto it = config.find("interface");
+ if (it != config.end() && it->second.length())
+ interface = it->second;
+
+ it = config.find("announcementIntervalTimer");
+ if (it != config.end() && it->second.length())
+ announcementIntervalTimer = atoi(std::string(it->second).c_str());
+ if(announcementIntervalTimer < 20)
+ announcementIntervalTimer = 20;
+
+ it = config.find("announcementCount");
+ if (it != config.end() && it->second.length())
+ announcementCount = atoi(std::string(it->second).c_str());
+ if(announcementCount < 1)
+ announcementIntervalTimer = 1;
+
+ registerMessages();
+}
+
+AmbTmplPlugin::~AmbTmplPlugin()
+{
+ std::list<guint> timerList;
+
+ mutex.lock();
+ for(auto it=timers.begin();it!=timers.end();++it)
+ timerList.push_back(it->second);
+ mutex.unlock();
+
+ for(auto it=timerList.begin();it!=timerList.end();++it)
+ g_source_remove(*it);
+
+ canBus->stop();
+}
+
+void AmbTmplPlugin::init()
+{
+ canBus->start(interface.c_str());
+}
+
+AsyncPropertyReply *AmbTmplPlugin::setProperty(const AsyncSetPropertyRequest& request )
+{
+ AsyncPropertyReply* reply = new AsyncPropertyReply(request);
+ reply->success = false;
+ reply->error = AsyncPropertyReply::InvalidOperation;
+
+ AbstractPropertyType *value = findPropertyType(request.property, request.zoneFilter);
+ if (value && request.value) {
+ DebugOut(2) << "updating property "<< request.property << " to: " << request.value->toString() << endl;
+
+ std::unique_ptr<GVariant, decltype(&g_variant_unref)> variant(request.value->toVariant(), &g_variant_unref);
+ value->fromVariant(variant.get());
+
+ if(sendValue(request.value)) {
+ DebugOut(2) << "New value of property "<< request.property << " is: " << value->toString() << endl;
+ value->timestamp = amb::currentTime();
+ routingEngine->updateProperty(value, uuid());
+
+ reply->success = true;
+ reply->error = AsyncPropertyReply::NoError;
+ }
+ }
+
+ try {
+ if(reply->completed)
+ reply->completed(reply);
+ }
+ catch (...) { }
+
+ return reply;
+}
+
+int AmbTmplPlugin::supportedOperations() const
+{
+ return AbstractSource::Get | AbstractSource::Set;
+}
+
+void AmbTmplPlugin::onMessage(const can_frame& frame)
+{
+ auto messageIt = messages.find(frame.can_id);
+ if(messageIt == messages.end())
+ return;
+
+ CANMessage& message(messageIt->second);
+ const std::string guid = uuid();
+ AbstractRoutingEngine* re = routingEngine;
+ message.onMessage( frame, [&re, &guid](AbstractPropertyType* value){re->updateProperty(value, guid);} );
+}
+
+bool AmbTmplPlugin::sendValue(AbstractPropertyType* value)
+{
+ if(!value)
+ return false;
+
+ auto it = propertyToMessage.find(value->name);
+ if(it == propertyToMessage.end())
+ return false;
+
+ CANMessage* canMessage = it->second;
+ can_frame frame;
+ canMessage->setupFrame(&frame);
+ return sendStandardFrame(frame);
+}
+
+// from CANObserver
+void AmbTmplPlugin::errorOccured(CANObserver::CANError error)
+{
+ (void) error;
+ LOG_INFO( "AmbTmplPlugin::errorOccured() not implemented "<< std::endl );
+}
+
+void AmbTmplPlugin::standardFrameReceived(const can_frame& frame)
+{
+ LOG_INFO("AmbTmplPlugin::standardFrameReceived()");
+ printFrame( frame );
+
+ onMessage(frame);
+}
+
+void AmbTmplPlugin::extendedFrameReceived(const can_frame& frame)
+{
+ LOG_INFO("AmbTmplPlugin::extendedFrameReceived()");
+ printFrame(frame);
+
+ onMessage(frame);
+}
+
+void AmbTmplPlugin::errorFrameReceived(const can_frame& frame)
+{
+ LOG_INFO("AmbTmplPlugin::errorFrameReceived()");
+ printFrame(frame);
+}
+
+void AmbTmplPlugin::remoteTransmissionRequest(const can_frame& frame)
+{
+ (void) frame;
+ LOG_INFO( "AmbTmplPlugin::remoteTransmissionRequest() not implemented "<< std::endl );
+}
+
+bool AmbTmplPlugin::sendStandardFrame(const can_frame& frame)
+{
+ guint oldTimer(0);
+ mutex.lock();
+ auto it = timers.find(frame.can_id);
+ if(it != timers.end()){
+ oldTimer = it->second;
+ timers.erase(it);
+ }
+ mutex.unlock();
+
+ if(oldTimer != 0)
+ g_source_remove(oldTimer);
+
+ if ( canBus->sendStandardFrame(frame) ) {
+ LOG_TRACE( "AmbTmplPlugin::sendStandardFrame() success "<< std::endl );
+ scoped_lock<interprocess_recursive_mutex> lock(mutex);
+ std::unique_ptr< TimerData > timerData(new TimerData(this, canBus.get(), announcementCount, frame));
+ guint timer = g_timeout_add_full(G_PRIORITY_HIGH, announcementIntervalTimer, timeoutCallback, timerData.get(), timerDestroyNotify);
+ if(timer){
+ timers[frame.can_id] = timer;
+ timerData.release();
+ }
+ return true;
+ }
+ else {
+ LOG_WARNING( "AmbTmplPlugin::sendStandardFrame() failed "<< std::endl );
+ return false;
+ }
+}
+
+bool AmbTmplPlugin::sendExtendedFrame(const can_frame& frame)
+{
+ if ( canBus->sendExtendedFrame(frame) ) {
+ LOG_TRACE( "AmbTmplPlugin::sendExtendedFrame() success "<< std::endl );
+ return true;
+ }
+ else {
+ LOG_WARNING( "AmbTmplPlugin::sendExtendedFrame() failed "<< std::endl );
+ return false;
+ }
+}
+
+void AmbTmplPlugin::printFrame(const can_frame& frame) const
+{
+ LOG_INFO( "AmbTmplPlugin::printFrame can_id: " << std::hex << frame.can_id << std::dec );
+ LOG_INFO( "AmbTmplPlugin::printFrame can_dlc: " << int(frame.can_dlc) );
+
+ std::stringstream ss;
+ for(int i=0; i<frame.can_dlc; ++i){
+ ss << " " << std::hex << (int)(frame.data[i]);
+ }
+ ss << std::dec;
+
+ LOG_INFO( "AmbTmplPlugin::printFrame can data" << ss.str() );
+}
+
+void AmbTmplPlugin::registerMessages()
+{
+/*GENERATED_CODE*/
+}
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.h b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.h
new file mode 100644
index 00000000..9e22f554
--- /dev/null
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.h
@@ -0,0 +1,196 @@
+/*****************************************************************
+Copyright (C) 2014 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *****************************************************************/
+
+#ifndef AMBTMPL_PLUGIN_H_
+#define AMBTMPL_PLUGIN_H_
+
+#include <map>
+#include <memory>
+#include <tgmath.h>
+#include <limits>
+#include <byteswap.h>
+#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+
+#include <canbus.h>
+#include <canobserver.h>
+
+#include <ambpluginimpl.h>
+#include "ambtmpl_cansignal.h"
+
+using namespace boost::interprocess;
+
+// forward declaration
+class CANSignal;
+class CANMessage;
+
+class AmbTmplPlugin : public AmbPluginImpl, public CANObserver {
+
+public:
+ AmbTmplPlugin(AbstractRoutingEngine* re, const std::map<std::string, std::string>& config, AbstractSink& parent);
+ virtual ~AmbTmplPlugin(); // has to be virtual because of unit tests
+
+ // from AbstractSink
+public:
+
+ /*! uuid() is a unique identifier of the plugin
+ * @return a guid-style unique identifier
+ */
+ const std::string uuid() const { return "/*GENERATED_CODE*/"; }
+
+ /*!
+ * \brief setProperty is called when a sink requests to set a value for a given property.
+ * This is only called if the source supports the Set Operation.
+ * \param request the requested property to set.
+ * \return returns a pointer to the new value for the property.
+ */
+ AsyncPropertyReply *setProperty(const AsyncSetPropertyRequest& request );
+
+ /*!
+ * \brief supportedOperations
+ * \return returns the supported operations.
+ */
+ int supportedOperations() const;
+
+
+ // from CANObserver
+public:
+ /*!
+ * Called when error occurred on the bus.
+ * \fn errorOccured
+ * \param error \link CANObserver#CANError Bus error code \endlink
+ */
+ virtual void errorOccured(CANObserver::CANError error);/* socket error */
+ /*!
+ * Called when standard frame was is received from the bus.
+ * \fn standardFrameReceived
+ * \param frame Received frame
+ */
+ virtual void standardFrameReceived(const can_frame& frame);/* SFF was present */
+ /*!
+ * Called when extended frame was is received from the bus.
+ * \fn extendedFrameReceived
+ * \param frame Received frame
+ */
+ virtual void extendedFrameReceived(const can_frame& frame);/* EFF was present */
+ /*!
+ * Called when error frame was received from the bus.
+ * \fn errorFrameReceived
+ * \param frame Error frame
+ */
+ virtual void errorFrameReceived(const can_frame& frame);/* error frame */
+ /*!
+ * Called when remote transmission frame was received from the bus.
+ * \fn remoteTransmissionRequest
+ * \param frame RTR frame
+ */
+ virtual void remoteTransmissionRequest(const can_frame& frame);/* remote transmission request (SFF/EFF is still present)*/
+
+ /**
+ * Sends standard(11bit) CAN frame over the bus
+ * \fn sendStandardFrame
+ * \param frame CAN frame to be sent
+ * \return True if frame was sent
+ */
+ bool sendStandardFrame(const can_frame& frame);
+
+ /**
+ * Sends extended(29bit) CAN frame over the bus
+ * \fn sendExtendedFrame
+ * \param frame CAN frame to be sent
+ * \return True if frame was sent
+ */
+ bool sendExtendedFrame(const can_frame& frame);
+
+ /*!
+ * Second phase of the plugin initialization.
+ * \fn init
+ */
+ virtual void init();
+
+ void eraseTimer(const canid_t& id)
+ {
+ scoped_lock<interprocess_recursive_mutex> lock(mutex);
+ auto it = timers.find(id);
+ if(it != timers.end()){
+ timers.erase(it);
+ }
+ }
+
+protected:
+
+ void registerMessage(const canid_t& canId, const __u8& canDlc)
+ {
+ LOG_MESSAGE("registered message: " << canId);
+ }
+
+ template<typename Signal, typename... Rest>
+ void registerMessage(const canid_t& canId, const __u8& canDlc, Signal* canSignal, Rest... rest)
+ {
+ static_assert(std::is_base_of<CANSignal, Signal>::value, "CANSignal has to be a base of Signal");
+
+ if(!canSignal)
+ return;
+
+ std::shared_ptr<AbstractPropertyType> prop(AmbPluginImpl::addPropertySupport(Zone::None, canSignal->factory()));
+ if(prop) {
+ canSignal->setAmbProperty(prop);
+ auto messageIt = messages.find(canId);
+ if(messageIt == messages.end()){
+ messageIt = messages.insert(make_pair(canId, CANMessage(canId, canDlc))).first;
+ }
+ auto& message = messageIt->second;
+ message.addSignal(prop->name, std::shared_ptr<CANSignal>(canSignal));
+ propertyToMessage[prop->name] = &message;
+ }
+
+ registerMessage(canId, canDlc, rest...);
+ }
+
+private:
+
+ void printFrame(const can_frame& frame) const;
+ void onMessage(const can_frame& frame);
+ bool sendValue(AbstractPropertyType* value);
+ void registerMessages();
+
+ static void timerDestroyNotify(gpointer data);
+ static gboolean timeoutCallback(gpointer data);
+//
+// data:
+//
+ std::map< canid_t, CANMessage > messages;
+ std::map< VehicleProperty::Property, CANMessage* > propertyToMessage;
+
+ std::string interface;
+
+ /**
+ * CANBus class instance
+ * \property canBus
+ * \private
+ */
+ std::unique_ptr<CANBus> canBus;
+
+ typedef std::tuple<AmbTmplPlugin*, CANBus*, int, const can_frame> TimerData;
+ std::map< canid_t, guint > timers;
+ interprocess_recursive_mutex mutex;
+ uint announcementIntervalTimer;
+ uint announcementCount;
+};
+
+#endif /* AMBTMPL_PLUGIN_H_ */
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.idl b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.idl
new file mode 100644
index 00000000..fcc0bfcd
--- /dev/null
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.idl
@@ -0,0 +1,18 @@
+/**
+
+
+Details.
+
+\def-api-feature http://tizen.org/api/vehicle
+\brief Allows access to the AmbTmplPlugin API
+
+
+
+*/
+
+module AmbTmplPlugin {
+
+/*GENERATED_CODE*/
+
+};
+
diff --git a/tools/AmbSignalMapper/t/00-load.t b/tools/AmbSignalMapper/t/00-load.t
new file mode 100644
index 00000000..e781cd6f
--- /dev/null
+++ b/tools/AmbSignalMapper/t/00-load.t
@@ -0,0 +1,13 @@
+#!perl -T
+use 5.006;
+use strict;
+use warnings FATAL => 'all';
+use Test::More;
+
+plan tests => 1;
+
+BEGIN {
+ use_ok( 'Intel::IviPoc::AmbPluginGenerator' ) || print "Bail out!\n";
+}
+
+diag( "Testing Intel::IviPoc::AmbPluginGenerator $Intel::IviPoc::AmbPluginGenerator::VERSION, Perl $], $^X" );
diff --git a/tools/AmbSignalMapper/t/ambsignalmapper.t b/tools/AmbSignalMapper/t/ambsignalmapper.t
new file mode 100644
index 00000000..e266d350
--- /dev/null
+++ b/tools/AmbSignalMapper/t/ambsignalmapper.t
@@ -0,0 +1,18 @@
+#!perl -T
+use 5.006;
+use strict;
+use warnings FATAL => 'all';
+use Test::More;
+use Intel::IviPoc::AmbPluginGenerator;
+
+plan tests => 1;
+
+# TEST
+{
+ my $src_text = "This is a text strig to check if AmbTmpl, AMBTMPL and ambtmpl are replaced with myplugin respectively and with proper caseing";
+ my $replace_text = "MyPlugin";
+ my $dst_text = "This is a text strig to check if MyPlugin, MYPLUGIN and myplugin are replaced with myplugin respectively and with proper caseing";
+ my $ret = Intel::IviPoc::AmbPluginGenerator::replaceTemplateStrings($src_text, $replace_text);
+ ok ( $ret eq $dst_text, " replaceTemplateStrings works" );
+}
+
diff --git a/tools/AmbSignalMapper/t/boilerplate.t b/tools/AmbSignalMapper/t/boilerplate.t
new file mode 100644
index 00000000..35d1da66
--- /dev/null
+++ b/tools/AmbSignalMapper/t/boilerplate.t
@@ -0,0 +1,57 @@
+#!perl -T
+use 5.006;
+use strict;
+use warnings FATAL => 'all';
+use Test::More;
+
+plan tests => 3;
+
+sub not_in_file_ok {
+ my ($filename, %regex) = @_;
+ open( my $fh, '<', $filename )
+ or die "couldn't open $filename for reading: $!";
+
+ my %violated;
+
+ while (my $line = <$fh>) {
+ while (my ($desc, $regex) = each %regex) {
+ if ($line =~ $regex) {
+ push @{$violated{$desc}||=[]}, $.;
+ }
+ }
+ }
+
+ if (%violated) {
+ fail("$filename contains boilerplate text");
+ diag "$_ appears on lines @{$violated{$_}}" for keys %violated;
+ } else {
+ pass("$filename contains no boilerplate text");
+ }
+}
+
+sub module_boilerplate_ok {
+ my ($module) = @_;
+ not_in_file_ok($module =>
+ 'the great new $MODULENAME' => qr/ - The great new /,
+ 'boilerplate description' => qr/Quick summary of what the module/,
+ 'stub function definition' => qr/function[12]/,
+ );
+}
+
+TODO: {
+ local $TODO = "Need to replace the boilerplate text";
+
+ not_in_file_ok(README =>
+ "The README is used..." => qr/The README is used/,
+ "'version information here'" => qr/to provide version information/,
+ );
+
+ not_in_file_ok(Changes =>
+ "placeholder date/time" => qr(Date/time)
+ );
+
+ module_boilerplate_ok('lib/Intel/IviPoc/AmbPluginGenerator.pm');
+
+
+}
+
diff --git a/tools/AmbSignalMapper/t/manifest.t b/tools/AmbSignalMapper/t/manifest.t
new file mode 100644
index 00000000..6ddfe364
--- /dev/null
+++ b/tools/AmbSignalMapper/t/manifest.t
@@ -0,0 +1,15 @@
+#!perl -T
+use 5.006;
+use strict;
+use warnings FATAL => 'all';
+use Test::More;
+
+unless ( $ENV{RELEASE_TESTING} ) {
+ plan( skip_all => "Author tests not required for installation" );
+}
+
+my $min_tcm = 0.9;
+eval "use Test::CheckManifest $min_tcm";
+plan skip_all => "Test::CheckManifest $min_tcm required" if $@;
+
+ok_manifest();
diff --git a/tools/AmbSignalMapper/t/pod-coverage.t b/tools/AmbSignalMapper/t/pod-coverage.t
new file mode 100644
index 00000000..866fac2b
--- /dev/null
+++ b/tools/AmbSignalMapper/t/pod-coverage.t
@@ -0,0 +1,20 @@
+#!perl -T
+use 5.006;
+use strict;
+use warnings FATAL => 'all';
+use Test::More;
+
+# Ensure a recent version of Test::Pod::Coverage
+my $min_tpc = 1.08;
+eval "use Test::Pod::Coverage $min_tpc";
+plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage"
+ if $@;
+
+# Test::Pod::Coverage doesn't require a minimum Pod::Coverage version,
+# but older versions don't recognize some common documentation styles
+my $min_pc = 0.18;
+eval "use Pod::Coverage $min_pc";
+plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage"
+ if $@;
+
+all_pod_coverage_ok();
diff --git a/tools/AmbSignalMapper/t/pod.t b/tools/AmbSignalMapper/t/pod.t
new file mode 100644
index 00000000..a0054e97
--- /dev/null
+++ b/tools/AmbSignalMapper/t/pod.t
@@ -0,0 +1,12 @@
+#!perl -T
+use 5.006;
+use strict;
+use warnings FATAL => 'all';
+use Test::More;
+
+# Ensure a recent version of Test::Pod
+my $min_tp = 1.22;
+eval "use Test::Pod $min_tp";
+plan skip_all => "Test::Pod $min_tp required for testing POD" if $@;
+
+all_pod_files_ok();
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
new file mode 100644
index 00000000..9ab1df8f
--- /dev/null
+++ b/tools/CMakeLists.txt
@@ -0,0 +1,4 @@
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/genmapping.py ${CMAKE_CURRENT_BINARY_DIR}/genmapping @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/ambctl.py ${CMAKE_CURRENT_BINARY_DIR}/ambctl @ONLY)
+
+install (PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/ambctl DESTINATION bin)
diff --git a/tools/ambctl.py b/tools/ambctl.py
new file mode 100644
index 00000000..269b5708
--- /dev/null
+++ b/tools/ambctl.py
@@ -0,0 +1,574 @@
+#!/usr/bin/python
+
+import argparse
+import dbus
+import sys
+import json
+import fileinput
+import termios, fcntl, os
+import curses.ascii
+import traceback
+from gi.repository import GObject, GLib
+
+from dbus.mainloop.glib import DBusGMainLoop
+
+class bcolors:
+ HEADER = '\x1b[95m'
+ OKBLUE = '\x1b[94m'
+ OKGREEN = '\x1b[92m'
+ WARNING = '\x1b[93m'
+ FAIL = '\x1b[91m'
+ ENDC = '\x1b[0m'
+ GREEN = '\x1b[32m'
+ 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'))
+
+ try:
+ bus = dbus.SystemBus()
+ 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, commandsOnly = False):
+ results = []
+
+ sameString = ""
+
+ for cmd in self.commands:
+ if not (len(partialString)) or cmd.name.startswith(partialString):
+ results.append(cmd.name)
+
+ if not commandsOnly:
+ 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")
+ 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)
+ try:
+ data = json.load(pluginFile)
+
+ data['segmentPath'] = fullpath
+ list.append(data)
+ except ValueError, e:
+ print "error parsing json file", file, ":", e
+ traceback.print_stack()
+ finally: pluginFile.close()
+ return list
+
+def enablePlugin(pluginName, enabled):
+ return setPluginProperty(pluginName, "enabled", enabled);
+
+def setPluginProperty(pluginName, key, value):
+ list = listPlugins()
+
+ for plugin in list:
+ if plugin["name"] == pluginName:
+ try :
+ if key not in plugin:
+ print "Key not found: ", key
+ return False
+ type = plugin[key].__class__
+ if type == bool:
+ value = value.lower() == "true"
+ value = type(value)
+ plugin[key] = value
+ file = open(plugin["segmentPath"], 'rw+')
+ plugin.pop('segmentPath', None)
+ fixedData = json.dumps(plugin, separators=(', ', ' : '), indent=4)
+ fixedData = fixedData.replace(' ','\t');
+ file.truncate()
+ file.write(fixedData)
+ file.close()
+ return True
+ except IOError, error:
+ print error
+ return False
+ return False
+class Subscribe:
+ subscriptions = {}
+def processCommand(command, commandArgs, noMain=True):
+
+ if command == 'help':
+ print help()
+ return 1
+
+
+ def getManager():
+ try:
+ bus = dbus.SystemBus()
+ managerObject = bus.get_object("org.automotive.message.broker", "/");
+ managerInterface = dbus.Interface(managerObject, "org.automotive.Manager")
+ return managerInterface, bus
+ except:
+ print "Error connecting to AMB. is AMB running?"
+ return None
+
+ if command == "list" :
+ managerInterface, bus = getManager()
+ if managerInterface == None:
+ return 0
+ supportedList = managerInterface.List()
+ for objectName in supportedList:
+ print objectName
+ return 1
+ elif command == "get":
+ if len(commandArgs) == 0:
+ commandArgs = ['help']
+ if commandArgs[0] == "help":
+ print "ObjectName [ObjectName...]"
+ return 1
+ managerInterface, bus = getManager()
+ if managerInterface == None:
+ return 0
+ for objectName in commandArgs:
+ objects = managerInterface.FindObject(objectName)
+ print objectName
+ for o in objects:
+ propertiesInterface = dbus.Interface(bus.get_object("org.automotive.message.broker", o),"org.freedesktop.DBus.Properties")
+ print json.dumps(propertiesInterface.GetAll("org.automotive."+objectName), indent=2)
+ return 1
+ elif command == "listen":
+ off = False
+ if len(commandArgs) == 0:
+ commandArgs = ['help']
+ if commandArgs[0] == "help":
+ print "[help] [off] ObjectName [ObjectName...]"
+ return 1
+ elif commandArgs[0] == "off":
+ off=True
+ commandArgs=commandArgs[1:]
+ managerInterface, bus = getManager()
+ if managerInterface == None:
+ return 1
+ for objectName in commandArgs:
+ objects = managerInterface.FindObject(objectName)
+ for o in objects:
+ if off == False:
+ signalMatch = bus.add_signal_receiver(changed, dbus_interface="org.freedesktop.DBus.Properties", signal_name="PropertiesChanged", path=o)
+ Subscribe.subscriptions[o] = signalMatch
+ else:
+ try:
+ signalMatch = Subscribe.subscriptions.get(o)
+ signalMatch.remove()
+ del Subscribe.subscriptions[o]
+ except KeyError:
+ print "not lisenting to object at: ", o
+ pass
+ if not noMain == True:
+ try:
+ main_loop = gobject.MainLoop(None, False)
+ main_loop.run()
+ except KeyboardInterrupt:
+ return 1
+ except:
+ traceback.print_stack()
+ elif command == "set":
+ if len(commandArgs) == 0:
+ commandArgs = ['help']
+ if len(commandArgs) and commandArgs[0] == "help":
+ print "ObjectName PropertyName VALUE [ZONE]"
+ return 1
+ if len(commandArgs) < 3:
+ print "set requires more arguments (see set help)"
+ return 1
+ objectName = commandArgs[0]
+ propertyName = commandArgs[1]
+ value = commandArgs[2]
+ zone = 0
+ if len(commandArgs) == 4:
+ zone = int(commandArgs[3])
+ managerInterface, bus = getManager()
+ if managerInterface == None:
+ return 1
+ object = managerInterface.FindObjectForZone(objectName, zone)
+ propertiesInterface = dbus.Interface(bus.get_object("org.automotive.message.broker", object),"org.freedesktop.DBus.Properties")
+ property = propertiesInterface.Get("org.automotive."+objectName, propertyName)
+ if property.__class__ == dbus.Boolean:
+ value = value.lower() == "true"
+ realValue = property.__class__(value)
+ propertiesInterface.Set("org.automotive."+objectName, propertyName, realValue)
+ property = propertiesInterface.Get("org.automotive."+objectName, propertyName)
+ if property == realValue:
+ print propertyName + " = ", property
+ else:
+ print "Error setting property. Expected value: ", realValue, " Received: ", property
+ return 1
+ elif command == "getHistory":
+ if len(commandArgs) == 0:
+ commandArgs = ['help']
+ if commandArgs[0] == "help":
+ print "ObjectName [ZONE] [STARTTIME] [ENDTIME] "
+ return 1
+ if len(commandArgs) < 1:
+ print "getHistory requires more arguments (see getHistory help)"
+ return 1
+ objectName = commandArgs[0]
+ start = 1
+ if len(commandArgs) >= 3:
+ start = float(commandArgs[2])
+ end = 9999999999
+ if len(commandArgs) >= 4:
+ end = float(commandArgs[3])
+ zone = 0
+ if len(commandArgs) >= 2:
+ zone = int(commandArgs[1])
+ managerInterface, bus = getManager()
+ if managerInterface == None:
+ return 1
+ 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] [key value]"
+ 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) < 3:
+ return 1
+ plugin = commandArgs[0]
+ key = commandArgs[1]
+ value = commandArgs[2]
+
+ if not setPluginProperty(plugin, key, value):
+ print "Could not set property"
+ print plugin, key, ":", value
+ return 1
+
+ else:
+ print "Invalid command"
+ return 1
+
+
+
+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')
+parser.add_argument('-h', '--help', help='print help', action='store_true')
+
+args = parser.parse_args()
+
+if args.help:
+ parser.print_help()
+ print
+ print help()
+ sys.exit()
+
+dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+if args.command == "stdin":
+ class Data:
+ history = []
+ line = ""
+ templine = ""
+ promptAmbctl = "[ambctl]"
+ promptEnd = "# "
+ 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):
+ if self.curpos == len(self.line):
+ self.line+=str
+ self.curpos = len(self.line)
+ else:
+ self.line = self.line[:self.curpos] + str + self.line[self.curpos:]
+ self.curpos+=1
+ def arrow_back(self):
+ if self.curpos > 0:
+ self.curpos-=1
+ return True
+ return False
+
+ def arrow_forward(self):
+ if self.curpos < len(self.line):
+ self.curpos+=1
+ return True
+ return False
+
+ def back_space(self):
+ if self.curpos > 0:
+ self.curpos-=1
+ self.line = self.line[:self.curpos] + self.line[self.curpos+1:]
+ return True
+ return False
+ def delete(self):
+ if self.curpos < len(self.line):
+ self.line = self.line[:self.curpos] + self.line[self.curpos+2:]
+ return True
+ return False
+
+ def save_temp(self):
+ if len(self.history)-1 == 0 or len(self.history)-1 != self.historypos:
+ return
+ self.templine = self.line
+
+ def push(self):
+ self.history.append(self.line)
+ self.historypos = len(self.history)-1
+ self.clear()
+
+ def set(self, str):
+ self.line = str
+ self.curpos = len(self.line)
+
+ def history_up(self):
+ if self.historypos >= 0:
+ self.line = self.history[self.historypos]
+ if self.historypos != 0:
+ self.historypos-=1
+ return True
+ return False
+
+ def history_down(self):
+ if self.historypos >= 0 and self.historypos < len(self.history)-1:
+ self.historypos+=1
+ self.line = self.history[self.historypos]
+
+ else:
+ self.historypos = len(self.history)-1
+ self.set(self.templine)
+
+ return True
+
+ def clear(self):
+ self.set("")
+ templist = ""
+
+ def erase_line():
+ sys.stdout.write('\x1b[2K\x1b[80D')
+
+ def cursor_left():
+ sys.stdout.write('\x1b[1D')
+
+ def cursor_right():
+ sys.stdout.write('\x1b[1C')
+
+ def display_prompt():
+ sys.stdout.write(bcolors.OKBLUE+Data.promptAmbctl+bcolors.WHITE+Data.promptEnd);
+
+ def redraw(data):
+ erase_line()
+ display_prompt()
+ sys.stdout.write(data.line)
+ cursorpos = len(data.line) - data.curpos
+ for x in xrange(cursorpos):
+ cursor_left()
+ sys.stdout.flush()
+
+ def handle_keyboard(source, cond, data):
+ str = source.read()
+ #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]
+ traceback.print_stack()
+ 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)
+ i=0
+ while i < len(results):
+ row = ""
+ numCols = 3
+ if len(results) < i+3:
+ numCols = len(results) - i
+ for n in xrange(numCols):
+ row += results[i]
+ for n in xrange((longestLen + 5) - len(results[i])):
+ row += ' '
+ i = i + 1
+ print row
+
+ redraw(data)
+ elif curses.ascii.isprint(ord(str)) or ord(str) == curses.ascii.SP: #regular text
+ data.insert(str)
+ redraw(data)
+
+ return True
+ print "@PROJECT_PRETTY_NAME@ @PROJECT_VERSION@"
+
+ data = Data()
+ fd = sys.stdin.fileno()
+ old = termios.tcgetattr(fd)
+ new = termios.tcgetattr(fd)
+ new[3] = new[3] & ~termios.ICANON & ~termios.ECHO
+ termios.tcsetattr(fd, termios.TCSANOW, new)
+
+ oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
+ fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
+
+ io_stdin = GLib.IOChannel(fd)
+ io_stdin.add_watch(GLib.IO_IN, handle_keyboard, data)
+
+ try:
+ erase_line()
+ display_prompt()
+ sys.stdout.flush()
+ main_loop = GObject.MainLoop()
+ main_loop.run()
+ except KeyboardInterrupt:
+ sys.exit()
+ except:
+ traceback.print_stack()
+ finally:
+ termios.tcsetattr(fd, termios.TCSAFLUSH, old)
+ fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
+ print ""
+ sys.exit()
+
+else:
+ try:
+ processCommand(args.command, args.commandArgs, False)
+ except dbus.exceptions.DBusException, error:
+ print error
diff --git a/tools/genmapping.py b/tools/genmapping.py
new file mode 100755
index 00000000..8516bfef
--- /dev/null
+++ b/tools/genmapping.py
@@ -0,0 +1,101 @@
+#!/usr/bin/python
+
+import os
+import argparse
+
+parser = argparse.ArgumentParser(description='Process DBus mappings.')
+parser.add_argument('mappingFiles', metavar='N', nargs='+',
+ help='dbus headers to find mappings in')
+parser.add_argument('--output', dest='output',
+ help='output file to write idl to')
+args = parser.parse_args()
+print "parsing"
+print args.mappingFiles
+
+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):
+ 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):
+ self.name = ""
+ self.members = []
+ def __repr__(self):
+ return "Interface('" + name + "')"
+ def toString(self):
+ output = self.name + ":"
+ for member in self.members:
+ output += member.toString() + ","
+ return output
+ def toIdl(self):
+ 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"
+ return output
+
+for input in args.mappingFiles:
+ try: file = open(input)
+ except IOError:
+ print "Failed to open " + input
+ with file:
+ for line in file:
+ i = line.find("DBusSink(\"");
+ if i != -1:
+ interface = Interface()
+ ifaceNameBeg = line.find('("')
+ ifaceNameEnd = line.find('",')
+ interface.name = line[ifaceNameBeg+2 : ifaceNameEnd]
+ interfaces.append(interface)
+ wantPropertyVariant = 'wantPropertyVariant('
+ i = line.find(wantPropertyVariant)
+ if i!= -1:
+ member = Member(interfaces[-1].name)
+ ambNameEnd = line.find(', "')-2
+ member.ambName = line[i+len(wantPropertyVariant) : i + ambNameEnd].replace("VehicleProperty::", "")
+ memberNameBeg = line.find(', "')+3
+ memberNameEnd = line.find('",')
+ member.memberName = line[memberNameBeg : memberNameEnd]
+ interfaces[-1].members.append(member)
+ file.close()
+
+try: outputFile = open(args.output, 'w')
+except IOError:
+ print "Error could not open output file: " + args.output
+with outputFile:
+ header =("/*!\n"
+ " * \\name AMB to AMB-DBus Mapping Tables\n"
+ " * \\file " + os.path.basename(args.output) + "\n"
+ " * \\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.\n"
+ " *\n"
+ " * For documentation on the interface and members, please see the \ref dbus_api.\n")
+ header += " */\n\n"
+ outputFile.write(header)
+ for iface in interfaces:
+ outputFile.write(iface.toIdl())
+ outputFile.write("\n")
+ outputFile.close()
+
+
+
diff --git a/xwalk/CMakeLists.txt b/xwalk/CMakeLists.txt
new file mode 100644
index 00000000..c2ae60f4
--- /dev/null
+++ b/xwalk/CMakeLists.txt
@@ -0,0 +1,30 @@
+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/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 )
+
+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)
+
+add_custom_target(js3cc DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/vehicle_api.cc)
+add_dependencies(vehicle_extension js3cc)
+
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/vehicle_api.js ${CMAKE_CURRENT_SOURCE_DIR}/vehicle_api.js @ONLY)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/vehicle.html ${CMAKE_CURRENT_SOURCE_DIR}/vehicle.html @ONLY)
+
+set(html_files ${CMAKE_CURRENT_SOURCE_DIR}/vehicle.html)
+set(js_files ${CMAKE_CURRENT_SOURCE_DIR}/js/js-test-pre.js ${CMAKE_CURRENT_SOURCE_DIR}/js/js-test-post.js)
+
+install(TARGETS vehicle_extension LIBRARY DESTINATION "${LIB_INSTALL_DIR}/${XWALK_EXTENSION_PATH}")
+install(FILES ${html_files} DESTINATION /usr/share/automotive-message-broker/xwalk/examples)
+install(FILES ${js_files} DESTINATION /usr/share/automotive-message-broker/xwalk/examples/js)
+endif(xwalk_vehicle_extension)
+
diff --git a/xwalk/LICENSE b/xwalk/LICENSE
new file mode 100644
index 00000000..ac380b1a
--- /dev/null
+++ b/xwalk/LICENSE
@@ -0,0 +1,27 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/xwalk/common/XW_Extension.h b/xwalk/common/XW_Extension.h
new file mode 100644
index 00000000..174915ad
--- /dev/null
+++ b/xwalk/common/XW_Extension.h
@@ -0,0 +1,185 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+
+// Crosswalk Extensions are modules of code loaded by Crosswalk runtime that
+// allow extending its capabilities. The extension is expected to define a
+// XW_Initialize() function as declared below, get the interfaces it need to
+// use and register to whatever callbacks it needs, then return XW_OK.
+//
+// The Extension is represented by the type XW_Extension. Each extension
+// loaded may be used multiple times for different pages, so to each execution
+// there will be an associated XW_Instance. A reasonable analogy is that the
+// XW_Extension represent a "class", and have concrete instances running.
+//
+// An interface is a struct with a set of functions, provided by Crosswalk,
+// that allow the extension code to interact with the web content. Certain
+// functions in an interface are used to register callbacks, so that Crosswalk
+// can call the extension at specific situations.
+//
+// Crosswalk won't call an extension's XW_Initialize() multiple times in the
+// same process.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if __GNUC__ >= 4
+#define XW_EXPORT __attribute__ ((visibility("default")))
+#elif defined(_MSC_VER)
+#define XW_EXPORT __declspec(dllexport)
+#endif
+
+#include <stdint.h>
+
+
+// XW_Extension is used to identify your extension when calling functions from
+// the API. You should always use the XW_Extension received at XW_Initialize().
+//
+// XW_Instance is used to identify different web contents using your
+// extension. Each time a new web content is created you can be notified
+// registering the XW_CreatedInstanceCallback, that receives the new
+// XW_Instance. When interacting with an Instance (for example to post a
+// message), you should pass the corresponding XW_Instance.
+//
+// In both types the zero value is never used by Crosswalk, so can be used to
+// initialize variables.
+typedef int32_t XW_Extension;
+typedef int32_t XW_Instance;
+
+enum {
+ XW_OK = 0,
+ XW_ERROR = -1
+};
+
+// Returns a struct containing functions to be used by the extension. Those
+// structs can be stored statically and used until the extension is unloaded.
+// Extensions should use definitions like XW_CORE_INTERFACE, instead of using
+// the versioned definition or the literal string. Returns NULL if the
+// interface is not supported.
+typedef const void* (*XW_GetInterface)(const char* interface_name);
+
+
+typedef int32_t (*XW_Initialize_Func)(XW_Extension extension,
+ XW_GetInterface get_interface);
+
+// XW_Initialize is called after the extension code is loaded. The 'extension'
+// value should be used in further calls that expect XW_Extension argument.
+//
+// The 'get_interface' function should be used to get access to functions that
+// interact with the web content. It is only valid during the execution of the
+// XW_Initialize() function.
+//
+// This function should return XW_OK when the extension was succesfully
+// loaded, otherwise XW_ERROR.
+XW_EXPORT int32_t XW_Initialize(XW_Extension extension,
+ XW_GetInterface get_interface);
+
+
+//
+// XW_CORE_INTERFACE: Basic functionality for Crosswalk Extensions. All
+// extensions should use this interface to set at least their name.
+//
+
+#define XW_CORE_INTERFACE_1 "XW_CoreInterface_1"
+#define XW_CORE_INTERFACE XW_CORE_INTERFACE_1
+
+typedef void (*XW_CreatedInstanceCallback)(XW_Instance instance);
+typedef void (*XW_DestroyedInstanceCallback)(XW_Instance instance);
+typedef void (*XW_ShutdownCallback)(XW_Extension extension);
+
+struct XW_CoreInterface_1 {
+ // Set the name of the extension. It is used as the namespace for the
+ // JavaScript code exposed by the extension. So extension named
+ // 'my_extension', will expose its JavaScript functionality inside
+ // the 'my_extension' namespace.
+ //
+ // This function should be called only during XW_Initialize().
+ void (*SetExtensionName)(XW_Extension extension, const char* name);
+
+ // Set the JavaScript code loaded in the web content when the extension is
+ // used. This can be used together with the messaging mechanism to implement
+ // a higher-level API that posts messages to extensions, see
+ // XW_MESSAGING_INTERFACE below.
+ //
+ // The code will be executed inside a JS function context with the following
+ // objects available:
+ //
+ // - exports: this object should be filled with properties and functions
+ // that will be exposed in the namespace associated with this
+ // extension.
+ //
+ // - extension.postMessage(): post a string message to the extension native
+ // code. See below for details.
+ // - extension.setMessageListener(): allow setting a callback that is called
+ // when the native code sends a message
+ // to JavaScript. Callback takes a string.
+ //
+ // This function should be called only during XW_Initialize().
+ void (*SetJavaScriptAPI)(XW_Extension extension, const char* api);
+
+ // Register callbacks that are called when an instance of this extension
+ // is created or destroyed. Everytime a new web content is loaded, it will
+ // get a new associated instance.
+ //
+ // This function should be called only during XW_Initialize().
+ void (*RegisterInstanceCallbacks)(XW_Extension extension,
+ XW_CreatedInstanceCallback created,
+ XW_DestroyedInstanceCallback destroyed);
+
+ // Register a callback to be executed when the extension will be unloaded.
+ //
+ // This function should be called only during XW_Initialize().
+ void (*RegisterShutdownCallback)(XW_Extension extension,
+ XW_ShutdownCallback shutdown_callback);
+
+ // These two functions are conveniences used to associated arbitrary data
+ // with a given XW_Instance. They can be used only with instances that were
+ // created but not yet completely destroyed. GetInstanceData() can be used
+ // during the destroyed instance callback. If not instance data was set,
+ // getting it returns NULL.
+ void (*SetInstanceData)(XW_Instance instance, void* data);
+ void* (*GetInstanceData)(XW_Instance instance);
+};
+
+typedef struct XW_CoreInterface_1 XW_CoreInterface;
+
+
+//
+// XW_MESSAGING_INTERFACE: Exchange asynchronous messages with JavaScript
+// code provided by extension.
+//
+
+#define XW_MESSAGING_INTERFACE_1 "XW_MessagingInterface_1"
+#define XW_MESSAGING_INTERFACE XW_MESSAGING_INTERFACE_1
+
+typedef void (*XW_HandleMessageCallback)(XW_Instance instance,
+ const char* message);
+
+struct XW_MessagingInterface_1 {
+ // Register a callback to be called when the JavaScript code associated
+ // with the extension posts a message. Note that the callback will be called
+ // with the XW_Instance that posted the message as well as the message
+ // contents.
+ void (*Register)(XW_Extension extension,
+ XW_HandleMessageCallback handle_message);
+
+ // Post a message to the web content associated with the instance. To
+ // receive this message the extension's JavaScript code should set a
+ // listener using extension.setMessageListener() function.
+ //
+ // This function is thread-safe and can be called until the instance is
+ // destroyed.
+ void (*PostMessage)(XW_Instance instance, const char* message);
+};
+
+typedef struct XW_MessagingInterface_1 XW_MessagingInterface;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
diff --git a/xwalk/common/XW_Extension_EntryPoints.h b/xwalk/common/XW_Extension_EntryPoints.h
new file mode 100644
index 00000000..54532a91
--- /dev/null
+++ b/xwalk/common/XW_Extension_EntryPoints.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_ENTRYPOINTS_H_
+#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_ENTRYPOINTS_H_
+
+// NOTE: This file and interfaces marked as internal are not considered stable
+// and can be modified in incompatible ways between Crosswalk versions.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+#error "You should include XW_Extension.h before this file"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define XW_INTERNAL_ENTRY_POINTS_INTERFACE_1 \
+ "XW_Internal_EntryPointsInterface_1"
+#define XW_INTERNAL_ENTRY_POINTS_INTERFACE \
+ XW_INTERNAL_ENTRY_POINTS_INTERFACE_1
+
+//
+// XW_INTERNAL_ENTRY_POINTS_INTERFACE: provides a way for extensions to add
+// more information about its implementation. For now, allow extensions to
+// specify more objects that the access should cause the extension to be
+// loaded.
+//
+
+struct XW_Internal_EntryPointsInterface_1 {
+ // Register extra entry points for this extension. An "extra" entry points
+ // are objects outside the implicit namespace for which the extension should
+ // be loaded when they are touched.
+ //
+ // This function should be called only during XW_Initialize().
+ void (*SetExtraJSEntryPoints)(XW_Extension extension,
+ const char** entry_points);
+};
+
+typedef struct XW_Internal_EntryPointsInterface_1
+ XW_Internal_EntryPointsInterface;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_ENTRYPOINTS_H_
+
diff --git a/xwalk/common/XW_Extension_Permissions.h b/xwalk/common/XW_Extension_Permissions.h
new file mode 100644
index 00000000..d25484ea
--- /dev/null
+++ b/xwalk/common/XW_Extension_Permissions.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_PERMISSIONS_H_
+#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_PERMISSIONS_H_
+
+// NOTE: This file and interfaces marked as internal are not considered stable
+// and can be modified in incompatible ways between Crosswalk versions.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+#error "You should include XW_Extension.h before this file"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define XW_INTERNAL_PERMISSIONS_INTERFACE_1 \
+ "XW_Internal_PermissionsInterface_1"
+#define XW_INTERNAL_PERMISSIONS_INTERFACE \
+ XW_INTERNAL_PERMISSIONS_INTERFACE_1
+
+//
+// XW_INTERNAL_PERMISSIONS_INTERFACE: provides a way for extensions
+// check if they have the proper permissions for certain APIs.
+//
+
+struct XW_Internal_PermissionsInterface_1 {
+ int (*CheckAPIAccessControl)(XW_Extension extension, const char* api_name);
+ int (*RegisterPermissions)(XW_Extension extension, const char* perm_table);
+};
+
+typedef struct XW_Internal_PermissionsInterface_1
+ XW_Internal_PermissionsInterface;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_PERMISSIONS_H_
diff --git a/xwalk/common/XW_Extension_Runtime.h b/xwalk/common/XW_Extension_Runtime.h
new file mode 100644
index 00000000..f5858f3e
--- /dev/null
+++ b/xwalk/common/XW_Extension_Runtime.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_RUNTIME_H_
+#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_RUNTIME_H_
+
+// NOTE: This file and interfaces marked as internal are not considered stable
+// and can be modified in incompatible ways between Crosswalk versions.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+#error "You should include XW_Extension.h before this file"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define XW_INTERNAL_RUNTIME_INTERFACE_1 \
+ "XW_Internal_RuntimeInterface_1"
+#define XW_INTERNAL_RUNTIME_INTERFACE \
+ XW_INTERNAL_RUNTIME_INTERFACE_1
+
+//
+// XW_INTERNAL_RUNTIME_INTERFACE: allow extensions to gather information
+// from the runtime.
+//
+
+struct XW_Internal_RuntimeInterface_1 {
+ void (*GetRuntimeVariableString)(XW_Extension extension,
+ const char* key,
+ char* value,
+ size_t value_len);
+};
+
+typedef struct XW_Internal_RuntimeInterface_1
+ XW_Internal_RuntimeInterface;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_RUNTIME_H_
+
diff --git a/xwalk/common/XW_Extension_SyncMessage.h b/xwalk/common/XW_Extension_SyncMessage.h
new file mode 100644
index 00000000..4eddbf9b
--- /dev/null
+++ b/xwalk/common/XW_Extension_SyncMessage.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_SYNCMESSAGE_H_
+#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_SYNCMESSAGE_H_
+
+// NOTE: This file and interfaces marked as internal are not considered stable
+// and can be modified in incompatible ways between Crosswalk versions.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+#error "You should include XW_Extension.h before this file"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// XW_INTERNAL_SYNC_MESSAGING_INTERFACE: allow JavaScript code to send a
+// synchronous message to extension code and block until response is
+// available. The response is made available by calling the SetSyncReply
+// function, that can be done from outside the context of the SyncMessage
+// handler.
+//
+
+#define XW_INTERNAL_SYNC_MESSAGING_INTERFACE_1 \
+ "XW_InternalSyncMessagingInterface_1"
+#define XW_INTERNAL_SYNC_MESSAGING_INTERFACE \
+ XW_INTERNAL_SYNC_MESSAGING_INTERFACE_1
+
+typedef void (*XW_HandleSyncMessageCallback)(XW_Instance instance,
+ const char* message);
+
+struct XW_Internal_SyncMessagingInterface_1 {
+ void (*Register)(XW_Extension extension,
+ XW_HandleSyncMessageCallback handle_sync_message);
+ void (*SetSyncReply)(XW_Instance instance, const char* reply);
+};
+
+typedef struct XW_Internal_SyncMessagingInterface_1
+ XW_Internal_SyncMessagingInterface;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_SYNCMESSAGE_H_
diff --git a/xwalk/common/extension.cc b/xwalk/common/extension.cc
new file mode 100644
index 00000000..168483a3
--- /dev/null
+++ b/xwalk/common/extension.cc
@@ -0,0 +1,212 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "common/extension.h"
+
+#include <assert.h>
+#include <iostream>
+#include <vector>
+
+namespace {
+
+common::Extension* g_extension = NULL;
+XW_Extension g_xw_extension = 0;
+
+const XW_CoreInterface* g_core = NULL;
+const XW_MessagingInterface* g_messaging = NULL;
+const XW_Internal_SyncMessagingInterface* g_sync_messaging = NULL;
+const XW_Internal_EntryPointsInterface* g_entry_points = NULL;
+const XW_Internal_RuntimeInterface* g_runtime = NULL;
+const XW_Internal_PermissionsInterface* g_permission = NULL;
+
+bool InitializeInterfaces(XW_GetInterface get_interface) {
+ g_core = reinterpret_cast<const XW_CoreInterface*>(
+ get_interface(XW_CORE_INTERFACE));
+ if (!g_core) {
+ std::cerr << "Can't initialize extension: error getting Core interface.\n";
+ return false;
+ }
+
+ g_messaging = reinterpret_cast<const XW_MessagingInterface*>(
+ get_interface(XW_MESSAGING_INTERFACE));
+ if (!g_messaging) {
+ std::cerr <<
+ "Can't initialize extension: error getting Messaging interface.\n";
+ return false;
+ }
+
+ g_sync_messaging =
+ reinterpret_cast<const XW_Internal_SyncMessagingInterface*>(
+ get_interface(XW_INTERNAL_SYNC_MESSAGING_INTERFACE));
+ if (!g_sync_messaging) {
+ std::cerr <<
+ "Can't initialize extension: error getting SyncMessaging interface.\n";
+ return false;
+ }
+
+ g_entry_points = reinterpret_cast<const XW_Internal_EntryPointsInterface*>(
+ get_interface(XW_INTERNAL_ENTRY_POINTS_INTERFACE));
+ if (!g_entry_points) {
+ std::cerr << "NOTE: Entry points interface not available in this version "
+ << "of Crosswalk, ignoring entry point data for extensions.\n";
+ }
+
+ g_runtime = reinterpret_cast<const XW_Internal_RuntimeInterface*>(
+ get_interface(XW_INTERNAL_RUNTIME_INTERFACE));
+ if (!g_runtime) {
+ std::cerr << "NOTE: runtime interface not available in this version "
+ << "of Crosswalk, ignoring runtime variables for extensions.\n";
+ }
+
+ g_permission = reinterpret_cast<const XW_Internal_PermissionsInterface*>(
+ get_interface(XW_INTERNAL_PERMISSIONS_INTERFACE));
+ if (!g_permission) {
+ std::cerr << "NOTE: permission interface not available in this version "
+ << "of Crosswalk, ignoring permission for extensions.\n";
+ }
+
+ return true;
+}
+
+} // namespace
+
+int32_t XW_Initialize(XW_Extension extension, XW_GetInterface get_interface) {
+ assert(extension);
+ g_xw_extension = extension;
+
+ if (!InitializeInterfaces(get_interface))
+ return XW_ERROR;
+
+ g_extension = CreateExtension();
+ if (!g_extension) {
+ std::cerr << "Can't initialize extension: "
+ << "create extension returned NULL.\n";
+ return XW_ERROR;
+ }
+
+ using common::Extension;
+ g_core->RegisterShutdownCallback(g_xw_extension, Extension::OnShutdown);
+ g_core->RegisterInstanceCallbacks(
+ g_xw_extension, Extension::OnInstanceCreated,
+ Extension::OnInstanceDestroyed);
+ g_messaging->Register(g_xw_extension, Extension::HandleMessage);
+ g_sync_messaging->Register(g_xw_extension, Extension::HandleSyncMessage);
+ return XW_OK;
+}
+
+namespace common {
+
+Extension::Extension() {}
+
+Extension::~Extension() {}
+
+void Extension::SetExtensionName(const char* name) {
+ g_core->SetExtensionName(g_xw_extension, name);
+}
+
+void Extension::SetJavaScriptAPI(const char* api) {
+ g_core->SetJavaScriptAPI(g_xw_extension, api);
+}
+
+void Extension::SetExtraJSEntryPoints(const char** entry_points) {
+ if (g_entry_points)
+ g_entry_points->SetExtraJSEntryPoints(g_xw_extension, entry_points);
+}
+
+bool Extension::RegisterPermissions(const char* perm_table) {
+ if (g_permission)
+ return g_permission->RegisterPermissions(g_xw_extension, perm_table);
+ return false;
+}
+
+bool Extension::CheckAPIAccessControl(const char* api_name) {
+ if (g_permission)
+ return g_permission->CheckAPIAccessControl(g_xw_extension, api_name);
+ return false;
+}
+
+Instance* Extension::CreateInstance() {
+ return NULL;
+}
+
+std::string Extension::GetRuntimeVariable(const char* var_name, unsigned len) {
+ if (!g_runtime)
+ return "";
+
+ std::vector<char> res(len + 1, 0);
+ g_runtime->GetRuntimeVariableString(g_xw_extension, var_name, &res[0], len);
+ return std::string(res.begin(), res.end());
+}
+
+// static
+void Extension::OnShutdown(XW_Extension) {
+ delete g_extension;
+ g_extension = NULL;
+}
+
+// static
+void Extension::OnInstanceCreated(XW_Instance xw_instance) {
+ assert(!g_core->GetInstanceData(xw_instance));
+ Instance* instance = g_extension->CreateInstance();
+ if (!instance)
+ return;
+ instance->xw_instance_ = xw_instance;
+ g_core->SetInstanceData(xw_instance, instance);
+ instance->Initialize();
+}
+
+// static
+void Extension::OnInstanceDestroyed(XW_Instance xw_instance) {
+ Instance* instance =
+ reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
+ if (!instance)
+ return;
+ instance->xw_instance_ = 0;
+ delete instance;
+}
+
+// static
+void Extension::HandleMessage(XW_Instance xw_instance, const char* msg) {
+ Instance* instance =
+ reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
+ if (!instance)
+ return;
+ instance->HandleMessage(msg);
+}
+
+// static
+void Extension::HandleSyncMessage(XW_Instance xw_instance, const char* msg) {
+ Instance* instance =
+ reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
+ if (!instance)
+ return;
+ instance->HandleSyncMessage(msg);
+}
+
+Instance::Instance()
+ : xw_instance_(0) {}
+
+Instance::~Instance() {
+ assert(xw_instance_ == 0);
+}
+
+void Instance::PostMessage(const char* msg) {
+ if (!xw_instance_) {
+ std::cerr << "Ignoring PostMessage() in the constructor or after the "
+ << "instance was destroyed.";
+ return;
+ }
+ g_messaging->PostMessage(xw_instance_, msg);
+}
+
+void Instance::SendSyncReply(const char* reply) {
+ if (!xw_instance_) {
+ std::cerr << "Ignoring SendSyncReply() in the constructor or after the "
+ << "instance was destroyed.";
+ return;
+ }
+ g_sync_messaging->SetSyncReply(xw_instance_, reply);
+}
+
+} // namespace common
diff --git a/xwalk/common/extension.h b/xwalk/common/extension.h
new file mode 100644
index 00000000..66d8bef0
--- /dev/null
+++ b/xwalk/common/extension.h
@@ -0,0 +1,96 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_EXTENSION_H_
+#define COMMON_EXTENSION_H_
+
+// This is a C++ wrapper over Crosswalk Extension C API. It implements once the
+// boilerplate for the common case of mapping XW_Extension and XW_Instance to
+// objects of their own. The wrapper deals automatically with creating and
+// destroying the objects.
+//
+// Extension object lives during the lifetime of the extension, and when the
+// extension process is properly shutdown, it's destructor will be
+// called. Instance objects (there can be many) live during the lifetime of a
+// script context associated with a frame in the page. These objects serves as
+// storage points for extension specific objects, use them for that.
+
+#include <sys/types.h>
+
+#include <string>
+
+#include "common/XW_Extension.h"
+#include "common/XW_Extension_EntryPoints.h"
+#include "common/XW_Extension_Permissions.h"
+#include "common/XW_Extension_Runtime.h"
+#include "common/XW_Extension_SyncMessage.h"
+
+namespace common {
+
+class Instance;
+class Extension;
+
+} // namespace common
+
+
+// This function should be implemented by each extension and should return
+// an appropriate Extension subclass.
+common::Extension* CreateExtension();
+
+
+namespace common {
+
+class Extension {
+ public:
+ Extension();
+ virtual ~Extension();
+
+ // These should be called in the subclass constructor.
+ void SetExtensionName(const char* name);
+ void SetJavaScriptAPI(const char* api);
+ void SetExtraJSEntryPoints(const char** entry_points);
+ bool RegisterPermissions(const char* perm_table);
+
+ // This API should be called in the message handler of extension
+ bool CheckAPIAccessControl(const char* api_name);
+
+ virtual Instance* CreateInstance();
+
+ static std::string GetRuntimeVariable(const char* var_name, unsigned len);
+
+ private:
+ friend int32_t ::XW_Initialize(XW_Extension extension,
+ XW_GetInterface get_interface);
+
+ // XW_Extension callbacks.
+ static void OnShutdown(XW_Extension xw_extension);
+ static void OnInstanceCreated(XW_Instance xw_instance);
+ static void OnInstanceDestroyed(XW_Instance xw_instance);
+ static void HandleMessage(XW_Instance xw_instance, const char* msg);
+ static void HandleSyncMessage(XW_Instance xw_instance, const char* msg);
+};
+
+class Instance {
+ public:
+ Instance();
+ virtual ~Instance();
+
+ void PostMessage(const char* msg);
+ void SendSyncReply(const char* reply);
+
+ virtual void Initialize() {}
+ virtual void HandleMessage(const char* msg) = 0;
+ virtual void HandleSyncMessage(const char* msg) {}
+
+ XW_Instance xw_instance() const { return xw_instance_; }
+
+ private:
+ friend class Extension;
+
+ XW_Instance xw_instance_;
+};
+
+} // namespace common
+
+#endif // COMMON_EXTENSION_H_
diff --git a/xwalk/common/utils.h b/xwalk/common/utils.h
new file mode 100644
index 00000000..ea866c43
--- /dev/null
+++ b/xwalk/common/utils.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_UTILS_H_
+#define COMMON_UTILS_H_
+
+// Put this in the private: declarations for a class to be uncopyable.
+#define DISALLOW_COPY(TypeName) \
+ TypeName(const TypeName&)
+
+// Put this in the private: declarations for a class to be unassignable.
+#define DISALLOW_ASSIGN(TypeName) \
+ void operator=(const TypeName&)
+
+// A macro to disallow the copy constructor and operator= functions
+// This should be used in the private: declarations for a class
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+
+#endif // COMMON_UTILS_H_
diff --git a/xwalk/common/virtual_fs.cc b/xwalk/common/virtual_fs.cc
new file mode 100644
index 00000000..93984a0b
--- /dev/null
+++ b/xwalk/common/virtual_fs.cc
@@ -0,0 +1,317 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "common/virtual_fs.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <pkgmgr-info.h>
+#include <tzplatform_config.h>
+
+#include <cassert>
+#include <algorithm>
+#include <sstream>
+#include <string>
+
+#include "common/extension.h"
+
+namespace {
+
+const char kInternalStorage[] = "internal";
+const char kRemovableStorage[] = "removable";
+
+const char kStorageTypeInternal[] = "INTERNAL";
+const char kStorageTypeExternal[] = "EXTERNAL";
+const char kStorageStateMounted[] = "MOUNTED";
+const char kStorageStateRemoved[] = "REMOVED";
+const char kStorageStateUnmountable[] = "UNMOUNTABLE";
+
+} // namespace
+
+namespace vfs_const {
+
+const unsigned kDefaultFileMode = 0755;
+const char kLocationCamera[] = "camera";
+const char kLocationMusic[] = "music";
+const char kLocationImages[] = "images";
+const char kLocationVideos[] = "videos";
+const char kLocationDownloads[] = "downloads";
+const char kLocationDocuments[] = "documents";
+const char kLocationRingtones[] = "ringtones";
+const char kLocationWgtPackage[] = "wgt-package";
+const char kLocationWgtPrivate[] = "wgt-private";
+const char kLocationWgtPrivateTmp[] = "wgt-private-tmp";
+
+} // namespace vfs_const
+
+VirtualFS::VirtualFS() {
+ std::string app_path = GetApplicationPath();
+ if (!app_path.empty()) {
+ AddInternalStorage(vfs_const::kLocationWgtPackage, app_path);
+ AddInternalStorage(vfs_const::kLocationWgtPrivate, JoinPath(app_path, "private"));
+ AddInternalStorage(vfs_const::kLocationWgtPrivateTmp, JoinPath(app_path, "tmp"));
+ }
+
+ AddInternalStorage(vfs_const::kLocationCamera, tzplatform_getenv(TZ_USER_CAMERA));
+ AddInternalStorage(vfs_const::kLocationMusic, tzplatform_getenv(TZ_USER_SOUNDS));
+ AddInternalStorage(vfs_const::kLocationImages, tzplatform_getenv(TZ_USER_IMAGES));
+ AddInternalStorage(vfs_const::kLocationVideos, tzplatform_getenv(TZ_USER_VIDEOS));
+ AddInternalStorage(vfs_const::kLocationDownloads, tzplatform_getenv(TZ_USER_DOWNLOADS));
+ AddInternalStorage(vfs_const::kLocationDocuments, tzplatform_getenv(TZ_USER_DOCUMENTS));
+ AddInternalStorage(vfs_const::kLocationRingtones,
+ tzplatform_mkpath(TZ_USER_SHARE, "settings/Ringtones"));
+ storage_changed_cb_ = NULL;
+ cb_user_data_ = NULL;
+}
+
+VirtualFS::~VirtualFS() {
+}
+
+std::string VirtualFS::JoinPath(const std::string& one,
+ const std::string& another) {
+ return one + '/' + another;
+}
+
+bool VirtualFS::MakePath(const std::string& path, int mode) {
+ // Path should start with '/' and contain at least 1 character after '/'.
+ if (path.empty() || path[0] != '/' || path.length() < 2)
+ return false;
+
+ struct stat st;
+ std::string dir = path;
+ if (stat(dir.c_str(), &st) == 0)
+ return true;
+
+ // Add trailing '/' if missing, so we can iterate till the end of the path.
+ if (dir[dir.size() - 1] != '/')
+ dir += '/';
+
+ for (std::string::iterator iter = dir.begin(); iter != dir.end();) {
+ std::string::iterator cur_iter = std::find(iter, dir.end(), '/');
+
+ // If '/' is found at the beginning of the string, iterate to the next '/'.
+ if (cur_iter == iter) {
+ ++iter;
+ cur_iter = std::find(iter, dir.end(), '/');
+ }
+
+ std::string new_path = std::string(dir.begin(), cur_iter);
+
+ // If path doesn't exist, try to create one and continue iteration.
+ // In case of error, stop iteration and return.
+ if (stat(new_path.c_str(), &st) != 0) {
+ if (mkdir(new_path.c_str(), mode) != 0 && errno != EEXIST )
+ return false;
+ // If path exists and it is not a directory, stop iteration and return.
+ } else if (!S_ISDIR(st.st_mode)) {
+ return false;
+ }
+
+ // Advance iterator and create next parent folder.
+ iter = cur_iter;
+ if (cur_iter != dir.end())
+ ++iter;
+ }
+ return true;
+}
+
+int VirtualFS::GetDirEntryCount(const char* path) {
+ int count = 0;
+ DIR* dir = opendir(path);
+ if (!dir)
+ return count;
+
+ struct dirent entry;
+ struct dirent *result;
+ int ret = readdir_r(dir, &entry, &result);
+
+ for (; ret == 0 && result != NULL; ret = readdir_r(dir, &entry, &result)) {
+ if (entry.d_type == DT_REG || entry.d_type == DT_DIR)
+ count++;
+ }
+
+ closedir(dir);
+ return count;
+}
+
+std::string VirtualFS::GetAppId(const std::string& package_id) {
+ char* appid = NULL;
+ pkgmgrinfo_pkginfo_h pkginfo_handle;
+ int ret = pkgmgrinfo_pkginfo_get_pkginfo(package_id.c_str(), &pkginfo_handle);
+ if (ret != PMINFO_R_OK)
+ return std::string();
+ ret = pkgmgrinfo_pkginfo_get_mainappid(pkginfo_handle, &appid);
+ if (ret != PMINFO_R_OK) {
+ pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_handle);
+ return std::string();
+ }
+
+ std::string retval(appid);
+ pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_handle);
+ return retval;
+}
+
+std::string VirtualFS::GetExecPath(const std::string& app_id) {
+ char* exec_path = NULL;
+ pkgmgrinfo_appinfo_h appinfo_handle;
+ int ret = pkgmgrinfo_appinfo_get_appinfo(app_id.c_str(), &appinfo_handle);
+ if (ret != PMINFO_R_OK)
+ return std::string();
+ ret = pkgmgrinfo_appinfo_get_exec(appinfo_handle, &exec_path);
+ if (ret != PMINFO_R_OK) {
+ pkgmgrinfo_appinfo_destroy_appinfo(appinfo_handle);
+ return std::string();
+ }
+
+ std::string retval(exec_path);
+ pkgmgrinfo_appinfo_destroy_appinfo(appinfo_handle);
+ return retval;
+}
+
+bool VirtualFS::GetStorageByLabel(const std::string& label, Storage& storage) {
+ storage_foreach_device_supported(OnStorageDeviceSupported, this);
+ Storages::const_iterator it = storages_.find(label);
+
+ if (it == storages_.end()) {
+ return false;
+ }
+ storage = it->second;
+ return true;
+}
+
+Storages::iterator VirtualFS::begin() {
+ storage_foreach_device_supported(OnStorageDeviceSupported, this);
+ return storages_.begin();
+}
+
+Storages::const_iterator VirtualFS::end() const {
+ return storages_.end();
+}
+
+std::string VirtualFS::GetApplicationPath() {
+ std::string id_str = common::Extension::GetRuntimeVariable("app_id", 64);
+ std::string pkg_id = id_str.substr(1, id_str.rfind('"') - 1);
+ if (pkg_id.empty())
+ return std::string();
+ std::string app_id = GetAppId(pkg_id);
+ if (app_id.empty())
+ return std::string();
+ std::string exec_path = GetExecPath(app_id);
+ if (exec_path.empty())
+ return std::string();
+
+ size_t index = exec_path.find(pkg_id);
+ if (index != std::string::npos)
+ return exec_path.substr(0, index + pkg_id.length());
+ return std::string();
+}
+
+std::string VirtualFS::GetRealPath(const std::string& fullPath) const {
+ std::size_t pos = fullPath.find_first_of('/');
+ Storages::const_iterator it = storages_.find(fullPath.substr(0, pos));
+
+ if (it == storages_.end())
+ return std::string();
+
+ if (pos != std::string::npos)
+ return it->second.GetFullPath() + fullPath.substr(pos);
+
+ return it->second.GetFullPath();
+}
+
+void VirtualFS::AddInternalStorage(
+ const std::string& label, const std::string& path) {
+ if (MakePath(path, vfs_const::kDefaultFileMode))
+ storages_.insert(StorageLabelPair(label,
+ Storage(-1,
+ Storage::STORAGE_TYPE_INTERNAL,
+ Storage::STORAGE_STATE_MOUNTED,
+ path)));
+}
+
+void VirtualFS::AddStorage(int id,
+ storage_type_e type,
+ storage_state_e state,
+ const std::string& path) {
+ std::string label;
+ if (type == STORAGE_TYPE_INTERNAL)
+ label = kInternalStorage + std::to_string(id);
+ else if (type == STORAGE_TYPE_EXTERNAL)
+ label = kRemovableStorage + std::to_string(id);
+
+ storages_.insert(StorageLabelPair(label,
+ Storage(id,
+ type,
+ state,
+ path)));
+ if (std::find(watched_storages_.begin(),
+ watched_storages_.end(), id) != watched_storages_.end()) {
+ watched_storages_.push_back(id);
+ storage_set_state_changed_cb(id, OnStorageStateChanged, this);
+ }
+}
+
+void VirtualFS::SetOnStorageChangedCb(CallBackFunctionPtr cb, void* user_data) {
+ storage_changed_cb_ = cb;
+ cb_user_data_ = user_data;
+}
+
+void VirtualFS::NotifyStorageStateChanged(int id, storage_state_e state) {
+ for (Storages::iterator it = storages_.begin(); it != storages_.end(); ++it) {
+ if (it->second.GetId() == id) {
+ it->second.SetState(state);
+ if (storage_changed_cb_) {
+ storage_changed_cb_(it->first, it->second, cb_user_data_);
+ }
+ break;
+ }
+ }
+}
+
+bool VirtualFS::OnStorageDeviceSupported(
+ int id, storage_type_e type, storage_state_e state,
+ const char* path, void* user_data) {
+ reinterpret_cast<VirtualFS*>(user_data)->AddStorage(
+ id, type, state, path);
+ return true;
+}
+
+void VirtualFS::OnStorageStateChanged(
+ int id, storage_state_e state, void* user_data) {
+ reinterpret_cast<VirtualFS*>(user_data)->NotifyStorageStateChanged(
+ id, state);
+}
+
+/*
+ * Storage Class
+ */
+
+Storage::Storage(
+ int id, int type, int state, const std::string& fullpath)
+ : id_(id),
+ type_(type),
+ state_(state),
+ full_path_(fullpath) { }
+
+std::string Storage::GetType() const {
+ return (type_ == Storage::STORAGE_TYPE_INTERNAL) ? kStorageTypeInternal :
+ kStorageTypeExternal;
+}
+
+std::string Storage::GetState() const {
+ switch (state_) {
+ case Storage::STORAGE_STATE_MOUNTED:
+ case Storage::STORAGE_STATE_MOUNTED_READONLY:
+ return kStorageStateMounted;
+ case Storage::STORAGE_STATE_REMOVED:
+ return kStorageStateRemoved;
+ case Storage::STORAGE_STATE_UNMOUNTABLE:
+ return kStorageStateUnmountable;
+ default:
+ assert(!"Not reached");
+ }
+ return std::string();
+}
diff --git a/xwalk/common/virtual_fs.h b/xwalk/common/virtual_fs.h
new file mode 100644
index 00000000..94a988f1
--- /dev/null
+++ b/xwalk/common/virtual_fs.h
@@ -0,0 +1,130 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_VIRTUAL_FS_H_
+#define COMMON_VIRTUAL_FS_H_
+
+#include <appfw/app_storage.h>
+
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace vfs_const {
+
+extern const unsigned kDefaultFileMode;
+extern const char kLocationCamera[];
+extern const char kLocationMusic[];
+extern const char kLocationImages[];
+extern const char kLocationVideos[];
+extern const char kLocationDownloads[];
+extern const char kLocationDocuments[];
+extern const char kLocationRingtones[];
+extern const char kLocationWgtPackage[];
+extern const char kLocationWgtPrivate[];
+extern const char kLocationWgtPrivateTmp[];
+
+} // namespace vfs_const
+
+class Storage {
+ public:
+ /* Mapped to storage_type_e */
+ enum StorageType {
+ STORAGE_TYPE_INTERNAL, STORAGE_TYPE_EXTERNAL,
+ };
+
+ /* Mapped to storage_state_e */
+ enum StorageState {
+ STORAGE_STATE_UNMOUNTABLE = -2,
+ STORAGE_STATE_REMOVED = -1,
+ STORAGE_STATE_MOUNTED = 0,
+ STORAGE_STATE_MOUNTED_READONLY = 1,
+ };
+
+ Storage(int id = 0, int type = 0, int state = 0,
+ const std::string& fullpath = "");
+
+ std::string GetType() const;
+ std::string GetState() const;
+ int GetId() const { return id_; }
+ const std::string& GetFullPath() const { return full_path_; }
+ void SetState(int state) { state_ = state; }
+
+ private:
+ int id_;
+ int type_;
+ int state_;
+ std::string full_path_;
+};
+
+typedef std::map<std::string, Storage> Storages;
+typedef void(*CallBackFunctionPtr)(const std::string&, Storage, void*);
+
+/**
+ * The VirtualFS class provide an abstraction of the TIZEN virtual filesystem.
+ * It manages mounted storages and virtual roots, creating missing directories
+ * if needed.
+ * Convenient functions are also provided for working with paths (real or
+ * virtual).
+ */
+class VirtualFS {
+ public:
+ VirtualFS();
+ ~VirtualFS();
+ /**
+ * Resolve the given fullpath within the virtual filesystem to an absolute
+ * path within the real filesystem.
+ * @param fullPath: fully-qualified path of the form: <root name>/<path>
+ * where <rootname> is the name of the virtual root and <path> is the path
+ * to the file or directory relative to that root.
+ * @return full Linux path.
+ */
+ std::string GetRealPath(const std::string& fullPath) const;
+ bool GetStorageByLabel(const std::string& label, Storage& storage);
+ Storages::iterator begin();
+ Storages::const_iterator end() const;
+ void SetOnStorageChangedCb(CallBackFunctionPtr cb, void* user_data);
+
+ /**
+ * Concatenate two paths.
+ * @param one: base path.
+ * @param another: path within 'one'.
+ * @return new path.
+ */
+ static std::string JoinPath(const std::string& one,
+ const std::string& another);
+ /**
+ * Create full path and parent directories when needed.
+ * Similar to "mkdir -p".
+ * @param path: the path to be created.
+ * @param mode: the unix access mode applied to the new directories.
+ * @return true if success.
+ */
+ static bool MakePath(const std::string& path, int mode);
+ static int GetDirEntryCount(const char* path);
+ static std::string GetAppId(const std::string& package_id);
+ static std::string GetExecPath(const std::string& app_id);
+ static std::string GetApplicationPath();
+
+ private:
+ void AddInternalStorage(const std::string& label, const std::string& path);
+ void AddStorage(int storage, storage_type_e type, storage_state_e state,
+ const std::string& path);
+ void NotifyStorageStateChanged(int id, storage_state_e state);
+ static bool OnStorageDeviceSupported(int id, storage_type_e type,
+ storage_state_e state, const char* path, void* user_data);
+ static void OnStorageStateChanged(int id, storage_state_e state,
+ void* user_data);
+
+ CallBackFunctionPtr storage_changed_cb_;
+ void* cb_user_data_;
+
+ typedef std::pair<std::string, Storage> StorageLabelPair;
+ Storages storages_;
+ std::vector<int> watched_storages_;
+};
+
+#endif // COMMON_VIRTUAL_FS_H_
diff --git a/xwalk/generate_api.py b/xwalk/generate_api.py
new file mode 100755
index 00000000..cef97b7a
--- /dev/null
+++ b/xwalk/generate_api.py
@@ -0,0 +1,19 @@
+# Copyright (c) 2013 Intel Corporation. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+
+TEMPLATE = """\
+extern const char %s[];
+const char %s[] = { %s, 0 };
+"""
+
+js_code = sys.argv[1]
+lines = file(js_code).read()
+c_code = ', '.join(str(ord(c)) for c in lines)
+
+symbol_name = sys.argv[2]
+output = open(sys.argv[3], "w")
+output.write(TEMPLATE % (symbol_name, symbol_name, c_code))
+output.close()
diff --git a/xwalk/js/js-test-post.js b/xwalk/js/js-test-post.js
new file mode 100644
index 00000000..9218c561
--- /dev/null
+++ b/xwalk/js/js-test-post.js
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ * Copyright (C) 2013 Intel Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+wasPostTestScriptParsed = true;
+finishJSTest();
diff --git a/xwalk/js/js-test-pre.js b/xwalk/js/js-test-pre.js
new file mode 100644
index 00000000..3a2d181d
--- /dev/null
+++ b/xwalk/js/js-test-pre.js
@@ -0,0 +1,604 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ * Copyright (C) 2013 Intel Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// svg/dynamic-updates tests set enablePixelTesting=true, as we want to dump text + pixel results
+var description, debug, successfullyParsed, errorMessage;
+
+(function() {
+
+ function getOrCreate(id, tagName)
+ {
+ var element = document.getElementById(id);
+ if (element)
+ return element;
+
+ element = document.createElement(tagName);
+ element.id = id;
+ var refNode;
+ var parent = document.body || document.documentElement;
+ if (id == 'description')
+ refNode = getOrCreate('console', 'div');
+ else
+ refNode = parent.firstChild;
+
+ parent.insertBefore(element, refNode);
+ return element;
+ }
+
+ description = function description(msg, quiet)
+ {
+ // For MSIE 6 compatibility
+ var span = document.createElement('span');
+ if (quiet)
+ span.innerHTML = '<p>' + msg +
+ '</p><p>' +
+ 'On success, you will see no "<span class="fail">FAIL</span>" messages, ' +
+ 'followed by "<span class="pass">TEST COMPLETE</span>".' +
+ '</p>';
+ else
+ span.innerHTML = '<p>' + msg +
+ '</p><p>' +
+ 'On success, you will see a series of "<span class="pass">PASS</span>" messages, ' +
+ 'followed by "<span class="pass">TEST COMPLETE</span>".' +
+ '</p>';
+
+ var description = getOrCreate('description', 'p');
+ if (description.firstChild)
+ description.replaceChild(span, description.firstChild);
+ else
+ description.appendChild(span);
+ };
+
+ debug = function debug(msg)
+ {
+ var span = document.createElement('span');
+ getOrCreate('console', 'div').appendChild(span); // insert it first so XHTML knows the namespace
+ span.innerHTML = msg + '<br />';
+ };
+
+ var css =
+ '.pass {' +
+ 'font-weight: bold;' +
+ 'color: green;' +
+ '}' +
+ '.fail {' +
+ 'font-weight: bold;' +
+ 'color: red;' +
+ '}' +
+ '#console {' +
+ 'white-space: pre-wrap;' +
+ 'font-family: monospace;' +
+ '}';
+
+ function insertStyleSheet()
+ {
+ var styleElement = document.createElement('style');
+ styleElement.textContent = css;
+ (document.head || document.documentElement).appendChild(styleElement);
+ }
+
+ insertStyleSheet();
+
+ if (!self.isOnErrorTest) {
+ self.onerror = function(message)
+ {
+ errorMessage = message;
+ };
+ }
+
+})();
+
+function descriptionQuiet(msg) { description(msg, true); }
+
+function escapeHTML(text)
+{
+ return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\0/g, '\\0');
+}
+
+function testPassed(msg)
+{
+ debug('<span><span class="pass">PASS</span> ' + escapeHTML(msg) + '</span>');
+}
+
+function testFailed(msg)
+{
+ debug('<span><span class="fail">FAIL</span> ' + escapeHTML(msg) + '</span>');
+}
+
+function areArraysEqual(_a, _b)
+{
+ try {
+ if (_a.length !== _b.length)
+ return false;
+ for (var i = 0; i < _a.length; i++)
+ if (_a[i] !== _b[i])
+ return false;
+ } catch (ex) {
+ return false;
+ }
+ return true;
+}
+
+function isMinusZero(n)
+{
+ // the only way to tell 0 from -0 in JS is the fact that 1/-0 is
+ // -Infinity instead of Infinity
+ return n === 0 && 1 / n < 0;
+}
+
+function isResultCorrect(_actual, _expected)
+{
+ if (_expected === 0)
+ return _actual === _expected && (1 / _actual) === (1 / _expected);
+ if (_actual === _expected)
+ return true;
+ if (typeof(_expected) == 'number' && isNaN(_expected))
+ return typeof(_actual) == 'number' && isNaN(_actual);
+ if (_expected &&
+ (Object.prototype.toString.call(_expected) == Object.prototype.toString.call([])))
+ return areArraysEqual(_actual, _expected);
+ return false;
+}
+
+function stringify(v)
+{
+ if (v === 0 && 1 / v < 0)
+ return '-0';
+ else return '' + v;
+}
+
+function evalAndLog(_a, _quiet)
+{
+ if (typeof _a != 'string')
+ debug('WARN: tryAndLog() expects a string argument');
+
+ // Log first in case things go horribly wrong or this causes a sync event.
+ if (!_quiet)
+ debug(_a);
+
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ testFailed(_a + ' threw exception ' + e);
+ }
+ return _av;
+}
+
+function shouldBe(_a, _b, quiet)
+{
+ if (typeof _a != 'string' || typeof _b != 'string')
+ debug('WARN: shouldBe() expects string arguments');
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+ var _bv = eval(_b);
+
+ if (exception)
+ testFailed(_a + ' should be ' + _bv + '. Threw exception ' + exception);
+ else if (isResultCorrect(_av, _bv)) {
+ if (!quiet) {
+ testPassed(_a + ' is ' + _b);
+ }
+ } else if (typeof(_av) == typeof(_bv))
+ testFailed(_a + ' should be ' + _bv + '. Was ' + stringify(_av) + '.');
+ else
+ testFailed(_a + ' should be ' + _bv + ' (of type ' + typeof _bv + '). Was ' +
+ _av + ' (of type ' + typeof _av + ').');
+}
+
+// Execute condition every 5 milliseconds until it succeed or failureTime is reached.
+// completionHandler is executed on success, failureHandler is executed on timeout.
+function _waitForCondition(condition, failureTime, completionHandler, failureHandler)
+{
+ if (condition()) {
+ completionHandler();
+ } else if (Date.now() > failureTime) {
+ failureHandler();
+ } else {
+ setTimeout(_waitForCondition, 5, condition, failureTime, completionHandler, failureHandler);
+ }
+}
+
+function shouldBecomeEqual(_a, _b, completionHandler, timeout)
+{
+ if (typeof _a != 'string' || typeof _b != 'string')
+ debug('WARN: shouldBecomeEqual() expects string arguments');
+
+ if (timeout === undefined)
+ timeout = 500;
+
+ var condition = function() {
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+ var _bv = eval(_b);
+ if (exception)
+ testFailed(_a + ' should become ' + _bv + '. Threw exception ' + exception);
+ if (isResultCorrect(_av, _bv)) {
+ testPassed(_a + ' became ' + _b);
+ return true;
+ }
+ return false;
+ };
+ var failureTime = Date.now() + timeout;
+ var failureHandler = function() {
+ testFailed(_a + ' failed to change to ' + _b + ' in ' + (timeout / 1000) + ' seconds.');
+ completionHandler();
+ };
+ _waitForCondition(condition, failureTime, completionHandler, failureHandler);
+}
+
+function shouldBecomeEqualToString(value, reference, completionHandler, timeout)
+{
+ if (typeof value !== 'string' || typeof reference !== 'string')
+ debug('WARN: shouldBecomeEqualToString() expects string arguments');
+ var unevaledString = JSON.stringify(reference);
+ shouldBecomeEqual(value, unevaledString, completionHandler, timeout);
+}
+
+function shouldBeType(_a, _type) {
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+
+ var _typev = eval(_type);
+ if (_av instanceof _typev) {
+ testPassed(_a + ' is an instance of ' + _type);
+ } else {
+ testFailed(_a + ' is not an instance of ' + _type);
+ }
+}
+
+// Variant of shouldBe()--confirms that result of eval(_to_eval) is within
+// numeric _tolerance of numeric _target.
+function shouldBeCloseTo(_to_eval, _target, _tolerance, quiet)
+{
+ if (typeof _to_eval != 'string') {
+ testFailed('shouldBeCloseTo() requires string argument _to_eval. was type ' + typeof _to_eval);
+ return;
+ }
+ if (typeof _target != 'number') {
+ testFailed('shouldBeCloseTo() requires numeric argument _target. was type ' + typeof _target);
+ return;
+ }
+ if (typeof _tolerance != 'number') {
+ testFailed('shouldBeCloseTo() requires numeric argument _tolerance. was type ' +
+ typeof _tolerance);
+ return;
+ }
+
+ var _result;
+ try {
+ _result = eval(_to_eval);
+ } catch (e) {
+ testFailed(_to_eval + ' should be within ' + _tolerance + ' of ' +
+ _target + '. Threw exception ' + e);
+ return;
+ }
+
+ if (typeof(_result) != typeof(_target)) {
+ testFailed(_to_eval + ' should be of type ' + typeof _target +
+ ' but was of type ' + typeof _result);
+ } else if (Math.abs(_result - _target) <= _tolerance) {
+ if (!quiet) {
+ testPassed(_to_eval + ' is within ' + _tolerance + ' of ' + _target);
+ }
+ } else {
+ testFailed(_to_eval + ' should be within ' + _tolerance + ' of ' + _target +
+ '. Was ' + _result + '.');
+ }
+}
+
+function shouldNotBe(_a, _b, quiet)
+{
+ if (typeof _a != 'string' || typeof _b != 'string')
+ debug('WARN: shouldNotBe() expects string arguments');
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+ var _bv = eval(_b);
+
+ if (exception)
+ testFailed(_a + ' should not be ' + _bv + '. Threw exception ' + exception);
+ else if (!isResultCorrect(_av, _bv)) {
+ if (!quiet) {
+ testPassed(_a + ' is not ' + _b);
+ }
+ } else
+ testFailed(_a + ' should not be ' + _bv + '.');
+}
+
+function shouldBecomeDifferent(_a, _b, completionHandler, timeout)
+{
+ if (typeof _a != 'string' || typeof _b != 'string')
+ debug('WARN: shouldBecomeDifferent() expects string arguments');
+ if (timeout === undefined)
+ timeout = 500;
+
+ var condition = function() {
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+ var _bv = eval(_b);
+ if (exception)
+ testFailed(_a + ' should became not equal to ' + _bv + '. Threw exception ' + exception);
+ if (!isResultCorrect(_av, _bv)) {
+ testPassed(_a + ' became different from ' + _b);
+ return true;
+ }
+ return false;
+ };
+ var failureTime = Date.now() + timeout;
+ var failureHandler = function() {
+ testFailed(_a + ' did not become different from ' +
+ _b + ' in ' + (timeout / 1000) + ' seconds.');
+ completionHandler();
+ };
+ _waitForCondition(condition, failureTime, completionHandler, failureHandler);
+}
+
+function shouldBeTrue(_a) { shouldBe(_a, 'true'); }
+function shouldBeTrueQuiet(_a) { shouldBe(_a, 'true', true); }
+function shouldBeFalse(_a) { shouldBe(_a, 'false'); }
+function shouldBeNaN(_a) { shouldBe(_a, 'NaN'); }
+function shouldBeNull(_a) { shouldBe(_a, 'null'); }
+function shouldBeZero(_a) { shouldBe(_a, '0'); }
+
+function shouldBeEqualToString(a, b)
+{
+ if (typeof a !== 'string' || typeof b !== 'string')
+ debug('WARN: shouldBeEqualToString() expects string arguments');
+ var unevaledString = JSON.stringify(b);
+ shouldBe(a, unevaledString);
+}
+
+function shouldBeEmptyString(_a) { shouldBeEqualToString(_a, ''); }
+
+function shouldEvaluateTo(actual, expected) {
+ // A general-purpose comparator. 'actual' should be a string to be
+ // evaluated, as for shouldBe(). 'expected' may be any type and will be
+ // used without being eval'ed.
+ if (expected == null) {
+ // Do this before the object test, since null is of type 'object'.
+ shouldBeNull(actual);
+ } else if (typeof expected == 'undefined') {
+ shouldBeUndefined(actual);
+ } else if (typeof expected == 'function') {
+ // All this fuss is to avoid the string-arg warning from shouldBe().
+ try {
+ actualValue = eval(actual);
+ } catch (e) {
+ testFailed('Evaluating ' + actual + ': Threw exception ' + e);
+ return;
+ }
+ shouldBe("'" + actualValue.toString().replace(/\n/g, '') + "'",
+ "'" + expected.toString().replace(/\n/g, '') + "'");
+ } else if (typeof expected == 'object') {
+ shouldBeTrue(actual + " == '" + expected + "'");
+ } else if (typeof expected == 'string') {
+ shouldBe(actual, expected);
+ } else if (typeof expected == 'boolean') {
+ shouldBe('typeof ' + actual, "'boolean'");
+ if (expected)
+ shouldBeTrue(actual);
+ else
+ shouldBeFalse(actual);
+ } else if (typeof expected == 'number') {
+ shouldBe(actual, stringify(expected));
+ } else {
+ debug(expected + ' is unknown type ' + typeof expected);
+ shouldBeTrue(actual, "'" + expected.toString() + "'");
+ }
+}
+
+function shouldBeNonZero(_a)
+{
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+
+ if (exception)
+ testFailed(_a + ' should be non-zero. Threw exception ' + exception);
+ else if (_av != 0)
+ testPassed(_a + ' is non-zero.');
+ else
+ testFailed(_a + ' should be non-zero. Was ' + _av);
+}
+
+function shouldBeNonNull(_a)
+{
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+
+ if (exception)
+ testFailed(_a + ' should be non-null. Threw exception ' + exception);
+ else if (_av != null)
+ testPassed(_a + ' is non-null.');
+ else
+ testFailed(_a + ' should be non-null. Was ' + _av);
+}
+
+function shouldBeUndefined(_a)
+{
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+
+ if (exception)
+ testFailed(_a + ' should be undefined. Threw exception ' + exception);
+ else if (typeof _av == 'undefined')
+ testPassed(_a + ' is undefined.');
+ else
+ testFailed(_a + ' should be undefined. Was ' + _av);
+}
+
+function shouldBeDefined(_a)
+{
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+
+ if (exception)
+ testFailed(_a + ' should be defined. Threw exception ' + exception);
+ else if (_av !== undefined)
+ testPassed(_a + ' is defined.');
+ else
+ testFailed(_a + ' should be defined. Was ' + _av);
+}
+
+function shouldBeGreaterThanOrEqual(_a, _b) {
+ if (typeof _a != 'string' || typeof _b != 'string')
+ debug('WARN: shouldBeGreaterThanOrEqual expects string arguments');
+
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+ var _bv = eval(_b);
+
+ if (exception)
+ testFailed(_a + ' should be >= ' + _b + '. Threw exception ' + exception);
+ else if (typeof _av == 'undefined' || _av < _bv)
+ testFailed(_a + ' should be >= ' + _b + '. Was ' + _av + ' (of type ' + typeof _av + ').');
+ else
+ testPassed(_a + ' is >= ' + _b);
+}
+
+function shouldNotThrow(_a) {
+ try {
+ eval(_a);
+ testPassed(_a + ' did not throw exception.');
+ } catch (e) {
+ testFailed(_a + ' should not throw exception. Threw exception ' + e + '.');
+ }
+}
+
+function shouldThrow(_a, _e)
+{
+ var exception;
+ var _av;
+ try {
+ _av = eval(_a);
+ } catch (e) {
+ exception = e;
+ }
+
+ var _ev;
+ if (_e)
+ _ev = eval(_e);
+
+ if (exception) {
+ // Handle WebAPIException and WebAPIError.
+ if (exception instanceof tizen.WebAPIException || exception instanceof tizen.WebAPIError) {
+ exception = exception.name;
+ _ev = _ev.name;
+ }
+
+ if (typeof _e == 'undefined' || exception == _ev)
+ testPassed(_a + ' threw exception ' + exception + '.');
+ else
+ testFailed(_a + ' should throw ' + (typeof _e == 'undefined' ? 'an exception' : _ev) +
+ '. Threw exception ' + exception + '.');
+ } else if (typeof _av == 'undefined') {
+ testFailed(_a + ' should throw ' + (typeof _e == 'undefined' ? 'an exception' : _ev) +
+ '. Was undefined.');
+ } else {
+ testFailed(_a + ' should throw ' + (typeof _e == 'undefined' ? 'an exception' : _ev) +
+ '. Was ' + _av + '.');
+ }
+}
+
+function shouldHaveHadError(message)
+{
+ if (errorMessage) {
+ if (!message)
+ testPassed('Got expected error');
+ else if (errorMessage.indexOf(message) !== -1)
+ testPassed("Got expected error: '" + message + "'");
+ else
+ testFailed("Unexpexted error '" + message + "'");
+ } else
+ testFailed('Missing expexted error');
+ errorMessage = undefined;
+}
+
+function isSuccessfullyParsed()
+{
+ // FIXME: Remove this and only report unexpected syntax errors.
+ if (!errorMessage)
+ successfullyParsed = true;
+ shouldBeTrue('successfullyParsed');
+ debug('<br /><span class="pass">TEST COMPLETE</span>');
+}
+
+function finishJSTest()
+{
+ wasFinishJSTestCalled = true;
+ if (!self.wasPostTestScriptParsed)
+ return;
+ isSuccessfullyParsed();
+}
diff --git a/xwalk/vehicle.cc b/xwalk/vehicle.cc
new file mode 100644
index 00000000..84a41b02
--- /dev/null
+++ b/xwalk/vehicle.cc
@@ -0,0 +1,816 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "vehicle.h"
+
+#include <abstractpropertytype.h>
+#include <debugout.h>
+#include <gio/gio.h>
+#include <glib.h>
+#include <listplusplus.h>
+#include <picojson.h>
+#include <superptr.hpp>
+
+#include <algorithm>
+#include <map>
+#include <memory>
+
+#include "common/extension.h"
+
+common::Instance* Vehicle::CallbackInfo::instance = nullptr;
+
+namespace {
+const char* amb_service = "org.automotive.message.broker";
+const char* prop_iface = "org.freedesktop.DBus.Properties";
+
+const char* vehicle_error_permission_denied = "permission_denied";
+const char* vehicle_error_invalid_operation = "invalid_operation";
+const char* vehicle_error_timeout = "timeout";
+const char* vehicle_error_invalid_zone = "invalid_zone";
+const char* vehicle_error_unknown = "unknown";
+
+picojson::value::array AmbZoneToW3C(const std::vector<int>& amb_zones);
+picojson::value::array AmbZoneToW3C(int amb_zone);
+
+template<typename T> unique_ptr<T> make_unique(T* t) {
+ return unique_ptr<T>(t);
+}
+
+void PostReply(Vehicle::CallbackInfo* cb_obj, picojson::value object) {
+ DebugOut() << "Posting reply" << endl;
+ picojson::object msg;
+
+ msg["method"] = picojson::value(cb_obj->method);
+ msg["asyncCallId"] = picojson::value(cb_obj->callback_id);
+ msg["value"] = object;
+
+ std::string message = picojson::value(msg).serialize();
+
+ DebugOut() << "Reply message: " << message << endl;
+
+ cb_obj->instance->PostMessage(message.c_str());
+}
+
+void PostError(Vehicle::CallbackInfo* cb_obj, const std::string& error) {
+ picojson::object msg;
+ msg["method"] = picojson::value(cb_obj->method);
+ msg["error"] = picojson::value(true);
+ msg["value"] = picojson::value(error);
+ msg["asyncCallId"] =
+ picojson::value(static_cast<double>(cb_obj->callback_id));
+
+ std::string message = picojson::value(msg).serialize();
+
+ DebugOut() << "Error Reply message: " << message << endl;
+
+ cb_obj->instance->PostMessage(message.c_str());
+}
+
+picojson::value GetBasic(GVariant* value) {
+ std::string type = g_variant_get_type_string(value);
+ picojson::value v;
+
+ if (type == "i") {
+ int tempVal = GVS<int>::value(value);
+ v = picojson::value(static_cast<double>(tempVal));
+ } else if (type == "d") {
+ v = picojson::value(GVS<double>::value(value));
+ } else if (type == "q") {
+ v = picojson::value(static_cast<double>(GVS<uint16_t>::value(value)));
+ } else if (type == "n") {
+ v = picojson::value(static_cast<double>(GVS<int16_t>::value(value)));
+ } else if (type == "y") {
+ v = picojson::value(static_cast<double>(GVS<char>::value(value)));
+ } else if (type == "u") {
+ v = picojson::value(static_cast<double>(GVS<uint32_t>::value(value)));
+ } else if (type == "x") {
+ v = picojson::value(static_cast<double>(GVS<int64_t>::value(value)));
+ } else if (type == "t") {
+ v = picojson::value(static_cast<double>(GVS<uint64_t>::value(value)));
+ } else if (type == "b") {
+ v = picojson::value(GVS<bool>::value(value));
+ } else if (type == "s") {
+ v = picojson::value(g_variant_get_string(value, nullptr));
+ } else {
+ DebugOut(DebugOut::Error) << "Unsupported type: " << type << endl;
+ }
+
+ return v;
+}
+
+GVariant* GetBasic(picojson::value value, const std::string& type) {
+ GVariant* v = nullptr;
+
+ if (type == "i") {
+ v = g_variant_new(type.c_str(), (int32_t)value.get<double>());
+ } else if (type == "d") {
+ v = g_variant_new(type.c_str(), value.get<double>());
+ } else if (type == "q") {
+ v = g_variant_new(type.c_str(), (uint16_t)value.get<double>());
+ } else if (type == "n") {
+ v = g_variant_new(type.c_str(), (int16_t)value.get<double>());
+ } else if (type == "u") {
+ v = g_variant_new(type.c_str(), (uint32_t)value.get<double>());
+ } else if (type == "x") {
+ v = g_variant_new(type.c_str(), (int64_t)value.get<double>());
+ } else if (type == "t") {
+ v = g_variant_new(type.c_str(), (uint64_t)value.get<double>());
+ } else if (type == "b") {
+ v = g_variant_new(type.c_str(), value.get<bool>());
+ } else if (type == "s") {
+ v = g_variant_new(type.c_str(), value.get<std::string>().c_str());
+ } else {
+ DebugOut(DebugOut::Error) << "Unsupported type: " << type << endl;
+ }
+
+ return v;
+}
+
+void AsyncGetCallback(GObject* source, GAsyncResult* res, gpointer user_data) {
+ debugOut("GetAll() method call completed");
+
+ Vehicle::CallbackInfo *cb_obj =
+ static_cast<Vehicle::CallbackInfo*>(user_data);
+
+ auto cb_obj_ptr = make_unique(cb_obj);
+
+ if (!cb_obj_ptr) {
+ debugOut("invalid cb object");
+ return;
+ }
+
+ GError* error = nullptr;
+
+ auto property_map = amb::make_super(
+ g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut() << "failed to call GetAll on interface: "
+ << error_ptr->message << endl;
+ PostError(cb_obj_ptr.get(), "unknown");
+ return;
+ }
+
+ GVariantIter* iter;
+ gchar* key;
+ GVariant* value;
+
+ g_variant_get(property_map.get(), "(a{sv})", &iter);
+
+ auto iter_ptr = amb::make_super(iter);
+
+ picojson::value::object object;
+
+ while (g_variant_iter_next(iter_ptr.get(), "{sv}", &key, &value)) {
+ auto key_ptr = amb::make_super(key);
+ auto value_ptr = amb::make_super(value);
+
+ std::string temp_key = key_ptr.get();
+
+ std::transform(temp_key.begin(), temp_key.begin() + 1,
+ temp_key.begin(), ::tolower);
+
+ object[temp_key] = GetBasic(value_ptr.get());
+
+ if (temp_key == "zone") {
+ object[temp_key] =
+ picojson::value(AmbZoneToW3C(object[temp_key].get<double>()));
+ }
+ }
+
+ PostReply(cb_obj_ptr.get(), picojson::value(object));
+}
+
+picojson::value::array AmbZoneToW3C(int amb_zone) {
+ picojson::value::array z;
+
+ if (amb_zone & Zone::Left) {
+ z.push_back(picojson::value("left"));
+ }
+ if (amb_zone & Zone::Right) {
+ z.push_back(picojson::value("right"));
+ }
+ if (amb_zone & Zone::Front) {
+ z.push_back(picojson::value("front"));
+ }
+ if (amb_zone & Zone::Middle) {
+ z.push_back(picojson::value("middle"));
+ }
+ if (amb_zone & Zone::Center) {
+ z.push_back(picojson::value("center"));
+ }
+ if (amb_zone & Zone::Rear) {
+ z.push_back(picojson::value("rear"));
+ }
+
+ return z;
+}
+
+picojson::value::array AmbZoneToW3C(const std::vector<int>& amb_zones) {
+ picojson::value::array zones;
+
+ for (auto i : amb_zones) {
+ zones.push_back(picojson::value(AmbZoneToW3C(i)));
+ }
+
+ return zones;
+}
+
+static void SignalCallback(GDBusConnection* connection,
+ const gchar*,
+ const gchar* object_path,
+ const gchar*,
+ const gchar*,
+ GVariant* parameters,
+ gpointer user_data) {
+ DebugOut() << "Got signal" << endl;
+ std::vector<ObjectZone*> amb_objects_ =
+ *(static_cast<std::vector<ObjectZone*>*>(user_data));
+
+ GVariant* value_array;
+ GVariant* iface_name;
+ GVariant* invalidated;
+
+ g_variant_get(parameters,
+ "(&s@a{sv}^a&s)",
+ &iface_name,
+ &value_array,
+ &invalidated);
+
+ GVariantIter iter;
+
+ g_variant_iter_init(&iter, value_array);
+
+ ObjectZone* object = nullptr;
+
+ for (auto i : amb_objects_) {
+ if (i->object_path == object_path) {
+ object = i;
+ }
+ }
+
+ if (!object) {
+ DebugOut(DebugOut::Error) << "received signal for which "
+ << "we have no corresponding amb object" << endl;
+ return;
+ }
+
+ char* key;
+ GVariant* value;
+
+ while (g_variant_iter_next(&iter, "{sv}", &key, &value)) {
+ auto key_ptr = amb::make_super(key);
+ auto value_ptr = amb::make_super(value);
+
+ std::string tempkey = key_ptr.get();
+
+ std::transform(tempkey.begin(), tempkey.begin() + 1, tempkey.begin(),
+ ::tolower);
+
+ object->value[tempkey] = GetBasic(value_ptr.get());
+
+ if (tempkey == "zone") {
+ object->value[tempkey] =
+ picojson::value(AmbZoneToW3C(object->value[tempkey].get<double>()));
+ }
+ }
+
+ object->value["interfaceName"] = picojson::value(object->name);
+
+ Vehicle::CallbackInfo call;
+ call.method = "subscribe";
+ call.callback_id = -1;
+
+ PostReply(&call, picojson::value(object->value));
+}
+
+} // namespace
+
+Vehicle::Vehicle(common::Instance* instance)
+ : main_loop_(g_main_loop_new(0, FALSE)),
+ thread_(Vehicle::SetupMainloop, this),
+ instance_(instance),
+ manager_proxy_(nullptr){
+ CallbackInfo::instance = instance_;
+ thread_.detach();
+
+ GError* error = nullptr;
+
+ dbus_connection_ = amb::make_super(g_bus_get_sync(G_BUS_TYPE_SYSTEM,
+ nullptr,
+ &error));
+
+ auto errorPtr = amb::make_super(error);
+ if (errorPtr) {
+ DebugOut(DebugOut::Error) << "getting bus: "
+ << errorPtr->message << std::endl;
+ }
+
+ GError* error_manager = nullptr;
+ manager_proxy_ = amb::make_super(g_dbus_proxy_new_sync(dbus_connection_.get(),
+ G_DBUS_PROXY_FLAGS_NONE, NULL,
+ amb_service,
+ "/",
+ "org.automotive.Manager",
+ NULL,
+ &error));
+
+ auto error_ptr = amb::make_super(error_manager);
+
+ if (error_ptr) {
+ 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() {
+ g_main_loop_quit(main_loop_);
+ g_main_loop_unref(main_loop_);
+
+ for (auto i : amb_objects_) {
+ delete i;
+ }
+}
+
+void Vehicle::Get(const std::string& property, Zone::Type zone, double ret_id) {
+ CallbackInfo* data = new CallbackInfo;
+
+ data->callback_id = ret_id;
+ data->method = "get";
+ data->instance = instance_;
+
+
+ std::string find_error;
+ std::string obj_pstr = FindProperty(property, zone, find_error);
+
+ if (obj_pstr.empty()) {
+ debugOut("could not find property " + property);
+ PostError(data, find_error);
+ return;
+ }
+
+ GError* error = nullptr;
+
+ auto properties_proxy = amb::make_super(
+ g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE, NULL,
+ amb_service,
+ obj_pstr.c_str(),
+ prop_iface,
+ NULL,
+ &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut(DebugOut::Error) << "failed to get properties proxy: " << error->message << endl;
+ return;
+ }
+
+ std::string interfaceName = "org.automotive." + property;
+
+ g_dbus_proxy_call(properties_proxy.get(),
+ "GetAll",
+ g_variant_new("(s)", interfaceName.c_str()),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL,
+ AsyncGetCallback, data);
+}
+
+void Vehicle::GetZones(const std::string& object_name, double ret_id) {
+ GError* error(nullptr);
+
+ auto zones_variant = amb::make_super(
+ g_dbus_proxy_call_sync(manager_proxy_.get(),
+ "ZonesForObjectName",
+ g_variant_new("(s)",
+ object_name.c_str()),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut() << "error calling ZonesForObjectName: "
+ << error_ptr->message << endl;
+ return;
+ }
+
+ if (!zones_variant) {
+ DebugOut() << "Invalid response from ZonesForObjectName " << endl;
+ return;
+ }
+
+ GVariantIter* iter(nullptr);
+
+ g_variant_get(zones_variant.get(), "(ai)", &iter);
+
+ if (!iter) {
+ DebugOut() << "No zones for object " << object_name << endl;
+ return;
+ }
+
+ auto iter_ptr = amb::make_super(iter);
+
+ std::vector<int> zones_array;
+
+ GVariant* value(nullptr);
+
+ while ((value = g_variant_iter_next_value(iter_ptr.get()))) {
+ auto value_ptr = amb::make_super(value);
+ int v = 0;
+
+ g_variant_get(value_ptr.get(), "i", &v);
+ zones_array.push_back(v);
+ }
+
+ picojson::value::array w3c_zones = AmbZoneToW3C(zones_array);
+
+ CallbackInfo* data = new CallbackInfo;
+
+ data->callback_id = ret_id;
+ data->method = "zones";
+ data->instance = instance_;
+
+ PostReply(data, picojson::value(w3c_zones));
+}
+
+std::string Vehicle::FindProperty(const std::string& object_name, int zone, std::string& error_str) {
+ GError* error(nullptr);
+
+ auto object_path_variant = amb::make_super(
+ g_dbus_proxy_call_sync(manager_proxy_.get(),
+ "FindObjectForZone",
+ g_variant_new("(si)",
+ object_name.c_str(),
+ zone),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut(DebugOut::Error) << "error calling FindObjectForZone: "
+ << error_ptr->message << endl;
+
+ DebugOut() << "Could not find object in zone: " << zone << endl;
+ error_str = vehicle_error_invalid_operation;
+ return "";
+ }
+
+ if (!object_path_variant) {
+ DebugOut() << "Could not find object in zone: " << zone << endl;
+ error_str = vehicle_error_invalid_operation;
+ return "";
+ }
+
+ gchar* obj_path = nullptr;
+ g_variant_get(object_path_variant.get(), "(o)", &obj_path);
+
+ auto obj_path_ptr = amb::make_super(obj_path);
+
+ DebugOut() << "FindObjectForZone() returned object path: "
+ << obj_path_ptr.get() << endl;
+
+ return obj_path;
+}
+
+void Vehicle::SetupMainloop(void* data) {
+ Vehicle* self = reinterpret_cast<Vehicle*>(data);
+ GMainContext* ctx = g_main_context_default();
+
+ g_main_context_push_thread_default(ctx);
+ g_main_loop_run(self->main_loop_);
+}
+
+
+void Vehicle::Subscribe(const std::string& object_name, Zone::Type zone) {
+ std::string find_error;
+ std::string object_path = FindProperty(object_name, zone, find_error);
+
+ if (object_path.empty()) {
+ DebugOut() << "Error FindProperty failed for " << object_name;
+ return;
+ }
+
+ bool already_subscribed = false;
+
+ for (auto i : amb_objects_) {
+ if (i->object_path == object_path) {
+ already_subscribed = true;
+ break;
+ }
+ }
+
+ if (!already_subscribed) {
+ GError* proxy_error = nullptr;
+
+ auto properties_proxy =
+ amb::make_super(g_dbus_proxy_new_sync(dbus_connection_.get(),
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ amb_service,
+ object_path.c_str(),
+ prop_iface,
+ NULL,
+ &proxy_error));
+
+ auto proxy_error_ptr = amb::make_super(proxy_error);
+
+ if (proxy_error_ptr) {
+ DebugOut() << "error creating properties proxy: "
+ << proxy_error_ptr->message << endl;
+ }
+
+ std::string interface_name = "org.automotive." + object_name;
+
+ GError* get_all_error = nullptr;
+
+ GVariant* property_map =
+ g_dbus_proxy_call_sync(properties_proxy.get(),
+ "GetAll",
+ g_variant_new("(s)", interface_name.c_str()),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL,
+ &get_all_error);
+
+ auto get_all_error_ptr = amb::make_super(get_all_error);
+
+ if (get_all_error_ptr) {
+ DebugOut(DebugOut::Error) << "failed to call GetAll on interface "
+ << interface_name << " "
+ << get_all_error_ptr->message << endl;
+ return;
+ }
+
+ GVariantIter* iter;
+
+ g_variant_get(property_map, "(a{sv})", &iter);
+
+ auto iter_ptr = amb::make_super(iter);
+
+ char* key;
+ GVariant* value;
+
+ ObjectZone* object = new ObjectZone(object_name, zone, object_path);
+
+ while (g_variant_iter_next(iter_ptr.get(), "{sv}", &key, &value)) {
+ auto key_ptr = amb::make_super(key);
+ auto value_ptr = amb::make_super(value);
+
+ std::string tempkey = key_ptr.get();
+
+ std::transform(tempkey.begin(), tempkey.begin() + 1, tempkey.begin(),
+ ::tolower);
+
+ object->value[tempkey] = GetBasic(value_ptr.get());
+ }
+
+ object->handle =
+ g_dbus_connection_signal_subscribe(dbus_connection_.get(),
+ amb_service,
+ prop_iface,
+ "PropertiesChanged",
+ object_path.c_str(), NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ SignalCallback, &amb_objects_,
+ NULL);
+
+ amb_objects_.push_back(object);
+ } else {
+ DebugOut() << "Already subscribed to " << object_name << endl;
+ }
+}
+
+
+void Vehicle::Unsubscribe(const std::string& property, Zone::Type zone) {
+ std::vector<ObjectZone*> to_clean;
+
+ for (auto obj : amb_objects_) {
+ if (obj->name == property && obj->zone == zone) {
+ g_dbus_connection_signal_unsubscribe(dbus_connection_.get(),
+ obj->handle);
+ to_clean.push_back(obj);
+ }
+ }
+
+ for (auto obj : to_clean) {
+ removeOne(&amb_objects_, obj);
+ delete obj;
+ }
+}
+
+
+void Vehicle::Set(const std::string &object_name, picojson::object value,
+ Zone::Type zone, double ret_id)
+{
+ std::string find_error;
+ std::string object_path = FindProperty(object_name, zone, find_error);
+
+ Vehicle::CallbackInfo callback;
+ callback.callback_id = ret_id;
+ callback.method = "set";
+ callback.instance = instance_;
+
+ if (object_path.empty() || !find_error.empty()) {
+ DebugOut(DebugOut::Error) << "Object not found. Check object Name and zone."
+ << object_name << std::endl;
+ PostError(&callback, find_error);
+ return;
+ }
+
+ GError* proxy_error = nullptr;
+
+ auto properties_proxy =
+ amb::make_super(g_dbus_proxy_new_sync(dbus_connection_.get(),
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ amb_service,
+ object_path.c_str(),
+ prop_iface,
+ NULL,
+ &proxy_error));
+
+ auto proxy_error_ptr = amb::make_super(proxy_error);
+
+ if (proxy_error_ptr) {
+ DebugOut(DebugOut::Error) << "Error creating property proxy for " << object_path << std::endl;
+ PostError(&callback, vehicle_error_unknown);
+ return;
+ }
+
+ std::string interface_name = "org.automotive." + object_name;
+
+ for (auto itr : value) {
+ GError* err = nullptr;
+ std::string attribute = itr.first;
+
+ std::transform(attribute.begin(), attribute.begin()+1, attribute.begin(), ::toupper);
+
+ auto var_value =
+ amb::make_super(g_dbus_proxy_call_sync(properties_proxy.get(),
+ "Get",
+ g_variant_new("(ss)",
+ interface_name.c_str(),
+ attribute.c_str()),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &err));
+ auto err_ptr = amb::make_super(err);
+ if (err_ptr || !var_value) {
+ DebugOut(DebugOut::Error) << "Error getting initial property signature type: " <<
+ err_ptr->message << endl;
+ PostError(&callback, vehicle_error_unknown);
+ return;
+ }
+
+ GVariant* get_value = nullptr;
+ g_variant_get(var_value.get(), "(v)", &get_value);
+
+ auto get_value_ptr = amb::make_super(get_value);
+
+ if (!get_value_ptr) {
+ DebugOut(DebugOut::Error) << "Error getting variant value." << endl;
+ PostError(&callback, vehicle_error_unknown);
+ return;
+ }
+
+ GVariant* v = GetBasic(itr.second, g_variant_get_type_string(get_value_ptr.get()));
+
+ if (!v) {
+ DebugOut(DebugOut::Error) << "Error converting value to GVariant" << endl;
+ PostError(&callback, vehicle_error_unknown);
+ return;
+ }
+
+ GError* set_error = nullptr;
+
+ DebugOut() << "Trying to set " << attribute << " to " << itr.second.serialize() << endl;
+
+ g_dbus_proxy_call_sync(properties_proxy.get(), "Set",
+ g_variant_new("(ssv)",
+ interface_name.c_str(),
+ attribute.c_str(),
+ v),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &set_error);
+
+ auto set_error_ptr = amb::make_super(set_error);
+
+ if (set_error_ptr) {
+ DebugOut(DebugOut::Error) << "error setting property:" << set_error_ptr->message << endl;
+
+ if(set_error_ptr->code == G_IO_ERROR_PERMISSION_DENIED
+ || std::string(g_dbus_error_get_remote_error(set_error_ptr.get())) == "org.freedesktop.DBus.Error.AccessDenied")
+ {
+ DebugOut(DebugOut::Error) << "permission denied" << endl;
+ PostError(&callback, vehicle_error_permission_denied);
+ return;
+ }
+ PostError(&callback, vehicle_error_unknown);
+ return;
+ }
+ }
+
+ PostReply(&callback, picojson::value());
+}
+
+void Vehicle::Supported(const string& object_name, double ret_id)
+{
+ Vehicle::CallbackInfo callback;
+ callback.callback_id = ret_id;
+ callback.method = "supported";
+ callback.instance = instance_;
+
+ GError* error(nullptr);
+
+ auto object_path_variant = amb::make_super(
+ g_dbus_proxy_call_sync(manager_proxy_.get(),
+ "FindObject",
+ g_variant_new("(s)", object_name.c_str()),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut(DebugOut::Error) << "error calling FindObjectForZone: "
+ << error_ptr->message << endl;
+
+ DebugOut() << "Could not find object for: " << object_name << endl;
+ PostReply(&callback, picojson::value(false));
+ return;
+ }
+
+ if (!object_path_variant) {
+ DebugOut() << "Could not find object for: " << object_name << endl;
+ PostReply(&callback, picojson::value(false));
+ return;
+ }
+
+ PostReply(&callback, picojson::value(true));
+}
+
+bool Vehicle::AvailableForRetrieval(const string &objectName, const string &attName)
+{
+ GError* error = nullptr;
+
+ auto supportedVariant = amb::make_super(
+ g_dbus_proxy_call_sync(manager_proxy_.get(),
+ "SupportsProperty",
+ g_variant_new("(ss)", objectName.c_str(), attName.c_str()),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
+
+ auto error_ptr = amb::make_super(error);
+
+ if (error_ptr) {
+ DebugOut(DebugOut::Error) << "error calling SupportsProperty: "
+ << error_ptr->message << endl;
+
+ DebugOut() << "Could not find object for: " << objectName << endl;
+ return false;
+ }
+
+ bool supported = false;
+ g_variant_get(supportedVariant.get(), "(b)", &supported);
+
+ return supported;
+}
diff --git a/xwalk/vehicle.h b/xwalk/vehicle.h
new file mode 100644
index 00000000..877f031f
--- /dev/null
+++ b/xwalk/vehicle.h
@@ -0,0 +1,90 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef VEHICLE_VEHICLE_H_
+#define VEHICLE_VEHICLE_H_
+
+#include <abstractpropertytype.h>
+#include <gio/gio.h>
+#include <glib.h>
+#include <picojson.h>
+#include <superptr.hpp>
+
+#include <string>
+#include <thread> // NOLINT
+#include <vector>
+
+
+namespace common {
+
+class Instance;
+
+} // namespace common
+
+struct ObjectZone {
+ ObjectZone():zone(0) {}
+
+ ObjectZone(const std::string& o, int z, const std::string& op)
+ : name(o), zone(z), object_path(op) {}
+
+ ObjectZone(const ObjectZone& other)
+ : name(other.name), zone(other.zone), object_path(other.object_path) {}
+
+ std::string name;
+ int zone;
+ uint handle;
+
+ std::string object_path;
+
+ bool operator ==(const ObjectZone& other) const {
+ return object_path == other.object_path;
+ }
+
+ picojson::object value;
+};
+
+struct ObjectZoneCompare {
+ bool operator() (const ObjectZone& lhs, const ObjectZone& rhs) {
+ return (lhs.name == rhs.name && lhs.zone < rhs.zone) ||
+ (lhs.name < rhs.name);
+ }
+};
+
+typedef std::function<void (picojson::object)> GetReply;
+typedef std::function<void (std::string)> ErrorReply;
+
+class Vehicle {
+ public:
+ struct CallbackInfo {
+ std::string method;
+ static common::Instance* instance;
+ double callback_id;
+ };
+
+ explicit Vehicle(common::Instance* i);
+ ~Vehicle();
+
+ void Get(const std::string& property, Zone::Type zone, double ret_id);
+ void GetZones(const std::string& property, double ret_id);
+ void Subscribe(const std::string& property, Zone::Type zone);
+ void Unsubscribe(const std::string& property, Zone::Type zone);
+ void Set(const std::string& property, picojson::object value, Zone::Type zone, double ret_id);
+ void Supported(const std::string& property, double ret_id);
+ bool AvailableForRetrieval(const std::string& objectName, const std::string& attName);
+
+ private:
+ std::string FindProperty(const std::string& object_name, int zone, string &error_str);
+
+ static void SetupMainloop(void* data);
+ GMainLoop* main_loop_;
+ std::thread thread_;
+ common::Instance* instance_;
+
+ std::vector<ObjectZone*> amb_objects_;
+
+ amb::super_ptr<GDBusProxy> manager_proxy_;
+ amb::super_ptr<GDBusConnection> dbus_connection_;
+};
+
+#endif // VEHICLE_VEHICLE_H_
diff --git a/xwalk/vehicle.html b/xwalk/vehicle.html
new file mode 100644
index 00000000..cd875030
--- /dev/null
+++ b/xwalk/vehicle.html
@@ -0,0 +1,102 @@
+<!DOCTYPE text/html>
+<html>
+<h1>Hello,Vehicle API!</h1>
+
+<body>
+<pre id="console"></pre>
+<script src="js/js-test-pre.js"></script>
+<script>
+
+vehicle = navigator.vehicle;
+
+function get(objName) {
+
+ if(!vehicle[objName].get) {
+ debug("Error no get() method for " + objName);
+ return;
+ }
+
+ getSuccess = function(data) {
+ try {
+ debug("get " + objName + ": " + JSON.stringify(data));
+ } catch(error) {
+ debug("error " + error.message);
+ }
+ }
+
+ getError = function(error) {
+ debug("error getting " + objName + ": " + error.message);
+ }
+
+ var zones = vehicle[objName].zones;
+
+ if(zones.length !== 0)
+ {
+ for(var zone in zones)
+ {
+ vehicle[objName].get(zone).then(getSuccess, getError);
+ }
+ }
+ else
+ {
+ vehicle[objName].get().then(getSuccess, getError);
+ }
+}
+
+debug("testing zones...");
+var zone = new Zone;
+
+debug('Driver zone: ' + zone.driver.value);
+
+var zone1 = new Zone(["Front", "Left"]);
+var zone2 = new Zone(["Left", "Front"]);
+var zone3 = new Zone(["Front", "Right"]);
+var zone4 = new Zone([]);
+
+debug("zone1 == zone2 ? " + zone1.equals(zone2));
+debug("zone1 == zone3 ? " + zone1.equals(zone3));
+debug("zone1 == zone1 ? " + zone1.equals(zone1));
+debug("zone1 == empty zone ? " + zone1.equals(zone4));
+
+
+debug("testing supported");
+debug("vehicle speed supported? " + vehicle.vehicleSpeed.supported);
+
+debug("testing subscribe()");
+
+var subReplies = 0;
+var handle = vehicle.vehicleSpeed.subscribe(function(data) {
+ console.log("got subscribe callback");
+ debug("Vehicle speed changed: " + data.speed);
+ subReplies++;
+
+ if (subReplies === 5) {
+ debug("unsubscribing");
+ vehicle.vehicleSpeed.unsubscribe(handle);
+ }
+});
+
+debug("test invalid zone error");
+vehicle.vehicleSpeed.get("invalidzone").then(function() { },
+ function(error) { debug("Invalid zone: " + error.message); });
+
+///test set()
+debug("testing set()");
+
+vehicle.lightStatus.set({"fog" : false}).then(function() {
+ debug("set success!");
+}, function(error) {
+ debug("set fail! " + error.message);
+});
+
+for(var propName in vehicle) {
+ if(typeof(vehicle[propName]) != "undefined") {
+ debug("vehicle." + propName);
+ get(propName);
+ }
+}
+
+</script>
+<script src="js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/xwalk/vehicle_api.js b/xwalk/vehicle_api.js
new file mode 100644
index 00000000..ec14a9c3
--- /dev/null
+++ b/xwalk/vehicle_api.js
@@ -0,0 +1,382 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var next_async_call_id = 0;
+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;
+
+ extension.postMessage(JSON.stringify(msg));
+}
+
+function vehicleInterfaceCommonContructor(obj, attname) {
+ obj.attributeName = attname;
+
+ var msg = {};
+ msg['method'] = 'zones';
+ msg['name'] = obj.attributeName;
+
+ obj._zones = new Zone;
+ obj._supported = false;
+
+ var call = new AsyncCall(function(data) {
+ obj._zones = data;
+ });
+
+ makeCall(call, msg);
+
+ var supportedMessage = {};
+ supportedMessage['method'] = 'supported';
+ supportedMessage['name'] = obj.attributeName;
+
+ var supportedCall = new AsyncCall(function(data) {
+ obj._supported = data;
+ });
+
+ makeCall(supportedCall, supportedMessage);
+
+ Object.defineProperty(obj, 'zones', { get: function() { return obj._zones } });
+ Object.defineProperty(obj, 'supported', { get: function() { return obj._supported; } });
+}
+
+function VehicleInterface(attname) {
+ vehicleInterfaceCommonContructor(this, attname);
+}
+
+VehicleInterface.prototype.get = function(zone) {
+ var msg = {};
+ msg['method'] = 'get';
+ msg['name'] = this.attributeName;
+ msg['zone'] = zone;
+
+ return createPromise(msg);
+};
+
+VehicleInterface.prototype.availableForRetrieval = function(attName) {
+ return isAvailable(this, attName);
+}
+
+VehicleInterface.prototype.availabilityChangedListener = function(callback) {
+ if(this.changedListenerCount) {
+ this.changedListenerCount++;
+ }
+ else {
+ this.changedListenerCount = 0;
+ }
+ return this.changedListenerCount;
+}
+
+VehicleInterface.prototype.removeAvailabilityChangedListener = function(handle) {
+
+}
+
+function VehicleSignalInterface(attname) {
+ vehicleInterfaceCommonContructor(this, attname);
+}
+
+VehicleSignalInterface.prototype = VehicleInterface.prototype;
+
+VehicleSignalInterface.prototype.subscribe = function(callback, zone) {
+ if (!zone) zone = new Zone();
+
+ var msg = {};
+ msg['method'] = 'subscribe';
+ msg['name'] = this.attributeName;
+ msg['zone'] = zone;
+
+ extension.postMessage(JSON.stringify(msg));
+
+ msg['callback'] = callback;
+
+ subscriptions.push(msg);
+
+ return subscriptions.length - 1;
+};
+
+VehicleSignalInterface.prototype.unsubscribe = function(handle) {
+ var obj = subscriptions[handle];
+ subscriptions.splice(handle, 1);
+
+ var unsubscribe = true;
+
+ 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 (unsubscribe) {
+ var msg = {};
+ msg['method'] = 'unsubscribe';
+ msg['name'] = this.attributeName;
+ msg['zone'] = obj.zone;
+
+ 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;
+
+ return createPromise(msg);
+}
+
+VehicleSignalInterface.prototype.availableForSubscription = function(attName) {
+ return isAvailable(this, attName);
+}
+
+VehicleSignalInterface.prototype.availableForSetting = function(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";
+ }
+}
+
+function AsyncCall(resolve, 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);
+ });
+
+ msg.asyncCallId = next_async_call_id;
+ extension.postMessage(JSON.stringify(msg));
+ ++next_async_call_id;
+
+ return promise;
+}
+
+window.Zone = function(zone) {
+ this.value = zone ? zone : [];
+
+ Object.defineProperty(this, 'driver',
+ { enumerable: false, get: function() {
+ return new Zone(['Front', 'Left']);
+ } });
+};
+
+window.Zone.prototype.equals = function(zone) {
+ var is_equal = true;
+
+ for (var i = 0; i < zone.value.length; i++) {
+ is_equal = is_equal && this.value.indexOf(zone.value[i]) !== -1;
+ }
+
+ for (var i = 0; i < this.value.length; i++) {
+ is_equal = is_equal && zone.value.indexOf(this.value[i]) !== -1;
+ }
+
+ return is_equal;
+};
+
+function _defineVehicleProperty(obj, 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) });
+}
+
+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;
+ case 'vehicleSupportedAttributes':
+ handleVehicleSupported(msg);
+ break;
+ default:
+ break;
+ }
+ } 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);
+ }
+ cbobj.resolve(msg.value);
+ }
+
+ delete async_calls[msg.asyncCallId];
+}
+
+function handleZonesReply(msg) {
+ var cbobj = async_calls[msg.asyncCallId];
+
+ if (cbobj)
+ cbobj.resolve(new Zone(msg.value));
+}
+
+function handleSupportedReply(msg) {
+ var cbobj = async_calls[msg.asyncCallId];
+
+ 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);
+ }
+ }
+}
+
+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');
+_defineVehicleSignalProperty(exports, 'powertrainTorque');
+_defineVehicleSignalProperty(exports, 'acceleratorPedalPosition');
+_defineVehicleSignalProperty(exports, 'throttlePosition');
+_defineVehicleSignalProperty(exports, 'transmission');
+_defineVehicleSignalProperty(exports, 'cruiseControlStatus');
+_defineVehicleSignalProperty(exports, 'lightStatus');
+_defineVehicleSignalProperty(exports, 'horn');
+_defineVehicleSignalProperty(exports, 'chime');
+_defineVehicleSignalProperty(exports, 'fuel');
+_defineVehicleSignalProperty(exports, 'engineOil');
+_defineVehicleSignalProperty(exports, 'acceleration');
+_defineVehicleSignalProperty(exports, 'engineCoolant');
+_defineVehicleSignalProperty(exports, 'steeringWheel');
+_defineVehicleSignalProperty(exports, 'wheelTick');
+_defineVehicleSignalProperty(exports, 'ignitionTime');
+_defineVehicleSignalProperty(exports, 'yawRate');
+_defineVehicleSignalProperty(exports, 'brakeOperation');
+_defineVehicleSignalProperty(exports, 'buttonEvent');
+_defineVehicleSignalProperty(exports, 'nightMode');
+_defineVehicleSignalProperty(exports, 'drivingMode');
+
+/// Maintenance attributes:
+_defineVehicleSignalProperty(exports, 'odometer');
+_defineVehicleSignalProperty(exports, 'transmissionOil');
+_defineVehicleSignalProperty(exports, 'transmissionClutch');
+_defineVehicleSignalProperty(exports, 'brakeMaintenance');
+_defineVehicleSignalProperty(exports, 'washerFluid');
+_defineVehicleSignalProperty(exports, 'malfunctionIndicator');
+_defineVehicleSignalProperty(exports, 'batteryStatus');
+_defineVehicleSignalProperty(exports, 'tire');
+_defineVehicleSignalProperty(exports, 'diagnostic');
+
+/// Personalization attributes:
+_defineVehicleSignalProperty(exports, 'mirror');
+_defineVehicleSignalProperty(exports, 'seatAdjustment');
+_defineVehicleSignalProperty(exports, 'driveMode');
+_defineVehicleSignalProperty(exports, 'dashboardIllumination');
+_defineVehicleSignalProperty(exports, 'vehicleSound');
+
+/// Driving Safety attributes:
+_defineVehicleSignalProperty(exports, 'antilockBreakingSystem');
+_defineVehicleSignalProperty(exports, 'tractionControlSystem');
+_defineVehicleSignalProperty(exports, 'electronicStabilityControl');
+_defineVehicleSignalProperty(exports, 'topSpeedLimit');
+_defineVehicleSignalProperty(exports, 'airbagStatus');
+_defineVehicleSignalProperty(exports, 'door');
+_defineVehicleSignalProperty(exports, 'childSafetyLock');
+_defineVehicleSignalProperty(exports, 'seat');
+
+/// Climate attributes:
+_defineVehicleSignalProperty(exports, 'temperature');
+_defineVehicleSignalProperty(exports, 'rainSensor');
+_defineVehicleSignalProperty(exports, 'wiperStatus');
+_defineVehicleSignalProperty(exports, 'climateControl');
+_defineVehicleSignalProperty(exports, 'defrost');
+_defineVehicleSignalProperty(exports, 'sunroof');
+_defineVehicleSignalProperty(exports, 'atmosphericPressure');
+
+/// Vision and Parking Interfaces
+_defineVehicleSignalProperty(exports, 'langeDepartureStatus');
+_defineVehicleSignalProperty(exports, 'alarm');
+_defineVehicleSignalProperty(exports, 'parkingBrake');
+
+
diff --git a/xwalk/vehicle_extension.cc b/xwalk/vehicle_extension.cc
new file mode 100644
index 00000000..a021c142
--- /dev/null
+++ b/xwalk/vehicle_extension.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "vehicle_extension.h"
+
+#include "vehicle_instance.h"
+
+common::Extension* CreateExtension() {
+ return new VehicleExtension();
+}
+
+extern const char kSource_vehicle_api[];
+
+VehicleExtension::VehicleExtension() {
+ SetExtensionName("navigator.vehicle");
+ SetJavaScriptAPI(kSource_vehicle_api);
+
+ const char* entry_points[] = {"Zone", NULL};
+
+ SetExtraJSEntryPoints(entry_points);
+}
+
+VehicleExtension::~VehicleExtension() {
+}
+
+common::Instance* VehicleExtension::CreateInstance() {
+ return new VehicleInstance;
+}
diff --git a/xwalk/vehicle_extension.h b/xwalk/vehicle_extension.h
new file mode 100644
index 00000000..ebd50811
--- /dev/null
+++ b/xwalk/vehicle_extension.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef VEHICLE_VEHICLE_EXTENSION_H_
+#define VEHICLE_VEHICLE_EXTENSION_H_
+
+#include "common/extension.h"
+
+class VehicleExtension : public common::Extension {
+ public:
+ VehicleExtension();
+ virtual ~VehicleExtension();
+
+ private:
+ // common::Extension implementation.
+ virtual common::Instance* CreateInstance();
+};
+
+#endif // VEHICLE_VEHICLE_EXTENSION_H_
diff --git a/xwalk/vehicle_instance.cc b/xwalk/vehicle_instance.cc
new file mode 100644
index 00000000..4e8027ca
--- /dev/null
+++ b/xwalk/vehicle_instance.cc
@@ -0,0 +1,169 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "vehicle_instance.h"
+
+#include <abstractpropertytype.h>
+
+#include <algorithm>
+#include <string>
+
+#include "vehicle.h"
+
+VehicleInstance::VehicleInstance(): vehicle_(new Vehicle(this)) {
+ DebugOut::setDebugThreshhold(5);
+}
+
+void VehicleInstance::HandleMessage(const char* message) {
+ DebugOut() << "VehicleInstance message received " << message << endl;
+
+ picojson::value v;
+
+ std::string err;
+ picojson::parse(v, message, message + strlen(message), &err);
+ if (!err.empty()) {
+ return;
+ }
+
+ std::string method = v.get("method").to_str();
+
+ Zone::Type amb_zone = 0;
+ if (v.contains("zone")) {
+ picojson::value zone = v.get("zone");
+ if (zone.is<picojson::object>() && zone.contains("value")) {
+ picojson::value::array zones = zone.get("value").get<picojson::value::array>();
+ amb_zone = ZoneToAMBZone(zones);
+ DebugOut() << "Converted W3C zone " << picojson::value(zones).to_str() << " to AMB zone: " << amb_zone << endl;
+ } else {
+ int callback_id = -1;
+ if (v.contains("asyncCallId"))
+ callback_id = v.get("asyncCallId").get<double>();
+ PostError(callback_id, method, "invalid_zone");
+ return;
+ }
+ }
+
+ if (method == "get") {
+ std::string attribute = v.get("name").to_str();
+ int callback_id = v.get("asyncCallId").get<double>();
+
+ std::transform(attribute.begin(), attribute.begin() + 1, attribute.begin(),
+ ::toupper);
+
+ vehicle_->Get(attribute, amb_zone, callback_id);
+ } else if (method == "zones") {
+ std::string attribute = v.get("name").to_str();
+ int callback_id = v.get("asyncCallId").get<double>();
+ std::transform(attribute.begin(), attribute.begin() + 1, attribute.begin(),
+ ::toupper);
+
+ vehicle_->GetZones(attribute, callback_id);
+ } else if (method == "subscribe") {
+ std::string attribute = v.get("name").to_str();
+ std::transform(attribute.begin(), attribute.begin() + 1, attribute.begin(),
+ ::toupper);
+
+ vehicle_->Subscribe(attribute, amb_zone);
+ } else if (method == "unsubscribe") {
+ std::string attribute = v.get("name").to_str();
+ std::transform(attribute.begin(), attribute.begin() + 1, attribute.begin(),
+ ::toupper);
+
+ vehicle_->Unsubscribe(attribute, amb_zone);
+ } else if (method == "set") {
+ std::string attribute = v.get("name").to_str();
+ int callback_id = v.get("asyncCallId").get<double>();
+
+ std::transform(attribute.begin(), attribute.begin() + 1, attribute.begin(),
+ ::toupper);
+
+ if (!v.get("value").is<picojson::object>()) {
+ PostError(callback_id, "set", "invalid_operation");
+ }
+ picojson::object value = v.get("value").get<picojson::object>();
+
+ vehicle_->Set(attribute, value, amb_zone, callback_id);
+ } else if (method == "supported") {
+ std::string attribute = v.get("name").to_str();
+ int callback_id = v.get("asyncCallId").get<double>();
+
+ std::transform(attribute.begin(), attribute.begin() + 1, attribute.begin(),
+ ::toupper);
+ vehicle_->Supported(attribute, callback_id);
+ }
+}
+
+void VehicleInstance::HandleSyncMessage(const char* message) {
+ DebugOut() << "VehicleInstance Sync message received " << message << endl;
+ picojson::value v;
+
+ std::string err;
+ picojson::parse(v, message, message + strlen(message), &err);
+ if (!err.empty()) {
+ return;
+ }
+
+ std::string method = v.get("method").to_str();
+ std::string objectName = v.get("name").to_str();
+ std::string attName = v.get("attName").to_str();
+
+ std::transform(objectName.begin(), objectName.begin() + 1, objectName.begin(),
+ ::toupper);
+
+ std::transform(attName.begin(), attName.begin() + 1, attName.begin(),
+ ::toupper);
+
+ if(method == "availableForRetrieval")
+ {
+ std::string reply = vehicle_->AvailableForRetrieval(objectName, attName) ? "true" : "false";
+ DebugOut() << "VehicleInstance reply: " << reply << endl;
+ SendSyncReply(reply.c_str());
+ }
+
+}
+
+int VehicleInstance::ZoneToAMBZone(picojson::array zones) {
+ Zone::Type amb_zone = 0;
+
+ for (auto zone : zones) {
+ std::string tempzone = zone.to_str();
+
+ std::transform(tempzone.begin(), tempzone.end(), tempzone.begin(),
+ ::tolower);
+
+ if (tempzone == "front") {
+ amb_zone |= Zone::Front;
+ } else if (tempzone == "middle") {
+ amb_zone |= Zone::Middle;
+ } else if (tempzone == "right") {
+ amb_zone |= Zone::Right;
+ } else if (tempzone == "left") {
+ amb_zone |= Zone::Left;
+ } else if (tempzone == "rear") {
+ amb_zone |= Zone::Rear;
+ } else if (tempzone == "center") {
+ amb_zone |= Zone::Center;
+ }
+ }
+
+ return amb_zone;
+}
+
+void VehicleInstance::PostError(double callback_id, const std::string& method,
+ const std::string& error) {
+ picojson::object msg;
+ msg["method"] = picojson::value(method);
+ msg["error"] = picojson::value(true);
+ msg["value"] = picojson::value(error);
+ if (callback_id != -1) {
+ msg["asyncCallId"] =
+ picojson::value(static_cast<double>(callback_id));
+ }
+
+ std::string message = picojson::value(msg).serialize();
+
+ DebugOut() << "Error Reply message: " << message << endl;
+
+ PostMessage(message.c_str());
+}
diff --git a/xwalk/vehicle_instance.h b/xwalk/vehicle_instance.h
new file mode 100644
index 00000000..48093b63
--- /dev/null
+++ b/xwalk/vehicle_instance.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef VEHICLE_VEHICLE_INSTANCE_H_
+#define VEHICLE_VEHICLE_INSTANCE_H_
+
+#include <string>
+
+#include <picojson.h>
+
+#include "common/extension.h"
+#include "vehicle.h"
+
+class VehicleInstance : public common::Instance {
+ public:
+ VehicleInstance();
+ virtual ~VehicleInstance() {}
+
+ private:
+ // common::Instance implementation.
+ virtual void HandleMessage(const char* msg);
+ virtual void HandleSyncMessage(const char* msg);
+
+ int ZoneToAMBZone(picojson::array);
+
+ void PostError(double callback_id, const std::string& method,
+ const std::string& error);
+
+ Vehicle* vehicle_;
+};
+
+#endif // VEHICLE_VEHICLE_INSTANCE_H_