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