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

m2mobjectinstance.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/m2mobjectinstance.h"
00017 #include "mbed-client/m2mobject.h"
00018 #include "mbed-client/m2mconstants.h"
00019 #include "mbed-client/m2mresource.h"
00020 #include "mbed-client/m2mresource.h"
00021 #include "mbed-client/m2mobservationhandler.h"
00022 #include "mbed-client/m2mstring.h"
00023 #include "mbed-client/m2mstringbuffer.h"
00024 #include "include/m2mtlvserializer.h"
00025 #include "include/m2mtlvdeserializer.h"
00026 #include "include/m2mreporthandler.h"
00027 #include "mbed-trace/mbed_trace.h"
00028 #include "include/m2mcallbackstorage.h"
00029 #include <stdlib.h>
00030 
00031 #define BUFFER_SIZE 10
00032 #define TRACE_GROUP "mClt"
00033 
00034 M2MObjectInstance::M2MObjectInstance(M2MObject& parent,
00035                                      const String &resource_type,
00036                                      char *path,
00037                                      bool external_blockwise_store)
00038 : M2MBase("",
00039           M2MBase::Dynamic,
00040 #ifndef DISABLE_RESOURCE_TYPE
00041           resource_type,
00042 #endif
00043           path,
00044           external_blockwise_store,
00045           false),
00046   _parent(parent)
00047 {
00048     M2MBase::set_base_type(M2MBase::ObjectInstance);
00049     M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00050     M2MBase::set_operation(M2MBase::GET_ALLOWED);
00051 }
00052 
00053 M2MObjectInstance::M2MObjectInstance(M2MObject& parent, const lwm2m_parameters_s* static_res)
00054 : M2MBase(static_res), _parent(parent)
00055 {
00056     M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00057     M2MBase::set_operation(M2MBase::GET_ALLOWED);
00058 }
00059 
00060 M2MObjectInstance::~M2MObjectInstance()
00061 {
00062     if(!_resource_list.empty()) {
00063         M2MResource* res = NULL;
00064         M2MResourceList::const_iterator it;
00065         it = _resource_list.begin();
00066         for (; it!=_resource_list.end(); it++ ) {
00067             //Free allocated memory for resources.
00068             res = *it;
00069             delete res;
00070         }
00071         _resource_list.clear();
00072     }
00073 
00074     free_resources();
00075 }
00076 
00077 // TBD, ResourceType to the base class struct?? TODO!
00078 M2MResource* M2MObjectInstance::create_static_resource(const lwm2m_parameters_s* static_res,
00079                                                        M2MResourceInstance::ResourceType type)
00080 {
00081     tr_debug("M2MObjectInstance::create_static_resource(lwm2m_parameters_s resource_name %s)", static_res->identifier.name);
00082     M2MResource *res = NULL;
00083     if (validate_string_length(static_res->identifier.name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
00084         return res;
00085     }
00086     if(!resource(static_res->identifier.name)) {
00087         res = new M2MResource(*this, static_res, convert_resource_type(type));
00088         if(res) {
00089             res->add_observation_level(observation_level());
00090             //if (multiple_instance) {
00091                 //res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00092             //}
00093             _resource_list.push_back(res);
00094             set_changed();
00095         }
00096     }
00097     return res;
00098 }
00099 
00100 M2MResource* M2MObjectInstance::create_static_resource(const String &resource_name,
00101                                                        const String &resource_type,
00102                                                        M2MResourceInstance::ResourceType type,
00103                                                        const uint8_t *value,
00104                                                        const uint8_t value_length,
00105                                                        bool multiple_instance,
00106                                                        bool external_blockwise_store)
00107 {
00108     tr_debug("M2MObjectInstance::create_static_resource(resource_name %s)",resource_name.c_str());
00109     M2MResource *res = NULL;
00110     if (validate_string_length(resource_name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
00111         return res;
00112     }
00113     if(!resource(resource_name)) {
00114         char *path = create_path(*this, resource_name.c_str());
00115 
00116         if (path) {
00117             res = new M2MResource(*this, resource_name, M2MBase::Static, resource_type, convert_resource_type(type),
00118                                   value, value_length, path,
00119                                   multiple_instance, external_blockwise_store);
00120             if(res) {
00121                 res->add_observation_level(observation_level());
00122                 if (multiple_instance) {
00123                     res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00124                 }
00125                 _resource_list.push_back(res);
00126                 set_changed();
00127             }
00128         }
00129     }
00130     return res;
00131 }
00132 
00133 M2MResource* M2MObjectInstance::create_dynamic_resource(const lwm2m_parameters_s* static_res,
00134                                                         M2MResourceInstance::ResourceType type,
00135                                                         bool observable)
00136 {
00137     tr_debug("M2MObjectInstance::create_dynamic_resource(resource_name %s)", static_res->identifier.name);
00138     M2MResource *res = NULL;
00139 
00140     if (validate_string_length(static_res->identifier.name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
00141         return res;
00142     }
00143     if(!resource(static_res->identifier.name)) {
00144         res = new M2MResource(*this, static_res, convert_resource_type(type));
00145         if(res) {
00146             //if (multiple_instance) { // TODO!
00147               //  res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE);
00148             //}
00149             res->add_observation_level(observation_level());
00150             _resource_list.push_back(res);
00151             set_changed();
00152         }
00153     }
00154     return res;
00155 }
00156 
00157 M2MResource* M2MObjectInstance::create_dynamic_resource(const String &resource_name,
00158                                                 const String &resource_type,
00159                                                 M2MResourceInstance::ResourceType type,
00160                                                 bool observable,
00161                                                 bool multiple_instance,
00162                                                 bool external_blockwise_store)
00163 {
00164     tr_debug("M2MObjectInstance::create_dynamic_resource(resource_name %s)",resource_name.c_str());
00165     M2MResource *res = NULL;
00166     if (validate_string_length(resource_name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
00167         return res;
00168     }
00169     if(!resource(resource_name)) {
00170         char *path = create_path(*this, resource_name.c_str());
00171         if (path) {
00172             res = new M2MResource(*this, resource_name, M2MBase::Dynamic, resource_type, convert_resource_type(type),
00173                                   observable, path,
00174                                   multiple_instance, external_blockwise_store);
00175             if(res) {
00176                 if (multiple_instance) {
00177                     res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00178                 }
00179                 res->add_observation_level(observation_level());
00180                 _resource_list.push_back(res);
00181                 set_changed();
00182             }
00183         }
00184     }
00185     return res;
00186 }
00187 
00188 M2MResourceInstance* M2MObjectInstance::create_static_resource_instance(const String &resource_name,
00189                                                                         const String &resource_type,
00190                                                                         M2MResourceInstance::ResourceType type,
00191                                                                         const uint8_t *value,
00192                                                                         const uint8_t value_length,
00193                                                                         uint16_t instance_id,
00194                                                                         bool external_blockwise_store)
00195 {
00196     tr_debug("M2MObjectInstance::create_static_resource_instance(resource_name %s)",resource_name.c_str());
00197     M2MResourceInstance *instance = NULL;
00198     if (validate_string_length(resource_name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
00199 
00200         return instance;
00201     }
00202     M2MResource *res = resource(resource_name);
00203     if(!res) {
00204         char *path = create_path(*this, resource_name.c_str());
00205         if (path) {
00206             res = new M2MResource(*this, resource_name, M2MBase::Static, resource_type, convert_resource_type(type),
00207                                   value, value_length, path,
00208                                   true, external_blockwise_store);
00209             _resource_list.push_back(res);
00210             set_changed();
00211             res->set_operation(M2MBase::GET_ALLOWED);
00212             res->set_observable(false);
00213             res->set_register_uri(false);
00214         }
00215     }
00216     if(res && res->supports_multiple_instances()&& (res->resource_instance(instance_id) == NULL)) {
00217         char *path = M2MBase::create_path(*res, instance_id);
00218         if (path) {
00219             instance = new M2MResourceInstance(*res, "", M2MBase::Static, resource_type, convert_resource_type(type),
00220                                                value, value_length,
00221                                                path, external_blockwise_store,true);
00222             if(instance) {
00223                 instance->set_operation(M2MBase::GET_ALLOWED);
00224                 instance->set_instance_id(instance_id);
00225                 res->add_resource_instance(instance);
00226             }
00227         }
00228     }
00229     return instance;
00230 }
00231 
00232 M2MResourceInstance* M2MObjectInstance::create_dynamic_resource_instance(const String &resource_name,
00233                                                                          const String &resource_type,
00234                                                                          M2MResourceInstance::ResourceType type,
00235                                                                          bool observable,
00236                                                                          uint16_t instance_id,
00237                                                                          bool external_blockwise_store)
00238 {
00239     tr_debug("M2MObjectInstance::create_dynamic_resource_instance(resource_name %s)",resource_name.c_str());
00240     M2MResourceInstance *instance = NULL;
00241     if (validate_string_length(resource_name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
00242         return instance;
00243     }
00244     M2MResource *res = resource(resource_name);
00245     if(!res) {
00246         char *path = create_path(*this, resource_name.c_str());
00247         if (path) {
00248             res = new M2MResource(*this, resource_name, M2MBase::Dynamic, resource_type, convert_resource_type(type),
00249                                   false, path, true, external_blockwise_store);
00250             _resource_list.push_back(res);
00251             res->set_register_uri(false);
00252             res->set_operation(M2MBase::GET_ALLOWED);
00253         }
00254     }
00255     if (res && res->supports_multiple_instances() && (res->resource_instance(instance_id) == NULL)) {
00256         char *path = create_path(*res, instance_id);
00257         if (path) {
00258             instance = new M2MResourceInstance(*res, "", M2MBase::Dynamic, resource_type, convert_resource_type(type),
00259                                                path, external_blockwise_store,true);
00260             if(instance) {
00261                 instance->set_operation(M2MBase::GET_ALLOWED);
00262                 instance->set_observable(observable);
00263                 instance->set_instance_id(instance_id);
00264                 res->add_resource_instance(instance);
00265                 set_changed();
00266             }
00267         }
00268     }
00269     return instance;
00270 }
00271 
00272 bool M2MObjectInstance::remove_resource(const String &resource_name)
00273 {
00274     return remove_resource(resource_name.c_str());
00275 }
00276 
00277 bool M2MObjectInstance::remove_resource(const char *resource_name)
00278 {
00279     tr_debug("M2MObjectInstance::remove_resource(resource_name %s)", resource_name);
00280 
00281     bool success = false;
00282     if(!_resource_list.empty()) {
00283          M2MResource* res = NULL;
00284          M2MResourceList::const_iterator it;
00285          it = _resource_list.begin();
00286          int pos = 0;
00287          for ( ; it != _resource_list.end(); it++, pos++ ) {
00288              if(strcmp((*it)->name(), resource_name) == 0) {
00289                 // Resource found and deleted.
00290                 res = *it;
00291                 delete res;
00292                 _resource_list.erase(pos);
00293                 set_changed();
00294                 success = true;
00295                 break;
00296              }
00297          }
00298     }
00299     return success;
00300 }
00301 
00302 bool M2MObjectInstance::remove_resource_instance(const String &resource_name,
00303                                                  uint16_t inst_id)
00304 {
00305     tr_debug("M2MObjectInstance::remove_resource_instance(resource_name %s inst_id %d)",
00306              resource_name.c_str(), inst_id);
00307     bool success = false;
00308     M2MResource *res = resource(resource_name);
00309     if(res) {
00310         const M2MResourceInstanceList &list = res->resource_instances();
00311         M2MResourceInstanceList::const_iterator it;
00312         it = list.begin();
00313         for ( ; it != list.end(); it++) {
00314             if((*it)->instance_id() == inst_id) {
00315                 success = res->remove_resource_instance(inst_id);
00316                 if(res->resource_instance_count() == 0) {
00317                     M2MResourceList::const_iterator itr;
00318                     itr = _resource_list.begin();
00319                     int pos = 0;
00320                     for ( ; itr != _resource_list.end(); itr++, pos++ ) {
00321                         if(strcmp((*itr)->name(),resource_name.c_str()) == 0) {
00322                             delete res;
00323                             _resource_list.erase(pos);
00324                             set_changed();
00325                             break;
00326                         }
00327                     }
00328                 }
00329                 break;
00330             }
00331         }
00332     }
00333     return success;
00334 }
00335 
00336 M2MResource* M2MObjectInstance::resource(const String &resource_name) const
00337 {
00338     return resource(resource_name.c_str());
00339 }
00340 
00341 M2MResource* M2MObjectInstance::resource(const char *resource_name) const
00342 {
00343     M2MResource *res = NULL;
00344     if(!_resource_list.empty()) {
00345         M2MResourceList::const_iterator it;
00346         it = _resource_list.begin();
00347         for (; it!=_resource_list.end(); it++ ) {
00348             if(strcmp((*it)->name(), resource_name) == 0) {
00349                 res = *it;
00350                 break;
00351             }
00352         }
00353     }
00354     return res;
00355 }
00356 
00357 const M2MResourceList& M2MObjectInstance::resources() const
00358 {
00359     return _resource_list;
00360 }
00361 
00362 uint16_t M2MObjectInstance::resource_count() const
00363 {
00364     uint16_t count = 0;
00365     if(!_resource_list.empty()) {
00366         M2MResourceList::const_iterator it;
00367         it = _resource_list.begin();
00368         for ( ; it != _resource_list.end(); it++ ) {
00369             if((*it)->supports_multiple_instances()) {
00370                 count += (*it)->resource_instance_count();
00371             } else {
00372                 count++;
00373             }
00374         }
00375     }
00376     return count;
00377 }
00378 
00379 uint16_t M2MObjectInstance::resource_count(const String& resource) const
00380 {
00381 
00382     return resource_count(resource.c_str());
00383 }
00384 
00385 uint16_t M2MObjectInstance::resource_count(const char *resource) const
00386 {
00387     uint16_t count = 0;
00388     if(!_resource_list.empty()) {
00389         M2MResourceList::const_iterator it;
00390         it = _resource_list.begin();
00391         for ( ; it != _resource_list.end(); it++ ) {
00392             if(strcmp((*it)->name(), resource) == 0) {
00393                 if((*it)->supports_multiple_instances()) {
00394                     count += (*it)->resource_instance_count();
00395                 } else {
00396                     count++;
00397                 }
00398             }
00399         }
00400     }
00401     return count;
00402 }
00403 
00404 M2MObservationHandler* M2MObjectInstance::observation_handler() const
00405 {
00406     // XXX: need to check the flag too
00407     return _parent.observation_handler();
00408 }
00409 
00410 void M2MObjectInstance::set_observation_handler(M2MObservationHandler *handler)
00411 {
00412     // XXX: need to set the flag too
00413     _parent.set_observation_handler(handler);
00414 }
00415 
00416 void M2MObjectInstance::add_observation_level(M2MBase::Observation observation_level)
00417 {
00418     M2MBase::add_observation_level(observation_level);
00419     if(!_resource_list.empty()) {
00420         M2MResourceList::const_iterator it;
00421         it = _resource_list.begin();
00422         for ( ; it != _resource_list.end(); it++ ) {
00423             (*it)->add_observation_level(observation_level);
00424         }
00425     }
00426 }
00427 
00428 void M2MObjectInstance::remove_observation_level(M2MBase::Observation observation_level)
00429 {
00430     M2MBase::remove_observation_level(observation_level);
00431     if(!_resource_list.empty()) {
00432         M2MResourceList::const_iterator it;
00433         it = _resource_list.begin();
00434         for ( ; it != _resource_list.end(); it++ ) {
00435            (*it)->remove_observation_level(observation_level);
00436         }
00437     }
00438 }
00439 
00440 sn_coap_hdr_s* M2MObjectInstance::handle_get_request(nsdl_s *nsdl,
00441                                                      sn_coap_hdr_s *received_coap_header,
00442                                                      M2MObservationHandler *observation_handler)
00443 {
00444     tr_info("M2MObjectInstance::handle_get_request()");
00445     sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
00446     sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
00447                                                            received_coap_header,
00448                                                            msg_code);
00449     uint8_t * data = NULL;
00450     uint32_t  data_length = 0;
00451 
00452     if (received_coap_header) {
00453         // process the GET if we have registered a callback for it
00454         if ((operation() & SN_GRS_GET_ALLOWED) != 0) {
00455             if (coap_response) {
00456                 bool content_type_present = false;
00457                 bool is_content_type_supported = true;
00458 
00459                 if (received_coap_header->options_list_ptr &&
00460                         received_coap_header->options_list_ptr->accept != COAP_CT_NONE) {
00461                     content_type_present = true;
00462                     coap_response->content_format = received_coap_header->options_list_ptr->accept;
00463 
00464                 }
00465 
00466                 // Check if preferred content type is supported
00467                 if (content_type_present) {
00468                     if (coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE_OLD &&
00469                         coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE) {
00470                         is_content_type_supported = false;
00471                     }
00472                 }
00473 
00474                 if (is_content_type_supported) {
00475                     if (!content_type_present &&
00476                        (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
00477                         M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
00478                         coap_response->content_format = sn_coap_content_format_e(M2MBase::coap_content_type());
00479                     }
00480 
00481                     // fill in the CoAP response payload
00482                     if (COAP_CONTENT_OMA_TLV_TYPE == coap_response->content_format  ||
00483                         COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_response->content_format) {
00484                         set_coap_content_type(coap_response->content_format);
00485                         data = M2MTLVSerializer::serialize(_resource_list, data_length);
00486                     }
00487 
00488                     coap_response->payload_len = data_length;
00489                     coap_response->payload_ptr = data;
00490 
00491                     if (data) {
00492                         coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
00493                         if (coap_response->options_list_ptr) {
00494                             coap_response->options_list_ptr->max_age = max_age();
00495                         }
00496 
00497                         if (received_coap_header->options_list_ptr) {
00498                             if (received_coap_header->options_list_ptr->observe != -1) {
00499                                 if (is_observable()) {
00500                                     uint32_t number = 0;
00501                                     uint8_t observe_option = 0;
00502                                     observe_option = received_coap_header->options_list_ptr->observe;
00503                                     if (START_OBSERVATION == observe_option) {
00504                                         // If the observe length is 0 means register for observation.
00505                                         if (received_coap_header->options_list_ptr->observe != -1) {
00506                                             number = received_coap_header->options_list_ptr->observe;
00507                                         }
00508 
00509                                         // If the observe value is 0 means register for observation.
00510                                         if (number == 0) {
00511                                             tr_info("M2MObjectInstance::handle_get_request - put resource under observation");
00512                                             set_under_observation(true,observation_handler);
00513                                             add_observation_level(M2MBase::OI_Attribute);
00514                                             send_notification_delivery_status(*this, NOTIFICATION_STATUS_SUBSCRIBED);
00515                                             if (coap_response->options_list_ptr) {
00516                                                 coap_response->options_list_ptr->observe = observation_number();
00517                                             }
00518                                         }
00519 
00520                                         if (received_coap_header->token_ptr) {
00521                                             set_observation_token(received_coap_header->token_ptr,
00522                                                                   received_coap_header->token_len);
00523                                         }
00524 
00525                                     } else if (STOP_OBSERVATION == observe_option) {
00526                                         tr_info("M2MObjectInstance::handle_get_request - stops observation");
00527                                         set_under_observation(false,NULL);
00528                                         remove_observation_level(M2MBase::OI_Attribute);
00529                                         send_notification_delivery_status(*this, NOTIFICATION_STATUS_UNSUBSCRIBED);
00530                                     }
00531                                     msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
00532                                 }
00533                                 else {
00534                                     msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00535                                 }
00536                             }
00537                         }
00538                     } else {
00539                         msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; // Content format not supported
00540                     }
00541                 } else {
00542                     tr_error("M2MObjectInstance::handle_get_request() - Content-type: %d not supported", coap_response->content_format);
00543                     msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE;
00544                 }
00545             }
00546         } else {
00547             tr_error("M2MObjectInstance::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
00548             // Operation is not allowed.
00549             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00550         }
00551     } else {
00552         msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00553     }
00554     if(coap_response) {
00555         coap_response->msg_code = msg_code;
00556     }
00557     return coap_response;
00558 }
00559 
00560 sn_coap_hdr_s* M2MObjectInstance::handle_put_request(nsdl_s *nsdl,
00561                                                      sn_coap_hdr_s *received_coap_header,
00562                                                      M2MObservationHandler *observation_handler,
00563                                                      bool &/*execute_value_updated*/)
00564 {
00565     tr_info("M2MObjectInstance::handle_put_request()");
00566     sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
00567     sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
00568                                                            received_coap_header,
00569                                                            msg_code);;
00570     if(received_coap_header) {
00571         uint16_t coap_content_type = 0;
00572         bool content_type_present = false;
00573 
00574         if(received_coap_header->content_format != COAP_CT_NONE) {
00575             content_type_present = true;
00576             set_coap_content_type(received_coap_header->content_format);
00577             if(coap_response) {
00578                 coap_content_type = received_coap_header->content_format;
00579             }
00580         }
00581         if(received_coap_header->options_list_ptr &&
00582            received_coap_header->options_list_ptr->uri_query_ptr) {
00583             char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr,
00584                                                     received_coap_header->options_list_ptr->uri_query_len);
00585             if (query){
00586                 tr_info("M2MObjectInstance::handle_put_request() - query %s", query);
00587                 // if anything was updated, re-initialize the stored notification attributes
00588                 if (!handle_observation_attribute(query)){
00589                     tr_debug("M2MObjectInstance::handle_put_request() - Invalid query");
00590                     msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00
00591                 } else {
00592                     msg_code =COAP_MSG_CODE_RESPONSE_CHANGED;
00593                 }
00594                 free(query);
00595             }
00596         } else if ((operation() & SN_GRS_PUT_ALLOWED) != 0) {
00597             if(!content_type_present &&
00598                (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
00599                 M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
00600                 coap_content_type = M2MBase::coap_content_type();
00601             }
00602 
00603             tr_debug("M2MObjectInstance::handle_put_request() - Request Content-type: %d", coap_content_type);
00604 
00605             if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type ||
00606                COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type ) {
00607                 set_coap_content_type(coap_content_type);
00608                 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
00609                 if(received_coap_header->payload_ptr) {
00610                     error = M2MTLVDeserializer::deserialize_resources(
00611                                 received_coap_header->payload_ptr,
00612                                 received_coap_header->payload_len, *this,
00613                                 M2MTLVDeserializer::Put);
00614                     switch(error) {
00615                         case M2MTLVDeserializer::None:
00616                             if(observation_handler) {
00617                                 observation_handler->value_updated(this);
00618                             }
00619                             msg_code = COAP_MSG_CODE_RESPONSE_CHANGED;
00620                             break;
00621                         case M2MTLVDeserializer::NotFound:
00622                             msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
00623                             break;
00624                         case M2MTLVDeserializer::NotAllowed:
00625                             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00626                             break;
00627                         case M2MTLVDeserializer::NotValid:
00628                             msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
00629                             break;
00630                         case M2MTLVDeserializer::OutOfMemory:
00631                             msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
00632                             break;
00633                     }
00634                 }
00635             } else {
00636                 msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
00637             } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type)
00638         } else {
00639             // Operation is not allowed.
00640             tr_error("M2MObjectInstance::handle_put_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
00641             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00642         }
00643     } else {
00644        msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00645     }
00646     if(coap_response) {
00647         coap_response->msg_code = msg_code;
00648     }
00649     return coap_response;
00650 }
00651 
00652 sn_coap_hdr_s* M2MObjectInstance::handle_post_request(nsdl_s *nsdl,
00653                                                       sn_coap_hdr_s *received_coap_header,
00654                                                       M2MObservationHandler *observation_handler,
00655                                                       bool &execute_value_updated,
00656                                                       sn_nsdl_addr_s *)
00657 {
00658     tr_info("M2MObjectInstance::handle_post_request()");
00659     sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
00660     sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
00661                                                            received_coap_header,
00662                                                            msg_code);
00663     if(received_coap_header) {
00664         if ((operation() & SN_GRS_POST_ALLOWED) != 0) {
00665             uint16_t coap_content_type = 0;
00666             bool content_type_present = false;
00667             if(received_coap_header->content_format != COAP_CT_NONE) {
00668                 set_coap_content_type(received_coap_header->content_format);
00669                 content_type_present = true;
00670                 if(coap_response) {
00671                     coap_content_type = received_coap_header->content_format;
00672                 }
00673             }
00674             if(!content_type_present &&
00675                (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
00676                 M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
00677                 coap_content_type = M2MBase::coap_content_type();
00678             }
00679 
00680             tr_debug("M2MObjectInstance::handle_post_request() - Request Content-type: %d", coap_content_type);
00681 
00682             if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type ||
00683                COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type) {
00684                 set_coap_content_type(coap_content_type);
00685                 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
00686                 error = M2MTLVDeserializer::deserialize_resources(
00687                             received_coap_header->payload_ptr,
00688                             received_coap_header->payload_len, *this,
00689                             M2MTLVDeserializer::Post);
00690 
00691                 uint16_t instance_id = M2MTLVDeserializer::instance_id(received_coap_header->payload_ptr);
00692                 switch(error) {
00693                     case M2MTLVDeserializer::None:
00694                         if(observation_handler) {
00695                             execute_value_updated = true;
00696                         }
00697                         coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
00698 
00699                         if (coap_response->options_list_ptr) {
00700 
00701                             StringBuffer<MAX_PATH_SIZE_3> obj_name;
00702                             if(!build_path(obj_name, _parent.name(), M2MBase::instance_id(), instance_id)) {
00703                                 msg_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
00704                                 break;
00705                             }
00706 
00707                             coap_response->options_list_ptr->location_path_len = obj_name.get_size();
00708                             coap_response->options_list_ptr->location_path_ptr =
00709                               alloc_string_copy((uint8_t*)obj_name.c_str(),
00710                                                 coap_response->options_list_ptr->location_path_len);
00711                             // todo: handle allocation error
00712                         }
00713                         msg_code = COAP_MSG_CODE_RESPONSE_CREATED;
00714                         break;
00715                     case M2MTLVDeserializer::NotAllowed:
00716                         msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00717                         break;
00718                     case M2MTLVDeserializer::NotValid:
00719                         msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
00720                         break;
00721                     case M2MTLVDeserializer::NotFound:
00722                         msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
00723                         break;
00724                     case M2MTLVDeserializer::OutOfMemory:
00725                         msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
00726                         break;
00727                     default:
00728                         break;
00729                 }
00730             } else {
00731                 msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
00732             } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type)
00733         } else {
00734             // Operation is not allowed.
00735             tr_error("M2MObjectInstance::handle_post_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
00736             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00737         }
00738     } else {
00739         msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00740     }
00741     if(coap_response) {
00742         coap_response->msg_code = msg_code;
00743     }
00744     return coap_response;
00745 }
00746 
00747 void M2MObjectInstance::notification_update(M2MBase::Observation observation_level)
00748 {
00749     tr_debug("M2MObjectInstance::notification_update() - level(%d)", observation_level);
00750     if((M2MBase::O_Attribute & observation_level) == M2MBase::O_Attribute) {
00751         tr_debug("M2MObjectInstance::notification_update() - object callback");
00752         _parent.notification_update(instance_id());
00753     }
00754     if((M2MBase::OI_Attribute & observation_level) == M2MBase::OI_Attribute) {
00755         tr_debug("M2MObjectInstance::notification_update() - object instance callback");
00756         M2MReportHandler *report_handler = M2MBase::report_handler();
00757         if(report_handler && is_under_observation()) {
00758             report_handler->set_notification_trigger();
00759         }
00760 
00761     }
00762 }
00763 
00764 M2MBase *M2MObjectInstance::get_parent() const
00765 {
00766     return (M2MBase *) &get_parent_object();
00767 }
00768 
00769 M2MBase::DataType M2MObjectInstance::convert_resource_type(M2MResourceInstance::ResourceType type)
00770 {
00771     M2MBase::DataType data_type = M2MBase::OBJLINK;
00772     switch(type) {
00773         case M2MResourceInstance::STRING:
00774             data_type = M2MBase::STRING;
00775             break;
00776         case M2MResourceInstance::INTEGER:
00777             data_type = M2MBase::INTEGER;
00778             break;
00779         case M2MResourceInstance::FLOAT:
00780             data_type = M2MBase::FLOAT;
00781             break;
00782         case M2MResourceInstance::OPAQUE:
00783             data_type = M2MBase::OPAQUE;
00784             break;
00785         case M2MResourceInstance::BOOLEAN:
00786             data_type = M2MBase::BOOLEAN;
00787             break;
00788         case M2MResourceInstance::TIME:
00789             data_type = M2MBase::TIME;
00790             break;
00791         case M2MResourceInstance::OBJLINK:
00792             data_type = M2MBase::OBJLINK;
00793             break;
00794     }
00795     return data_type;
00796 }