Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Tue Jul 12 2022 12:58:28 by
1.7.2