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