Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FXAS21002 FXOS8700Q
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() & M2MBase::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 handle_observation(nsdl, *received_coap_header, *coap_response, observation_handler, msg_code); 00283 } 00284 } 00285 } else { 00286 msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; // Content format not supported 00287 } 00288 } else { 00289 tr_error("M2MObject::handle_get_request() - Content-Type %d not supported", coap_response->content_format); 00290 msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE; 00291 } 00292 } 00293 }else { 00294 tr_error("M2MResource::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); 00295 // Operation is not allowed. 00296 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00297 } 00298 } else { 00299 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00300 } 00301 if(coap_response) { 00302 coap_response->msg_code = msg_code; 00303 } 00304 return coap_response; 00305 } 00306 00307 sn_coap_hdr_s* M2MObject::handle_put_request(nsdl_s *nsdl, 00308 sn_coap_hdr_s *received_coap_header, 00309 M2MObservationHandler */*observation_handler*/, 00310 bool &/*execute_value_updated*/) 00311 { 00312 tr_info("M2MObject::handle_put_request()"); 00313 sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04 00314 sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl, 00315 received_coap_header, 00316 msg_code); 00317 if(received_coap_header) { 00318 if(received_coap_header->content_format != COAP_CT_NONE) { 00319 set_coap_content_type(received_coap_header->content_format); 00320 } 00321 if(received_coap_header->options_list_ptr && 00322 received_coap_header->options_list_ptr->uri_query_ptr) { 00323 char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr, 00324 received_coap_header->options_list_ptr->uri_query_len); 00325 00326 if (query){ 00327 tr_info("M2MObject::handle_put_request() - query %s", query); 00328 // if anything was updated, re-initialize the stored notification attributes 00329 if (!handle_observation_attribute(query)){ 00330 tr_debug("M2MObject::handle_put_request() - Invalid query"); 00331 msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00 00332 } 00333 free(query); 00334 } 00335 } else { 00336 tr_error("M2MObject::handle_put_request() - COAP_MSG_CODE_RESPONSE_BAD_REQUEST - Empty URI_QUERY"); 00337 msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 00338 } 00339 } else { 00340 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00341 } 00342 if(coap_response) { 00343 coap_response->msg_code = msg_code; 00344 } 00345 return coap_response; 00346 } 00347 00348 00349 sn_coap_hdr_s* M2MObject::handle_post_request(nsdl_s *nsdl, 00350 sn_coap_hdr_s *received_coap_header, 00351 M2MObservationHandler *observation_handler, 00352 bool &execute_value_updated, 00353 sn_nsdl_addr_s *) 00354 { 00355 tr_info("M2MObject::handle_post_request()"); 00356 sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04 00357 // process the POST if we have registered a callback for it 00358 sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl, 00359 received_coap_header, 00360 msg_code); 00361 00362 if (received_coap_header) { 00363 if ((operation() & M2MBase::POST_ALLOWED) != 0) { 00364 if (received_coap_header->content_format != COAP_CT_NONE) { 00365 set_coap_content_type(received_coap_header->content_format); 00366 } 00367 if(received_coap_header->payload_ptr) { 00368 tr_debug("M2MObject::handle_post_request() - Update Object with new values"); 00369 uint16_t coap_content_type = 0; 00370 bool content_type_present = false; 00371 if(received_coap_header->content_format != COAP_CT_NONE) { 00372 content_type_present = true; 00373 if(coap_response) { 00374 coap_content_type = received_coap_header->content_format; 00375 } 00376 } // if(received_coap_header->content_format) 00377 if(!content_type_present && 00378 (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE || 00379 M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) { 00380 coap_content_type = M2MBase::coap_content_type(); 00381 } 00382 00383 tr_debug("M2MObject::handle_post_request() - Request Content-type: %d", coap_content_type); 00384 00385 if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type || 00386 COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type) { 00387 set_coap_content_type(coap_content_type); 00388 uint32_t instance_id = 0; 00389 // Check next free instance id 00390 for(instance_id = 0; instance_id <= MAX_UNINT_16_COUNT; instance_id++) { 00391 if(NULL == object_instance(instance_id)) { 00392 break; 00393 } 00394 if(instance_id == MAX_UNINT_16_COUNT) { 00395 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00396 break; 00397 } 00398 } 00399 if(COAP_MSG_CODE_RESPONSE_CHANGED == msg_code) { 00400 bool is_obj_instance = false; 00401 bool obj_instance_exists = false; 00402 is_obj_instance = M2MTLVDeserializer::is_object_instance(received_coap_header->payload_ptr); 00403 if (is_obj_instance) { 00404 instance_id = M2MTLVDeserializer::instance_id(received_coap_header->payload_ptr); 00405 tr_debug("M2MObject::handle_post_request() - instance id in TLV: %" PRIu32, instance_id); 00406 // Check if instance id already exists 00407 if (object_instance(instance_id)){ 00408 obj_instance_exists = true; 00409 } 00410 } 00411 if (!obj_instance_exists && coap_response) { 00412 M2MObjectInstance *obj_instance = create_object_instance(instance_id); 00413 if (obj_instance) { 00414 obj_instance->set_operation(M2MBase::GET_PUT_ALLOWED); 00415 } 00416 00417 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00418 if(is_obj_instance) { 00419 tr_debug("M2MObject::handle_post_request() - TLV data contains ObjectInstance"); 00420 error = M2MTLVDeserializer::deserialise_object_instances(received_coap_header->payload_ptr, 00421 received_coap_header->payload_len, 00422 *this, 00423 M2MTLVDeserializer::Post); 00424 } else if(obj_instance && 00425 (M2MTLVDeserializer::is_resource(received_coap_header->payload_ptr) || 00426 M2MTLVDeserializer::is_multiple_resource(received_coap_header->payload_ptr))) { 00427 tr_debug("M2MObject::handle_post_request() - TLV data contains Resources"); 00428 error = M2MTLVDeserializer::deserialize_resources(received_coap_header->payload_ptr, 00429 received_coap_header->payload_len, 00430 *obj_instance, 00431 M2MTLVDeserializer::Post); 00432 } else { 00433 error = M2MTLVDeserializer::NotValid; 00434 } 00435 switch(error) { 00436 case M2MTLVDeserializer::None: 00437 if(observation_handler) { 00438 execute_value_updated = true; 00439 } 00440 coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response); 00441 00442 if (coap_response->options_list_ptr) { 00443 00444 StringBuffer<MAX_OBJECT_PATH_NAME> obj_name; 00445 00446 if (obj_name.ensure_space(M2MBase::resource_name_length() + (1 + 5 + 1))) { 00447 obj_name.append(M2MBase::name()); 00448 obj_name.append('/'); 00449 obj_name.append_int(instance_id); 00450 00451 coap_response->options_list_ptr->location_path_len = obj_name.get_size(); 00452 coap_response->options_list_ptr->location_path_ptr = 00453 alloc_copy((uint8_t*)obj_name.c_str(), obj_name.get_size()); 00454 // todo: else return error 00455 } 00456 } 00457 // todo: else return error 00458 msg_code = COAP_MSG_CODE_RESPONSE_CREATED; 00459 break; 00460 case M2MTLVDeserializer::NotAllowed: 00461 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00462 break; 00463 case M2MTLVDeserializer::NotValid: 00464 msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 00465 break; 00466 case M2MTLVDeserializer::NotFound: 00467 msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND; 00468 break; 00469 case M2MTLVDeserializer::OutOfMemory: 00470 msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE; 00471 break; 00472 } 00473 00474 } else { 00475 tr_error("M2MObject::handle_post_request() - COAP_MSG_CODE_RESPONSE_BAD_REQUEST"); 00476 msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 00477 } 00478 } 00479 } else { 00480 msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; 00481 } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) 00482 } else { 00483 tr_error("M2MObject::handle_post_request - COAP_MSG_CODE_RESPONSE_BAD_REQUEST - Missing Payload"); 00484 msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 00485 } 00486 } else { // if ((object->operation() & SN_GRS_POST_ALLOWED) != 0) 00487 tr_error("M2MObject::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); 00488 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.05 00489 } 00490 } else { //if(received_coap_header) 00491 tr_error("M2MObject::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); 00492 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.05 00493 } 00494 00495 if(coap_response) { 00496 coap_response->msg_code = msg_code; 00497 } 00498 return coap_response; 00499 } 00500 00501 void M2MObject::notification_update(uint16_t obj_instance_id) 00502 { 00503 tr_debug("M2MObject::notification_update - id: %d", obj_instance_id); 00504 M2MReportHandler *report_handler = M2MBase::report_handler(); 00505 if(report_handler && is_under_observation()) { 00506 report_handler->set_notification_trigger(obj_instance_id); 00507 } 00508 } 00509 00510 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION 00511 void M2MObject::set_endpoint(M2MEndpoint *endpoint) 00512 { 00513 _endpoint = endpoint; 00514 } 00515 00516 M2MEndpoint* M2MObject::get_endpoint() const 00517 { 00518 return _endpoint; 00519 } 00520 #endif 00521 00522 M2MBase *M2MObject::get_parent() const 00523 { 00524 #ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION 00525 return (M2MBase *) get_endpoint(); 00526 #else 00527 return NULL; 00528 #endif 00529 }
Generated on Tue Jul 12 2022 20:21:00 by
