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.
Fork of mbed-client by
m2mresourceinstance.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 <stdlib.h> 00017 #include "mbed-client/m2mresource.h" 00018 #include "mbed-client/m2mconstants.h" 00019 #include "mbed-client/m2mobservationhandler.h" 00020 #include "mbed-client/m2mobjectinstance.h" 00021 #include "include/m2mreporthandler.h" 00022 #include "include/nsdllinker.h" 00023 #include "mbed-trace/mbed_trace.h" 00024 00025 #define TRACE_GROUP "mClt" 00026 00027 M2MResourceInstance& M2MResourceInstance::operator=(const M2MResourceInstance& other) 00028 { 00029 if (this != &other) { // protect against invalid self-assignment 00030 if(_value) { 00031 free(_value); 00032 _value = NULL; 00033 _value_length = 0; 00034 } 00035 _value_length = other._value_length; 00036 if(other._value) { 00037 _value = (uint8_t *)malloc(other._value_length+1); 00038 if(_value) { 00039 memset(_value, 0, other._value_length+1); 00040 memcpy((uint8_t *)_value, (uint8_t *)other._value, other._value_length); 00041 } 00042 } 00043 } 00044 return *this; 00045 } 00046 00047 M2MResourceInstance::M2MResourceInstance(const M2MResourceInstance& other) 00048 : M2MBase(other), 00049 _object_instance_callback(other._object_instance_callback), 00050 _execute_callback(NULL), 00051 _value(NULL), 00052 _value_length(0), 00053 _resource_type(M2MResourceInstance::STRING), 00054 _resource_callback(NULL), 00055 _object_instance_id(other._object_instance_id), 00056 _object_name(other._object_name), 00057 _function_pointer(NULL) 00058 { 00059 this->operator=(other); 00060 } 00061 00062 M2MResourceInstance::M2MResourceInstance(const String &res_name, 00063 const String &resource_type, 00064 M2MResourceInstance::ResourceType type, 00065 M2MObjectInstanceCallback &object_instance_callback, 00066 const uint16_t object_instance_id, 00067 const String &object_name) 00068 : M2MBase(res_name, 00069 M2MBase::Dynamic), 00070 _object_instance_callback(object_instance_callback), 00071 _execute_callback(NULL), 00072 _value(NULL), 00073 _value_length(0), 00074 _resource_type(type), 00075 _resource_callback(NULL), 00076 _object_instance_id(object_instance_id), 00077 _object_name(object_name), 00078 _function_pointer(NULL) 00079 { 00080 M2MBase::set_resource_type(resource_type); 00081 M2MBase::set_base_type(M2MBase::ResourceInstance); 00082 } 00083 00084 M2MResourceInstance::M2MResourceInstance(const String &res_name, 00085 const String &resource_type, 00086 M2MResourceInstance::ResourceType type, 00087 const uint8_t *value, 00088 const uint8_t value_length, 00089 M2MObjectInstanceCallback &object_instance_callback, 00090 const uint16_t object_instance_id, 00091 const String &object_name) 00092 : M2MBase(res_name, 00093 M2MBase::Static), 00094 _object_instance_callback(object_instance_callback), 00095 _execute_callback(NULL), 00096 _value(NULL), 00097 _value_length(0), 00098 _resource_type(type), 00099 _resource_callback(NULL), 00100 _object_instance_id(object_instance_id), 00101 _object_name(object_name), 00102 _function_pointer(NULL) 00103 { 00104 M2MBase::set_resource_type(resource_type); 00105 M2MBase::set_base_type(M2MBase::Resource); 00106 if( value != NULL && value_length > 0 ) { 00107 _value = (uint8_t *)malloc(value_length+1); 00108 if(_value) { 00109 memset(_value, 0, value_length+1); 00110 memcpy((uint8_t *)_value, (uint8_t *)value, value_length); 00111 _value_length = value_length; 00112 } 00113 } 00114 } 00115 00116 M2MResourceInstance::~M2MResourceInstance() 00117 { 00118 if(_value) { 00119 free(_value); 00120 _value = NULL; 00121 _value_length = 0; 00122 } 00123 if (_function_pointer) { 00124 delete _function_pointer; 00125 _function_pointer = NULL; 00126 } 00127 _resource_callback = NULL; 00128 } 00129 00130 M2MBase::BaseType M2MResourceInstance::base_type() const 00131 { 00132 return M2MBase::base_type(); 00133 } 00134 00135 M2MResourceInstance::ResourceType M2MResourceInstance::resource_instance_type() const 00136 { 00137 return _resource_type; 00138 } 00139 00140 bool M2MResourceInstance::handle_observation_attribute(char *&query) 00141 { 00142 tr_debug("M2MResourceInstance::handle_observation_attribute()"); 00143 bool success = false; 00144 M2MReportHandler *handler = M2MBase::report_handler(); 00145 if (handler) { 00146 success = handler->parse_notification_attribute(query, 00147 M2MBase::base_type(), _resource_type); 00148 if (success) { 00149 if ((handler->attribute_flags() & M2MReportHandler::Cancel) == 0) { 00150 handler->set_under_observation(true); 00151 } else { 00152 handler->set_under_observation(false); 00153 } 00154 } 00155 else { 00156 handler->set_default_values(); 00157 } 00158 } 00159 return success; 00160 } 00161 00162 void M2MResourceInstance::set_execute_function(execute_callback callback) 00163 { 00164 _execute_callback = callback; 00165 } 00166 00167 void M2MResourceInstance::set_execute_function(execute_callback_2 callback) 00168 { 00169 if (_function_pointer) { 00170 delete _function_pointer; 00171 } 00172 _function_pointer = new FP1<void, void*> (callback); 00173 set_execute_function(execute_callback (_function_pointer, &FP1<void, void*>::call)); 00174 } 00175 00176 void M2MResourceInstance::clear_value() 00177 { 00178 tr_debug("M2MResourceInstance::clear_value"); 00179 if(_value) { 00180 free(_value); 00181 _value = NULL; 00182 _value_length = 0; 00183 } 00184 report(); 00185 } 00186 00187 bool M2MResourceInstance::set_value(const uint8_t *value, 00188 const uint32_t value_length) 00189 { 00190 tr_debug("M2MResourceInstance::set_value()"); 00191 bool success = false; 00192 bool value_changed = false; 00193 if(is_value_changed(value,value_length)) { 00194 value_changed = true; 00195 } 00196 if( value != NULL && value_length > 0 ) { 00197 success = true; 00198 if(_value) { 00199 free(_value); 00200 _value = NULL; 00201 _value_length = 0; 00202 } 00203 _value = (uint8_t *)malloc(value_length+1); 00204 if(_value) { 00205 memset(_value, 0, value_length+1); 00206 memcpy((uint8_t *)_value, (uint8_t *)value, value_length); 00207 _value_length = value_length; 00208 if( value_changed ) { // 00209 if (_resource_type == M2MResourceInstance::STRING) { 00210 M2MReportHandler *report_handler = M2MBase::report_handler(); 00211 if(report_handler && is_observable()) { 00212 report_handler->set_notification_trigger(); 00213 } 00214 } 00215 else { 00216 report(); 00217 } 00218 } 00219 } 00220 } 00221 return success; 00222 } 00223 00224 void M2MResourceInstance::report() 00225 { 00226 tr_debug("M2MResourceInstance::report()"); 00227 M2MBase::Observation observation_level = M2MBase::observation_level(); 00228 if(M2MBase::O_Attribute == observation_level || 00229 M2MBase::OI_Attribute == observation_level|| 00230 M2MBase::OOI_Attribute == observation_level) { 00231 tr_debug("M2MResourceInstance::report() -- object level"); 00232 _object_instance_callback.notification_update(observation_level); 00233 } 00234 00235 if(M2MBase::Dynamic == mode() && M2MBase::R_Attribute == observation_level) { 00236 tr_debug("M2MResourceInstance::report() - resource level"); 00237 if(!_resource_callback && _resource_type != M2MResourceInstance::STRING) { 00238 M2MReportHandler *report_handler = M2MBase::report_handler(); 00239 if (report_handler && is_observable()) { 00240 if(_value) { 00241 report_handler->set_value(atof((const char*)_value)); 00242 } else { 00243 report_handler->set_value(0); 00244 } 00245 } 00246 } 00247 else { 00248 if (_resource_callback && base_type() == M2MBase::ResourceInstance) { 00249 _resource_callback->notification_update(); 00250 } 00251 } 00252 } else if(M2MBase::Static == mode()) { 00253 M2MObservationHandler *observation_handler = M2MBase::observation_handler(); 00254 if(observation_handler) { 00255 observation_handler->value_updated(this); 00256 } 00257 } else { 00258 tr_debug("M2MResourceInstance::report() - mode = %d, is_observable = %d", mode(), is_observable()); 00259 } 00260 } 00261 00262 bool M2MResourceInstance::is_value_changed(const uint8_t* value, const uint32_t value_len) 00263 { 00264 tr_debug("M2MResourceInstance::is_value_changed()"); 00265 bool changed = false; 00266 if(value_len != _value_length) { 00267 changed = true; 00268 } else if(value && !_value) { 00269 changed = true; 00270 } else if(_value && !value) { 00271 changed = true; 00272 } else { 00273 if (_value) { 00274 String val((const char*)value); 00275 String tmp_val((const char*)_value); 00276 if(!(val == tmp_val)){ 00277 changed = true; 00278 } 00279 } 00280 } 00281 return changed; 00282 } 00283 00284 void M2MResourceInstance::execute(void *arguments) 00285 { 00286 tr_debug("M2MResourceInstance::execute"); 00287 if(_execute_callback) { 00288 _execute_callback(arguments); 00289 } 00290 } 00291 00292 void M2MResourceInstance::get_value(uint8_t *&value, uint32_t &value_length) 00293 { 00294 value_length = 0; 00295 if(value) { 00296 free(value); 00297 value = NULL; 00298 } 00299 if(_value && _value_length > 0) { 00300 value = (uint8_t *)malloc(_value_length+1); 00301 if(value) { 00302 value_length = _value_length; 00303 memset(value, 0, _value_length+1); 00304 memcpy((uint8_t *)value, (uint8_t *)_value, value_length); 00305 } 00306 } 00307 } 00308 00309 uint8_t* M2MResourceInstance::value() const 00310 { 00311 return _value; 00312 } 00313 00314 uint32_t M2MResourceInstance::value_length() const 00315 { 00316 return _value_length; 00317 } 00318 00319 sn_coap_hdr_s* M2MResourceInstance::handle_get_request(nsdl_s *nsdl, 00320 sn_coap_hdr_s *received_coap_header, 00321 M2MObservationHandler *observation_handler) 00322 { 00323 tr_debug("M2MResourceInstance::handle_get_request()"); 00324 sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; 00325 sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl, 00326 received_coap_header, 00327 msg_code); 00328 if(received_coap_header) { 00329 // process the GET if we have registered a callback for it 00330 if ((operation() & SN_GRS_GET_ALLOWED) != 0) { 00331 if(coap_response) { 00332 if(_resource_type == M2MResourceInstance::OPAQUE) { 00333 coap_response->content_type_ptr = 00334 m2m::String::convert_integer_to_array(COAP_CONTENT_OMA_OPAQUE_TYPE, 00335 coap_response->content_type_len); 00336 } else { 00337 coap_response->content_type_ptr = 00338 m2m::String::convert_integer_to_array(0, 00339 coap_response->content_type_len); 00340 } 00341 00342 // fill in the CoAP response payload 00343 coap_response->payload_ptr = NULL; 00344 uint32_t payload_len = 0; 00345 get_value(coap_response->payload_ptr,payload_len); 00346 coap_response->payload_len = payload_len; 00347 00348 coap_response->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); 00349 memset(coap_response->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); 00350 00351 coap_response->options_list_ptr->max_age_ptr = 00352 m2m::String::convert_integer_to_array(max_age(), 00353 coap_response->options_list_ptr->max_age_len); 00354 00355 if(received_coap_header->token_ptr) { 00356 tr_debug("M2MResourceInstance::handle_get_request - Sets Observation Token to resource"); 00357 set_observation_token(received_coap_header->token_ptr, 00358 received_coap_header->token_len); 00359 } 00360 00361 if(received_coap_header->options_list_ptr) { 00362 if(received_coap_header->options_list_ptr->observe) { 00363 if (is_observable()) { 00364 uint32_t number = 0; 00365 uint8_t observe_option = 0; 00366 if(received_coap_header->options_list_ptr->observe_ptr) { 00367 observe_option = *received_coap_header->options_list_ptr->observe_ptr; 00368 } 00369 if(START_OBSERVATION == observe_option) { 00370 tr_debug("M2MResourceInstance::handle_get_request - Starts Observation"); 00371 // If the observe length is 0 means register for observation. 00372 if(received_coap_header->options_list_ptr->observe_len != 0) { 00373 for(int i=0;i < received_coap_header->options_list_ptr->observe_len; i++) { 00374 number = (*(received_coap_header->options_list_ptr->observe_ptr + i) & 0xff) << 00375 8*(received_coap_header->options_list_ptr->observe_len- 1 - i); 00376 } 00377 } 00378 // If the observe value is 0 means register for observation. 00379 if(number == 0) { 00380 tr_debug("M2MResourceInstance::handle_get_request - Put Resource under Observation"); 00381 set_under_observation(true,observation_handler); 00382 M2MBase::add_observation_level(M2MBase::R_Attribute); 00383 coap_response->options_list_ptr->observe_ptr = 00384 m2m::String::convert_integer_to_array(observation_number(), 00385 coap_response->options_list_ptr->observe_len); 00386 } 00387 } else if (STOP_OBSERVATION == observe_option) { 00388 tr_debug("M2MResourceInstance::handle_get_request - Stops Observation"); 00389 set_under_observation(false,NULL); 00390 M2MBase::remove_observation_level(M2MBase::R_Attribute); 00391 } 00392 } else { 00393 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00394 } 00395 } 00396 } 00397 } 00398 }else { 00399 tr_error("M2MResourceInstance::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); 00400 // Operation is not allowed. 00401 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00402 } 00403 } else { 00404 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00405 } 00406 if(coap_response) { 00407 coap_response->msg_code = msg_code; 00408 } 00409 return coap_response; 00410 } 00411 00412 sn_coap_hdr_s* M2MResourceInstance::handle_put_request(nsdl_s *nsdl, 00413 sn_coap_hdr_s *received_coap_header, 00414 M2MObservationHandler *observation_handler, 00415 bool &execute_value_updated) 00416 { 00417 tr_debug("M2MResourceInstance::handle_put_request()"); 00418 sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04 00419 sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl, 00420 received_coap_header, 00421 msg_code); 00422 // process the PUT if we have registered a callback for it 00423 if(received_coap_header) { 00424 uint16_t coap_content_type = 0; 00425 if(received_coap_header->content_type_ptr) { 00426 if(coap_response) { 00427 coap_response->content_type_ptr = 00428 m2m::String::convert_integer_to_array(0, 00429 coap_response->content_type_len, 00430 received_coap_header->content_type_ptr, 00431 received_coap_header->content_type_len); 00432 00433 if(coap_response->content_type_ptr) { 00434 for(uint8_t i = 0; i < coap_response->content_type_len; i++) { 00435 coap_content_type = (coap_content_type << 8) + 00436 (coap_response->content_type_ptr[i] & 0xFF); 00437 } 00438 } 00439 } 00440 } 00441 if(received_coap_header->options_list_ptr && 00442 received_coap_header->options_list_ptr->uri_query_ptr) { 00443 char *query = (char*)malloc(received_coap_header->options_list_ptr->uri_query_len+1); 00444 if (query){ 00445 memset(query, 0, received_coap_header->options_list_ptr->uri_query_len+1); 00446 memcpy(query, 00447 received_coap_header->options_list_ptr->uri_query_ptr, 00448 received_coap_header->options_list_ptr->uri_query_len); 00449 memset(query + received_coap_header->options_list_ptr->uri_query_len,'\0',1);//String terminator 00450 tr_debug("M2MResourceInstance::handle_put_request() - Query %s", query); 00451 00452 // if anything was updated, re-initialize the stored notification attributes 00453 if (!handle_observation_attribute(query)){ 00454 tr_debug("M2MResourceInstance::handle_put_request() - Invalid query"); 00455 msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00 00456 } 00457 free(query); 00458 } 00459 } else if ((operation() & SN_GRS_PUT_ALLOWED) != 0) { 00460 tr_debug("M2MResourceInstance::handle_put_request() - Request Content-Type %d", coap_content_type); 00461 00462 if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) { 00463 msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; 00464 } else { 00465 set_value(received_coap_header->payload_ptr, received_coap_header->payload_len); 00466 if(received_coap_header->payload_ptr) { 00467 tr_debug("M2MResourceInstance::handle_put_request() - Update Resource with new values"); 00468 if(observation_handler) { 00469 String value = ""; 00470 if (received_coap_header->uri_path_ptr != NULL && 00471 received_coap_header->uri_path_len > 0) { 00472 char* buf = (char*)malloc(received_coap_header->uri_path_len+1); 00473 if(buf) { 00474 memset(buf,0,received_coap_header->uri_path_len+1); 00475 memcpy(buf,received_coap_header->uri_path_ptr,received_coap_header->uri_path_len); 00476 value = String(buf); 00477 free(buf); 00478 } 00479 } 00480 execute_value_updated = true; 00481 } 00482 } 00483 } 00484 } else { 00485 // Operation is not allowed. 00486 tr_error("M2MResourceInstance::handle_put_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); 00487 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00488 } 00489 } else { 00490 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00491 } 00492 if(coap_response) { 00493 coap_response->msg_code = msg_code; 00494 } 00495 return coap_response; 00496 } 00497 00498 void M2MResourceInstance::set_resource_observer(M2MResourceCallback *resource) 00499 { 00500 _resource_callback = resource; 00501 } 00502 00503 const String& M2MResourceInstance::object_name() const 00504 { 00505 return _object_name; 00506 } 00507 00508 uint16_t M2MResourceInstance::object_instance_id() const 00509 { 00510 return _object_instance_id; 00511 }
Generated on Tue Jul 12 2022 18:06:59 by
 1.7.2
 1.7.2 
    