summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRomain Forlot <romain.forlot@iot.bzh>2017-09-14 19:31:42 +0200
committerRomain Forlot <romain.forlot@iot.bzh>2017-12-14 11:00:25 +0100
commiteabae24ea592420de46e36f0b1af5d39eee5b8a4 (patch)
tree16cbc39e84eb71d655add40e715f7d87b4b02132
parent140fd3d8f76a8cbbde8f6b0bf997808855f3da43 (diff)
Attach and recursion check working
Change-Id: I2f9509d4b6aa63a16df8db2187810337fd802ef4 Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
m---------afb-utilities0
m---------conf.d/app-templates0
-rw-r--r--conf.d/project/etc/init-daemon.json19
-rw-r--r--conf.d/project/etc/sig-doors.json121
-rw-r--r--conf.d/project/etc/sig-sources.json59
-rw-r--r--conf.d/project/etc/sources.json50
-rw-r--r--conf.d/project/lua.d/onload-daemon-04-oncall.lua2
-rw-r--r--controller/ctl-config.c81
-rw-r--r--controller/ctl-config.h11
-rw-r--r--controller/ctl-plugin.c23
-rw-r--r--low-can/CMakeLists.txt40
-rw-r--r--low-can/doors.c112
-rw-r--r--signal-composer-binding/CMakeLists.txt7
-rw-r--r--signal-composer-binding/observer.hpp30
-rw-r--r--signal-composer-binding/signal-composer-binding.cpp23
-rw-r--r--signal-composer-binding/signal-composer-binding.hpp3
-rw-r--r--signal-composer-binding/signal-composer.cpp167
-rw-r--r--signal-composer-binding/signal-composer.hpp18
-rw-r--r--signal-composer-binding/signal-conf.cpp16
-rw-r--r--signal-composer-binding/signal-conf.hpp27
-rw-r--r--signal-composer-binding/signal.cpp107
-rw-r--r--signal-composer-binding/signal.hpp37
-rw-r--r--signal-composer-binding/source.cpp19
-rw-r--r--signal-composer-binding/source.hpp14
24 files changed, 603 insertions, 383 deletions
diff --git a/afb-utilities b/afb-utilities
-Subproject fdf2c27980f756cf63890576d80eef20b78fe98
+Subproject 49a99fef3e1e1ea0ecd7f131fd56da4c54bcd14
diff --git a/conf.d/app-templates b/conf.d/app-templates
-Subproject 784e0e5a0624185a2190a6c979cf1c7440645c4
+Subproject 908a0372d53c74a037da3debe1e276a214343c4
diff --git a/conf.d/project/etc/init-daemon.json b/conf.d/project/etc/init-daemon.json
new file mode 100644
index 0000000..dc18f7e
--- /dev/null
+++ b/conf.d/project/etc/init-daemon.json
@@ -0,0 +1,19 @@
+{
+ "$schema": "ToBeDone",
+ "metadata": {
+ "label": "Signal Composer",
+ "version": "1.0",
+ "api": "signal-composer",
+ "info": "Signal composer Configuration",
+ "require": ["low-can"],
+ "files": ["sources", "sig-doors"]
+ },
+ "plugins": [
+ {
+ "label": "Door handle",
+ "version": "1.0",
+ "info": "Manage all doors and windows status",
+ "basename": "doors"
+ }
+ ]
+}
diff --git a/conf.d/project/etc/sig-doors.json b/conf.d/project/etc/sig-doors.json
index e93745e..bc26296 100644
--- a/conf.d/project/etc/sig-doors.json
+++ b/conf.d/project/etc/sig-doors.json
@@ -1,83 +1,60 @@
{
"signals": [
{
- "id": "rear_left_windows",
- "source": "low-can/messages.windows.rear_left.open",
- "class": "state",
- "onReceived": {
- "function": "_Door_opened",
- "args": {
- "evtname": "messages.windows.rear_left.open"
- }
- }
+ "id": "rear_left_window",
+ "source": "low-can/messages.windows.rear_left.open"
},
{
"id": "rear_left_door",
- "source": "low-can/messages.doors.rear_left.open",
- "class": "state",
- "onReceived": {
- "function": "_Door_opened",
- "args": {
- "evtname": "messages.doors.rear_left.open"
- }
- }
+ "source": "low-can/messages.doors.rear_left.open"
},
{
- "id": "rear_left",
- "source": [
- "rear_left_windows",
- "rear_left_doors"
- ],
- "class": "state",
- "onReceived": {
- "function": "_Door_opened",
- "args": {
- "ojoi": "pok"
- }
- }
+ "id": "rear_right_window",
+ "source": "low-can/messages.windows.rear_right.open"
+ },
+ {
+ "id": "rear_right_door",
+ "source": "low-can/messages.doors.rear_right.open"
+ },
+ {
+ "id": "front_left_window",
+ "source": "low-can/messages.windows.front_left.open"
+ },
+ {
+ "id": "front_left_door",
+ "source": "low-can/messages.doors.front_left.open"
},
{
"id": "front_right_window",
- "source": "low-can/messages.windows.front_right.open",
- "class": "state",
- "onReceived": {
- "function": "_Door_opened",
- "args": {
- "evtname": "messages.windows.front_right.open"
- }
- }
+ "source": "low-can/messages.windows.front_right.open"
},
{
- "id": "rear_right_door",
- "source": "low-can/messages.doors.rear_right.open",
- "class": "state",
- "onReceived": {
- "function": "_Door_opened",
- "args": {
- "evtname": "messages.doors.rear_right.open"
- }
- }
+ "id": "front_right_door",
+ "source": "low-can/messages.doors.front_right.open"
},
{
- "id": "rear_right_window",
- "source": "low-can/messages.windows.rear_right.open",
- "class": "state",
+ "id": "rear_left",
+ "source": [
+ "rear_left_window",
+ "rear_left_door"
+ ],
"onReceived": {
- "function": "_Door_opened",
+ "plugin": "Door handle",
+ "function": "isOpen",
"args": {
- "evtname": "messages.windows.rear_right.open"
+ "ojoi": "pok"
}
}
},
{
"id": "rear_right",
"source": [
- "rear_right_doors",
- "rear_right_windows"
+ "rear_right_door",
+ "rear_right_window"
],
- "class": "state",
"onReceived": {
- "function": "_Complete_Door",
+ "plugin": "Door handle",
+ "function": "isOpen",
"args": {}
}
},
@@ -85,41 +62,41 @@
"id": "front_left",
"source": [
"front_left_door",
- "front_left_windows"
+ "front_left_window"
],
- "class": "state",
"onReceived": {
- "function": "_Complete_Door",
+ "plugin": "Door handle",
+ "function": "isOpen",
"args": {}
}
},
{
"id": "front_right",
"source": [
- "front_right_doors",
- "front_right_windows"
+ "front_right_door",
+ "front_right_window"
],
- "class": "state",
"onReceived": {
- "function": "_Complete_Door",
+ "plugin": "Door handle",
+ "function": "isOpen",
"args": {}
}
},
{
"id": "all_doors",
"source": [
- "front_left_doors",
- "front_left_windows",
- "front_right_doors",
- "front_right_windows",
- "rear_left_doors",
- "rear_left_windows",
- "rear_right_doors",
- "rear_right_windows"
+ "front_left_door",
+ "front_left_window",
+ "front_right_door",
+ "front_right_window",
+ "rear_left_door",
+ "rear_left_window",
+ "rear_right_door",
+ "rear_right_window"
],
- "class": "state",
"onReceived": {
- "function": "_Door_opened",
+ "plugin": "Door handle",
+ "function": "isOpen",
"args": {
"evtname": "doors.open"
}
diff --git a/conf.d/project/etc/sig-sources.json b/conf.d/project/etc/sig-sources.json
deleted file mode 100644
index 1142196..0000000
--- a/conf.d/project/etc/sig-sources.json
+++ /dev/null
@@ -1,59 +0,0 @@
-{
- "$schema": "ToBeDone",
- "metadata": {
- "label": "signal-composer",
- "info": "Signal composer Configuration",
- "name": "afb-signal-composer",
- "version": "1.0"
- },
- "sources": [
- {
- "api": "low-can",
- "info": "Low level binding to handle CAN bus communications",
- "init": {
- "function": "c/lua (depend on name) function to initialize binding",
- "args": {
- "arg1": "first argument"
- }
- },
- "getSignal": {
- "function": "c/lua (depend on name) function to get signals",
- "args": {
- "arg": "first argument"
- }
- }
- }, {
- "api": "gps",
- "info": "Low level binding which retrieve Satellite positionning values",
- "actions": [{
- "label": "init",
- "function": "c/lua (depend on name) function to initialize binding",
- "args": {
- "arg": "first argument"
- }
- }, {
- "label": "getSignal",
- "function": "c/lua (depend on name) function to get signals",
- "args": {
- "arg": "first argument"
- }
- }]
- }, {
- "api": "mraa",
- "info": "Low level binding which retrieve different values from several sensors like gyroscope, accelerometer, etc",
- "actions": [{
- "label": "init",
- "function": "c/lua (depend on name) function to initialize binding",
- "args": {
- "arg": "first argument"
- }
- }, {
- "label": "getSignal",
- "function": "c/lua (depend on name) function to get signals",
- "args": {
- "arg": "first argument"
- }
- }]
- }
- ]
-}
diff --git a/conf.d/project/etc/sources.json b/conf.d/project/etc/sources.json
new file mode 100644
index 0000000..a70da50
--- /dev/null
+++ b/conf.d/project/etc/sources.json
@@ -0,0 +1,50 @@
+{
+ "sources": [
+ {
+ "api": "low-can",
+ "info": "Low level binding to handle CAN bus communications",
+ "init": {
+ "function": "low-can/subscribe",
+ "args": {
+ "event": "message*"
+ }
+ },
+ "getSignal": {
+ "function": "_LUA_Simple_Echo_Args",
+ "args": {
+ "arg": "first argument"
+ }
+ }
+ }, {
+ "api": "gps",
+ "info": "Low level binding which retrieve Satellite positionning values",
+ "init": {
+ "function": "_LUA_Simple_Echo_Args",
+ "args": {
+ "arg1": "first argument"
+ }
+ },
+ "getSignal": {
+ "function": "_LUA_Simple_Echo_Args",
+ "args": {
+ "arg": "first argument"
+ }
+ }
+ }, {
+ "api": "mraa",
+ "info": "Low level binding which retrieve different values from several sensors like gyroscope, accelerometer, etc",
+ "init": {
+ "function": "_LUA_Simple_Echo_Args",
+ "args": {
+ "arg1": "first argument"
+ }
+ },
+ "getSignal": {
+ "function": "_LUA_Simple_Echo_Args",
+ "args": {
+ "arg": "first argument"
+ }
+ }
+ }
+ ]
+}
diff --git a/conf.d/project/lua.d/onload-daemon-04-oncall.lua b/conf.d/project/lua.d/onload-daemon-04-oncall.lua
index b450932..7c0e9bc 100644
--- a/conf.d/project/lua.d/onload-daemon-04-oncall.lua
+++ b/conf.d/project/lua.d/onload-daemon-04-oncall.lua
@@ -22,7 +22,7 @@
_count=0
-- Display receive arguments and echo them to caller
-function _Simple_Echo_Args (request, args)
+function _LUA_Simple_Echo_Args (request, args)
_count=_count+1
AFB:notice("LUA OnCall Echo Args count=%d args=%s", count, args)
diff --git a/controller/ctl-config.c b/controller/ctl-config.c
index 95f6db8..948f0d1 100644
--- a/controller/ctl-config.c
+++ b/controller/ctl-config.c
@@ -28,12 +28,16 @@
// Load control config file
-char* CtlConfigSearch(const char *dirList) {
+char* CtlConfigSearch(const char *dirList, const char* fileName) {
int index;
char controlFile [CONTROL_MAXPATH_LEN];
- strncpy(controlFile, CONTROL_CONFIG_PRE "-", CONTROL_MAXPATH_LEN);
- strncat(controlFile, GetBinderName(), CONTROL_MAXPATH_LEN);
+ if(fileName) {
+ strncpy(controlFile, fileName, CONTROL_MAXPATH_LEN);
+ } else {
+ strncpy(controlFile, CONTROL_CONFIG_PRE "-", CONTROL_MAXPATH_LEN);
+ strncat(controlFile, GetBinderName(), CONTROL_MAXPATH_LEN);
+ }
// search for default dispatch config file
json_object* responseJ = ScanForConfig(dirList, CTL_SCAN_RECURSIVE, controlFile, ".json");
@@ -97,9 +101,6 @@ int CtlConfigExec(CtlConfigT *ctlConfig) {
errcount += ctlConfig->sections[idx].loadCB(&ctlConfig->sections[idx], NULL);
}
return errcount;
-
-OnErrorExit:
- return 1;
}
CtlConfigT *CtlConfigLoad(const char* filepath, CtlSectionT *sections) {
@@ -112,18 +113,22 @@ CtlConfigT *CtlConfigLoad(const char* filepath, CtlSectionT *sections) {
if (err) goto OnErrorExit;
#endif
- // Search for config in filepath
- filepath = CtlConfigSearch(filepath);
-
- if (!filepath) {
- AFB_ERROR("CTL-LOAD-CONFIG No JSON Config found invalid JSON %s ", filepath);
- goto OnErrorExit;
+ json_object* loadJSON(const char* fileName)
+ {
+ // Search for config in filepath
+ const char* filepathFound = CtlConfigSearch(filepath, fileName);
+ if(!filepathFound)
+ {
+ AFB_ERROR("CTL-LOAD-CONFIG No JSON Config found in %s", filepath);
+ return NULL;
+ }
+ return json_object_from_file(filepathFound);
}
// Load JSON file
- ctlConfigJ = json_object_from_file(filepath);
+ ctlConfigJ = loadJSON(NULL);
if (!ctlConfigJ) {
- AFB_ERROR("CTL-LOAD-CONFIG Not invalid JSON %s ", filepath);
+ AFB_ERROR("CTL-LOAD-CONFIG Invalid JSON %s ", filepath);
goto OnErrorExit;
}
@@ -132,9 +137,13 @@ CtlConfigT *CtlConfigLoad(const char* filepath, CtlSectionT *sections) {
json_object *metadataJ;
int done = json_object_object_get_ex(ctlConfigJ, "metadata", &metadataJ);
if (done) {
- CtlConfigT *ctlConfig = calloc(1, sizeof (CtlConfigT));
- err = wrap_json_unpack(metadataJ, "{ss,ss,ss,s?s,s?o !}", "label", &ctlConfig->label, "version", &ctlConfig->version
- , "api", &ctlConfig->api, "info", &ctlConfig->info, "require", &ctlConfig->requireJ);
+ err = wrap_json_unpack(metadataJ, "{ss,ss,ss,s?s,s?o,s?o !}",
+ "label", &ctlConfig->label,
+ "version", &ctlConfig->version,
+ "api", &ctlConfig->api,
+ "info", &ctlConfig->info,
+ "require", &ctlConfig->requireJ,
+ "files",&ctlConfig->filesJ);
if (err) {
AFB_ERROR("CTL-LOAD-CONFIG:METADATA Missing something label|api|version|[info]|[require] in:\n-- %s", json_object_get_string(metadataJ));
goto OnErrorExit;
@@ -145,22 +154,52 @@ CtlConfigT *CtlConfigLoad(const char* filepath, CtlSectionT *sections) {
err = afb_daemon_rename_api(ctlConfig->api);
if (err) AFB_WARNING("Fail to rename api to:%s", ctlConfig->api);
}
-
}
//load config sections
err = 0;
ctlConfig->sections = sections;
+
for (int idx = 0; sections[idx].key != NULL; idx++) {
json_object * sectionJ;
int done = json_object_object_get_ex(ctlConfigJ, sections[idx].key, &sectionJ);
if (!done) {
- AFB_ERROR("CtlConfigLoad: fail to find '%s' section in config '%s'", sections[idx].key, filepath);
- err++;
+ json_object* configJ = NULL;
+ const char* fileName;
+ AFB_DEBUG("CtlConfigLoad: fail to find '%s' section in config '%s'. Searching deeper", sections[idx].key, filepath);
+ if (json_object_get_type(ctlConfig->filesJ) == json_type_array) {
+ int filesEnd = json_object_array_length(ctlConfig->filesJ);
+ for (int jdx = 0; jdx < filesEnd; jdx++) {
+ fileName = json_object_get_string(json_object_array_get_idx(ctlConfig->filesJ, jdx));
+ configJ = loadJSON(fileName);
+ if(json_object_object_get_ex(configJ, sections[idx].key, &sectionJ))
+ {
+ const char* k = sections[idx].key;
+ err += sections[idx].loadCB(&sections[idx], sectionJ);
+ done++;
+ }
+ }
+ if(!done) {
+ AFB_ERROR("CtlConfigLoad: fail to find '%s' section in config '%s' with '%s' in its name", sections[idx].key, filepath, fileName);
+ err++;
+ }
+ if(err) {goto OnErrorExit;}
+ } else {
+ fileName = json_object_get_string(ctlConfig->filesJ);
+ configJ = loadJSON(fileName);
+ if(json_object_object_get_ex(configJ, sections[idx].key, &sectionJ)) {
+ err += sections[idx].loadCB(&sections[idx], sectionJ);
+ done++;
+ }
+ else {
+ AFB_ERROR("CtlConfigLoad: fail to find '%s' section in config '%s' with '%s' in its name", sections[idx].key, filepath, fileName);
+ err++;
+ }
+ if(err) {goto OnErrorExit;}
+ }
} else {
err += sections[idx].loadCB(&sections[idx], sectionJ);
}
-
}
if (err) goto OnErrorExit;
diff --git a/controller/ctl-config.h b/controller/ctl-config.h
index 3b39f53..7c3631c 100644
--- a/controller/ctl-config.h
+++ b/controller/ctl-config.h
@@ -75,11 +75,11 @@ typedef struct {
} DispatchHandleT;
typedef struct ConfigSectionS {
- const char *key;
- const char *label;
- const char *info;
- int (*loadCB)(struct ConfigSectionS *section, json_object *sectionJ);
- void *handle;
+ const char *key;
+ const char *label;
+ const char *info;
+ int (*loadCB)(struct ConfigSectionS *section, json_object *sectionJ);
+ void *handle;
} CtlSectionT;
typedef struct {
@@ -88,6 +88,7 @@ typedef struct {
const char *info;
const char *version;
json_object *requireJ;
+ json_object *filesJ;
CtlSectionT *sections;
} CtlConfigT;
diff --git a/controller/ctl-plugin.c b/controller/ctl-plugin.c
index 748c78b..ae203af 100644
--- a/controller/ctl-plugin.c
+++ b/controller/ctl-plugin.c
@@ -44,8 +44,7 @@ int PluginGetCB (CtlActionT *action , json_object *callbackJ) {
goto OnErrorExit;
}
-
- int err = wrap_json_unpack(callbackJ, "{ss,ss,s?s,s?o!}", "plugin", &plugin, "function", &function, "args", &argsJ);
+ int err = wrap_json_unpack(callbackJ, "{ss,ss,s?o!}", "plugin", &plugin, "function", &function, "args", &argsJ);
if (err) {
AFB_ERROR("PluginGet missing plugin|function|[args] in %s", json_object_get_string(callbackJ));
goto OnErrorExit;
@@ -87,7 +86,8 @@ STATIC int DispatchOneL2c(lua_State* luaState, char *funcname, Lua2cFunctionT ca
STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* handle) {
json_object *lua2csJ = NULL, *actionsJ = NULL;
- const char*ldSearchPath = NULL, *basename = NULL;
+ const char *basename = NULL;
+ char *ldSearchPath = NULL;
void *dlHandle;
@@ -95,15 +95,23 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
if (!pluginJ) return 0;
int err = wrap_json_unpack(pluginJ, "{ss,s?s,s?s,s?s,ss,s?o,s?o!}",
- "label", &ctlPlugin->label, "version", &ctlPlugin->version, "info", &ctlPlugin->info, "ldpath", &ldSearchPath, "basename", &basename, "lua2c", &lua2csJ, "actions", &actionsJ);
+ "label", &ctlPlugin->label,
+ "version", &ctlPlugin->version,
+ "info", &ctlPlugin->info,
+ "ldpath", &ldSearchPath,
+ "basename", &basename,
+ "lua2c", &lua2csJ,
+ "actions", &actionsJ);
if (err) {
AFB_ERROR("CTL-PLUGIN-LOADONE Plugin missing label|basename|version|[info]|[ldpath]|[lua2c]|[actions] in:\n-- %s", json_object_get_string(pluginJ));
goto OnErrorExit;
}
// if search path not in Json config file, then try default binding dir
- ldSearchPath = getenv("CONTROL_PLUGIN_PATH");
- if (!ldSearchPath) ldSearchPath = strncat(GetBindingDirPath(), "/lib", sizeof(GetBindingDirPath()) - strlen(GetBindingDirPath()) - 1);
+ if (!ldSearchPath) ldSearchPath = getenv("CONTROL_PLUGIN_PATH");
+ if (!ldSearchPath) {
+ ldSearchPath = strncat(GetBindingDirPath(), "/lib", sizeof(GetBindingDirPath()) - strlen(GetBindingDirPath()) - 1);
+ }
// search for default policy config file
json_object *pluginPathJ = ScanForConfig(ldSearchPath, CTL_SCAN_RECURSIVE, basename, CTL_PLUGIN_EXT);
@@ -145,7 +153,7 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
// store dlopen handle to enable onload action at exec time
ctlPlugin->dlHandle = dlHandle;
- // Jose hack to make verbosity visible from sharelib
+ // Jose hack to make verbosity visible from sharedlib
struct afb_binding_data_v2 *afbHidenData = dlsym(dlHandle, "afbBindingV2data");
if (afbHidenData) *afbHidenData = afbBindingV2data;
@@ -208,7 +216,6 @@ OnErrorExit:
return 1;
}
-
int PluginConfig(CtlSectionT *section, json_object *pluginsJ) {
int err=0;
diff --git a/low-can/CMakeLists.txt b/low-can/CMakeLists.txt
new file mode 100644
index 0000000..e1e1907
--- /dev/null
+++ b/low-can/CMakeLists.txt
@@ -0,0 +1,40 @@
+###########################################################################
+# Copyright 2015, 2016, 2017 IoT.bzh
+#
+# author: Romain Forlot <romain.forlot@iot.bzh>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+###########################################################################
+
+
+
+PROJECT_TARGET_ADD(doors)
+
+ # Define targets
+ ADD_LIBRARY(${TARGET_NAME} MODULE ${TARGET_NAME}.c)
+
+ # Alsa Plugin properties
+ SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
+ LABELS "PLUGIN"
+ PREFIX ""
+ SUFFIX ".ctlso"
+ OUTPUT_NAME ${TARGET_NAME}
+ )
+
+ # Library dependencies (include updates automatically)
+ TARGET_LINK_LIBRARIES(${TARGET_NAME}
+ afb-utilities
+ ${link_libraries}
+ )
+
+ include_directories("../controller")
diff --git a/low-can/doors.c b/low-can/doors.c
new file mode 100644
index 0000000..ce0b0c9
--- /dev/null
+++ b/low-can/doors.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author Romain Forlot <romain.forlot@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#define _GNU_SOURCE // needed for vasprintf
+
+#define AFB_BINDING_VERSION 2
+#include <afb/afb-binding.h>
+#include <systemd/sd-event.h>
+#include <json-c/json_object.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "ctl-plugin.h"
+#include "wrap-json.h"
+
+CTLP_REGISTER("low-can");
+
+typedef struct {
+ bool door;
+ bool window;
+} doorT;
+
+typedef struct {
+ doorT* front_left;
+ doorT* front_right;
+ doorT* rear_left;
+ doorT* rear_right;
+} allDoorsCtxT;
+
+// Call at initialisation time
+CTLP_ONLOAD(plugin, api) {
+ allDoorsCtxT *allDoorCtx = (allDoorsCtxT*)calloc (1, sizeof(allDoorsCtxT));
+ memset(allDoorCtx, 0, sizeof(allDoorsCtxT));
+
+ AFB_NOTICE ("Low-can door plugin: label='%s' version='%s' info='%s'", plugin->label, plugin->version, plugin->info);
+ return (void*)allDoorCtx;
+}
+
+CTLP_CAPI (isOpen, source, argsJ, eventJ, context) {
+
+ const char* eventName;
+ json_object *eventStatus = NULL;
+ long long int *timestamp = NULL;
+ allDoorsCtxT *ctx=(allDoorsCtxT*)context;
+
+ AFB_DEBUG("Here is the situation: source:%s, args:%s, event:%s,\n fld: %s, flw: %s, frd: %s, frw: %s, rld: %s, rlw: %s, rrd: %s, rrw: %s",
+ source->label,
+ json_object_to_json_string(argsJ),
+ json_object_to_json_string(eventJ),
+ ctx->front_left->door ? "true":"false",
+ ctx->front_left->window ? "true":"false",
+ ctx->front_right->door ? "true":"false",
+ ctx->front_right->window ? "true":"false",
+ ctx->rear_left->door ? "true":"false",
+ ctx->rear_left->window ? "true":"false",
+ ctx->rear_right->door ? "true":"false",
+ ctx->rear_right->window ? "true":"false"
+ );
+
+ int err = wrap_json_unpack(eventJ, "{ss,sb,s?F}",
+ "event", &eventName,
+ "value", &eventStatus,
+ "timestamp", &timestamp);
+ if(err)
+ {
+ AFB_ERROR("Error parsing event %s", json_object_to_json_string(eventJ));
+ return -1;
+ }
+
+ if(strcasestr(eventName, "front_left"))
+ {
+ if(strcasestr(eventName, "door")) {ctx->front_left->door = eventStatus;}
+ else if(strcasestr(eventName, "window")) {ctx->front_left->window = eventStatus;}
+ else {AFB_WARNING("Unexpected behavior, this '%s' is not a door ! ", json_object_to_json_string(eventJ));}
+ }
+ else if(strcasestr(eventName, "front_right"))
+ {
+ if(strcasestr(eventName, "door")) {ctx->front_right->door = eventStatus;}
+ else if(strcasestr(eventName, "window")) {ctx->front_right->window = eventStatus;}
+ else {AFB_WARNING("Unexpected behavior, this '%s' is not a door ! ", json_object_to_json_string(eventJ));}
+ }
+ else if(strcasestr(eventName, "rear_left"))
+ {
+ if(strcasestr(eventName, "door")) {ctx->rear_left->door = eventStatus;}
+ else if(strcasestr(eventName, "window")) {ctx->rear_left->window = eventStatus;}
+ else {AFB_WARNING("Unexpected behavior, this '%s' is not a door ! ", json_object_to_json_string(eventJ));}
+ }
+ else if(strcasestr(eventName, "rear_right"))
+ {
+ if(strcasestr(eventName, "door")) {ctx->rear_right->door = eventStatus;}
+ else if(strcasestr(eventName, "window")) {ctx->rear_right->window = eventStatus;}
+ else {AFB_WARNING("Unexpected behavior, this '%s' is not a door ! ", json_object_to_json_string(eventJ));}
+ }
+ else {AFB_WARNING("Unexpected behavior, this '%s' is not a door ! ", json_object_to_json_string(eventJ));}
+
+ return 0;
+}
diff --git a/signal-composer-binding/CMakeLists.txt b/signal-composer-binding/CMakeLists.txt
index 8757204..3d7130b 100644
--- a/signal-composer-binding/CMakeLists.txt
+++ b/signal-composer-binding/CMakeLists.txt
@@ -21,7 +21,7 @@
PROJECT_TARGET_ADD(signal-composer)
# Define project Targets
- add_library(${TARGET_NAME} MODULE ${TARGET_NAME}-binding.cpp ${TARGET_NAME}.cpp signal-composer.cpp source.cpp)
+ add_library(${TARGET_NAME} MODULE ${TARGET_NAME}-binding.cpp ${TARGET_NAME}.cpp source.cpp signal.cpp)
# Binder exposes a unique public entry point
SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
@@ -31,8 +31,9 @@ PROJECT_TARGET_ADD(signal-composer)
OUTPUT_NAME ${TARGET_NAME}
)
-
- TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+ TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME}
+ PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
+ )
# Library dependencies (include updates automatically)
TARGET_LINK_LIBRARIES(${TARGET_NAME}
diff --git a/signal-composer-binding/observer.hpp b/signal-composer-binding/observer.hpp
deleted file mode 100644
index e4129c6..0000000
--- a/signal-composer-binding/observer.hpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <vector>
-
-class Observer
-{
-public:
- virtual void update(double timestamp, double value) = 0;
-};
-
-class Subject
-{
- double timestamp_;
- double value_;
- std::vector<Observer*> m_views;
-public:
- void attach(Observer *obs)
- {
- m_views.push_back(obs);
- }
- void set_val(double timestamp, double value)
- {
- timestamp_ = timestamp;
- value_ = value;
- notify();
- }
- void notify()
- {
- for (int i = 0; i < m_views.size(); ++i)
- m_views[i]->update(timestamp_, value_);
- }
-};
diff --git a/signal-composer-binding/signal-composer-binding.cpp b/signal-composer-binding/signal-composer-binding.cpp
index 90401f2..860de07 100644
--- a/signal-composer-binding/signal-composer-binding.cpp
+++ b/signal-composer-binding/signal-composer-binding.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#include <string>
#include <string.h>
// afb-utilities
#include <wrap-json.h>
@@ -29,6 +30,14 @@
/// @brief callback for receiving message from low binding. Treatment itself is made in SigComp class.
void onEvent(const char *event, json_object *object)
{
+ AFB_DEBUG("Received event json: %s", json_object_to_json_string(object));
+ bindingApp& bApp = bindingApp::instance();
+
+ std::shared_ptr<Signal> sig = bApp.searchSignal(event);
+ if(sig != nullptr)
+ {
+ sig->onReceivedCB(object);
+ }
}
/// @brief entry point for client subscription request. Treatment itself is made in SigComp class.
void subscribe(afb_req request)
@@ -55,20 +64,18 @@ void loadConf(afb_req request)
const char* confd;
wrap_json_unpack(args, "{s:s}", "path", &confd);
- int ret = 0;
- if( ret == 0)
+ if(true)
afb_req_success(request, NULL, NULL);
else
- afb_req_fail_f(request, "Loading configuration or subscription error", "Error code: %d", ret);
+ afb_req_fail_f(request, "Loading configuration or subscription error", "Error code: -1");
}
/// @brief entry point for get requests. Treatment itself is made in SigComp class.
void get(afb_req request)
{
- json_object *jobj;
if(true)
{
- afb_req_success(request, jobj, NULL);
+ afb_req_success(request, NULL, NULL);
}
else
{
@@ -83,7 +90,7 @@ int loadConf()
sizeof(GetBindingDirPath()) - strlen(GetBindingDirPath()) -1);
bindingApp& bApp = bindingApp::instance();
- bApp.loadConfig(rootdir);
+ ret = bApp.loadConfig(rootdir);
#ifdef CONTROL_SUPPORT_LUA
ret += LuaConfigLoad();
@@ -98,6 +105,10 @@ int execConf()
int ret = CtlConfigExec(bApp.ctlConfig());
std::vector<std::shared_ptr<Signal>> allSignals = bApp.getAllSignals();
ssize_t sigCount = allSignals.size();
+ for( std::shared_ptr<Signal>& sig: allSignals)
+ {
+ sig->attachToSources(bApp);
+ }
for(auto& sig: allSignals)
{
diff --git a/signal-composer-binding/signal-composer-binding.hpp b/signal-composer-binding/signal-composer-binding.hpp
index e73438b..8599a13 100644
--- a/signal-composer-binding/signal-composer-binding.hpp
+++ b/signal-composer-binding/signal-composer-binding.hpp
@@ -1,8 +1,5 @@
#pragma once
-#include <systemd/sd-event.h>
-#include <ctl-config.h>
-
extern "C"
{
#define AFB_BINDING_VERSION 2
diff --git a/signal-composer-binding/signal-composer.cpp b/signal-composer-binding/signal-composer.cpp
index 6f629e1..a1300e3 100644
--- a/signal-composer-binding/signal-composer.cpp
+++ b/signal-composer-binding/signal-composer.cpp
@@ -15,16 +15,21 @@
* limitations under the License.
*/
+#include <string.h>
+
#include "signal-composer.hpp"
CtlSectionT bindingApp::ctlSections_[] = {
- [0]={.key="sources" ,.label = "sources", .info=nullptr,
- .loadCB=loadSources,
+ [0]={.key="plugins" ,.label = "plugins", .info=nullptr,
+ .loadCB=PluginConfig,
+ .handle=nullptr},
+ [1]={.key="sources" ,.label = "sources", .info=nullptr,
+ .loadCB=loadSourcesAPI,
.handle=nullptr},
- [1]={.key="signals" , .label= "signals", .info=nullptr,
+ [2]={.key="signals" , .label= "signals", .info=nullptr,
.loadCB=loadSignals,
.handle=nullptr},
- [2]={.key=nullptr, .label=nullptr, .info=nullptr,
+ [3]={.key=nullptr, .label=nullptr, .info=nullptr,
.loadCB=nullptr,
.handle=nullptr}
};
@@ -32,9 +37,16 @@ CtlSectionT bindingApp::ctlSections_[] = {
bindingApp::bindingApp()
{}
-void bindingApp::loadConfig(const std::string& filepath)
+bindingApp::~bindingApp()
+{
+ free(ctlConfig_);
+}
+
+int bindingApp::loadConfig(const std::string& filepath)
{
ctlConfig_ = CtlConfigLoad(filepath.c_str(), ctlSections_);
+ if(ctlConfig_ != nullptr) {return 0;}
+ return -1;
}
bindingApp& bindingApp::instance()
@@ -43,7 +55,7 @@ bindingApp& bindingApp::instance()
return bApp;
}
-Source* bindingApp::getSource(const std::string& api)
+SourceAPI* bindingApp::getSourceAPI(const std::string& api)
{
for(auto& source: sourcesList_)
{
@@ -53,46 +65,53 @@ Source* bindingApp::getSource(const std::string& api)
return nullptr;
}
-CtlActionT* bindingApp::convert2Action(const std::string& name, json_object* action)
+CtlActionT* bindingApp::convert2Action(const std::string& name, json_object* actionJ)
{
- json_object *functionArgsJ = nullptr;
- const char* function;
-
- if(action &&
- wrap_json_unpack(action, "{ss,s?o !}", "function", &function, "args", &functionArgsJ))
+ json_object *functionArgsJ = nullptr, *action = nullptr;
+ char *function;
+ const char *plugin;
+
+ if(actionJ &&
+ !wrap_json_unpack(actionJ, "{ss,s?s,s?o !}", "function", &function,
+ "plugin", &plugin,
+ "args", &functionArgsJ))
{
- std::string functionS = function;
- json_object* action = nullptr;
- ssize_t sep;
- if(functionS.find("lua") != std::string::npos)
+ action = nullptr;
+ if(::strcasestr(function, "lua"))
{
- wrap_json_pack(&action, "{ss,s?s,s?o,s?s,s?s,s?s,s?o !}",
- "label", name,
+ wrap_json_pack(&action, "{ss,ss,so*}",
+ "label", name.c_str(),
"lua", function,
"args", functionArgsJ);
}
- else if( (sep = functionS.find_first_of("/")) != std::string::npos)
+ else if(strstr(function, "/"))
{
- std::string api = functionS.substr(0, sep);
- std::string verb = functionS.substr(sep);
- wrap_json_pack(&action, "{ss,s?s,s?o,s?s,s?s,s?s,s?o !}",
- "label", name,
+ const char* api = strsep(&function, "/");
+ //std::string api = functionS.substr(0, sep);
+ //std::string verb = functionS.substr(sep);
+ wrap_json_pack(&action, "{ss,ss,ss,so*}",
+ "label", name.c_str(),
"api", api,
- "verb", verb,
+ "verb", function,
"args", functionArgsJ);
}
else
{
- wrap_json_pack(&action, "{ss,s?s,s?o,s?s,s?s,s?s,s?o !}",
- "label", name,
- "callback", function,
- "args", functionArgsJ);
+ json_object *callbackJ = nullptr;
+ wrap_json_pack(&callbackJ, "{ss,ss,so*}",
+ "plugin", plugin,
+ "function", function,
+ "args", functionArgsJ);
+ wrap_json_pack(&action, "{ss,so}",
+ "label", name.c_str(),
+ "callback", callbackJ);
}
}
- return ActionLoad(action);
+ if(action) {return ActionLoad(action);}
+ return nullptr;
}
-int bindingApp::loadOneSource(json_object* sourceJ)
+int bindingApp::loadOneSourceAPI(json_object* sourceJ)
{
json_object *initJ = nullptr, *getSignalJ = nullptr;
CtlActionT *initCtl, *getSignalCtl;
@@ -109,44 +128,53 @@ int bindingApp::loadOneSource(json_object* sourceJ)
return err;
}
- initCtl = convert2Action("init", initJ);
- getSignalCtl =convert2Action("getSignal", getSignalJ);
+ if(ctlConfig_ && ctlConfig_->requireJ)
+ {
+ const char* requireS = json_object_to_json_string(ctlConfig_->requireJ);
+ if(!strcasestr(requireS, api))
+ {AFB_WARNING("Caution! You don't specify the API source as required in the metadata section. This API '%s' may not be initialized", api);}
+ }
- sourcesList_.push_back(Source(api, info, initCtl, getSignalCtl));
+ if(initJ) {initCtl = convert2Action("init", initJ);}
+ if(getSignalJ) {getSignalCtl = convert2Action("getSignal", getSignalJ);}
+
+ sourcesList_.push_back(SourceAPI(api, info, initCtl, getSignalCtl));
return err;
}
-int bindingApp::loadSources(CtlSectionT* section, json_object *sourcesJ)
+int bindingApp::loadSourcesAPI(CtlSectionT* section, json_object *sourcesJ)
{
int err = 0;
bindingApp& bApp = instance();
- // add the signal composer itself as source
json_object *sigCompJ = nullptr;
- wrap_json_pack(&sigCompJ, "{ss,ss,so,so !}",
- "api", "signal-composer",
- "info", "Api on behalf the virtual signals are sent",
- "init", nullptr,
- "getSignal", nullptr);
- json_object_array_add(sourcesJ, sigCompJ);
-
- if (json_object_get_type(sourcesJ) == json_type_array)
+ // add the signal composer itself as source
+ if(sourcesJ)
{
- int count = json_object_array_length(sourcesJ);
+ wrap_json_pack(&sigCompJ, "{ss,ss}",
+ "api", "signal-composer",
+ "info", "Api on behalf the virtual signals are sent");
- for (int idx = 0; idx < count; idx++)
+ json_object_array_add(sourcesJ, sigCompJ);
+
+ if (json_object_get_type(sourcesJ) == json_type_array)
{
- json_object *sourceJ = json_object_array_get_idx(sourcesJ, idx);
- err = bApp.loadOneSource(sourceJ);
- if (err) return err;
+ int count = json_object_array_length(sourcesJ);
+
+ for (int idx = 0; idx < count; idx++)
+ {
+ json_object *sourceJ = json_object_array_get_idx(sourcesJ, idx);
+ err = bApp.loadOneSourceAPI(sourceJ);
+ if (err) return err;
+ }
}
- }
- else
- {
- if ((err = bApp.loadOneSource(sourcesJ))) return err;
- if ((err = bApp.loadOneSource(sigCompJ))) return err;
- }
+ else
+ {
+ if ((err = bApp.loadOneSourceAPI(sourcesJ))) return err;
+ if (sigCompJ && (err = bApp.loadOneSourceAPI(sigCompJ))) return err;
+ }
+}
return err;
}
@@ -172,7 +200,7 @@ int bindingApp::loadOneSignal(json_object* signalJ)
"onReceived", &onReceivedJ);
if (err)
{
- AFB_ERROR("Missing something id|source|class|[unit]|[frequency]|onReceived in %s", json_object_get_string(signalJ));
+ AFB_ERROR("Missing something id|source|[class]|[unit]|[frequency]|[onReceived] in %s", json_object_get_string(signalJ));
return err;
}
@@ -183,7 +211,7 @@ int bindingApp::loadOneSignal(json_object* signalJ)
int count = json_object_array_length(sourcesJ);
for(int i = 0; i < count; i++)
{
- std::string sourceStr = json_object_get_string(sourcesJ);
+ std::string sourceStr = json_object_get_string(json_object_array_get_idx(sourcesJ, i));
if( (sep = sourceStr.find("/")) != std::string::npos)
{
AFB_ERROR("Signal composition needs to use signal 'id', don't use full low level signal name");
@@ -203,12 +231,13 @@ int bindingApp::loadOneSignal(json_object* signalJ)
}
// Set default sClass is not specified
- sClass = "state";
+ sClass = !sClass ? "state" : sClass;
+ unit = !unit ? "" : unit;
// Get an action handler
onReceivedCtl = convert2Action("onReceived", onReceivedJ);
- Source* src = getSource(api);
+ SourceAPI* src = getSourceAPI(api) ? getSourceAPI(api):getSourceAPI("signal-composer");
if( src != nullptr)
{src->addSignal(id, sourcesV, sClass, unit, frequency, onReceivedCtl);}
else
@@ -239,6 +268,28 @@ int bindingApp::loadSignals(CtlSectionT* section, json_object *signalsJ)
return err;
}
+std::shared_ptr<Signal> bindingApp::searchSignal(const std::string& aName)
+{
+ std::string api;
+ size_t sep = aName.find_first_of("/");
+ if(sep != std::string::npos)
+ {
+ api = aName.substr(0, sep);
+ SourceAPI* source = getSourceAPI(api);
+ return source->searchSignal(aName);
+ }
+ else
+ {
+ std::vector<std::shared_ptr<Signal>> allSignals = getAllSignals();
+ for (std::shared_ptr<Signal>& sig : allSignals)
+ {
+ if(sig->id() == aName)
+ {return sig;}
+ }
+ }
+ return nullptr;
+}
+
std::vector<std::shared_ptr<Signal>> bindingApp::getAllSignals()
{
std::vector<std::shared_ptr<Signal>> allSignals;
diff --git a/signal-composer-binding/signal-composer.hpp b/signal-composer-binding/signal-composer.hpp
index 44b958f..8affc7a 100644
--- a/signal-composer-binding/signal-composer.hpp
+++ b/signal-composer-binding/signal-composer.hpp
@@ -19,12 +19,8 @@
#include <memory>
#include <vector>
#include <string>
-#include <ctl-config.h>
-#include <json-c/json.h>
-#include <systemd/sd-event.h>
#include "source.hpp"
-#include "signal-composer-binding.hpp"
class bindingApp
{
@@ -32,7 +28,7 @@ private:
CtlConfigT* ctlConfig_;
static CtlSectionT ctlSections_[]; ///< Config Section definition (note: controls section index should match handle retrieval in)
- std::vector<Source> sourcesList_;
+ std::vector<SourceAPI> sourcesList_;
explicit bindingApp(const std::string& filepath);
bindingApp();
@@ -40,19 +36,19 @@ private:
CtlActionT* convert2Action(const std::string& name, json_object* action);
- int loadOneSource(json_object* sourcesJ);
- static int loadSources(CtlSectionT* section, json_object *sectionJ);
+ int loadOneSourceAPI(json_object* sourcesJ);
+ static int loadSourcesAPI(CtlSectionT* section, json_object *sectionJ);
int loadOneSignal(json_object* signalsJ);
static int loadSignals(CtlSectionT* section, json_object *sectionJ);
- Source* getSource(const std::string& api);
-
public:
static bindingApp& instance();
- void loadConfig(const std::string& filepath);
- void loadSignalsFile(std::string signalsFile);
+ int loadConfig(const std::string& filepath);
+ //void loadSignalsFile(std::string signalsFile);
+ SourceAPI* getSourceAPI(const std::string& api);
+ std::shared_ptr<Signal> searchSignal(const std::string& aName);
std::vector<std::shared_ptr<Signal>> getAllSignals();
CtlConfigT* ctlConfig();
};
diff --git a/signal-composer-binding/signal-conf.cpp b/signal-composer-binding/signal-conf.cpp
deleted file mode 100644
index 73f2450..0000000
--- a/signal-composer-binding/signal-conf.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Romain Forlot" <romain.forlot@iot.bzh>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
diff --git a/signal-composer-binding/signal-conf.hpp b/signal-composer-binding/signal-conf.hpp
deleted file mode 100644
index 3698135..0000000
--- a/signal-composer-binding/signal-conf.hpp
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Romain Forlot" <romain.forlot@iot.bzh>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <json.hpp>
-
- class signalConfiguration
-{
-private:
- nlohmann::json config_;
-
-public:
- void parseConfig(std::string configPath);
-}
diff --git a/signal-composer-binding/signal.cpp b/signal-composer-binding/signal.cpp
index 6b4947e..0689a99 100644
--- a/signal-composer-binding/signal.cpp
+++ b/signal-composer-binding/signal.cpp
@@ -15,72 +15,111 @@
* limitations under the License.
*/
-#include "signal.hpp"
+#include <memory>
-Signal::Signal()
-{}
+#include "signal.hpp"
+#include "signal-composer.hpp"
-Signal(std::string& id,
- std::vector<std::string>& sources,
- std::string& unit,
- float frequency,
- CtlActionT* onReceived)
+Signal::Signal(const std::string& id,
+ std::vector<std::string>& sources,
+ const std::string& unit,
+ double frequency,
+ CtlActionT* onReceived)
:id_(id),
- sources_(sources),
- unit_(unit),
+ sourcesSig_(sources),
frequency_(frequency),
+ unit_(unit),
onReceived_(onReceived)
+{}
+
+Signal::operator bool() const
+{
+ if(id_.empty())
+ {return false;}
+ return true;
+}
+
+bool Signal::operator ==(const Signal& other) const
{
- for (const std::string& src: sources)
+ if(id_ == other.id_) {return true;}
+ return false;
+}
+
+bool Signal::operator==(const std::string& aName) const
+{
+ if(id_ == aName) {return true;}
+ for( const std::string& src : sourcesSig_)
{
- if(src.find("/") == std::string::npos)
+ if(src == aName) {return true;}
+ }
+ return false;
+}
+
+std::string Signal::id() const
+{
+ return id_;
+}
+void update(double timestamp, double value)
+{
+ AFB_NOTICE("Got an update from observed signal");
+}
+
+int Signal::onReceivedCB(json_object *queryJ)
+{
+ return ActionExecOne(onReceived_, queryJ);
+}
+
+void Signal::attach(Signal* obs)
+{
+ Observers_.push_back(obs);
+}
+
+void Signal::attachToSources(bindingApp& bApp)
+{
+ for (const std::string& srcSig: sourcesSig_)
+ {
+ if(srcSig.find("/") == std::string::npos)
{
- AFB_NOTICE("Attaching %s to %s", sig->id(), src);
- if(sig.attach(src))
- {AFB_WARNING("Can't attach. Is %s exists ?", src);}
+ std::shared_ptr<Signal> sig = bApp.searchSignal(srcSig);
+ if(sig)
+ {
+ AFB_NOTICE("Attaching %s to %s", id_.c_str(), srcSig.c_str());
+ sig->attach(this);
+ continue;
+ }
+ AFB_WARNING("Can't attach. Is %s exists ?", srcSig.c_str());
}
}
}
-Signal::operator bool() const
+void Signal::notify()
{
- if(!id_ || !api_ || !signalName_)
- {return false;}
- return true;
+ for (int i = 0; i < Observers_.size(); ++i)
+ Observers_[i]->update(timestamp_, value_);
}
int Signal::recursionCheck(const std::string& origId)
{
for (const auto& obs: Observers_)
{
- if( id_ == obs.id())
+ if( id_ == obs->id())
{return -1;}
- if( origId == obs.id())
+ if( origId == obs->id())
{return -1;}
- if(! obs.recursionCheck(origId))
+ if(! obs->recursionCheck(origId))
{return -1;}
}
return 0;
}
-std::string Signal::id() const
-{
- return id_;
-}
-
int Signal::recursionCheck()
{
for (const auto& obs: Observers_)
{
- if( id_ == obs.id())
+ if( id_ == obs->id())
{return -1;}
- if(! obs.recursionCheck(id_))
+ if( obs->recursionCheck(id_))
{return -1;}
}
return 0;
}
-
-void update(double timestamp, double value)
-{
- AFB_NOTICE("Got an update from observed signal");
-}
diff --git a/signal-composer-binding/signal.hpp b/signal-composer-binding/signal.hpp
index ad944aa..cb50c67 100644
--- a/signal-composer-binding/signal.hpp
+++ b/signal-composer-binding/signal.hpp
@@ -19,40 +19,43 @@
#include <map>
#include <string>
-#include <memory>
#include <vector>
#include <ctl-config.h>
-#include "observer.hpp"
+class bindingApp;
-class Signal;
-
-//TODO: claneys: define observer and observable interface then inherit
-class Signal: public Observer, public Subject
+class Signal
{
private:
std::string id_;
- std::vector<std::string> sources_;
- std::map<long, double> history_; ///< history_ - Hold signal value history in map with <timestamp, value>
+ std::vector<std::string> sourcesSig_;
+ long long int timestamp_;
+ double value_;
+ std::map<long long int, double> history_; ///< history_ - Hold signal value history in map with <timestamp, value>
double frequency_;
std::string unit_;
CtlActionT* onReceived_;
+ std::vector<Signal*> Observers_;
- std::vector<std::shared_ptr<Signal>> observers_;
-
+ void attach(Signal *obs);
int recursionCheck(const std::string& origId);
+
public:
- Signal();
Signal(const std::string& id, std::vector<std::string>& sources, const std::string& unit, double frequency, CtlActionT* onReceived);
explicit operator bool() const;
+ bool operator==(const Signal& other) const;
+ bool operator==(const std::string& aName) const;
std::string id() const;
- int recursionCheck();
- /* virtual */ void update(double timestamp, double value);
+ void update(long long int timestamp, double value);
+ int onReceivedCB(json_object *queryJ);
+ void attachToSources(bindingApp& bApp);
+ void notify();
- virtual double average() const;
- virtual double min() const;
- virtual double max() const;
- double lastValue() const;
+ //virtual double average() const;
+ //virtual double min() const;
+ //virtual double max() const;
+ //double lastValue() const;
+ int recursionCheck();
};
diff --git a/signal-composer-binding/source.cpp b/signal-composer-binding/source.cpp
index 919ae5b..6e7fec2 100644
--- a/signal-composer-binding/source.cpp
+++ b/signal-composer-binding/source.cpp
@@ -17,26 +17,35 @@
#include "source.hpp"
-Source::Source()
+SourceAPI::SourceAPI()
{}
-Source::Source(const std::string& api, const std::string& info, CtlActionT* init, CtlActionT* getSignal):
+SourceAPI::SourceAPI(const std::string& api, const std::string& info, CtlActionT* init, CtlActionT* getSignal):
api_(api), info_(info), init_(init), getSignal_(getSignal)
{}
-std::string Source::api()
+std::string SourceAPI::api() const
{
return api_;
}
-void Source::addSignal(const std::string& id, std::vector<std::string>& sources, const std::string& sClass, const std::string& unit, double frequency, CtlActionT* onReceived)
+void SourceAPI::addSignal(const std::string& id, std::vector<std::string>& sources, const std::string& sClass, const std::string& unit, double frequency, CtlActionT* onReceived)
{
std::shared_ptr<Signal> sig = std::make_shared<Signal>(id, sources, unit, frequency, onReceived);
signals_.push_back(sig);
}
-std::vector<std::shared_ptr<Signal>> Source::getSignals()
+std::vector<std::shared_ptr<Signal>> SourceAPI::getSignals() const
{
return signals_;
}
+
+std::shared_ptr<Signal> SourceAPI::searchSignal(const std::string& name) const
+{
+ for (auto& sig: signals_)
+ {
+ if(*sig == name) {return sig;}
+ }
+ return nullptr;
+}
diff --git a/signal-composer-binding/source.hpp b/signal-composer-binding/source.hpp
index 694daae..c1644c5 100644
--- a/signal-composer-binding/source.hpp
+++ b/signal-composer-binding/source.hpp
@@ -18,12 +18,10 @@
#pragma once
#include <memory>
-#include <ctl-config.h>
-#include <signal-composer-binding.hpp>
#include "signal.hpp"
-class Source {
+class SourceAPI {
private:
std::string api_;
std::string info_;
@@ -33,10 +31,12 @@ private:
std::vector<std::shared_ptr<Signal>> signals_;
public:
- Source();
- Source(const std::string& api, const std::string& info, CtlActionT* init, CtlActionT* getSignal);
+ SourceAPI();
+ SourceAPI(const std::string& api, const std::string& info, CtlActionT* init, CtlActionT* getSignal);
- std::string api();
+ std::string api() const;
void addSignal(const std::string& id, std::vector<std::string>& sources, const std::string& sClass, const std::string& unit, double frequency, CtlActionT* onReceived);
- std::vector<std::shared_ptr<Signal>> getSignals();
+
+ std::vector<std::shared_ptr<Signal>> getSignals() const;
+ std::shared_ptr<Signal> searchSignal(const std::string& name) const;
};