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 <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 }
Generated on Tue Jul 12 2022 19:06:59 by
1.7.2