summaryrefslogtreecommitdiffstats
path: root/signal-composer-binding/signal-composer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'signal-composer-binding/signal-composer.cpp')
-rw-r--r--signal-composer-binding/signal-composer.cpp243
1 files changed, 242 insertions, 1 deletions
diff --git a/signal-composer-binding/signal-composer.cpp b/signal-composer-binding/signal-composer.cpp
index 73f2450..6f629e1 100644
--- a/signal-composer-binding/signal-composer.cpp
+++ b/signal-composer-binding/signal-composer.cpp
@@ -13,4 +13,245 @@
* 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 "signal-composer.hpp"
+
+CtlSectionT bindingApp::ctlSections_[] = {
+ [0]={.key="sources" ,.label = "sources", .info=nullptr,
+ .loadCB=loadSources,
+ .handle=nullptr},
+ [1]={.key="signals" , .label= "signals", .info=nullptr,
+ .loadCB=loadSignals,
+ .handle=nullptr},
+ [2]={.key=nullptr, .label=nullptr, .info=nullptr,
+ .loadCB=nullptr,
+ .handle=nullptr}
+};
+
+bindingApp::bindingApp()
+{}
+
+void bindingApp::loadConfig(const std::string& filepath)
+{
+ ctlConfig_ = CtlConfigLoad(filepath.c_str(), ctlSections_);
+}
+
+bindingApp& bindingApp::instance()
+{
+ static bindingApp bApp;
+ return bApp;
+}
+
+Source* bindingApp::getSource(const std::string& api)
+{
+ for(auto& source: sourcesList_)
+ {
+ if (source.api() == api)
+ {return &source;}
+ }
+ return nullptr;
+}
+
+CtlActionT* bindingApp::convert2Action(const std::string& name, json_object* action)
+{
+ json_object *functionArgsJ = nullptr;
+ const char* function;
+
+ if(action &&
+ wrap_json_unpack(action, "{ss,s?o !}", "function", &function, "args", &functionArgsJ))
+ {
+ std::string functionS = function;
+ json_object* action = nullptr;
+ ssize_t sep;
+ if(functionS.find("lua") != std::string::npos)
+ {
+ wrap_json_pack(&action, "{ss,s?s,s?o,s?s,s?s,s?s,s?o !}",
+ "label", name,
+ "lua", function,
+ "args", functionArgsJ);
+ }
+ else if( (sep = functionS.find_first_of("/")) != std::string::npos)
+ {
+ 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,
+ "api", api,
+ "verb", verb,
+ "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);
+ }
+ }
+ return ActionLoad(action);
+}
+
+int bindingApp::loadOneSource(json_object* sourceJ)
+{
+ json_object *initJ = nullptr, *getSignalJ = nullptr;
+ CtlActionT *initCtl, *getSignalCtl;
+ const char *api, *info;
+
+ int err = wrap_json_unpack(sourceJ, "{ss,s?s,s?o,s?o !}",
+ "api", &api,
+ "info", &info,
+ "init", &initJ,
+ "getSignal", &getSignalJ);
+ if (err)
+ {
+ AFB_ERROR("Missing something api|[info]|[init]|[getSignal] in %s", json_object_get_string(sourceJ));
+ return err;
+ }
+
+ initCtl = convert2Action("init", initJ);
+ getSignalCtl =convert2Action("getSignal", getSignalJ);
+
+ sourcesList_.push_back(Source(api, info, initCtl, getSignalCtl));
+
+ return err;
+}
+
+int bindingApp::loadSources(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)
+ {
+ 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.loadOneSource(sourceJ);
+ if (err) return err;
+ }
+ }
+ else
+ {
+ if ((err = bApp.loadOneSource(sourcesJ))) return err;
+ if ((err = bApp.loadOneSource(sigCompJ))) return err;
+ }
+
+ return err;
+}
+
+int bindingApp::loadOneSignal(json_object* signalJ)
+{
+ json_object *onReceivedJ = nullptr, *sourcesJ = nullptr;
+ CtlActionT* onReceivedCtl;
+ const char *id = nullptr,
+ *sClass = nullptr,
+ *unit = nullptr;
+ double frequency;
+ std::string api;
+ std::vector<std::string> sourcesV;
+ ssize_t sep;
+
+ int err = wrap_json_unpack(signalJ, "{ss,so,s?s,s?s,s?F,s?o !}",
+ "id", &id,
+ "source", &sourcesJ,
+ "class", &sClass,
+ "unit", &unit,
+ "frequency", &frequency,
+ "onReceived", &onReceivedJ);
+ if (err)
+ {
+ AFB_ERROR("Missing something id|source|class|[unit]|[frequency]|onReceived in %s", json_object_get_string(signalJ));
+ return err;
+ }
+
+ // Process sources JSON object
+ // TODO: claneys, really needs to factorize JSON array processing
+ if (json_object_get_type(sourcesJ) == json_type_array)
+ {
+ int count = json_object_array_length(sourcesJ);
+ for(int i = 0; i < count; i++)
+ {
+ std::string sourceStr = json_object_get_string(sourcesJ);
+ if( (sep = sourceStr.find("/")) != std::string::npos)
+ {
+ AFB_ERROR("Signal composition needs to use signal 'id', don't use full low level signal name");
+ return -1;
+ }
+ sourcesV.push_back(sourceStr);
+ }
+ }
+ else
+ {
+ std::string sourceStr = json_object_get_string(sourcesJ);
+ if( (sep = sourceStr.find("/")) != std::string::npos)
+ {
+ api = sourceStr.substr(0, sep);
+ }
+ sourcesV.push_back(sourceStr);
+ }
+
+ // Set default sClass is not specified
+ sClass = "state";
+
+ // Get an action handler
+ onReceivedCtl = convert2Action("onReceived", onReceivedJ);
+
+ Source* src = getSource(api);
+ if( src != nullptr)
+ {src->addSignal(id, sourcesV, sClass, unit, frequency, onReceivedCtl);}
+ else
+ {err = -1;}
+
+ return err;
+}
+
+int bindingApp::loadSignals(CtlSectionT* section, json_object *signalsJ)
+{
+ int err = 0;
+ bindingApp& bApp = instance();
+
+ if (json_object_get_type(signalsJ) == json_type_array)
+ {
+ int count = json_object_array_length(signalsJ);
+
+ for (int idx = 0; idx < count; idx++)
+ {
+ json_object *signalJ = json_object_array_get_idx(signalsJ, idx);
+ err = bApp.loadOneSignal(signalJ);
+ if (err) return err;
+ }
+ }
+ else
+ {err = bApp.loadOneSignal(signalsJ);}
+
+ return err;
+}
+
+std::vector<std::shared_ptr<Signal>> bindingApp::getAllSignals()
+{
+ std::vector<std::shared_ptr<Signal>> allSignals;
+ for( auto& source : sourcesList_)
+ {
+ std::vector<std::shared_ptr<Signal>> srcSignals = source.getSignals();
+ allSignals.insert(allSignals.end(), srcSignals.begin(), srcSignals.end());
+ }
+
+ return allSignals;
+}
+
+CtlConfigT* bindingApp::ctlConfig()
+{
+ return ctlConfig_;
+}