Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2mbase.cpp Source File

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 }
00136 
00137 char* M2MBase::create_path_base(const M2MBase &parent, const char *name)
00138 {
00139     char * result = NULL;
00140     // Expectation is that every element can be MAX_NAME_SZE, + 4 /'s + \0
00141     StringBuffer<(MAX_NAME_SIZE * 4 + (4 + 1))> path;
00142     path.append(parent.uri_path());
00143     path.append('/');
00144     path.append(name);
00145     result = stringdup(path.c_str());
00146 
00147     return result;
00148 }
00149 
00150 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
00151 char* M2MBase::create_path(const M2MEndpoint &parent, const char *name)
00152 {
00153     return create_path_base(parent, name);
00154 }
00155 #endif
00156 
00157 char* M2MBase::create_path(const M2MObject &parent, uint16_t object_instance)
00158 {
00159     StringBuffer<6> obj_inst_id;
00160     obj_inst_id.append_int(object_instance);
00161 
00162     return create_path_base(parent, obj_inst_id.c_str());
00163 }
00164 
00165 char* M2MBase::create_path(const M2MObject &parent, const char *name)
00166 {
00167     return create_path_base(parent, name);
00168 }
00169 
00170 char* M2MBase::create_path(const M2MResource &parent, uint16_t resource_instance)
00171 {
00172     StringBuffer<6> res_inst;
00173     res_inst.append_int(resource_instance);
00174 
00175     return create_path_base(parent, res_inst.c_str());
00176 }
00177 
00178 char* M2MBase::create_path(const M2MResource &parent, const char *name)
00179 {
00180     return create_path_base(parent, name);
00181 }
00182 
00183 char* M2MBase::create_path(const M2MObjectInstance &parent, const char *name)
00184 {
00185     return create_path_base(parent, name);
00186 }
00187 
00188 void M2MBase::set_operation(M2MBase::Operation opr)
00189 {
00190     // If the mode is Static, there is only GET_ALLOWED supported.
00191     if(M2MBase::Static == mode()) {
00192         _sn_resource->dynamic_resource_params->access = M2MBase::GET_ALLOWED;
00193     } else {
00194         _sn_resource->dynamic_resource_params->access = opr;
00195     }
00196 }
00197 
00198 #ifndef RESOURCE_ATTRIBUTES_LIST
00199 #ifndef MEMORY_OPTIMIZED_API
00200 #ifndef DISABLE_INTERFACE_DESCRIPTION
00201 void M2MBase::set_interface_description(const char *desc)
00202 {
00203     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00204     free(_sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr);
00205     _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr = NULL;
00206     const size_t len = strlen(desc);
00207     if (len > 0 ) {
00208         _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr =
00209                 (char*)alloc_string_copy((uint8_t*) desc, len);
00210     }
00211     set_changed();
00212 }
00213 
00214 void M2MBase::set_interface_description(const String &desc)
00215 {
00216     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00217     set_interface_description(desc.c_str());
00218 }
00219 #endif // DISABLE_INTERFACE_DESCRIPTION
00220 
00221 #ifndef DISABLE_RESOURCE_TYPE
00222 void M2MBase::set_resource_type(const String &res_type)
00223 {
00224     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00225     set_resource_type(res_type.c_str());
00226 }
00227 
00228 void M2MBase::set_resource_type(const char *res_type)
00229 {
00230     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00231     free(_sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr);
00232     _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr = NULL;
00233     const size_t len = strlen(res_type);
00234     if (len > 0) {
00235         _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr = (char*)
00236                 alloc_string_copy((uint8_t*) res_type, len);
00237     }
00238     set_changed();
00239 }
00240 #endif // DISABLE_RESOURCE_TYPE
00241 #endif //MEMORY_OPTIMIZED_API
00242 #else // RESOURCE_ATTRIBUTES_LIST
00243 void M2MBase::set_interface_description(const char *desc)
00244 {
00245     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00246     const size_t len = strlen(desc);
00247     if (len > 0 ) {
00248         sn_nsdl_attribute_item_s item;
00249         item.attribute_name = ATTR_INTERFACE_DESCRIPTION;
00250         item.value = (char*)alloc_string_copy((uint8_t*) desc, len);
00251         sn_nsdl_set_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, &item);
00252         set_changed();
00253     }
00254 }
00255 
00256 void M2MBase::set_interface_description(const String &desc)
00257 {
00258     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00259     set_interface_description(desc.c_str());
00260 }
00261 
00262 void M2MBase::set_resource_type(const String &res_type)
00263 {
00264     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00265     set_resource_type(res_type.c_str());
00266 }
00267 
00268 void M2MBase::set_resource_type(const char *res_type)
00269 {
00270     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00271     const size_t len = strlen(res_type);
00272     if (len > 0) {
00273         sn_nsdl_attribute_item_s item;
00274         item.attribute_name = ATTR_RESOURCE_TYPE;
00275         item.value = (char*)alloc_string_copy((uint8_t*) res_type, len);
00276         sn_nsdl_set_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, &item);
00277         set_changed();
00278     }
00279 }
00280 #endif // RESOURCE_ATTRIBUTES_LIST
00281 
00282 void M2MBase::set_coap_content_type(const uint16_t con_type)
00283 {
00284     _sn_resource->dynamic_resource_params->coap_content_type = con_type;
00285     set_changed();
00286 }
00287 
00288 void M2MBase::set_observable(bool observable)
00289 {
00290     _sn_resource->dynamic_resource_params->observable = observable;
00291     set_changed();
00292 }
00293 
00294 void M2MBase::set_auto_observable(bool auto_observable)
00295 {
00296     _sn_resource->dynamic_resource_params->auto_observable = auto_observable;
00297     set_changed();
00298 }
00299 
00300 void M2MBase::add_observation_level(M2MBase::Observation obs_level)
00301 {
00302     if(_report_handler) {
00303         _report_handler->add_observation_level(obs_level);
00304     }
00305 }
00306 
00307 void M2MBase::remove_observation_level(M2MBase::Observation obs_level)
00308 {
00309     if(_report_handler) {
00310         _report_handler->remove_observation_level(obs_level);
00311     }
00312 }
00313 
00314 
00315 void M2MBase::set_under_observation(bool observed,
00316                                     M2MObservationHandler *handler)
00317 {
00318     tr_debug("M2MBase::set_under_observation - observed: %d", observed);
00319     tr_debug("M2MBase::set_under_observation - base_type: %d", base_type());
00320     if(_report_handler) {
00321         _report_handler->set_under_observation(observed);
00322     }
00323 
00324     set_observation_handler(handler);
00325 
00326     if (handler) {
00327         if (base_type() != M2MBase::ResourceInstance) {
00328             // Create report handler only if it does not exist and one wants observation
00329             // This saves 76 bytes of memory on most usual case.
00330             if (observed) {
00331                 if(!_report_handler) {
00332                     _report_handler = new M2MReportHandler(*this);
00333                 }
00334             }
00335             if (_report_handler) {
00336                 _report_handler->set_under_observation(observed);
00337             }
00338         }
00339     } else {
00340         delete _report_handler;
00341         _report_handler = NULL;
00342     }
00343 }
00344 
00345 void M2MBase::set_observation_token(const uint8_t *token, const uint8_t length)
00346 {
00347     if (_report_handler) {
00348         _report_handler->set_observation_token(token, length);
00349         // This relates to sn_nsdl_auto_obs_token_callback in sn_nsdl.c
00350         set_changed();
00351     }
00352 }
00353 
00354 void M2MBase::set_instance_id(const uint16_t inst_id)
00355 {
00356     _sn_resource->identifier_int_type = true;
00357     _sn_resource->identifier.instance_id = inst_id;
00358 }
00359 
00360 void M2MBase::set_max_age(const uint32_t max_age)
00361 {
00362     _sn_resource->max_age = max_age;
00363 }
00364 
00365 M2MBase::BaseType M2MBase::base_type() const
00366 {
00367     return (M2MBase::BaseType)_sn_resource->base_type;
00368 }
00369 
00370 M2MBase::Operation M2MBase::operation() const
00371 {
00372     return (M2MBase::Operation)_sn_resource->dynamic_resource_params->access;
00373 }
00374 
00375 const char* M2MBase::name() const
00376 {
00377     assert(_sn_resource->identifier_int_type == false);
00378     return _sn_resource->identifier.name;
00379 }
00380 
00381 int32_t M2MBase::name_id() const
00382 {
00383     int32_t name_id = -1;
00384     assert(_sn_resource->identifier_int_type == false);
00385     if(is_integer(_sn_resource->identifier.name) && strlen(_sn_resource->identifier.name) <= MAX_ALLOWED_STRING_LENGTH) {
00386         name_id = strtoul(_sn_resource->identifier.name, NULL, 10);
00387         if(name_id > 65535){
00388             name_id = -1;
00389         }
00390     }
00391     return name_id;
00392 }
00393 
00394 uint16_t M2MBase::instance_id() const
00395 {
00396     assert(_sn_resource->identifier_int_type == true);
00397     return _sn_resource->identifier.instance_id;
00398 }
00399 
00400 #ifndef RESOURCE_ATTRIBUTES_LIST
00401 #ifndef DISABLE_INTERFACE_DESCRIPTION
00402 const char* M2MBase::interface_description() const
00403 {
00404     return (reinterpret_cast<char*>(
00405         _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr));
00406 }
00407 #endif
00408 
00409 #ifndef DISABLE_RESOURCE_TYPE
00410 const char* M2MBase::resource_type() const
00411 {
00412     return (reinterpret_cast<char*>(
00413         _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr));
00414 }
00415 #endif
00416 #else // RESOURCE_ATTRIBUTES_LIST
00417 #ifndef DISABLE_INTERFACE_DESCRIPTION
00418 const char* M2MBase::interface_description() const
00419 {
00420     return sn_nsdl_get_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, ATTR_INTERFACE_DESCRIPTION);
00421 }
00422 #endif
00423 
00424 #ifndef DISABLE_RESOURCE_TYPE
00425 const char* M2MBase::resource_type() const
00426 {
00427     return sn_nsdl_get_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, ATTR_RESOURCE_TYPE);
00428 }
00429 #endif
00430 #endif // RESOURCE_ATTRIBUTES_LIST
00431 const char* M2MBase::uri_path() const
00432 {
00433     return (reinterpret_cast<char*>(
00434         _sn_resource->dynamic_resource_params->static_resource_parameters->path));
00435 }
00436 
00437 uint16_t M2MBase::coap_content_type() const
00438 {
00439     return _sn_resource->dynamic_resource_params->coap_content_type;
00440 }
00441 
00442 bool M2MBase::is_observable() const
00443 {
00444     if (_sn_resource->dynamic_resource_params->auto_observable) {
00445         return true;
00446     } else {
00447         return _sn_resource->dynamic_resource_params->observable;
00448     }
00449 }
00450 
00451 M2MBase::Observation M2MBase::observation_level() const
00452 {
00453     M2MBase::Observation obs_level = M2MBase::None;
00454     if(_report_handler) {
00455         obs_level = _report_handler->observation_level();
00456     }
00457     return obs_level;
00458 }
00459 
00460 void M2MBase::get_observation_token(uint8_t *token, uint8_t &token_length) const
00461 {
00462     if(_report_handler) {
00463         _report_handler->get_observation_token(token, token_length);
00464     }
00465 }
00466 
00467 M2MBase::Mode M2MBase::mode() const
00468 {
00469     return (M2MBase::Mode)_sn_resource->dynamic_resource_params->static_resource_parameters->mode;
00470 }
00471 
00472 uint16_t M2MBase::observation_number() const
00473 {
00474     uint16_t obs_number = 0;
00475     if(_report_handler) {
00476         obs_number = _report_handler->observation_number();
00477     }
00478     return obs_number;
00479 }
00480 
00481 uint32_t M2MBase::max_age() const
00482 {
00483     return _sn_resource->max_age;
00484 }
00485 
00486 bool M2MBase::handle_observation_attribute(const char *query)
00487 {
00488     tr_debug("M2MBase::handle_observation_attribute - under observation(%d)", is_under_observation());
00489     bool success = false;
00490     // Create handler if not already exists. Client must able to parse write attributes even when
00491     // observation is not yet set
00492     if (!_report_handler) {
00493         _report_handler = new M2MReportHandler(*this);
00494     }
00495 
00496     success = _report_handler->parse_notification_attribute(query,base_type());
00497     if (success) {
00498         if (is_under_observation()) {
00499             _report_handler->set_under_observation(true);
00500         }
00501      } else {
00502         _report_handler->set_default_values();
00503     }
00504     return success;
00505 }
00506 
00507 bool M2MBase::observation_to_be_sent(const m2m::Vector<uint16_t> &changed_instance_ids,
00508                                      uint16_t obs_number,
00509                                      bool send_object)
00510 {
00511     //TODO: Move this to M2MResourceInstance
00512     M2MObservationHandler *obs_handler = observation_handler();
00513     if (obs_handler) {
00514         return obs_handler->observation_to_be_sent(this,
00515                                             obs_number,
00516                                             changed_instance_ids,
00517                                             send_object);
00518     }
00519     return false;
00520 }
00521 
00522 void M2MBase::set_base_type(M2MBase::BaseType type)
00523 {
00524     assert(_sn_resource->free_on_delete);
00525     _sn_resource->base_type = type;
00526 }
00527 
00528 sn_coap_hdr_s* M2MBase::handle_get_request(nsdl_s */*nsdl*/,
00529                                            sn_coap_hdr_s */*received_coap_header*/,
00530                                            M2MObservationHandler */*observation_handler*/)
00531 {
00532     //Handled in M2MResource, M2MObjectInstance and M2MObject classes
00533     return NULL;
00534 }
00535 
00536 sn_coap_hdr_s* M2MBase::handle_put_request(nsdl_s */*nsdl*/,
00537                                            sn_coap_hdr_s */*received_coap_header*/,
00538                                            M2MObservationHandler */*observation_handler*/,
00539                                            bool &)
00540 {
00541     //Handled in M2MResource, M2MObjectInstance and M2MObject classes
00542     return NULL;
00543 }
00544 
00545 sn_coap_hdr_s* M2MBase::handle_post_request(nsdl_s */*nsdl*/,
00546                                             sn_coap_hdr_s */*received_coap_header*/,
00547                                             M2MObservationHandler */*observation_handler*/,
00548                                             bool &,
00549                                             sn_nsdl_addr_s *)
00550 {
00551     //Handled in M2MResource, M2MObjectInstance and M2MObject classes
00552     return NULL;
00553 }
00554 
00555 void *M2MBase::memory_alloc(uint32_t size)
00556 {
00557     if(size)
00558         return malloc(size);
00559     else
00560         return 0;
00561 }
00562 
00563 void M2MBase::memory_free(void *ptr)
00564 {
00565     free(ptr);
00566 }
00567 
00568 char* M2MBase::alloc_string_copy(const char* source)
00569 {
00570     assert(source != NULL);
00571 
00572     // Note: the armcc's libc does not have strdup, so we need to implement it here
00573     const size_t len = strlen(source);
00574 
00575     return (char*)alloc_string_copy((uint8_t*)source, len);
00576 }
00577 
00578 uint8_t* M2MBase::alloc_string_copy(const uint8_t* source, uint32_t size)
00579 {
00580     assert(source != NULL);
00581 
00582     uint8_t* result = (uint8_t*)memory_alloc(size + 1);
00583     if (result) {
00584         memcpy(result, source, size);
00585         result[size] = '\0';
00586     }
00587     return result;
00588 }
00589 
00590 uint8_t* M2MBase::alloc_copy(const uint8_t* source, uint32_t size)
00591 {
00592     assert(source != NULL);
00593 
00594     uint8_t* result = (uint8_t*)memory_alloc(size);
00595     if (result) {
00596         memcpy(result, source, size);
00597     }
00598     return result;
00599 }
00600 
00601 bool M2MBase::validate_string_length(const String &string, size_t min_length, size_t max_length)
00602 {
00603     bool valid = false;
00604 
00605     const size_t len = string.length();
00606     if ((len >= min_length) && (len <= max_length)) {
00607         valid = true;
00608     }
00609 
00610     return valid;
00611 }
00612 
00613 bool M2MBase::validate_string_length(const char* string, size_t min_length, size_t max_length)
00614 {
00615     bool valid = false;
00616 
00617     if (string != NULL) {
00618         const size_t len = strlen(string);
00619         if ((len >= min_length) && (len <= max_length)) {
00620             valid = true;
00621         }
00622     }
00623     return valid;
00624 }
00625 
00626 M2MReportHandler* M2MBase::create_report_handler()
00627 {
00628     if (!_report_handler) {
00629         _report_handler = new M2MReportHandler(*this);
00630     }
00631     return _report_handler;
00632 }
00633 
00634 M2MReportHandler* M2MBase::report_handler() const
00635 {
00636     return _report_handler;
00637 }
00638 
00639 void M2MBase::set_register_uri(bool register_uri)
00640 {
00641     _sn_resource->dynamic_resource_params->publish_uri = register_uri;
00642 }
00643 
00644 bool M2MBase::register_uri()
00645 {
00646     return _sn_resource->dynamic_resource_params->publish_uri;
00647 }
00648 
00649 bool M2MBase::is_integer(const String &value)
00650 {
00651     const char *s = value.c_str();
00652     if(value.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) {
00653         return false;
00654     }
00655     char * p;
00656     strtol(value.c_str(), &p, 10);
00657     return (*p == 0);
00658 }
00659 
00660 bool M2MBase::is_integer(const char *value)
00661 {
00662     assert(value != NULL);
00663 
00664     if((strlen(value) < 1) || ((!isdigit(value[0])) && (value[0] != '-') && (value[0] != '+'))) {
00665         return false;
00666     }
00667     char * p;
00668     strtol(value, &p, 10);
00669     return (*p == 0);
00670 }
00671 
00672 bool M2MBase::is_under_observation() const
00673 {
00674    bool under_observation = false;
00675     if(_report_handler) {
00676         under_observation = _report_handler->is_under_observation();
00677     }
00678     return under_observation;
00679 }
00680 
00681 bool M2MBase::set_value_updated_function(value_updated_callback callback)
00682 {
00683     value_updated_callback* old_callback = (value_updated_callback*)M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback);
00684     delete old_callback;
00685     // XXX: create a copy of the copy of callback object. Perhaps it would better to
00686     // give a reference as parameter and just store that, as it would save some memory.
00687     value_updated_callback* new_callback = new value_updated_callback(callback);
00688 
00689     return M2MCallbackStorage::add_callback(*this, new_callback, M2MCallbackAssociation::M2MBaseValueUpdatedCallback);
00690 }
00691 
00692 bool M2MBase::set_value_updated_function(value_updated_callback2 callback)
00693 {
00694     M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2);
00695 
00696     return M2MCallbackStorage::add_callback(*this, (void*)callback, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2);
00697 }
00698 
00699 bool M2MBase::is_value_updated_function_set() const
00700 {
00701     bool func_set = false;
00702     if ((M2MCallbackStorage::does_callback_exist(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback) == true) ||
00703         (M2MCallbackStorage::does_callback_exist(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2) == true)) {
00704 
00705         func_set = true;
00706     }
00707     return func_set;
00708 }
00709 
00710 void M2MBase::execute_value_updated(const String& name)
00711 {
00712     // Q: is there a point to call both callback types? Or should we call just one of them?
00713 
00714     value_updated_callback* callback = (value_updated_callback*)M2MCallbackStorage::get_callback(*this,
00715                                                                                                  M2MCallbackAssociation::M2MBaseValueUpdatedCallback);
00716     if (callback) {
00717         (*callback)(name.c_str());
00718     }
00719 
00720     value_updated_callback2 callback2 = (value_updated_callback2)M2MCallbackStorage::get_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2);
00721     if (callback2) {
00722         (*callback2)(name.c_str());
00723     }
00724 }
00725 
00726 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE> &buffer, const char *s1, uint16_t i1, const char *s2, uint16_t i2)
00727 {
00728 
00729     if(!buffer.ensure_space(strlen(s1) + strlen(s2) + (MAX_INSTANCE_SIZE * 2) + 3 + 1)){
00730         return false;
00731     }
00732 
00733     buffer.append(s1);
00734     buffer.append('/');
00735     buffer.append_int(i1);
00736     buffer.append('/');
00737     buffer.append(s2);
00738     buffer.append('/');
00739     buffer.append_int(i2);
00740 
00741     return true;
00742 
00743 }
00744 
00745 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_2> &buffer, const char *s1, uint16_t i1, const char *s2)
00746 {
00747     if(!buffer.ensure_space(strlen(s1) + strlen(s2) + MAX_INSTANCE_SIZE + 2 + 1)){
00748         return false;
00749     }
00750 
00751     buffer.append(s1);
00752     buffer.append('/');
00753     buffer.append_int(i1);
00754     buffer.append('/');
00755     buffer.append(s2);
00756 
00757     return true;
00758 }
00759 
00760 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_3> &buffer, const char *s1, uint16_t i1, uint16_t i2)
00761 {
00762     if(!buffer.ensure_space(strlen(s1) + (MAX_INSTANCE_SIZE * 2) + 2 + 1)){
00763         return false;
00764     }
00765 
00766     buffer.append(s1);
00767     buffer.append('/');
00768     buffer.append_int(i1);
00769     buffer.append('/');
00770     buffer.append_int(i2);
00771 
00772     return true;
00773 }
00774 
00775 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_4> &buffer, const char *s1, uint16_t i1)
00776 {
00777     if(!buffer.ensure_space(strlen(s1) + MAX_INSTANCE_SIZE + 1 + 1)){
00778         return false;
00779     }
00780 
00781     buffer.append(s1);
00782     buffer.append('/');
00783     buffer.append_int(i1);
00784 
00785     return true;
00786 }
00787 
00788 char* M2MBase::stringdup(const char* src)
00789 {
00790     assert(src != NULL);
00791 
00792     const size_t len = strlen(src) + 1;
00793 
00794     char *dest = (char*)malloc(len);
00795 
00796     if (dest) {
00797         memcpy(dest, src, len);
00798     }
00799     return dest;
00800 }
00801 
00802 void M2MBase::free_resources()
00803 {
00804     // remove the nsdl structures from the nsdlinterface's lists.
00805     M2MObservationHandler *obs_handler = observation_handler();
00806     if (obs_handler) {
00807         tr_debug("M2MBase::free_resources()");
00808         obs_handler->resource_to_be_deleted(this);
00809     }
00810 
00811     if (_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete) {
00812         sn_nsdl_static_resource_parameters_s *params =
00813                 const_cast<sn_nsdl_static_resource_parameters_s *>(_sn_resource->dynamic_resource_params->static_resource_parameters);
00814 
00815         free(params->path);
00816         //free(params->resource);
00817 #ifndef RESOURCE_ATTRIBUTES_LIST
00818 #ifndef DISABLE_RESOURCE_TYPE
00819         free(params->resource_type_ptr);
00820 #endif
00821 #ifndef DISABLE_INTERFACE_DESCRIPTION
00822         free(params->interface_description_ptr);
00823 #endif
00824 #else
00825         sn_nsdl_free_resource_attributes_list(_sn_resource->dynamic_resource_params->static_resource_parameters);
00826 #endif
00827         free(params);
00828     }
00829     if (_sn_resource->dynamic_resource_params->free_on_delete) {
00830         free(_sn_resource->dynamic_resource_params->resource);
00831         free(_sn_resource->dynamic_resource_params);
00832     }
00833 
00834     if(_sn_resource->free_on_delete && _sn_resource->identifier_int_type == false) {
00835         tr_debug("M2MBase::free_resources()");
00836         free(_sn_resource->identifier.name);
00837     }
00838     if(_sn_resource->free_on_delete) {
00839         free(_sn_resource);
00840     }
00841 }
00842 
00843 size_t M2MBase::resource_name_length() const
00844 {
00845     assert(_sn_resource->identifier_int_type == false);
00846     return strlen(_sn_resource->identifier.name);
00847 }
00848 
00849 sn_nsdl_dynamic_resource_parameters_s* M2MBase::get_nsdl_resource() const
00850 {
00851     return _sn_resource->dynamic_resource_params;
00852 }
00853 
00854 M2MBase::lwm2m_parameters_s* M2MBase::get_lwm2m_parameters() const
00855 {
00856     return _sn_resource;
00857 }
00858 
00859 uint16_t M2MBase::get_notification_msgid() const
00860 {
00861     return _sn_resource->dynamic_resource_params->msg_id;
00862 }
00863 
00864 void M2MBase::set_notification_msgid(uint16_t msgid)
00865 {
00866     _sn_resource->dynamic_resource_params->msg_id = msgid;
00867 }
00868 
00869 bool M2MBase::set_notification_delivery_status_cb(notification_delivery_status_cb callback, void *client_args)
00870 {
00871     M2MCallbackStorage::remove_callback(*this,
00872                                         M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback);
00873 
00874     return M2MCallbackStorage::add_callback(*this,
00875                                             (void*)callback,
00876                                             M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback,
00877                                             client_args);
00878 }
00879 
00880 void M2MBase::send_notification_delivery_status(const M2MBase& object, const NotificationDeliveryStatus status)
00881 {
00882     M2MCallbackAssociation* item = M2MCallbackStorage::get_association_item(object,
00883                                                                             M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback);
00884     if (item) {
00885         notification_delivery_status_cb callback = (notification_delivery_status_cb)item->_callback;
00886         if (callback) {
00887             (*callback)(object, status, item->_client_args);
00888         }
00889     }
00890 }
00891 
00892 void M2MBase::set_changed()
00893 {
00894 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
00895     M2MBase *parent = get_parent();
00896     if (parent) {
00897         parent->set_changed();
00898     }
00899 #endif
00900 }
00901 
00902 M2MBase *M2MBase::get_parent() const
00903 {
00904     return NULL;
00905 }
00906