joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

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