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 m2mobject.cpp Source File

m2mobject.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 // Note: this macro is needed on armcc to get the the PRI*32 macros
00018 // from inttypes.h in a C++ code.
00019 #ifndef __STDC_FORMAT_MACROS
00020 #define __STDC_FORMAT_MACROS
00021 #endif
00022 #include <inttypes.h>
00023 
00024 #include "mbed-client/m2mobject.h"
00025 #include "mbed-client/m2mendpoint.h"
00026 #include "mbed-client/m2mconstants.h"
00027 #include "include/m2mtlvserializer.h"
00028 #include "include/m2mtlvdeserializer.h"
00029 #include "include/m2mreporthandler.h"
00030 #include "mbed-trace/mbed_trace.h"
00031 #include "mbed-client/m2mstringbuffer.h"
00032 #include "include/m2mcallbackstorage.h"
00033 
00034 #include <stdlib.h>
00035 
00036 #define BUFFER_SIZE 10
00037 #define TRACE_GROUP "mClt"
00038 
00039 M2MObject::M2MObject(const String &object_name, char *path, bool external_blockwise_store)
00040 : M2MBase(object_name,
00041           M2MBase::Dynamic,
00042 #ifndef DISABLE_RESOURCE_TYPE
00043           "",
00044 #endif
00045           path,
00046           external_blockwise_store,
00047           false),
00048     _observation_handler(NULL)
00049 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
00050     ,_endpoint(NULL)
00051 #endif
00052 {
00053     M2MBase::set_base_type(M2MBase::Object);
00054     M2MBase::set_operation(M2MBase::GET_ALLOWED);
00055     if(M2MBase::name_id() != -1) {
00056         M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00057     }
00058 }
00059 
00060 M2MObject::M2MObject(const M2MBase::lwm2m_parameters_s* static_res)
00061 : M2MBase(static_res),
00062     _observation_handler(NULL)
00063 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
00064     ,_endpoint(NULL)
00065 #endif
00066 {
00067     M2MBase::set_operation(M2MBase::GET_ALLOWED);
00068     if(M2MBase::name_id() != -1) {
00069         M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00070     }
00071 }
00072 
00073 M2MObject::~M2MObject()
00074 {
00075     if(!_instance_list.empty()) {
00076 
00077         M2MObjectInstanceList::const_iterator it;
00078         it = _instance_list.begin();
00079         M2MObjectInstance* obj = NULL;
00080         uint16_t index = 0;
00081         for (; it!=_instance_list.end(); it++, index++ ) {
00082             //Free allocated memory for object instances.
00083             obj = *it;
00084             delete obj;
00085         }
00086 
00087         _instance_list.clear();
00088     }
00089 
00090     free_resources();
00091 }
00092 
00093 M2MObjectInstance* M2MObject::create_object_instance(uint16_t instance_id)
00094 {
00095     tr_debug("M2MObject::create_object_instance - id: %d", instance_id);
00096     M2MObjectInstance *instance = NULL;
00097     if(!object_instance(instance_id)) {
00098         char* path = create_path(*this, instance_id);
00099         if (path) {
00100             // Note: the object instance's name contains actually object's name.
00101             instance = new M2MObjectInstance(*this, "", path);
00102             if(instance) {
00103                 instance->add_observation_level(observation_level());
00104                 instance->set_instance_id(instance_id);
00105                 if(M2MBase::name_id() != -1) {
00106                     instance->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00107                 }
00108                 _instance_list.push_back(instance);
00109                 set_changed();
00110             }
00111         }
00112     }
00113     return instance;
00114 }
00115 
00116 
00117 M2MObjectInstance* M2MObject::create_object_instance(const lwm2m_parameters_s* s)
00118 {
00119     tr_debug("M2MObject::create_object_instance - id: %d", s->identifier.instance_id);
00120     M2MObjectInstance *instance = NULL;
00121     if(!object_instance(s->identifier.instance_id)) {
00122 
00123         instance = new M2MObjectInstance(*this, s);
00124         if(instance) {
00125             instance->add_observation_level(observation_level());
00126             //instance->set_instance_id(instance_id);
00127             //if(M2MBase::name_id() != -1) {
00128               //  instance->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00129             //}
00130             _instance_list.push_back(instance);
00131             set_changed();
00132         }
00133     }
00134     return instance;
00135 }
00136 
00137 bool M2MObject::remove_object_instance(uint16_t inst_id)
00138 {
00139     tr_debug("M2MObject::remove_object_instance(inst_id %d)", inst_id);
00140     bool success = false;
00141     if(!_instance_list.empty()) {
00142         M2MObjectInstance* obj = NULL;
00143         M2MObjectInstanceList::const_iterator it;
00144         it = _instance_list.begin();
00145         int pos = 0;
00146         for ( ; it != _instance_list.end(); it++, pos++ ) {
00147             if((*it)->instance_id() == inst_id) {
00148                 // Instance found and deleted.
00149                 obj = *it;
00150 
00151                 _instance_list.erase(pos);
00152                 delete obj;
00153                 success = true;
00154                 set_changed();
00155                 break;
00156             }
00157         }
00158     }
00159     return success;
00160 }
00161 
00162 M2MObjectInstance* M2MObject::object_instance(uint16_t inst_id) const
00163 {
00164     tr_debug("M2MObject::object_instance(inst_id %d)", inst_id);
00165     M2MObjectInstance *obj = NULL;
00166     if(!_instance_list.empty()) {
00167         M2MObjectInstanceList::const_iterator it;
00168         it = _instance_list.begin();
00169         for ( ; it != _instance_list.end(); it++ ) {
00170             if((*it)->instance_id() == inst_id) {
00171                 // Instance found.
00172                 obj = *it;
00173                 break;
00174             }
00175         }
00176     }
00177     return obj;
00178 }
00179 
00180 const M2MObjectInstanceList& M2MObject::instances() const
00181 {
00182     return _instance_list;
00183 }
00184 
00185 uint16_t M2MObject::instance_count() const
00186 {
00187     return (uint16_t)_instance_list.size();
00188 }
00189 
00190 M2MObservationHandler* M2MObject::observation_handler() const
00191 {
00192     // XXX: need to check the flag too
00193     return _observation_handler;
00194 }
00195 
00196 void M2MObject::set_observation_handler(M2MObservationHandler *handler)
00197 {
00198     tr_debug("M2MObject::set_observation_handler - handler: 0x%p", (void*)handler);
00199     _observation_handler = handler;
00200 }
00201 
00202 void M2MObject::add_observation_level(M2MBase::Observation observation_level)
00203 {
00204     M2MBase::add_observation_level(observation_level);
00205     if(!_instance_list.empty()) {
00206          M2MObjectInstanceList::const_iterator it;
00207          it = _instance_list.begin();
00208          for ( ; it != _instance_list.end(); it++ ) {
00209              (*it)->add_observation_level(observation_level);
00210          }
00211     }
00212 }
00213 
00214 void M2MObject::remove_observation_level(M2MBase::Observation observation_level)
00215 {
00216     M2MBase::remove_observation_level(observation_level);
00217     if(!_instance_list.empty()) {
00218         M2MObjectInstanceList::const_iterator it;
00219         it = _instance_list.begin();
00220         for ( ; it != _instance_list.end(); it++ ) {
00221             (*it)->remove_observation_level(observation_level);
00222         }
00223     }
00224 }
00225 
00226 sn_coap_hdr_s* M2MObject::handle_get_request(nsdl_s *nsdl,
00227                                              sn_coap_hdr_s *received_coap_header,
00228                                              M2MObservationHandler *observation_handler)
00229 {
00230     tr_info("M2MObject::handle_get_request()");
00231     sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
00232     sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
00233                                                            received_coap_header,
00234                                                            msg_code);
00235     uint8_t *data = NULL;
00236     uint32_t data_length = 0;
00237     if(received_coap_header) {
00238         // process the GET if we have registered a callback for it
00239         if ((operation() & SN_GRS_GET_ALLOWED) != 0) {
00240             if(coap_response) {
00241                 bool content_type_present = false;
00242                 bool is_content_type_supported = true;
00243 
00244                 if (received_coap_header->options_list_ptr &&
00245                         received_coap_header->options_list_ptr->accept != COAP_CT_NONE) {
00246                     content_type_present = true;
00247                     coap_response->content_format = received_coap_header->options_list_ptr->accept;
00248 
00249                 }
00250 
00251                 // Check if preferred content type is supported
00252                 if (content_type_present) {
00253                     if (coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE_OLD &&
00254                         coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE) {
00255                         is_content_type_supported = false;
00256                     }
00257                 }
00258 
00259                 if (is_content_type_supported) {
00260                     if(!content_type_present &&
00261                        (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
00262                         M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
00263                         coap_response->content_format = sn_coap_content_format_e(M2MBase::coap_content_type());
00264                     }
00265 
00266                     // fill in the CoAP response payload
00267                     if(COAP_CONTENT_OMA_TLV_TYPE == coap_response->content_format ||
00268                        COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_response->content_format) {
00269                         set_coap_content_type(coap_response->content_format);
00270                         data = M2MTLVSerializer::serialize(_instance_list, data_length);
00271                     }
00272 
00273                     coap_response->payload_len = data_length;
00274                     coap_response->payload_ptr = data;
00275                     if(data){
00276                         coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
00277                         if(coap_response->options_list_ptr){
00278                             coap_response->options_list_ptr->max_age = max_age();
00279                         }
00280                         if(received_coap_header->options_list_ptr) {
00281                             if(received_coap_header->options_list_ptr->observe != -1) {
00282                                 if (is_observable()) {
00283                                     uint32_t number = 0;
00284                                     uint8_t observe_option = 0;
00285                                     observe_option = received_coap_header->options_list_ptr->observe;
00286 
00287                                     if(START_OBSERVATION == observe_option) {
00288                                         // If the observe length is 0 means register for observation.
00289                                         if(received_coap_header->options_list_ptr->observe != -1) {
00290                                             number = received_coap_header->options_list_ptr->observe;
00291                                         }
00292 
00293                                         // If the observe value is 0 means register for observation.
00294                                         if(number == 0) {
00295                                             tr_info("M2MObject::handle_get_request - put resource under observation");
00296                                             set_under_observation(true,observation_handler);
00297                                             add_observation_level(M2MBase::O_Attribute);
00298                                             send_notification_delivery_status(*this, NOTIFICATION_STATUS_SUBSCRIBED);
00299                                             if(coap_response->options_list_ptr){
00300                                                 coap_response->options_list_ptr->observe = observation_number();
00301                                             }
00302                                         }
00303 
00304                                         if(received_coap_header->token_ptr) {
00305                                             set_observation_token(received_coap_header->token_ptr,
00306                                                                   received_coap_header->token_len);
00307                                         }
00308                                     } else if (STOP_OBSERVATION == observe_option) {
00309                                         tr_info("M2MObject::handle_get_request - stops observation");
00310                                         // If the observe options_list_ptr->observe value is 1 means de-register from observation.
00311                                         set_under_observation(false, NULL);
00312                                         remove_observation_level(M2MBase::O_Attribute);
00313                                         send_notification_delivery_status(*this, NOTIFICATION_STATUS_UNSUBSCRIBED);
00314                                     }
00315                                     msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
00316                                 }
00317                                 else {
00318                                     msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00319                                 }
00320                             }
00321                         }
00322                     } else {
00323                         msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; // Content format not supported
00324                     }
00325                 } else {
00326                     tr_error("M2MObject::handle_get_request() - Content-Type %d not supported", coap_response->content_format);
00327                     msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE;
00328                 }
00329             }
00330         }else {
00331             tr_error("M2MResource::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
00332             // Operation is not allowed.
00333             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00334         }
00335     } else {
00336         msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00337     }
00338     if(coap_response) {
00339         coap_response->msg_code = msg_code;
00340     }
00341     return coap_response;
00342 }
00343 
00344 sn_coap_hdr_s* M2MObject::handle_put_request(nsdl_s *nsdl,
00345                                              sn_coap_hdr_s *received_coap_header,
00346                                              M2MObservationHandler */*observation_handler*/,
00347                                              bool &/*execute_value_updated*/)
00348 {
00349     tr_info("M2MObject::handle_put_request()");
00350     sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
00351     sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl,
00352                                                           received_coap_header,
00353                                                           msg_code);
00354     if(received_coap_header) {
00355         if(received_coap_header->content_format != COAP_CT_NONE) {
00356             set_coap_content_type(received_coap_header->content_format);
00357         }
00358         if(received_coap_header->options_list_ptr &&
00359            received_coap_header->options_list_ptr->uri_query_ptr) {
00360             char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr,
00361                                                     received_coap_header->options_list_ptr->uri_query_len);
00362 
00363             if (query){
00364                 tr_info("M2MObject::handle_put_request() - query %s", query);
00365                 // if anything was updated, re-initialize the stored notification attributes
00366                 if (!handle_observation_attribute(query)){
00367                     tr_debug("M2MObject::handle_put_request() - Invalid query");
00368                     msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00
00369                 }
00370                 free(query);
00371             }
00372         } else {
00373             tr_error("M2MObject::handle_put_request() - COAP_MSG_CODE_RESPONSE_BAD_REQUEST - Empty URI_QUERY");
00374             msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
00375         }
00376     } else {
00377         msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00378     }
00379     if(coap_response) {
00380         coap_response->msg_code = msg_code;
00381     }
00382     return coap_response;
00383 }
00384 
00385 
00386 sn_coap_hdr_s* M2MObject::handle_post_request(nsdl_s *nsdl,
00387                                               sn_coap_hdr_s *received_coap_header,
00388                                               M2MObservationHandler *observation_handler,
00389                                               bool &execute_value_updated,
00390                                               sn_nsdl_addr_s *)
00391 {
00392     tr_info("M2MObject::handle_post_request()");
00393     sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
00394     // process the POST if we have registered a callback for it
00395     sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl,
00396                                       received_coap_header,
00397                                       msg_code);
00398 
00399     if (received_coap_header) {
00400         if ((operation() & SN_GRS_POST_ALLOWED) != 0) {
00401             if (received_coap_header->content_format != COAP_CT_NONE) {
00402                 set_coap_content_type(received_coap_header->content_format);
00403             }
00404             if(received_coap_header->payload_ptr) {
00405                 tr_debug("M2MObject::handle_post_request() - Update Object with new values");
00406                 uint16_t coap_content_type = 0;
00407                 bool content_type_present = false;
00408                 if(received_coap_header->content_format != COAP_CT_NONE) {
00409                     content_type_present = true;
00410                     if(coap_response) {
00411                         coap_content_type = received_coap_header->content_format;
00412                     }
00413                 } // if(received_coap_header->content_format)
00414                 if(!content_type_present &&
00415                    (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
00416                     M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
00417                     coap_content_type = M2MBase::coap_content_type();
00418                 }
00419 
00420                 tr_debug("M2MObject::handle_post_request() - Request Content-type: %d", coap_content_type);
00421 
00422                 if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type ||
00423                    COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type) {
00424                     set_coap_content_type(coap_content_type);
00425                     uint32_t instance_id = 0;
00426                     // Check next free instance id
00427                     for(instance_id = 0; instance_id <= MAX_UNINT_16_COUNT; instance_id++) {
00428                         if(NULL == object_instance(instance_id)) {
00429                             break;
00430                         }
00431                         if(instance_id == MAX_UNINT_16_COUNT) {
00432                             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00433                             break;
00434                         }
00435                     }
00436                     if(COAP_MSG_CODE_RESPONSE_CHANGED == msg_code) {
00437                         bool is_obj_instance = false;
00438                         bool obj_instance_exists = false;
00439                         is_obj_instance = M2MTLVDeserializer::is_object_instance(received_coap_header->payload_ptr);
00440                         if (is_obj_instance) {
00441                             instance_id = M2MTLVDeserializer::instance_id(received_coap_header->payload_ptr);
00442                             tr_debug("M2MObject::handle_post_request() - instance id in TLV: %" PRIu32, instance_id);
00443                             // Check if instance id already exists
00444                             if (object_instance(instance_id)){
00445                                 obj_instance_exists = true;
00446                             }
00447                         }
00448                         if (!obj_instance_exists && coap_response) {
00449                             M2MObjectInstance *obj_instance = create_object_instance(instance_id);
00450                             if (obj_instance) {
00451                                 obj_instance->set_operation(M2MBase::GET_PUT_ALLOWED);
00452                             }
00453 
00454                             M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
00455                             if(is_obj_instance) {
00456                                 tr_debug("M2MObject::handle_post_request() - TLV data contains ObjectInstance");
00457                                 error = M2MTLVDeserializer::deserialise_object_instances(received_coap_header->payload_ptr,
00458                                                                            received_coap_header->payload_len,
00459                                                                            *this,
00460                                                                            M2MTLVDeserializer::Post);
00461                             } else if(obj_instance &&
00462                                         (M2MTLVDeserializer::is_resource(received_coap_header->payload_ptr) ||
00463                                          M2MTLVDeserializer::is_multiple_resource(received_coap_header->payload_ptr))) {
00464                                 tr_debug("M2MObject::handle_post_request() - TLV data contains Resources");
00465                                 error = M2MTLVDeserializer::deserialize_resources(received_coap_header->payload_ptr,
00466                                                                             received_coap_header->payload_len,
00467                                                                             *obj_instance,
00468                                                                             M2MTLVDeserializer::Post);
00469                             } else {
00470                                 error = M2MTLVDeserializer::NotValid;
00471                             }
00472                             switch(error) {
00473                                 case M2MTLVDeserializer::None:
00474                                     if(observation_handler) {
00475                                         execute_value_updated = true;
00476                                     }
00477                                     coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
00478 
00479                                     if (coap_response->options_list_ptr) {
00480 
00481                                         StringBuffer<MAX_OBJECT_PATH_NAME> obj_name;
00482 
00483                                         if (obj_name.ensure_space(M2MBase::resource_name_length() + (1 + 5 + 1))) {
00484                                             obj_name.append(M2MBase::name());
00485                                             obj_name.append('/');
00486                                             obj_name.append_int(instance_id);
00487 
00488                                             coap_response->options_list_ptr->location_path_len = obj_name.get_size();
00489                                             coap_response->options_list_ptr->location_path_ptr =
00490                                                     alloc_copy((uint8_t*)obj_name.c_str(), obj_name.get_size());
00491                                             // todo: else return error
00492                                         }
00493                                     }
00494                                     // todo: else return error
00495                                     msg_code = COAP_MSG_CODE_RESPONSE_CREATED;
00496                                     break;
00497                                 case M2MTLVDeserializer::NotAllowed:
00498                                     msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00499                                     break;
00500                                 case M2MTLVDeserializer::NotValid:
00501                                     msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
00502                                     break;
00503                                 case M2MTLVDeserializer::NotFound:
00504                                     msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
00505                                     break;
00506                                 case M2MTLVDeserializer::OutOfMemory:
00507                                     msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
00508                                     break;
00509                             }
00510 
00511                         } else {
00512                             tr_error("M2MObject::handle_post_request() - COAP_MSG_CODE_RESPONSE_BAD_REQUEST");
00513                             msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
00514                         }
00515                     }
00516                 } else {
00517                     msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
00518                 } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type)
00519             } else {
00520                 tr_error("M2MObject::handle_post_request - COAP_MSG_CODE_RESPONSE_BAD_REQUEST - Missing Payload");
00521                 msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; //
00522             }
00523         } else { // if ((object->operation() & SN_GRS_POST_ALLOWED) != 0)
00524             tr_error("M2MObject::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
00525             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.05
00526         }
00527     } else { //if(received_coap_header)
00528         tr_error("M2MObject::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
00529         msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.05
00530     }
00531 
00532     if(coap_response) {
00533         coap_response->msg_code = msg_code;
00534     }
00535     return coap_response;
00536 }
00537 
00538 void M2MObject::notification_update(uint16_t obj_instance_id)
00539 {
00540     tr_debug("M2MObject::notification_update - id: %d", obj_instance_id);
00541     M2MReportHandler *report_handler = M2MBase::report_handler();
00542     if(report_handler && is_under_observation()) {
00543         report_handler->set_notification_trigger(obj_instance_id);
00544     }
00545 }
00546 
00547 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
00548 void M2MObject::set_endpoint(M2MEndpoint *endpoint)
00549 {
00550     _endpoint = endpoint;
00551 }
00552 
00553 M2MEndpoint* M2MObject::get_endpoint() const
00554 {
00555     return _endpoint;
00556 }
00557 #endif
00558 
00559 M2MBase *M2MObject::get_parent() const
00560 {
00561 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
00562     return (M2MBase *) get_endpoint();
00563 #else
00564     return NULL;
00565 #endif
00566 }