boting ren / Mbed OS BLEClient_mbedDevConn
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2mreporthandler.cpp Source File

m2mreporthandler.cpp

00001 /*
00002  * Copyright (c) 2015 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "mbed-client/m2mreportobserver.h"
00017 #include "mbed-client/m2mconstants.h"
00018 #include "mbed-client/m2mtimer.h"
00019 #include "include/m2mreporthandler.h"
00020 #include "mbed-trace/mbed_trace.h"
00021 #include <string.h>
00022 #include <stdlib.h>
00023 
00024 #define TRACE_GROUP "mClt"
00025 
00026 M2MReportHandler::M2MReportHandler(M2MReportObserver &observer)
00027 : _observer(observer),
00028   _attribute_state(0),
00029   _notify(false),
00030   _pmin_exceeded(false),
00031   _pmax_exceeded(false),
00032   _pmin_timer(*this),
00033   _pmax_timer(*this),
00034   _pmax(-1.0f),
00035   _pmin(1.0f),
00036   _current_value(0.0f),
00037   _gt(0.0f),
00038   _lt(0.0f),
00039   _st(0.0f),
00040   _high_step(0.0f),
00041   _low_step(0.0f),
00042   _last_value(-1.0f)
00043 {
00044     tr_debug("M2MReportHandler::M2MReportHandler()");
00045 }
00046 
00047 M2MReportHandler::~M2MReportHandler()
00048 {
00049     tr_debug("M2MReportHandler::~M2MReportHandler()");
00050 }
00051 
00052 void M2MReportHandler::set_under_observation(bool observed)
00053 {
00054     tr_debug("M2MReportHandler::set_under_observation(observed %d)", (int)observed);
00055     stop_timers();
00056     if(observed) {
00057         handle_timers();
00058     }
00059     else {
00060         set_default_values();
00061     }
00062 }
00063 
00064 void M2MReportHandler::set_value(float value)
00065 {
00066     tr_debug("M2MReportHandler::set_value() - current %f, last %f", value, _last_value);
00067     _current_value = value;
00068     if(_current_value != _last_value) {
00069         tr_debug("M2MReportHandler::set_value() - UNDER OBSERVATION");
00070         if (check_threshold_values()) {
00071             schedule_report();
00072         }
00073         else {
00074             tr_debug("M2MReportHandler::set_value - value not in range");
00075             _notify = false;
00076             _last_value = _current_value;
00077             if ((_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt ||
00078                     (_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt ||
00079                     (_attribute_state & M2MReportHandler::St) == M2MReportHandler::St) {
00080                 tr_debug("M2MReportHandler::set_value - stop pmin timer");
00081                 _pmin_timer.stop_timer();
00082                 _pmin_exceeded = true;
00083             }
00084         }
00085         _high_step = _current_value + _st;
00086         _low_step = _current_value - _st;
00087     }
00088 }
00089 
00090 void M2MReportHandler::set_notification_trigger(uint16_t obj_instance_id)
00091 {
00092     tr_debug("M2MReportHandler::set_notification_trigger(): %d", obj_instance_id);
00093     // Add to array if not there yet
00094     m2m::Vector<uint16_t>::const_iterator it;
00095     it = _changed_instance_ids.begin();
00096     bool found = false;
00097     for ( ; it != _changed_instance_ids.end(); it++) {
00098         if ((*it) == obj_instance_id) {
00099             found = true;
00100             break;
00101         }
00102     }
00103     if (!found) {
00104         _changed_instance_ids.push_back(obj_instance_id);
00105     }
00106 
00107     _current_value = 0.0f;
00108     _last_value = 1.0f;
00109     schedule_report();
00110 }
00111 
00112 bool M2MReportHandler::parse_notification_attribute(const char *query,
00113                                                     M2MBase::BaseType type,
00114                                                     M2MResourceInstance::ResourceType resource_type)
00115 {
00116     tr_debug("M2MReportHandler::parse_notification_attribute(Query %s, Base type %d)", query, (int)type);
00117     bool success = false;
00118     const char* sep_pos = strchr(query, '&');
00119     const char* rest = query;
00120     if( sep_pos != NULL ){
00121         char query_options[5][20];
00122         float pmin = _pmin;
00123         float pmax = _pmax;
00124         float lt = _lt;
00125         float gt = _gt;
00126         float st = _st;
00127         float high = _high_step;
00128         float low = _low_step;
00129         uint8_t attr = _attribute_state;
00130 
00131         memset(query_options, 0, sizeof(query_options[0][0]) * 5 * 20);
00132         uint8_t num_options = 0;
00133         while( sep_pos != NULL && num_options < 5){
00134             size_t len = (size_t)(sep_pos-rest);
00135             if( len > 19 ){
00136                 len = 19;
00137             }
00138             memcpy(query_options[num_options], rest, len);
00139             sep_pos++;
00140             rest = sep_pos;
00141             sep_pos = strchr(rest, '&');
00142             num_options++;
00143         }
00144         if( num_options < 5 && strlen(rest) > 0){
00145             size_t len = (size_t)strlen(rest);
00146             if( len > 19 ){
00147                 len = 19;
00148             }
00149             memcpy(query_options[num_options++], rest, len);
00150         }
00151 
00152         for (int option = 0; option < num_options; option++) {
00153             success = set_notification_attribute(query_options[option],type, resource_type);
00154             if (!success) {
00155                 tr_debug("M2MReportHandler::parse_notification_attribute - break");
00156                 break;
00157             }
00158         }
00159 
00160         if(success) {
00161              success = check_attribute_validity();
00162         }
00163         else {
00164             tr_debug("M2MReportHandler::parse_notification_attribute - not valid query");
00165             _pmin = pmin;
00166             _pmax = pmax;
00167             _st = st;
00168             _lt = lt;
00169             _gt = gt;
00170             _high_step = high;
00171             _low_step = low;
00172             _attribute_state = attr;
00173         }
00174     }
00175     else {
00176         if(set_notification_attribute(query, type, resource_type)) {
00177             success = check_attribute_validity();
00178         }
00179     }
00180 
00181     return success;
00182 }
00183 
00184 void M2MReportHandler::timer_expired(M2MTimerObserver::Type type)
00185 {
00186     switch(type) {
00187         case M2MTimerObserver::PMinTimer: {
00188             tr_debug("M2MReportHandler::timer_expired - PMIN");
00189             if (_notify ||
00190                     (_pmin > 0 &&
00191                      (_attribute_state & M2MReportHandler::Pmax) != M2MReportHandler::Pmax)){
00192                 report();
00193             }
00194             else{
00195                 _pmin_exceeded = true;
00196             }
00197         }
00198         break;
00199         case M2MTimerObserver::PMaxTimer: {
00200             tr_debug("M2MReportHandler::timer_expired - PMAX");
00201             _pmax_exceeded = true;
00202             if (_pmin_exceeded ||
00203                     (_attribute_state & M2MReportHandler::Pmin) != M2MReportHandler::Pmin ) {
00204                 report();
00205             }
00206         }
00207         break;
00208         default:
00209             break;
00210     }
00211 }
00212 
00213 bool M2MReportHandler::set_notification_attribute(const char* option,
00214                                                   M2MBase::BaseType type,
00215                                                   M2MResourceInstance::ResourceType resource_type)
00216 {
00217     tr_debug("M2MReportHandler::set_notification_attribute()");
00218     bool success = false;
00219     char attribute[20];
00220     char value[20];
00221     memset(&attribute, 0, 20);
00222     memset(&value, 0, 20);
00223 
00224     const char* pos = strstr(option, EQUAL);
00225     if( pos != NULL ){
00226         memcpy(attribute, option, (size_t)(pos-option));
00227         pos++;
00228         memcpy(value, pos, strlen(pos));
00229     }else{
00230         memcpy(attribute, option, (size_t)strlen(option) + 1);
00231     }
00232 
00233     if (strlen(value)) {
00234         if (strcmp(attribute, PMIN) == 0) {
00235            _pmin = atoi(value);
00236             success = true;
00237             _attribute_state |= M2MReportHandler::Pmin;
00238             tr_debug("M2MReportHandler::set_notification_attribute %s to %d", attribute, _pmin);
00239         }
00240         else if(strcmp(attribute, PMAX) == 0) {
00241             _pmax = atoi(value);
00242             success = true;
00243             _attribute_state |= M2MReportHandler::Pmax;
00244             tr_debug("M2MReportHandler::set_notification_attribute %s to %d", attribute, _pmax);
00245         }
00246         else if(strcmp(attribute, GT) == 0 &&
00247                 (M2MBase::Resource == type)){
00248             _gt = atof(value);
00249             success = true;
00250             _attribute_state |= M2MReportHandler::Gt;
00251             tr_debug("M2MReportHandler::set_notification_attribute %s to %f", attribute, _gt);
00252         }
00253         else if(strcmp(attribute, LT) == 0 &&
00254                 (M2MBase::Resource == type)){
00255             _lt = atof(value);
00256             success = true;
00257             _attribute_state |= M2MReportHandler::Lt;
00258             tr_debug("M2MReportHandler::set_notification_attribute %s to %f", attribute, _lt);
00259         }
00260         else if((strcmp(attribute, ST_SIZE) == 0 || (strcmp(attribute, STP) == 0))
00261                 && (M2MBase::Resource == type)){
00262             _st = atof(value);
00263             success = true;
00264             _high_step = _current_value + _st;
00265             _low_step = _current_value - _st;
00266             _attribute_state |= M2MReportHandler::St;
00267             tr_debug("M2MReportHandler::set_notification_attribute %s to %f", attribute, _st);
00268         }
00269         // Return false if try to set gt,lt or st when the resource type is something else than numerical
00270         if ((resource_type != M2MResourceInstance::INTEGER &&
00271                 resource_type != M2MResourceInstance::FLOAT) &&
00272                 ((_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt ||
00273                 (_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt ||
00274                 (_attribute_state & M2MReportHandler::St) == M2MReportHandler::St)) {
00275             tr_debug("M2MReportHandler::set_notification_attribute - not numerical resource");
00276             success = false;
00277         }
00278     }
00279     return success;
00280 }
00281 
00282 void M2MReportHandler::schedule_report()
00283 {
00284     tr_debug("M2MReportHandler::schedule_report()");
00285     _notify = true;
00286     if ((_attribute_state & M2MReportHandler::Pmin) != M2MReportHandler::Pmin ||
00287          _pmin_exceeded) {
00288         report();
00289     }
00290 }
00291 
00292 void M2MReportHandler::report()
00293 {
00294     tr_debug("M2MReportHandler::report()");
00295     if(_current_value != _last_value && _notify) {
00296         tr_debug("M2MReportHandler::report()- send with PMIN");
00297         _pmin_exceeded = false;
00298         _pmax_exceeded = false;
00299         _notify = false;
00300         _observer.observation_to_be_sent(_changed_instance_ids);
00301         _changed_instance_ids.clear();
00302         _pmax_timer.stop_timer();
00303     }
00304     else {
00305         if (_pmax_exceeded) {
00306             tr_debug("M2MReportHandler::report()- send with PMAX");
00307             _observer.observation_to_be_sent(_changed_instance_ids, true);
00308             _changed_instance_ids.clear();
00309         }
00310         else {
00311             tr_debug("M2MReportHandler::report()- no need to send");
00312         }
00313     }
00314     handle_timers();
00315     _last_value = _current_value;
00316 }
00317 
00318 void M2MReportHandler::handle_timers()
00319 {
00320     tr_debug("M2MReportHandler::handle_timers()");
00321     uint64_t time_interval = 0;
00322     if ((_attribute_state & M2MReportHandler::Pmin) == M2MReportHandler::Pmin) {
00323         if (_pmin == _pmax) {
00324             _pmin_exceeded = true;
00325         } else {
00326             _pmin_exceeded = false;
00327             time_interval = (uint64_t) ((uint64_t)_pmin * 1000);
00328             tr_debug("M2MReportHandler::handle_timers() - Start PMIN interval: %d", (int)time_interval);
00329             _pmin_timer.start_timer(time_interval,
00330                                      M2MTimerObserver::PMinTimer,
00331                                      true);
00332         }
00333     }
00334     if ((_attribute_state & M2MReportHandler::Pmax) == M2MReportHandler::Pmax) {
00335         if (_pmax > 0) {
00336             time_interval = (uint64_t) ((uint64_t)_pmax * 1000);
00337             tr_debug("M2MReportHandler::handle_timers() - Start PMAX interval: %d", (int)time_interval);
00338             _pmax_timer.start_timer(time_interval,
00339                                      M2MTimerObserver::PMaxTimer,
00340                                      true);
00341         }
00342     }
00343 }
00344 
00345 bool M2MReportHandler::check_attribute_validity()
00346 {
00347     bool success = true;
00348     if ((_attribute_state & M2MReportHandler::Pmax) == M2MReportHandler::Pmax &&
00349             ((_pmax >= -1.0) && (_pmin > _pmax))) {
00350         success = false;
00351     }
00352     float low = _lt + 2 * _st;
00353     if ((_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt &&
00354             (low >= _gt)) {
00355         success = false;
00356     }
00357     return success;
00358 }
00359 
00360 void M2MReportHandler::stop_timers()
00361 {
00362     tr_debug("M2MReportHandler::stop_timers()");
00363 
00364     _pmin_exceeded = false;
00365     _pmin_timer.stop_timer();
00366 
00367     _pmax_exceeded = false;
00368     _pmax_timer.stop_timer();
00369 
00370     tr_debug("M2MReportHandler::stop_timers() - out");
00371 }
00372 
00373 void M2MReportHandler::set_default_values()
00374 {
00375     tr_debug("M2MReportHandler::set_default_values");
00376     _pmax = -1.0;
00377     _pmin = 1.0;
00378     _gt = 0.0f;
00379     _lt = 0.0f;
00380     _st = 0.0f;
00381     _high_step = 0.0f;
00382     _low_step = 0.0f;
00383     _pmin_exceeded = false;
00384     _pmax_exceeded = false;
00385     _last_value = -1.0f;
00386     _attribute_state = 0;
00387     _changed_instance_ids.clear();
00388 }
00389 
00390 bool M2MReportHandler::check_threshold_values()
00391 {
00392     tr_debug("M2MReportHandler::check_threshold_values");
00393     tr_debug("Current value: %f", _current_value);
00394     tr_debug("High step: %f", _high_step);
00395     tr_debug("Low step: %f", _low_step);
00396     tr_debug("Less than: %f", _lt);
00397     tr_debug("Greater than: %f", _gt);
00398     tr_debug("Step: %f", _st);
00399     bool can_send = false;
00400     // Check step condition
00401     if ((_attribute_state & M2MReportHandler::St) == M2MReportHandler::St) {
00402         if ((_current_value >= _high_step ||
00403             _current_value <= _low_step)) {
00404             can_send = true;
00405         }
00406         else {
00407             if ((_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt ||
00408                     (_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt ) {
00409                 can_send = check_gt_lt_params();
00410             }
00411             else {
00412                 can_send = false;
00413             }
00414         }
00415     }
00416     else {
00417         can_send = check_gt_lt_params();
00418     }
00419     tr_debug("M2MReportHandler::check_threshold_values - value in range = %d", (int)can_send);
00420     return can_send;
00421 }
00422 
00423 bool M2MReportHandler::check_gt_lt_params()
00424 {
00425     tr_debug("M2MReportHandler::check_gt_lt_params");
00426     bool can_send = false;
00427     // GT & LT set.
00428     if ((_attribute_state & (M2MReportHandler::Lt | M2MReportHandler::Gt))
00429              == (M2MReportHandler::Lt | M2MReportHandler::Gt)) {
00430         if (_current_value > _gt || _current_value < _lt) {
00431             can_send = true;
00432         }
00433         else {
00434             can_send = false;
00435         }
00436     }
00437     // Only LT
00438     else if ((_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt &&
00439            (_attribute_state & M2MReportHandler::Gt) == 0 ) {
00440         if (_current_value < _lt) {
00441             can_send = true;
00442         }
00443         else {
00444             can_send = false;
00445         }
00446     }
00447     // Only GT
00448     else if ((_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt &&
00449            (_attribute_state & M2MReportHandler::Lt) == 0 ) {
00450         if (_current_value > _gt) {
00451             can_send = true;
00452         }
00453         else {
00454             can_send = false;
00455         }
00456     }
00457     // GT & LT not set.
00458     else {
00459         can_send = true;
00460     }
00461     tr_debug("M2MReportHandler::check_gt_lt_params - value in range = %d", (int)can_send);
00462     return can_send;
00463 }
00464 
00465 uint8_t M2MReportHandler::attribute_flags()
00466 {
00467     return _attribute_state;
00468 }