diff options
author | Romain Forlot <romain.forlot@iot.bzh> | 2017-09-12 00:29:28 +0200 |
---|---|---|
committer | Romain Forlot <romain.forlot@iot.bzh> | 2017-12-14 11:00:25 +0100 |
commit | d663f702c0e4fa562783504a483dce8f362d628e (patch) | |
tree | fdb656d0467a935aa6790dd9e05d3e373606a3e1 /signal-composer-binding/signal-composer.cpp | |
parent | 75cfbf3d0206f12422091e6479c508c69445bf4a (diff) |
Progression on config parsing.
Change-Id: Idd8d8987ccabef381f6d79c1d508930a2d4bae3c
Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
Diffstat (limited to 'signal-composer-binding/signal-composer.cpp')
-rw-r--r-- | signal-composer-binding/signal-composer.cpp | 243 |
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_; +} |