diff options
author | Romain Forlot <romain.forlot@iot.bzh> | 2018-07-22 01:13:17 +0200 |
---|---|---|
committer | Romain Forlot <romain.forlot@iot.bzh> | 2018-07-25 10:08:07 +0200 |
commit | 7f15ef65f420179b606f136ed805fae9d320b321 (patch) | |
tree | c4ef2dde841415ce4dedcaaa5f0edf7e258bc356 | |
parent | 3b08cec1ad06f313374bc1fd9cc64e1b28ce798d (diff) |
Improved performance
Before value was translated to a C type variable two times,
at the reception then at the emission. Now it just receives
and sends the signal value without translation nor interpretation
except if you ask for an average, minimum or maximum value. Then in
those cases it interprets the json to return you a value or an
error if there is no numeric values to compute.
Remove unneeded log message at event reception.
Improved signal search engine, will search in source's signals map
by the signal ID not the event name which lead to a more direct map
match.
Bugs-AGL: SPEC-1612
Depends-On: I43e79ed73a507ac2ca7ed4cdc3f16ec009392194
Change-Id: Ie253c3fe1e8cde42dabe8832da74e9f9bf442c14
Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
m--------- | ctl-utilities | 0 | ||||
-rw-r--r-- | plugins/builtin.cpp | 14 | ||||
-rw-r--r-- | plugins/gps.cpp | 2 | ||||
-rw-r--r-- | plugins/low-can.cpp | 34 | ||||
-rw-r--r-- | signal-composer-binding/signal-composer-binding.cpp | 4 | ||||
-rw-r--r-- | signal-composer-binding/signal-composer.cpp | 62 | ||||
-rw-r--r-- | signal-composer-binding/signal.cpp | 139 | ||||
-rw-r--r-- | signal-composer-binding/signal.hpp | 45 | ||||
-rw-r--r-- | signal-composer-binding/source.cpp | 2 |
9 files changed, 126 insertions, 176 deletions
diff --git a/ctl-utilities b/ctl-utilities -Subproject ff14c58cb3390065a20f598d58efaea088d7107 +Subproject a58d83be3c4dc0ea780ab4094b12dd9d125368b diff --git a/plugins/builtin.cpp b/plugins/builtin.cpp index e56d413..28bcba7 100644 --- a/plugins/builtin.cpp +++ b/plugins/builtin.cpp @@ -32,27 +32,23 @@ CTLP_LUA_REGISTER("builtin"); CTLP_LUA2C (setSignalValueWrap, source, argsJ, responseJ) { const char* name = nullptr; - double resultNum; + json_object* resultNumJ; uint64_t timestamp; struct signalCBT* ctx = (struct signalCBT*)source->context; - if(! wrap_json_unpack(argsJ, "{ss, sF, sI? !}", + if(! wrap_json_unpack(argsJ, "{ss, so, sI? !}", "name", &name, - "value", &resultNum, + "value", &resultNumJ, "timestamp", ×tamp)) { - *responseJ = json_object_new_string("Fail to unpack JSON arguments value"); return -1; } - *responseJ = json_object_new_string(json_object_to_json_string(argsJ)); - - struct signalValue result = resultNum; if(ctx->aSignal) - {ctx->setSignalValue(ctx->aSignal, timestamp*NANO, result);} + ctx->setSignalValue(ctx->aSignal, timestamp*NANO, resultNumJ); else - {ctx->searchNsetSignalValue(name, timestamp*NANO, result);} + ctx->searchNsetSignalValue(name, timestamp*NANO, resultNumJ); return 0; } diff --git a/plugins/gps.cpp b/plugins/gps.cpp index 646754a..4913f31 100644 --- a/plugins/gps.cpp +++ b/plugins/gps.cpp @@ -59,7 +59,7 @@ CTLP_CAPI (getHeading, source, argsJ, eventJ) { if(coordUpdated) { heading = round(r2d * atan2((curLon - prvLon) * cos(d2r * curLat), curLat - prvLat)); - ctx->setSignalValue(ctx->aSignal, 0, heading); + ctx->setSignalValue(ctx->aSignal, 0, json_object_new_double(heading)); } AFB_NOTICE("======== Heading: %f", heading); diff --git a/plugins/low-can.cpp b/plugins/low-can.cpp index 7bbe763..5153ee9 100644 --- a/plugins/low-can.cpp +++ b/plugins/low-can.cpp @@ -31,8 +31,8 @@ extern "C" CTLP_CAPI_REGISTER("low-can"); typedef struct { - bool door; - bool window; + json_object* door; + json_object* window; } doorT; typedef struct { @@ -47,11 +47,13 @@ struct pluginCtxT { allDoorsCtxT allDoorsCtx; }; -void setDoor(doorT* aDoor, const char* eventName, int eventStatus) +void setDoor(doorT* aDoor, const char* eventName, json_object* eventStatus) { - if(strcasestr(eventName, "door")) {aDoor->door = eventStatus;} - else if(strcasestr(eventName, "window")) {aDoor->window = eventStatus;} - else {AFB_WARNING("Unexpected behavior, this '%s' is not a door ! ", eventName);} + if(json_object_is_type(eventStatus, json_type_boolean)) { + if(strcasestr(eventName, "door")) aDoor->door = eventStatus; + else if(strcasestr(eventName, "window")) aDoor->window = eventStatus; + else AFB_WARNING("Unexpected behavior, this '%s' is not a door ! ", eventName); + } } // Call at initialisation time @@ -132,12 +134,12 @@ CTLP_CAPI (subscribeToLow, source, argsJ, eventJ) { CTLP_CAPI (isOpen, source, argsJ, eventJ) { const char *eventName = nullptr; - int eventStatus; + json_object *eventStatus; uint64_t timestamp; struct signalCBT* context = reinterpret_cast<struct signalCBT*>(source->context); struct pluginCtxT* pluginCtx = reinterpret_cast<struct pluginCtxT*>(context->pluginCtx); - int err = wrap_json_unpack(eventJ, "{ss,sb,s?I}", + int err = wrap_json_unpack(eventJ, "{ss,so,s?I}", "name", &eventName, "value", &eventStatus, "timestamp", ×tamp); @@ -177,14 +179,14 @@ CTLP_CAPI (isOpen, source, argsJ, eventJ) { source->uid, argsJ ? json_object_to_json_string(argsJ):"", eventJ ? json_object_to_json_string(eventJ):"", - pluginCtx->allDoorsCtx.front_left.door ? "true":"false", - pluginCtx->allDoorsCtx.front_left.window ? "true":"false", - pluginCtx->allDoorsCtx.front_right.door ? "true":"false", - pluginCtx->allDoorsCtx.front_right.window ? "true":"false", - pluginCtx->allDoorsCtx.rear_left.door ? "true":"false", - pluginCtx->allDoorsCtx.rear_left.window ? "true":"false", - pluginCtx->allDoorsCtx.rear_right.door ? "true":"false", - pluginCtx->allDoorsCtx.rear_right.window ? "true":"false" + json_object_get_string(pluginCtx->allDoorsCtx.front_left.door), + json_object_get_string(pluginCtx->allDoorsCtx.front_left.window), + json_object_get_string(pluginCtx->allDoorsCtx.front_right.door), + json_object_get_string(pluginCtx->allDoorsCtx.front_right.window), + json_object_get_string(pluginCtx->allDoorsCtx.rear_left.door), + json_object_get_string(pluginCtx->allDoorsCtx.rear_left.window), + json_object_get_string(pluginCtx->allDoorsCtx.rear_right.door), + json_object_get_string(pluginCtx->allDoorsCtx.rear_right.window) ); return 0; diff --git a/signal-composer-binding/signal-composer-binding.cpp b/signal-composer-binding/signal-composer-binding.cpp index 0d9c8e3..f7c8c73 100644 --- a/signal-composer-binding/signal-composer-binding.cpp +++ b/signal-composer-binding/signal-composer-binding.cpp @@ -32,10 +32,8 @@ /// @param[in] object - eventual data that comes with the event void onEvent(const char *event, json_object *object) { - Composer& composer = Composer::instance(); - AFB_NOTICE("event: %s", json_object_to_json_string(object)); + std::vector<std::shared_ptr<Signal>> signals { Composer::instance().searchSignals(event) }; - std::vector<std::shared_ptr<Signal>> signals = composer.searchSignals(event); if(!signals.empty()) { // If there is more than 1 element then maybe we can find a more diff --git a/signal-composer-binding/signal-composer.cpp b/signal-composer-binding/signal-composer.cpp index 99129b4..f7c1971 100644 --- a/signal-composer-binding/signal-composer.cpp +++ b/signal-composer-binding/signal-composer.cpp @@ -21,7 +21,7 @@ #include "clientApp.hpp" -extern "C" void searchNsetSignalValueHandle(const char* aName, uint64_t timestamp, struct signalValue value) +extern "C" void searchNsetSignalValueHandle(const char* aName, uint64_t timestamp, json_object* value) { std::vector<std::shared_ptr<Signal>> signals = Composer::instance().searchSignals(aName); if(!signals.empty()) @@ -31,7 +31,7 @@ extern "C" void searchNsetSignalValueHandle(const char* aName, uint64_t timestam } } -extern "C" void setSignalValueHandle(void* aSignal, uint64_t timestamp, struct signalValue value) +extern "C" void setSignalValueHandle(void* aSignal, uint64_t timestamp, json_object* value) { Signal* sig = static_cast<Signal*>(aSignal); sig->set(timestamp, value); @@ -380,47 +380,25 @@ void Composer::processOptions(const std::map<std::string, int>& opts, std::share { avg = true; double value = sig->average(o.second); - json_object_object_add(response, "value", - json_object_new_double(value)); + json_object_object_add(response, "value", json_object_new_double(value)); } else if (o.first.compare("minimum") && !min) { min = true; double value = sig->minimum(); - json_object_object_add(response, "value", - json_object_new_double(value)); + json_object_object_add(response, "value", json_object_new_double(value)); } else if (o.first.compare("maximum") && !max) { max = true; double value = sig->maximum(); - json_object_object_add(response, "value", - json_object_new_double(value)); + json_object_object_add(response, "value", json_object_new_double(value)); } else if (o.first.compare("last") && !last) { last = true; - struct signalValue value = sig->last_value(); - if(value.hasBool) - { - json_object_object_add(response, "value", - json_object_new_boolean(value.boolVal)); - } - else if(value.hasNum) - { - json_object_object_add(response, "value", - json_object_new_double(value.numVal)); - } - else if(value.hasStr) - { - json_object_object_add(response, "value", - json_object_new_string(value.strVal.c_str())); - } - else - { - json_object_object_add(response, "value", - json_object_new_string("No recorded value so far.")); - } + json_object* value = sig->last_value(); + json_object_object_add(response, "value", value); } else { @@ -568,8 +546,9 @@ std::vector<std::shared_ptr<Signal>> Composer::searchSignals(const std::string& if(sep != std::string::npos) { api = aName.substr(0, sep); + std::string signal_id = aName.substr(sep + 1, std::string::npos); std::shared_ptr<SourceAPI> source = getSourceAPI(api); - return source->searchSignals(aName); + return source->searchSignals(signal_id); } else { @@ -603,27 +582,8 @@ json_object* Composer::getsignalValue(const std::string& sig, json_object* optio "signal", sig->id().c_str()); if (opts.empty()) { - struct signalValue value = sig->last_value(); - if(value.hasBool) - { - json_object_object_add(response, "value", - json_object_new_boolean(value.boolVal)); - } - else if(value.hasNum) - { - json_object_object_add(response, "value", - json_object_new_double(value.numVal)); - } - else if(value.hasStr) - { - json_object_object_add(response, "value", - json_object_new_string(value.strVal.c_str())); - } - else - { - json_object_object_add(response, "value", - json_object_new_string("No recorded value so far.")); - } + json_object* value = sig->last_value(); + json_object_object_add(response, "value", value); } else {processOptions(opts, sig, response);} diff --git a/signal-composer-binding/signal.cpp b/signal-composer-binding/signal.cpp index 2f1aa57..14e85ba 100644 --- a/signal-composer-binding/signal.cpp +++ b/signal-composer-binding/signal.cpp @@ -148,9 +148,8 @@ json_object* Signal::toJSON() const if(timestamp_) json_object_object_add(sigJ, "timestamp", json_object_new_int64(timestamp_)); - if (value_.hasBool) {json_object_object_add(sigJ, "value", json_object_new_boolean(value_.boolVal));} - else if (value_.hasNum) {json_object_object_add(sigJ, "value", json_object_new_double(value_.numVal));} - else if (value_.hasStr) {json_object_object_add(sigJ, "value", json_object_new_string(value_.strVal.c_str()));} + if(value_) + json_object_object_add(sigJ, "value", value_); return sigJ; } @@ -198,19 +197,21 @@ json_object *Signal::getSignalsArgs() /// /// @param[in] timestamp - timestamp of occured signal /// @param[in] value - value of change -void Signal::set(uint64_t timestamp, struct signalValue& value) +void Signal::set(uint64_t timestamp, json_object*& value) { uint64_t diff = retention_+1; value_ = value; timestamp_ = timestamp; - history_[timestamp_] = value_; + history_[timestamp_] = json_object_get(value_); while(diff > retention_) { uint64_t first = history_.begin()->first; diff = (timestamp_ - first)/NANO; - if(diff > retention_) - {history_.erase(history_.cbegin());} + if(diff > retention_) { + json_object_put(history_.cbegin()->second); + history_.erase(history_.cbegin()); + } } notify(); @@ -253,37 +254,22 @@ void Signal::update(Signal* sig) /// @param[in] eventJ - json_object containing event data to process /// /// @return 0 if ok, -1 or others if not -void Signal::defaultReceivedCB(json_object *eventJ) +void Signal::defaultReceivedCB(Signal *signal, json_object *eventJ) { uint64_t ts = 0; - struct signalValue sv; + json_object* sv = nullptr; json_object_iterator iter = json_object_iter_begin(eventJ); json_object_iterator iterEnd = json_object_iter_end(eventJ); + while(!json_object_iter_equal(&iter, &iterEnd)) { std::string key = json_object_iter_peek_name(&iter); std::transform(key.begin(), key.end(), key.begin(), ::tolower); json_object *value = json_object_iter_peek_value(&iter); if (key.find("value") != std::string::npos || - key.find(id_) != std::string::npos) + key.find(signal->id()) != std::string::npos) { - switch (json_object_get_type(value)) { - case json_type_double: - sv = json_object_get_double(value); - break; - case json_type_int: - sv = json_object_get_int(value); - break; - case json_type_boolean: - sv = json_object_get_int(value); - break; - case json_type_string: - sv = json_object_get_string(value); - break; - default: - sv = signalValue(); - break; - } + sv = json_object_get(value); } else if (key.find("timestamp") != std::string::npos) { @@ -292,9 +278,9 @@ void Signal::defaultReceivedCB(json_object *eventJ) json_object_iter_next(&iter); } - if(!sv.hasBool && !sv.hasNum && !sv.hasStr) + if(!sv) { - AFB_ERROR("No data found to set signal %s in %s", id_.c_str(), json_object_to_json_string(eventJ)); + AFB_ERROR("No data found to set signal %s in %s", signal->id().c_str(), json_object_to_json_string(eventJ)); return; } else if(ts == 0) @@ -305,7 +291,7 @@ void Signal::defaultReceivedCB(json_object *eventJ) ts = (uint64_t)(t.tv_sec) * (uint64_t)NANO + (uint64_t)(t.tv_nsec); } - set(ts, sv); + signal->set(ts, sv); } /// @brief Notify observers that there is a change and execute callback defined @@ -343,7 +329,7 @@ void Signal::onReceivedCB(json_object *eventJ) if (onReceived_) ActionExecOne(&source, onReceived_, json_object_get(eventJ)); else - defaultReceivedCB(eventJ); + defaultReceivedCB(this, eventJ); } /// @brief Make a Signal observer observes Signals observables @@ -382,22 +368,31 @@ double Signal::average(int seconds) const double total = 0.0; int nbElt = 0; - for (const auto& val: history_) + for(const auto& val: history_) { - if(val.first >= end) - {break;} - if(val.second.hasNum) + if(val.first >= end) { + break; + } + if(val.second) { - total += val.second.numVal; + switch(json_object_get_type(val.second)) { + case json_type_int: + total += static_cast<double>(json_object_get_int64(val.second)); + break; + case json_type_double: + total += json_object_get_double(val.second); + break; + default: + AFB_ERROR("The stored value '%s' for the signal '%s' isn't numeric, it is not possible to compute an average value.", json_object_get_string(val.second), id_.c_str()); + break; + } nbElt++; } else { - AFB_ERROR("There isn't numerical value to compare with in that signal '%s'. Stored value : bool %d, num %lf, str: %s", + AFB_ERROR("There isn't numerical value to compare with in that signal '%s'. Stored value: %s", id_.c_str(), - val.second.boolVal, - val.second.numVal, - val.second.strVal.c_str()); + json_object_get_string(val.second)); break; } } @@ -416,21 +411,34 @@ double Signal::minimum(int seconds) const uint64_t end = seconds ? begin+(seconds*NANO) : history_.rbegin()->first; + double current = 0.0; double min = DBL_MAX; - for (auto& v : history_) + for(const auto& val : history_) { - if(v.first >= end) - {break;} - else if(v.second.hasNum && v.second.numVal < min) - {min = v.second.numVal;} + if(val.first >= end) { + break; + } + else if(val.second) { + switch(json_object_get_type(val.second)) { + case json_type_int: + current = static_cast<double>(json_object_get_int64(val.second)); + min = current < min ? current : min; + break; + case json_type_double: + current = json_object_get_double(val.second); + min = current < min ? current : min; + break; + default: + AFB_ERROR("The stored value '%s' for signal '%s' isn't numeric, it is not possible to find a minimum value.", json_object_get_string(val.second), id_.c_str()); + break; + } + } else { - AFB_ERROR("There isn't numerical value to compare with in that signal '%s'. Stored value : bool %d, num %lf, str: %s", + AFB_ERROR("There isn't numerical value to compare with in that signal '%s'. Stored value: %s", id_.c_str(), - v.second.boolVal, - v.second.numVal, - v.second.strVal.c_str()); + json_object_get_string(val.second)); break; } } @@ -448,21 +456,34 @@ double Signal::maximum(int seconds) const uint64_t end = seconds ? begin+(seconds*NANO) : history_.rbegin()->first; + double current = 0.0; double max = 0.0; - for (auto& v : history_) + for(const auto& val : history_) { - if(v.first >= end) - {break;} - else if(v.second.hasNum && v.second.hasNum > max) - {max = v.second.numVal;} + if(val.first >= end) { + break; + } + else if(val.second) { + switch(json_object_get_type(val.second)) { + case json_type_int: + current = static_cast<double>(json_object_get_int64(val.second)); + max = current > max ? current : max; + break; + case json_type_double: + current = json_object_get_double(val.second); + max = current > max ? current : max; + break; + default: + AFB_ERROR("The stored value '%s' for signal '%s' isn't numeric, it is not possible to find a maximum value.", json_object_get_string(val.second), id_.c_str()); + break; + } + } else { - AFB_ERROR("There isn't numerical value to compare with in that signal '%s'. Stored value : bool %d, num %lf, str: %s", + AFB_ERROR("There isn't numerical value to compare with in that signal '%s'. Stored value: %s", id_.c_str(), - v.second.boolVal, - v.second.numVal, - v.second.strVal.c_str()); + json_object_get_string(val.second)); break; } } @@ -472,7 +493,7 @@ double Signal::maximum(int seconds) const /// @brief Return last value recorded /// /// @return Last value -struct signalValue Signal::last_value() const +json_object* Signal::last_value() const { return value_; } diff --git a/signal-composer-binding/signal.hpp b/signal-composer-binding/signal.hpp index 0a12b16..6c7f43f 100644 --- a/signal-composer-binding/signal.hpp +++ b/signal-composer-binding/signal.hpp @@ -28,40 +28,14 @@ class Composer; -/// @brief Structure holding a possible value of a Signal -/// as it could be different type of value, we declare all -/// possibility. -/// Not very efficient or optimized, maybe use of Variant in -/// C++17 but this is a bit too new to uses it for now -struct signalValue { - bool undefined; - bool hasBool; - bool boolVal; - bool hasNum; - double numVal; - bool hasStr; - std::string strVal; - - signalValue(): - undefined(true), hasBool(false), boolVal(false), hasNum(false), numVal(0), hasStr(false), strVal("") {}; - signalValue(bool b): - undefined(false), hasBool(true), boolVal(b), hasNum(false), numVal(0), hasStr(false), strVal("") {}; - signalValue(int i): - undefined(false), hasBool(false), boolVal(false), hasNum(true), numVal(i), hasStr(false), strVal("") {}; - signalValue(double d): - undefined(false), hasBool(false), boolVal(false), hasNum(true), numVal(d), hasStr(false), strVal("") {}; - signalValue(const std::string& s): - undefined(false), hasBool(false), boolVal(false), hasNum(false), numVal(0), hasStr(true), strVal(s) {}; -}; - -extern "C" void searchNsetSignalValueHandle(const char* aName, uint64_t timestamp, struct signalValue value); -extern "C" void setSignalValueHandle(void* aSignal, uint64_t timestamp, struct signalValue value); +extern "C" void searchNsetSignalValueHandle(const char* aName, uint64_t timestamp, json_object* value); +extern "C" void setSignalValueHandle(void* aSignal, uint64_t timestamp, json_object* value); /// @brief Holds composer callbacks and obj to manipulate struct signalCBT { - void (*searchNsetSignalValue)(const char* aName, uint64_t timestamp, struct signalValue value); - void (*setSignalValue)(void* aSignal, uint64_t timestamp, struct signalValue value); + void (*searchNsetSignalValue)(const char* aName, uint64_t timestamp, json_object* value); + void (*setSignalValue)(void* aSignal, uint64_t timestamp, json_object* value); void* aSignal; void* pluginCtx; }; @@ -80,8 +54,8 @@ private: std::string event_; std::vector<std::string> dependsSigV_; uint64_t timestamp_; - struct signalValue value_; - std::map<uint64_t, struct signalValue> history_; ///< history_ - Hold signal value history in map with <timestamp, value> + json_object* value_; + std::map<uint64_t, json_object*> history_; ///< history_ - Hold signal value history in map with <timestamp, value> int retention_; double frequency_; std::string unit_; @@ -107,17 +81,16 @@ public: struct signalCBT* get_context(); json_object *getSignalsArgs(); - void set(uint64_t timestamp, struct signalValue& value); + void set(uint64_t timestamp, json_object*& value); void update(Signal* sig); - static int defaultOnReceivedCB(CtlSourceT* source, json_object* argsJ, json_object *queryJ); - void defaultReceivedCB(json_object *eventJ); + static void defaultReceivedCB(Signal *signal, json_object *eventJ); void onReceivedCB(json_object *eventJ); void attachToSourceSignals(Composer& composer); double average(int seconds = 0) const; double minimum(int seconds = 0) const; double maximum(int seconds = 0) const; - struct signalValue last_value() const; + json_object* last_value() const; uint64_t last_timestamp() const; int initialRecursionCheck(); diff --git a/signal-composer-binding/source.cpp b/signal-composer-binding/source.cpp index a46e766..bd988c9 100644 --- a/signal-composer-binding/source.cpp +++ b/signal-composer-binding/source.cpp @@ -122,7 +122,7 @@ std::vector<std::shared_ptr<Signal>> SourceAPI::searchSignals(const std::string& if(signalsM_.count(name)) {signals.emplace_back(signalsM_[name]);} - if(newSignalsM_.count(name)) + else if(newSignalsM_.count(name)) {signals.emplace_back(signalsM_[name]);} else { |