sandbox / mbed-client

Fork of mbed-client by Christopher Haster

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