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.
Dependencies: FXAS21002 FXOS8700Q
m2mbase.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 00017 #include "mbed-client/m2mbase.h" 00018 #include "mbed-client/m2mobservationhandler.h" 00019 #include "mbed-client/m2mconstants.h" 00020 #include "mbed-client/m2mtimer.h" 00021 00022 #include "mbed-client/m2mendpoint.h" 00023 #include "mbed-client/m2mobject.h" 00024 #include "mbed-client/m2mobjectinstance.h" 00025 #include "mbed-client/m2mresource.h" 00026 00027 #include "include/m2mreporthandler.h" 00028 #include "include/nsdlaccesshelper.h" 00029 #include "include/m2mcallbackstorage.h" 00030 #include "mbed-trace/mbed_trace.h" 00031 00032 #include "sn_nsdl_lib.h" 00033 #include <assert.h> 00034 #include <ctype.h> 00035 #include <string.h> 00036 #include <stdlib.h> 00037 #include "common_functions.h" 00038 00039 #define TRACE_GROUP "mClt" 00040 00041 M2MBase::M2MBase(const String& resource_name, 00042 M2MBase::Mode mode, 00043 #ifndef DISABLE_RESOURCE_TYPE 00044 const String &resource_type, 00045 #endif 00046 char *path, 00047 bool external_blockwise_store, 00048 bool multiple_instance, 00049 M2MBase::DataType type) 00050 : 00051 _sn_resource(NULL), 00052 _report_handler(NULL) 00053 { 00054 // Checking the name length properly, i.e returning error is impossible from constructor without exceptions 00055 assert(resource_name.length() <= MAX_ALLOWED_STRING_LENGTH); 00056 00057 _sn_resource = (lwm2m_parameters_s*)memory_alloc(sizeof(lwm2m_parameters_s)); 00058 if(_sn_resource) { 00059 memset(_sn_resource, 0, sizeof(lwm2m_parameters_s)); 00060 _sn_resource->free_on_delete = true; 00061 _sn_resource->multiple_instance = multiple_instance; 00062 _sn_resource->data_type = type; 00063 _sn_resource->read_write_callback_set = false; 00064 _sn_resource->dynamic_resource_params = 00065 (sn_nsdl_dynamic_resource_parameters_s*)memory_alloc(sizeof(sn_nsdl_dynamic_resource_parameters_s)); 00066 if(_sn_resource->dynamic_resource_params) { 00067 memset(_sn_resource->dynamic_resource_params, 00068 0, sizeof(sn_nsdl_dynamic_resource_parameters_s)); 00069 _sn_resource->dynamic_resource_params->static_resource_parameters = 00070 (sn_nsdl_static_resource_parameters_s*)memory_alloc(sizeof(sn_nsdl_static_resource_parameters_s)); 00071 00072 // Set callback function in case of both dynamic and static resource 00073 _sn_resource->dynamic_resource_params->sn_grs_dyn_res_callback = __nsdl_c_callback; 00074 00075 if(_sn_resource->dynamic_resource_params->static_resource_parameters) { 00076 // Cast const away to able to compile using MEMORY_OPTIMIZED_API flag 00077 sn_nsdl_static_resource_parameters_s *params = 00078 const_cast<sn_nsdl_static_resource_parameters_s *>(_sn_resource->dynamic_resource_params->static_resource_parameters); 00079 memset(params, 0, sizeof(sn_nsdl_static_resource_parameters_s)); 00080 const size_t len = strlen(resource_type.c_str()); 00081 params->free_on_delete = true; 00082 if (len > 0) { 00083 #ifndef RESOURCE_ATTRIBUTES_LIST 00084 #ifndef DISABLE_RESOURCE_TYPE 00085 params->resource_type_ptr = (char*)alloc_string_copy((uint8_t*) resource_type.c_str(), len); 00086 #endif 00087 #else 00088 sn_nsdl_attribute_item_s item; 00089 item.attribute_name = ATTR_RESOURCE_TYPE; 00090 item.value = (char*)alloc_string_copy((uint8_t*) resource_type.c_str(), len); 00091 sn_nsdl_set_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, &item); 00092 #endif 00093 } 00094 params->path = path; 00095 params->mode = (unsigned)mode; 00096 params->external_memory_block = external_blockwise_store; 00097 _sn_resource->dynamic_resource_params->static_resource_parameters = params; 00098 } 00099 } 00100 00101 if((!resource_name.empty())) { 00102 _sn_resource->identifier_int_type = false; 00103 _sn_resource->identifier.name = stringdup((char*)resource_name.c_str()); 00104 } else { 00105 tr_debug("M2MBase::M2Mbase resource name is EMPTY ==========="); 00106 _sn_resource->identifier_int_type = true; 00107 _sn_resource->identifier.instance_id = 0; 00108 } 00109 _sn_resource->dynamic_resource_params->publish_uri = true; 00110 _sn_resource->dynamic_resource_params->free_on_delete = true; 00111 _sn_resource->dynamic_resource_params->auto_observable = false; 00112 _sn_resource->dynamic_resource_params->publish_value = false; 00113 } 00114 } 00115 00116 M2MBase::M2MBase(const lwm2m_parameters_s *s): 00117 _sn_resource((lwm2m_parameters_s*) s), 00118 _report_handler(NULL) 00119 { 00120 tr_debug("M2MBase::M2MBase(const lwm2m_parameters_s *s)"); 00121 // Set callback function in case of both dynamic and static resource 00122 _sn_resource->dynamic_resource_params->sn_grs_dyn_res_callback = __nsdl_c_callback; 00123 } 00124 00125 M2MBase::~M2MBase() 00126 { 00127 tr_debug("M2MBase::~M2MBase() %p", this); 00128 delete _report_handler; 00129 00130 value_updated_callback* callback = (value_updated_callback*)M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback); 00131 delete callback; 00132 00133 M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2); 00134 M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback); 00135 #ifdef ENABLE_ASYNC_REST_RESPONSE 00136 M2MCallbackStorage::remove_callback(*this,M2MCallbackAssociation::M2MBaseAsyncCoapRequestCallback); 00137 #endif 00138 } 00139 00140 char* M2MBase::create_path_base(const M2MBase &parent, const char *name) 00141 { 00142 char * result = NULL; 00143 // Expectation is that every element can be MAX_NAME_SZE, + 4 /'s + \0 00144 StringBuffer<(MAX_NAME_SIZE * 4 + (4 + 1))> path; 00145 path.append(parent.uri_path()); 00146 path.append('/'); 00147 path.append(name); 00148 result = stringdup(path.c_str()); 00149 00150 return result; 00151 } 00152 00153 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION 00154 char* M2MBase::create_path(const M2MEndpoint &parent, const char *name) 00155 { 00156 return create_path_base(parent, name); 00157 } 00158 #endif 00159 00160 char* M2MBase::create_path(const M2MObject &parent, uint16_t object_instance) 00161 { 00162 StringBuffer<6> obj_inst_id; 00163 obj_inst_id.append_int(object_instance); 00164 00165 return create_path_base(parent, obj_inst_id.c_str()); 00166 } 00167 00168 char* M2MBase::create_path(const M2MObject &parent, const char *name) 00169 { 00170 return create_path_base(parent, name); 00171 } 00172 00173 char* M2MBase::create_path(const M2MResource &parent, uint16_t resource_instance) 00174 { 00175 StringBuffer<6> res_inst; 00176 res_inst.append_int(resource_instance); 00177 00178 return create_path_base(parent, res_inst.c_str()); 00179 } 00180 00181 char* M2MBase::create_path(const M2MResource &parent, const char *name) 00182 { 00183 return create_path_base(parent, name); 00184 } 00185 00186 char* M2MBase::create_path(const M2MObjectInstance &parent, const char *name) 00187 { 00188 return create_path_base(parent, name); 00189 } 00190 00191 void M2MBase::set_operation(M2MBase::Operation opr) 00192 { 00193 // If the mode is Static, there is only GET_ALLOWED supported. 00194 if(M2MBase::Static == mode()) { 00195 _sn_resource->dynamic_resource_params->access = M2MBase::GET_ALLOWED; 00196 } else { 00197 _sn_resource->dynamic_resource_params->access = opr; 00198 } 00199 } 00200 00201 #ifndef RESOURCE_ATTRIBUTES_LIST 00202 #ifndef MEMORY_OPTIMIZED_API 00203 #ifndef DISABLE_INTERFACE_DESCRIPTION 00204 void M2MBase::set_interface_description(const char *desc) 00205 { 00206 assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete); 00207 free(_sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr); 00208 _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr = NULL; 00209 const size_t len = strlen(desc); 00210 if (len > 0 ) { 00211 _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr = 00212 (char*)alloc_string_copy((uint8_t*) desc, len); 00213 } 00214 set_changed(); 00215 } 00216 00217 void M2MBase::set_interface_description(const String &desc) 00218 { 00219 assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete); 00220 set_interface_description(desc.c_str()); 00221 } 00222 #endif // DISABLE_INTERFACE_DESCRIPTION 00223 00224 #ifndef DISABLE_RESOURCE_TYPE 00225 void M2MBase::set_resource_type(const String &res_type) 00226 { 00227 assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete); 00228 set_resource_type(res_type.c_str()); 00229 } 00230 00231 void M2MBase::set_resource_type(const char *res_type) 00232 { 00233 assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete); 00234 free(_sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr); 00235 _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr = NULL; 00236 const size_t len = strlen(res_type); 00237 if (len > 0) { 00238 _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr = (char*) 00239 alloc_string_copy((uint8_t*) res_type, len); 00240 } 00241 set_changed(); 00242 } 00243 #endif // DISABLE_RESOURCE_TYPE 00244 #endif //MEMORY_OPTIMIZED_API 00245 #else // RESOURCE_ATTRIBUTES_LIST 00246 void M2MBase::set_interface_description(const char *desc) 00247 { 00248 assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete); 00249 const size_t len = strlen(desc); 00250 if (len > 0 ) { 00251 sn_nsdl_attribute_item_s item; 00252 item.attribute_name = ATTR_INTERFACE_DESCRIPTION; 00253 item.value = (char*)alloc_string_copy((uint8_t*) desc, len); 00254 sn_nsdl_set_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, &item); 00255 set_changed(); 00256 } 00257 } 00258 00259 void M2MBase::set_interface_description(const String &desc) 00260 { 00261 assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete); 00262 set_interface_description(desc.c_str()); 00263 } 00264 00265 void M2MBase::set_resource_type(const String &res_type) 00266 { 00267 assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete); 00268 set_resource_type(res_type.c_str()); 00269 } 00270 00271 void M2MBase::set_resource_type(const char *res_type) 00272 { 00273 assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete); 00274 const size_t len = strlen(res_type); 00275 if (len > 0) { 00276 sn_nsdl_attribute_item_s item; 00277 item.attribute_name = ATTR_RESOURCE_TYPE; 00278 item.value = (char*)alloc_string_copy((uint8_t*) res_type, len); 00279 sn_nsdl_set_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, &item); 00280 set_changed(); 00281 } 00282 } 00283 #endif // RESOURCE_ATTRIBUTES_LIST 00284 00285 void M2MBase::set_coap_content_type(const uint16_t con_type) 00286 { 00287 _sn_resource->dynamic_resource_params->coap_content_type = con_type; 00288 set_changed(); 00289 } 00290 00291 void M2MBase::set_observable(bool observable) 00292 { 00293 _sn_resource->dynamic_resource_params->observable = observable; 00294 set_changed(); 00295 } 00296 00297 void M2MBase::set_auto_observable(bool auto_observable) 00298 { 00299 _sn_resource->dynamic_resource_params->auto_observable = auto_observable; 00300 set_changed(); 00301 } 00302 00303 void M2MBase::add_observation_level(M2MBase::Observation obs_level) 00304 { 00305 if(_report_handler) { 00306 _report_handler->add_observation_level(obs_level); 00307 } 00308 } 00309 00310 void M2MBase::remove_observation_level(M2MBase::Observation obs_level) 00311 { 00312 if(_report_handler) { 00313 _report_handler->remove_observation_level(obs_level); 00314 } 00315 } 00316 00317 00318 void M2MBase::set_under_observation(bool observed, 00319 M2MObservationHandler *handler) 00320 { 00321 tr_debug("M2MBase::set_under_observation - observed: %d", observed); 00322 tr_debug("M2MBase::set_under_observation - base_type: %d", base_type()); 00323 if(_report_handler) { 00324 _report_handler->set_under_observation(observed); 00325 } 00326 00327 set_observation_handler(handler); 00328 00329 if (handler) { 00330 if (base_type() != M2MBase::ResourceInstance) { 00331 // Create report handler only if it does not exist and one wants observation 00332 // This saves 76 bytes of memory on most usual case. 00333 if (observed) { 00334 if(!_report_handler) { 00335 _report_handler = new M2MReportHandler(*this, _sn_resource->data_type); 00336 } 00337 } 00338 if (_report_handler) { 00339 _report_handler->set_under_observation(observed); 00340 } 00341 } 00342 } else { 00343 delete _report_handler; 00344 _report_handler = NULL; 00345 } 00346 } 00347 00348 void M2MBase::set_observation_token(const uint8_t *token, const uint8_t length) 00349 { 00350 if (_report_handler) { 00351 _report_handler->set_observation_token(token, length); 00352 // This relates to sn_nsdl_auto_obs_token_callback in sn_nsdl.c 00353 set_changed(); 00354 } 00355 } 00356 00357 void M2MBase::set_instance_id(const uint16_t inst_id) 00358 { 00359 _sn_resource->identifier_int_type = true; 00360 _sn_resource->identifier.instance_id = inst_id; 00361 } 00362 00363 void M2MBase::set_max_age(const uint32_t max_age) 00364 { 00365 _sn_resource->max_age = max_age; 00366 } 00367 00368 M2MBase::BaseType M2MBase::base_type() const 00369 { 00370 return (M2MBase::BaseType)_sn_resource->base_type; 00371 } 00372 00373 M2MBase::Operation M2MBase::operation() const 00374 { 00375 return (M2MBase::Operation)_sn_resource->dynamic_resource_params->access; 00376 } 00377 00378 const char* M2MBase::name() const 00379 { 00380 assert(_sn_resource->identifier_int_type == false); 00381 return _sn_resource->identifier.name; 00382 } 00383 00384 int32_t M2MBase::name_id() const 00385 { 00386 int32_t name_id = -1; 00387 assert(_sn_resource->identifier_int_type == false); 00388 if(is_integer(_sn_resource->identifier.name) && strlen(_sn_resource->identifier.name) <= MAX_ALLOWED_STRING_LENGTH) { 00389 name_id = strtoul(_sn_resource->identifier.name, NULL, 10); 00390 if(name_id > 65535){ 00391 name_id = -1; 00392 } 00393 } 00394 return name_id; 00395 } 00396 00397 uint16_t M2MBase::instance_id() const 00398 { 00399 assert(_sn_resource->identifier_int_type == true); 00400 return _sn_resource->identifier.instance_id; 00401 } 00402 00403 #ifndef RESOURCE_ATTRIBUTES_LIST 00404 #ifndef DISABLE_INTERFACE_DESCRIPTION 00405 #ifndef MEMORY_OPTIMIZED_API 00406 const char* M2MBase::interface_description() const 00407 { 00408 return (reinterpret_cast<char*>( 00409 _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr)); 00410 } 00411 #endif 00412 #endif 00413 00414 #ifndef DISABLE_RESOURCE_TYPE 00415 #ifndef MEMORY_OPTIMIZED_API 00416 const char* M2MBase::resource_type() const 00417 { 00418 return (reinterpret_cast<char*>( 00419 _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr)); 00420 } 00421 #endif 00422 #endif 00423 #else // RESOURCE_ATTRIBUTES_LIST 00424 #ifndef DISABLE_INTERFACE_DESCRIPTION 00425 const char* M2MBase::interface_description() const 00426 { 00427 return sn_nsdl_get_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, ATTR_INTERFACE_DESCRIPTION); 00428 } 00429 #endif 00430 00431 #ifndef DISABLE_RESOURCE_TYPE 00432 const char* M2MBase::resource_type() const 00433 { 00434 return sn_nsdl_get_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, ATTR_RESOURCE_TYPE); 00435 } 00436 #endif 00437 #endif // RESOURCE_ATTRIBUTES_LIST 00438 const char* M2MBase::uri_path() const 00439 { 00440 return (reinterpret_cast<char*>( 00441 _sn_resource->dynamic_resource_params->static_resource_parameters->path)); 00442 } 00443 00444 uint16_t M2MBase::coap_content_type() const 00445 { 00446 return _sn_resource->dynamic_resource_params->coap_content_type; 00447 } 00448 00449 bool M2MBase::is_observable() const 00450 { 00451 return _sn_resource->dynamic_resource_params->observable; 00452 } 00453 00454 bool M2MBase::is_auto_observable() const 00455 { 00456 return _sn_resource->dynamic_resource_params->auto_observable; 00457 } 00458 00459 M2MBase::Observation M2MBase::observation_level() const 00460 { 00461 M2MBase::Observation obs_level = M2MBase::None; 00462 if(_report_handler) { 00463 obs_level = _report_handler->observation_level(); 00464 } 00465 return obs_level; 00466 } 00467 00468 void M2MBase::get_observation_token(uint8_t *token, uint8_t &token_length) const 00469 { 00470 if(_report_handler) { 00471 _report_handler->get_observation_token(token, token_length); 00472 } 00473 } 00474 00475 M2MBase::Mode M2MBase::mode() const 00476 { 00477 return (M2MBase::Mode)_sn_resource->dynamic_resource_params->static_resource_parameters->mode; 00478 } 00479 00480 uint16_t M2MBase::observation_number() const 00481 { 00482 uint16_t obs_number = 0; 00483 if(_report_handler) { 00484 obs_number = _report_handler->observation_number(); 00485 } 00486 return obs_number; 00487 } 00488 00489 uint32_t M2MBase::max_age() const 00490 { 00491 return _sn_resource->max_age; 00492 } 00493 00494 bool M2MBase::handle_observation_attribute(const char *query) 00495 { 00496 tr_debug("M2MBase::handle_observation_attribute - under observation(%d)", is_under_observation()); 00497 bool success = false; 00498 // Create handler if not already exists. Client must able to parse write attributes even when 00499 // observation is not yet set 00500 if (!_report_handler) { 00501 _report_handler = new M2MReportHandler(*this, _sn_resource->data_type); 00502 } 00503 00504 success = _report_handler->parse_notification_attribute(query,base_type()); 00505 if (success) { 00506 if (is_under_observation()) { 00507 _report_handler->set_under_observation(true); 00508 } 00509 } else { 00510 _report_handler->set_default_values(); 00511 } 00512 return success; 00513 } 00514 00515 bool M2MBase::observation_to_be_sent(const m2m::Vector<uint16_t> &changed_instance_ids, 00516 uint16_t obs_number, 00517 bool send_object) 00518 { 00519 //TODO: Move this to M2MResourceInstance 00520 M2MObservationHandler *obs_handler = observation_handler(); 00521 if (obs_handler) { 00522 return obs_handler->observation_to_be_sent(this, 00523 obs_number, 00524 changed_instance_ids, 00525 send_object); 00526 } 00527 return false; 00528 } 00529 00530 void M2MBase::set_base_type(M2MBase::BaseType type) 00531 { 00532 assert(_sn_resource->free_on_delete); 00533 _sn_resource->base_type = type; 00534 } 00535 00536 sn_coap_hdr_s* M2MBase::handle_get_request(nsdl_s */*nsdl*/, 00537 sn_coap_hdr_s */*received_coap_header*/, 00538 M2MObservationHandler */*observation_handler*/) 00539 { 00540 //Handled in M2MResource, M2MObjectInstance and M2MObject classes 00541 return NULL; 00542 } 00543 00544 sn_coap_hdr_s* M2MBase::handle_put_request(nsdl_s */*nsdl*/, 00545 sn_coap_hdr_s */*received_coap_header*/, 00546 M2MObservationHandler */*observation_handler*/, 00547 bool &) 00548 { 00549 //Handled in M2MResource, M2MObjectInstance and M2MObject classes 00550 return NULL; 00551 } 00552 00553 sn_coap_hdr_s* M2MBase::handle_post_request(nsdl_s */*nsdl*/, 00554 sn_coap_hdr_s */*received_coap_header*/, 00555 M2MObservationHandler */*observation_handler*/, 00556 bool &, 00557 sn_nsdl_addr_s *) 00558 { 00559 //Handled in M2MResource, M2MObjectInstance and M2MObject classes 00560 return NULL; 00561 } 00562 00563 void *M2MBase::memory_alloc(uint32_t size) 00564 { 00565 if(size) 00566 return malloc(size); 00567 else 00568 return 0; 00569 } 00570 00571 void M2MBase::memory_free(void *ptr) 00572 { 00573 free(ptr); 00574 } 00575 00576 char* M2MBase::alloc_string_copy(const char* source) 00577 { 00578 assert(source != NULL); 00579 00580 // Note: the armcc's libc does not have strdup, so we need to implement it here 00581 const size_t len = strlen(source); 00582 00583 return (char*)alloc_string_copy((uint8_t*)source, len); 00584 } 00585 00586 uint8_t* M2MBase::alloc_string_copy(const uint8_t* source, uint32_t size) 00587 { 00588 assert(source != NULL); 00589 00590 uint8_t* result = (uint8_t*)memory_alloc(size + 1); 00591 if (result) { 00592 memcpy(result, source, size); 00593 result[size] = '\0'; 00594 } 00595 return result; 00596 } 00597 00598 uint8_t* M2MBase::alloc_copy(const uint8_t* source, uint32_t size) 00599 { 00600 assert(source != NULL); 00601 00602 uint8_t* result = (uint8_t*)memory_alloc(size); 00603 if (result) { 00604 memcpy(result, source, size); 00605 } 00606 return result; 00607 } 00608 00609 bool M2MBase::validate_string_length(const String &string, size_t min_length, size_t max_length) 00610 { 00611 bool valid = false; 00612 00613 const size_t len = string.length(); 00614 if ((len >= min_length) && (len <= max_length)) { 00615 valid = true; 00616 } 00617 00618 return valid; 00619 } 00620 00621 bool M2MBase::validate_string_length(const char* string, size_t min_length, size_t max_length) 00622 { 00623 bool valid = false; 00624 00625 if (string != NULL) { 00626 const size_t len = strlen(string); 00627 if ((len >= min_length) && (len <= max_length)) { 00628 valid = true; 00629 } 00630 } 00631 return valid; 00632 } 00633 00634 M2MReportHandler* M2MBase::create_report_handler() 00635 { 00636 if (!_report_handler) { 00637 _report_handler = new M2MReportHandler(*this, _sn_resource->data_type); 00638 } 00639 return _report_handler; 00640 } 00641 00642 M2MReportHandler* M2MBase::report_handler() const 00643 { 00644 return _report_handler; 00645 } 00646 00647 void M2MBase::set_register_uri(bool register_uri) 00648 { 00649 _sn_resource->dynamic_resource_params->publish_uri = register_uri; 00650 } 00651 00652 bool M2MBase::register_uri() 00653 { 00654 return _sn_resource->dynamic_resource_params->publish_uri; 00655 } 00656 00657 bool M2MBase::is_integer(const String &value) 00658 { 00659 const char *s = value.c_str(); 00660 if(value.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) { 00661 return false; 00662 } 00663 char * p; 00664 strtol(value.c_str(), &p, 10); 00665 return (*p == 0); 00666 } 00667 00668 bool M2MBase::is_integer(const char *value) 00669 { 00670 assert(value != NULL); 00671 00672 if((strlen(value) < 1) || ((!isdigit(value[0])) && (value[0] != '-') && (value[0] != '+'))) { 00673 return false; 00674 } 00675 char * p; 00676 strtol(value, &p, 10); 00677 return (*p == 0); 00678 } 00679 00680 bool M2MBase::is_under_observation() const 00681 { 00682 bool under_observation = false; 00683 if(_report_handler) { 00684 under_observation = _report_handler->is_under_observation(); 00685 } 00686 return under_observation; 00687 } 00688 00689 bool M2MBase::set_value_updated_function(value_updated_callback callback) 00690 { 00691 value_updated_callback* old_callback = (value_updated_callback*)M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback); 00692 delete old_callback; 00693 // XXX: create a copy of the copy of callback object. Perhaps it would better to 00694 // give a reference as parameter and just store that, as it would save some memory. 00695 value_updated_callback* new_callback = new value_updated_callback(callback); 00696 00697 return M2MCallbackStorage::add_callback(*this, new_callback, M2MCallbackAssociation::M2MBaseValueUpdatedCallback); 00698 } 00699 00700 bool M2MBase::set_value_updated_function(value_updated_callback2 callback) 00701 { 00702 M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2); 00703 00704 return M2MCallbackStorage::add_callback(*this, (void*)callback, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2); 00705 } 00706 00707 bool M2MBase::is_value_updated_function_set() const 00708 { 00709 bool func_set = false; 00710 if ((M2MCallbackStorage::does_callback_exist(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback) == true) || 00711 (M2MCallbackStorage::does_callback_exist(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2) == true)) { 00712 00713 func_set = true; 00714 } 00715 return func_set; 00716 } 00717 00718 void M2MBase::execute_value_updated(const String& name) 00719 { 00720 // Q: is there a point to call both callback types? Or should we call just one of them? 00721 00722 value_updated_callback* callback = (value_updated_callback*)M2MCallbackStorage::get_callback(*this, 00723 M2MCallbackAssociation::M2MBaseValueUpdatedCallback); 00724 if (callback) { 00725 (*callback)(name.c_str()); 00726 } 00727 00728 value_updated_callback2 callback2 = (value_updated_callback2)M2MCallbackStorage::get_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2); 00729 if (callback2) { 00730 (*callback2)(name.c_str()); 00731 } 00732 } 00733 00734 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE> &buffer, const char *s1, uint16_t i1, const char *s2, uint16_t i2) 00735 { 00736 00737 if(!buffer.ensure_space(strlen(s1) + strlen(s2) + (MAX_INSTANCE_SIZE * 2) + 3 + 1)){ 00738 return false; 00739 } 00740 00741 buffer.append(s1); 00742 buffer.append('/'); 00743 buffer.append_int(i1); 00744 buffer.append('/'); 00745 buffer.append(s2); 00746 buffer.append('/'); 00747 buffer.append_int(i2); 00748 00749 return true; 00750 00751 } 00752 00753 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_2> &buffer, const char *s1, uint16_t i1, const char *s2) 00754 { 00755 if(!buffer.ensure_space(strlen(s1) + strlen(s2) + MAX_INSTANCE_SIZE + 2 + 1)){ 00756 return false; 00757 } 00758 00759 buffer.append(s1); 00760 buffer.append('/'); 00761 buffer.append_int(i1); 00762 buffer.append('/'); 00763 buffer.append(s2); 00764 00765 return true; 00766 } 00767 00768 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_3> &buffer, const char *s1, uint16_t i1, uint16_t i2) 00769 { 00770 if(!buffer.ensure_space(strlen(s1) + (MAX_INSTANCE_SIZE * 2) + 2 + 1)){ 00771 return false; 00772 } 00773 00774 buffer.append(s1); 00775 buffer.append('/'); 00776 buffer.append_int(i1); 00777 buffer.append('/'); 00778 buffer.append_int(i2); 00779 00780 return true; 00781 } 00782 00783 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_4> &buffer, const char *s1, uint16_t i1) 00784 { 00785 if(!buffer.ensure_space(strlen(s1) + MAX_INSTANCE_SIZE + 1 + 1)){ 00786 return false; 00787 } 00788 00789 buffer.append(s1); 00790 buffer.append('/'); 00791 buffer.append_int(i1); 00792 00793 return true; 00794 } 00795 00796 char* M2MBase::stringdup(const char* src) 00797 { 00798 assert(src != NULL); 00799 00800 const size_t len = strlen(src) + 1; 00801 00802 char *dest = (char*)malloc(len); 00803 00804 if (dest) { 00805 memcpy(dest, src, len); 00806 } 00807 return dest; 00808 } 00809 00810 void M2MBase::free_resources() 00811 { 00812 // remove the nsdl structures from the nsdlinterface's lists. 00813 M2MObservationHandler *obs_handler = observation_handler(); 00814 if (obs_handler) { 00815 tr_debug("M2MBase::free_resources()"); 00816 obs_handler->resource_to_be_deleted(this); 00817 } 00818 00819 if (_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete) { 00820 sn_nsdl_static_resource_parameters_s *params = 00821 const_cast<sn_nsdl_static_resource_parameters_s *>(_sn_resource->dynamic_resource_params->static_resource_parameters); 00822 00823 free(params->path); 00824 //free(params->resource); 00825 #ifndef RESOURCE_ATTRIBUTES_LIST 00826 #ifndef DISABLE_RESOURCE_TYPE 00827 free(params->resource_type_ptr); 00828 #endif 00829 #ifndef DISABLE_INTERFACE_DESCRIPTION 00830 free(params->interface_description_ptr); 00831 #endif 00832 #else 00833 sn_nsdl_free_resource_attributes_list(_sn_resource->dynamic_resource_params->static_resource_parameters); 00834 #endif 00835 free(params); 00836 } 00837 if (_sn_resource->dynamic_resource_params->free_on_delete) { 00838 free(_sn_resource->dynamic_resource_params->resource); 00839 free(_sn_resource->dynamic_resource_params); 00840 } 00841 00842 if(_sn_resource->free_on_delete && _sn_resource->identifier_int_type == false) { 00843 tr_debug("M2MBase::free_resources()"); 00844 free(_sn_resource->identifier.name); 00845 } 00846 if(_sn_resource->free_on_delete) { 00847 free(_sn_resource); 00848 } 00849 } 00850 00851 size_t M2MBase::resource_name_length() const 00852 { 00853 assert(_sn_resource->identifier_int_type == false); 00854 return strlen(_sn_resource->identifier.name); 00855 } 00856 00857 sn_nsdl_dynamic_resource_parameters_s* M2MBase::get_nsdl_resource() const 00858 { 00859 return _sn_resource->dynamic_resource_params; 00860 } 00861 00862 M2MBase::lwm2m_parameters_s* M2MBase::get_lwm2m_parameters() const 00863 { 00864 return _sn_resource; 00865 } 00866 00867 #ifdef ENABLE_ASYNC_REST_RESPONSE 00868 bool M2MBase::send_async_response_with_code(const uint8_t *payload, 00869 size_t payload_len, 00870 const uint8_t* token, 00871 const uint8_t token_len, 00872 coap_response_code_e code) 00873 { 00874 bool success = false; 00875 if(is_async_coap_request_callback_set()) { 00876 success = true; 00877 // At least on some unit tests the resource object is not fully constructed, which would 00878 // cause issues if the observation_handler is NULL. So do the check before dereferencing pointer. 00879 M2MObservationHandler* obs = observation_handler(); 00880 if (obs) { 00881 obs->send_asynchronous_response(this, payload, payload_len, token, token_len, code); 00882 } 00883 } 00884 return success; 00885 } 00886 00887 bool M2MBase::set_async_coap_request_cb(handle_async_coap_request_cb callback, void *client_args) 00888 { 00889 M2MCallbackStorage::remove_callback(*this, 00890 M2MCallbackAssociation::M2MBaseAsyncCoapRequestCallback); 00891 00892 return M2MCallbackStorage::add_callback(*this, 00893 (void*)callback, 00894 M2MCallbackAssociation::M2MBaseAsyncCoapRequestCallback, 00895 client_args); 00896 } 00897 00898 void M2MBase::call_async_coap_request_callback(sn_coap_hdr_s *coap_request, 00899 M2MBase::Operation operation, 00900 bool &handled) 00901 { 00902 M2MCallbackAssociation* item = M2MCallbackStorage::get_association_item(*this, 00903 M2MCallbackAssociation::M2MBaseAsyncCoapRequestCallback); 00904 if (item) { 00905 handle_async_coap_request_cb callback = (handle_async_coap_request_cb)item->_callback; 00906 assert(callback); 00907 assert(coap_request); 00908 handled = true; 00909 (*callback)(*this, 00910 operation, 00911 coap_request->token_ptr, 00912 coap_request->token_len, 00913 coap_request->payload_ptr, 00914 coap_request->payload_len, 00915 item->_client_args); 00916 } 00917 } 00918 00919 bool M2MBase::is_async_coap_request_callback_set() 00920 { 00921 M2MCallbackAssociation* item = M2MCallbackStorage::get_association_item(*this, M2MCallbackAssociation::M2MBaseAsyncCoapRequestCallback); 00922 return (item) ? true : false; 00923 00924 } 00925 #endif // ENABLE_ASYNC_REST_RESPONSE 00926 00927 uint16_t M2MBase::get_notification_msgid() const 00928 { 00929 return 0; 00930 } 00931 00932 void M2MBase::set_notification_msgid(uint16_t /*msgid*/) 00933 { 00934 00935 } 00936 00937 bool M2MBase::set_notification_delivery_status_cb(notification_delivery_status_cb callback, void *client_args) 00938 { 00939 M2MCallbackStorage::remove_callback(*this, 00940 M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback); 00941 00942 return M2MCallbackStorage::add_callback(*this, 00943 (void*)callback, 00944 M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback, 00945 client_args); 00946 } 00947 00948 bool M2MBase::set_message_delivery_status_cb(message_delivery_status_cb callback, void *client_args) 00949 { 00950 M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseMessageDeliveryStatusCallback); 00951 00952 return M2MCallbackStorage::add_callback(*this, 00953 (void*)callback, 00954 M2MCallbackAssociation::M2MBaseMessageDeliveryStatusCallback, 00955 client_args); 00956 } 00957 00958 void M2MBase::send_notification_delivery_status(const M2MBase& object, const NotificationDeliveryStatus status) 00959 { 00960 M2MCallbackAssociation* item = M2MCallbackStorage::get_association_item(object, 00961 M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback); 00962 if (item) { 00963 notification_delivery_status_cb callback = (notification_delivery_status_cb)item->_callback; 00964 if (callback) { 00965 (*callback)(object, status, item->_client_args); 00966 } 00967 } 00968 } 00969 00970 void M2MBase::send_message_delivery_status(const M2MBase& object, const MessageDeliveryStatus status, const MessageType type) 00971 { 00972 M2MCallbackAssociation* item = M2MCallbackStorage::get_association_item(object, 00973 M2MCallbackAssociation::M2MBaseMessageDeliveryStatusCallback); 00974 if (item) { 00975 message_delivery_status_cb callback = (message_delivery_status_cb)item->_callback; 00976 if (callback) { 00977 (*callback)(object, status, type, item->_client_args); 00978 } 00979 } 00980 } 00981 00982 void M2MBase::set_changed() 00983 { 00984 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION 00985 M2MBase *parent = get_parent(); 00986 if (parent) { 00987 parent->set_changed(); 00988 } 00989 #endif 00990 } 00991 00992 M2MBase *M2MBase::get_parent() const 00993 { 00994 return NULL; 00995 } 00996 00997 bool M2MBase::is_blockwise_needed(const nsdl_s *nsdl, uint32_t payload_len) 00998 { 00999 01000 uint16_t block_size = sn_nsdl_get_block_size(nsdl); 01001 01002 if (payload_len > block_size && block_size > 0) { 01003 return true; 01004 } else { 01005 return false; 01006 } 01007 } 01008 01009 void M2MBase::handle_observation(nsdl_s *nsdl, 01010 const sn_coap_hdr_s &received_coap_header, 01011 sn_coap_hdr_s &coap_response, 01012 M2MObservationHandler *observation_handler, 01013 sn_coap_msg_code_e &response_code) 01014 { 01015 tr_debug("M2MBase::handle_observation()"); 01016 assert(nsdl); 01017 assert(received_coap_header.options_list_ptr); 01018 01019 response_code = COAP_MSG_CODE_RESPONSE_CONTENT; 01020 01021 if (is_auto_observable() || received_coap_header.token_ptr == NULL) { 01022 tr_error("M2MBase::handle_observation() - already auto-observable or missing token!"); 01023 response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 01024 return; 01025 } 01026 01027 if (!is_observable()) { 01028 tr_error("M2MBase::handle_observation() - not observable!"); 01029 response_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 01030 return; 01031 } 01032 01033 // Add observe value to response 01034 if (coap_response.options_list_ptr) { 01035 coap_response.options_list_ptr->observe = observation_number(); 01036 } 01037 01038 // In case of blockwise, delivery status callback is handled in m2mnsdlinterface after all the block have been transfered 01039 if (M2MBase::is_blockwise_needed(nsdl, coap_response.payload_len)) { 01040 tr_debug("M2MBase::handle_observation() - block message"); 01041 return; 01042 } 01043 01044 uint32_t obs_number = received_coap_header.options_list_ptr->observe; 01045 01046 // If the observe number is 0 means register for observation. 01047 if (START_OBSERVATION == obs_number) { 01048 01049 start_observation(received_coap_header, observation_handler); 01050 01051 } else if (STOP_OBSERVATION == obs_number) { 01052 tr_info("M2MBase::handle_observation() - stops observation"); 01053 01054 set_under_observation(false, NULL); 01055 send_notification_delivery_status(*this, NOTIFICATION_STATUS_UNSUBSCRIBED); 01056 send_message_delivery_status(*this, M2MBase::MESSAGE_STATUS_UNSUBSCRIBED, M2MBase::NOTIFICATION); 01057 01058 switch (base_type()) { 01059 case M2MBase::Object: 01060 M2MBase::remove_observation_level(M2MBase::O_Attribute); 01061 break; 01062 01063 case M2MBase::ObjectInstance: 01064 M2MBase::remove_observation_level(M2MBase::OI_Attribute); 01065 break; 01066 01067 case M2MBase::Resource: 01068 case M2MBase::ResourceInstance: 01069 M2MBase::remove_observation_level(M2MBase::R_Attribute); 01070 break; 01071 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION 01072 case M2MBase::ObjectDirectory: 01073 // Observation not supported! 01074 break; 01075 #endif 01076 } 01077 } 01078 } 01079 01080 void M2MBase::start_observation(const sn_coap_hdr_s &received_coap_header, M2MObservationHandler *observation_handler) 01081 { 01082 set_under_observation(true, observation_handler); 01083 01084 switch (base_type()) { 01085 case M2MBase::Object: 01086 M2MBase::add_observation_level(M2MBase::O_Attribute); 01087 break; 01088 01089 case M2MBase::ObjectInstance: 01090 M2MBase::add_observation_level(M2MBase::OI_Attribute); 01091 break; 01092 01093 case M2MBase::Resource: 01094 case M2MBase::ResourceInstance: 01095 M2MBase::add_observation_level(M2MBase::R_Attribute); 01096 break; 01097 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION 01098 case M2MBase::ObjectDirectory: 01099 // Observation not supported! 01100 break; 01101 #endif 01102 } 01103 01104 send_notification_delivery_status(*this, NOTIFICATION_STATUS_SUBSCRIBED); 01105 send_message_delivery_status(*this, M2MBase::MESSAGE_STATUS_SUBSCRIBED, M2MBase::NOTIFICATION); 01106 01107 set_observation_token(received_coap_header.token_ptr, 01108 received_coap_header.token_len); 01109 01110 } 01111 01112 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION 01113 01114 void M2MBase::set_deleted() 01115 { 01116 // no-op 01117 } 01118 01119 bool M2MBase::is_deleted() 01120 { 01121 return false; 01122 } 01123 01124 #endif // MBED_CLOUD_CLIENT_EDGE_EXTENSION
Generated on Tue Jul 12 2022 20:20:59 by
