joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2mresourceinstance.cpp Source File

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 }