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.
DynamicResource.cpp
00001 /** 00002 * @file DynamicResource.cpp 00003 * @brief mbed CoAP Endpoint Dynamic Resource class 00004 * @author Doug Anson/Chris Paola 00005 * @version 1.0 00006 * @see 00007 * 00008 * Copyright (c) 2014 00009 * 00010 * Licensed under the Apache License, Version 2.0 (the "License"); 00011 * you may not use this file except in compliance with the License. 00012 * You may obtain a copy of the License at 00013 * 00014 * http://www.apache.org/licenses/LICENSE-2.0 00015 * 00016 * Unless required by applicable law or agreed to in writing, software 00017 * distributed under the License is distributed on an "AS IS" BASIS, 00018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00019 * See the License for the specific language governing permissions and 00020 * limitations under the License. 00021 */ 00022 00023 #include "mbed-connector-interface/DynamicResource.h" 00024 00025 // ResourceObserver help 00026 #include "mbed-connector-interface/ResourceObserver.h" 00027 00028 // Options enablement 00029 #include "mbed-connector-interface/Options.h" 00030 00031 // Endpoint 00032 #include "mbed-connector-interface/ConnectorEndpoint.h" 00033 00034 // GET option that can be used to Start/Stop Observations... 00035 #define START_OBS 0 00036 #define STOP_OBS 1 00037 00038 // MaxAge support for each DynamicResource 00039 #define DEFAULT_MAXAGE 60 00040 00041 // ContentFormat defaults for each DynamicResource 00042 #define DEFAULT_CONTENT_FORMAT 0 00043 00044 // default constructor 00045 DynamicResource::DynamicResource(const Logger *logger,const char *obj_name,const char *res_name,const char *res_type,uint8_t res_mask,const bool observable) : Resource<string>(logger,string(obj_name),string(res_name),string("")) 00046 { 00047 this->m_res_type = string(res_type); 00048 this->m_observable = observable; 00049 this->m_res_mask = res_mask; 00050 this->m_obs_number = 0; 00051 this->m_data_wrapper = NULL; 00052 this->m_observer = NULL; 00053 this->m_maxage = DEFAULT_MAXAGE; 00054 this->m_content_format = DEFAULT_CONTENT_FORMAT; 00055 this->m_object = NULL; 00056 this->m_op_processor = NULL; 00057 } 00058 00059 // constructor (input initial value) 00060 DynamicResource::DynamicResource(const Logger *logger,const char *obj_name,const char *res_name,const char *res_type,const string value,uint8_t res_mask,const bool observable) : Resource<string>(logger,string(obj_name),string(res_name),value) 00061 { 00062 this->m_res_type = string(res_type); 00063 this->m_observable = observable; 00064 this->m_res_mask = res_mask; 00065 this->m_obs_number = 0; 00066 this->m_data_wrapper = NULL; 00067 this->m_observer = NULL; 00068 this->m_maxage = DEFAULT_MAXAGE; 00069 this->m_content_format = DEFAULT_CONTENT_FORMAT; 00070 this->m_object = NULL; 00071 this->m_op_processor = NULL; 00072 } 00073 00074 // constructor (strings) 00075 DynamicResource::DynamicResource(const Logger *logger,const string obj_name,const string res_name,const string res_type,const string value,uint8_t res_mask,const bool observable) : Resource<string>(logger,obj_name,res_name,value) 00076 { 00077 this->m_res_type = res_type; 00078 this->m_observable = observable; 00079 this->m_res_mask = res_mask; 00080 this->m_obs_number = 0; 00081 this->m_data_wrapper = NULL; 00082 this->m_observer = NULL; 00083 this->m_maxage = DEFAULT_MAXAGE; 00084 this->m_content_format = DEFAULT_CONTENT_FORMAT; 00085 this->m_object = NULL; 00086 this->m_op_processor = NULL; 00087 } 00088 00089 // copy constructor 00090 DynamicResource::DynamicResource(const DynamicResource &resource) : Resource<string>((const Resource<string> &)resource) 00091 { 00092 this->m_res_type = resource.m_res_type; 00093 this->m_observable = resource.m_observable; 00094 this->m_res_mask = resource.m_res_mask; 00095 this->m_obs_number = resource.m_obs_number; 00096 this->m_data_wrapper = resource.m_data_wrapper; 00097 this->m_observer = resource.m_observer; 00098 this->m_maxage = resource.m_maxage; 00099 this->m_content_format = resource.m_content_format; 00100 this->m_object = resource.m_object; 00101 this->m_op_processor = resource.m_op_processor; 00102 } 00103 00104 // destructor 00105 DynamicResource::~DynamicResource() { 00106 } 00107 00108 // bind CoAP Resource... 00109 M2MObject *DynamicResource::bind(void *p) { 00110 if (p != NULL) { 00111 this->m_object = M2MInterfaceFactory::create_object(this->getObjName().c_str()); 00112 if (this->m_object != NULL) { 00113 this->m_obj_instance = this->m_object->create_object_instance(); 00114 if (this->m_obj_instance != NULL) { 00115 this->m_res = this->m_obj_instance->create_dynamic_resource(this->getResName().c_str(),this->m_res_type.c_str(),M2MResourceInstance::STRING,this->m_observable); 00116 if (this->m_res != NULL) { 00117 // perform an initial get() to initialize our data value 00118 this->setValue(this->get()); 00119 00120 // now record the data value 00121 if (this->getDataWrapper() != NULL) { 00122 // wrap the data... 00123 this->getDataWrapper()->wrap((uint8_t *)this->getValue().c_str(),(int)this->getValue().size()); 00124 this->m_res->set_operation((M2MBase::Operation)this->m_res_mask); 00125 this->m_res->set_value( this->getDataWrapper()->get(),(uint8_t)this->getDataWrapper()->length()); 00126 this->logger()->log("%s: [%s] value: [%s] bound (observable: %d)",this->m_res_type.c_str(),this->getFullName().c_str(),this->getDataWrapper()->get(),this->m_observable); 00127 this->m_op_processor = (void *)p; 00128 } 00129 else { 00130 // do not wrap the data... 00131 this->m_res->set_operation((M2MBase::Operation)this->m_res_mask); 00132 this->m_res->set_value((uint8_t *)this->getValue().c_str(),(uint8_t)this->getValue().size()); 00133 this->logger()->log("%s: [%s] value: [%s] bound (observable: %d)",this->m_res_type.c_str(),this->getFullName().c_str(),this->getValue().c_str(),this->m_observable); 00134 this->m_op_processor = (void *)p; 00135 } 00136 00137 // For POST-enabled RESOURCES (only...), we must add a callback 00138 if ((this->m_res_mask & M2MBase::POST_ALLOWED) != 0) { 00139 // add a callback for the execute function...we will just direct through process()... 00140 //this->logger()->log("DynamicResource::bind(): Setting up POST execute callback function"); 00141 this->m_res->set_execute_function(execute_callback(this, &DynamicResource::process_resource_post)); 00142 } 00143 00144 // DISABLE for now... 00145 #if 0 00146 // For DELETE-enabled RESOURCES (only...), we must add a callback 00147 if ((this->m_res_mask & M2MBase::DELETE_ALLOWED) != 0) { 00148 // add a callback for the execute function...we will just direct through process()... 00149 //this->logger()->log("DynamicResource::bind(): Setting up DELETE execute callback function"); 00150 this->m_res->set_execute_function(execute_callback(this, &DynamicResource::process_resource_delete)); 00151 } 00152 #endif 00153 } 00154 else { 00155 // create_dynamic_resource() failed 00156 this->logger()->log("%s: Unable to create dynamic resource...",this->m_res_type.c_str()); 00157 delete this->m_object; 00158 this->m_object = NULL; 00159 } 00160 } 00161 else { 00162 // create_object_instance() failed... 00163 this->logger()->log("%s: Unable to create object instance...",this->m_res_type.c_str()); 00164 delete this->m_object; 00165 this->m_object = NULL; 00166 } 00167 } 00168 else { 00169 // create_object() failed 00170 this->logger()->log("%s: Unable to create object...",this->m_res_type.c_str()); 00171 } 00172 } 00173 else { 00174 this->logger()->log("%s: NULL value parameter in bind() request...",this->m_res_type.c_str()); 00175 } 00176 return this->m_object; 00177 } 00178 00179 // get our M2MBase representation 00180 M2MBase *DynamicResource::getResource() { 00181 return (M2MBase *)this->m_res; 00182 } 00183 00184 // process inbound mbed-client POST message for a Resource 00185 void DynamicResource::process_resource_post(void *args) { 00186 // just call process() for POST and Resources... 00187 //this->logger()->log("DynamicResource::process_resource_post(): calling process(POST)"); 00188 (void)this->process(M2MBase::POST_ALLOWED,this->m_res->base_type(),args); 00189 } 00190 00191 // process inbound mbed-client DELETE message for a Resource 00192 void DynamicResource::process_resource_delete(void *args) { 00193 // just call process() for DELETE and Resources... 00194 //this->logger()->log("DynamicResource::process_resource_delete(): calling process(DELETE)"); 00195 (void)this->process(M2MBase::DELETE_ALLOWED,this->m_res->base_type(),args); 00196 } 00197 00198 // process inbound mbed-client message 00199 uint8_t DynamicResource::process(M2MBase::Operation op,M2MBase::BaseType type,void *args) { 00200 #if defined (HAS_EXECUTE_PARAMS) 00201 M2MResource::M2MExecuteParameter* param = NULL; 00202 00203 // cast args if present... 00204 if (args != NULL) { 00205 param = (M2MResource::M2MExecuteParameter*)args; 00206 } 00207 #endif 00208 // DEBUG 00209 //this->logger()->log("in %s::process() Operation=0x0%x Type=%x%x",this->m_res_type.c_str(),op,type); 00210 00211 // PUT() check 00212 if ((op & M2MBase::PUT_ALLOWED) != 0) { 00213 string value = this->coapDataToString(this->m_res->value(),this->m_res->value_length()); 00214 this->logger()->log("%s: Calling resource(PUT) with [%s]=[%s]",this->m_res_type.c_str(),this->getFullName().c_str(),value.c_str()); 00215 this->put(value.c_str()); 00216 return 0; 00217 } 00218 00219 #if defined (HAS_EXECUTE_PARAMS) 00220 // POST() check 00221 if ((op & M2MBase::POST_ALLOWED) != 0) { 00222 string value; 00223 if (param != NULL) { 00224 // use parameters 00225 String object_name = param->get_argument_object_name(); 00226 int instance_id = (int)param->get_argument_object_instance_id(); 00227 String resource_name = param->get_argument_resource_name(); 00228 value = this->coapDataToString(param->get_argument_value(),param->get_argument_value_length()); 00229 this->logger()->log("%s: post() (resource: [%s/%d/%s] value: [%s]) invoked",this->m_res_type.c_str(),object_name.c_str(),instance_id,resource_name.c_str(),value.c_str()); 00230 } 00231 else { 00232 // use the resource value itself 00233 value = this->coapDataToString(this->m_res->value(),this->m_res->value_length()); 00234 this->logger()->log("%s: post() (resource: [%s] value: [%s] invoked",this->m_res_type.c_str(),this->getFullName().c_str(),value.c_str()); 00235 } 00236 00237 // invoke 00238 this->post(args); 00239 return 0; 00240 } 00241 #else 00242 // POST() check 00243 if ((op & M2MBase::POST_ALLOWED) != 0) { 00244 if (args != NULL) { 00245 this->logger()->log("%s: Calling resource(POST) with [%s]=[%s]",this->m_res_type.c_str(),this->getFullName().c_str(),(char *)args); 00246 this->post(args); 00247 } 00248 else { 00249 string value = this->coapDataToString(this->m_res->value(),this->m_res->value_length()); 00250 this->logger()->log("%s: Calling resource(POST) with [%s]=[%s]",this->m_res_type.c_str(),this->getFullName().c_str(),value.c_str()); 00251 this->post((void *)value.c_str()); 00252 } 00253 return 0; 00254 } 00255 #endif 00256 00257 #if defined (HAS_EXECUTE_PARAMS) 00258 // DELETE() check 00259 if ((op & M2MBase::DELETE_ALLOWED) != 0) { 00260 if (param != NULL) { 00261 // use parameters 00262 String object_name = param->get_argument_object_name(); 00263 int instance_id = (int)param->get_argument_object_instance_id(); 00264 String resource_name = param->get_argument_resource_name(); 00265 string value = this->coapDataToString(param->get_argument_value(),param->get_argument_value_length()); 00266 this->logger()->log("%s: delete() (resource: [%s/%d/%s] value: [%s]) invoked",this->m_res_type.c_str(),object_name.c_str(),instance_id,resource_name.c_str(),value.c_str()); 00267 } 00268 else { 00269 // use the resource value itself 00270 string value = this->coapDataToString(this->m_res->value(),this->m_res->value_length()); 00271 this->logger()->log("%s: delete() (resource: [%s] value: [%s] invoked",this->m_res_type.c_str(),this->getFullName().c_str(),value.c_str()); 00272 } 00273 00274 // invoke 00275 this->del(args); 00276 return 0; 00277 } 00278 #else 00279 // DELETE() check 00280 if ((op & M2MBase::DELETE_ALLOWED) != 0) { 00281 if (args != NULL) { 00282 this->logger()->log("%s: Calling resource(DELETE) with [%s]=[%s]",this->m_res_type.c_str(),this->getFullName().c_str(),(char *)args); 00283 this->del(args); 00284 } 00285 else { 00286 string value = this->coapDataToString(this->m_res->value(),this->m_res->value_length()); 00287 this->logger()->log("%s: Calling resource(DELETE) with [%s]=[%s]",this->m_res_type.c_str(),this->getFullName().c_str(),value.c_str()); 00288 this->del((void *)value.c_str()); 00289 } 00290 } 00291 #endif 00292 00293 // unknown type... 00294 this->logger()->log("%s: Unknown Operation (0x%x) for [%s]=[%s]... FAILED.",op,this->m_res_type.c_str(),this->getFullName().c_str(),this->m_res->value()); 00295 return 1; 00296 } 00297 00298 // send the notification 00299 int DynamicResource::notify(const string data) { 00300 return this->notify((uint8_t *)data.c_str(),(int)data.length()); 00301 } 00302 00303 // send the notification 00304 int DynamicResource::notify(uint8_t *data,int data_length) { 00305 uint8_t *notify_data = NULL; 00306 int notify_data_length = 0; 00307 int status = 0; 00308 00309 // convert the string from the GET to something suitable for CoAP payloads 00310 if (this->getDataWrapper() != NULL) { 00311 // wrap the data... 00312 this->getDataWrapper()->wrap((uint8_t *)data,data_length); 00313 00314 // announce (after wrap) 00315 //this->logger()->log("Notify payload [%s]...",this->getDataWrapper()->get()); 00316 00317 // fill notify 00318 notify_data_length = this->getDataWrapper()->length(); 00319 notify_data = this->getDataWrapper()->get(); 00320 } 00321 else { 00322 // announce (no wrap) 00323 //this->logger()->log("Notify payload [%s]...",data); 00324 00325 // do not wrap the data... 00326 notify_data_length = data_length; 00327 notify_data = data; 00328 } 00329 00330 // update the resource 00331 this->m_res->set_value((uint8_t *)notify_data,(uint8_t)notify_data_length); 00332 00333 // return our status 00334 return status; 00335 } 00336 00337 // default PUT (does nothing) 00338 void DynamicResource::put(const string value) 00339 { 00340 // not used by default 00341 this->logger()->log("DynamicResource::put() invoked (NOOP)"); 00342 } 00343 00344 // default POST (does nothing) 00345 void DynamicResource::post(void *args) 00346 { 00347 // not used by default 00348 this->logger()->log("DynamicResource::post() invoked (NOOP)"); 00349 } 00350 00351 // default DELETE (does nothing) 00352 void DynamicResource::del(void *args) 00353 { 00354 // not used by default 00355 this->logger()->log("DynamicResource::del() invoked (NOOP)"); 00356 } 00357 00358 // default observe behavior 00359 void DynamicResource::observe() { 00360 if (this->m_observable == true && this->isRegistered() == true) { 00361 this->notify(this->get()); 00362 } 00363 } 00364 00365 // set the observer pointer 00366 void DynamicResource::setObserver(void *observer) { 00367 this->m_observer = observer; 00368 } 00369 00370 // set the content-format in responses 00371 void DynamicResource::setContentFormat(uint8_t content_format) { 00372 this->m_content_format = content_format; 00373 } 00374 00375 // set the max-age of responses 00376 void DynamicResource::setMaxAge(uint8_t maxage) { 00377 this->m_maxage = maxage; 00378 } 00379 00380 // convenience method to get the URI from its buffer field... 00381 string DynamicResource::coapDataToString(uint8_t *coap_data_ptr,int coap_data_ptr_length) 00382 { 00383 if (coap_data_ptr != NULL && coap_data_ptr_length > 0) { 00384 if (this->getDataWrapper() != NULL) { 00385 // unwrap the data... 00386 this->getDataWrapper()->unwrap(coap_data_ptr,coap_data_ptr_length); 00387 char *buf = (char *)this->getDataWrapper()->get(); // assumes data is null terminated in DataWrapper... 00388 return string(buf); 00389 } 00390 else { 00391 // no unwrap of the data... 00392 char buf[MAX_VALUE_BUFFER_LENGTH+1]; 00393 memset(buf,0,MAX_VALUE_BUFFER_LENGTH+1); 00394 memcpy(buf,(char *)coap_data_ptr,coap_data_ptr_length); 00395 return string(buf); 00396 } 00397 } 00398 return string(""); 00399 } 00400 00401 // Determine if we are connected or not 00402 bool DynamicResource::isConnected() { 00403 bool is_connected = false; 00404 00405 // get our Endpoint 00406 Connector::Endpoint *ep = (Connector::Endpoint *)this->m_endpoint; 00407 if (ep != NULL) { 00408 is_connected = ep->isConnected(); 00409 if (is_connected) { 00410 //this->logger()->log("DynamicResource::isConnected = true"); 00411 } 00412 else { 00413 //this->logger()->log("DynamicResource::isConnected = false"); 00414 } 00415 } 00416 else { 00417 this->logger()->log("DynamicResource::isConnected = false (no endpoint)"); 00418 } 00419 00420 // return our endpoint connection state 00421 return is_connected; 00422 } 00423 00424 // Determine if we are registered or not 00425 bool DynamicResource::isRegistered() { 00426 bool is_registered = false; 00427 00428 if (this->isConnected() == true) { 00429 // get our Endpoint 00430 Connector::Endpoint *ep = (Connector::Endpoint *)this->m_endpoint; 00431 if (ep != NULL) { 00432 is_registered = ep->isRegistered(); 00433 if (is_registered) { 00434 //this->logger()->log("DynamicResource::isRegistered = true"); 00435 } 00436 else { 00437 //this->logger()->log("DynamicResource::isRegistered = false"); 00438 } 00439 } 00440 else { 00441 this->logger()->log("DynamicResource::isRegistered = false (no endpoint)"); 00442 } 00443 } 00444 00445 // return our endpoint registration state 00446 return is_registered; 00447 }
Generated on Wed Jul 13 2022 21:59:32 by
1.7.2