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