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
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 12:28:39 by
1.7.2
