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.
Fork of mbedConnectorInterfaceV3 by
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 // Class support 00024 #include "mbed-connector-interface/DynamicResource.h" 00025 00026 // ResourceObserver help 00027 #include "mbed-connector-interface/ResourceObserver.h" 00028 00029 // Options enablement 00030 #include "mbed-connector-interface/Options.h" 00031 00032 // Endpoint 00033 #include "mbed-connector-interface/ConnectorEndpoint.h" 00034 00035 // GET option that can be used to Start/Stop Observations... 00036 #define START_OBS 0 00037 #define STOP_OBS 1 00038 00039 // MaxAge support for each DynamicResource 00040 #define DEFAULT_MAXAGE 60 00041 00042 // ContentFormat defaults for each DynamicResource 00043 #define DEFAULT_CONTENT_FORMAT 0 00044 00045 // default constructor 00046 DynamicResource::DynamicResource(const Logger *logger,const char *obj_name,const char *res_name,const char *res_type,uint8_t res_mask,const bool observable,const ResourceType type) : Resource<string>(logger,string(obj_name),string(res_name),string("")) 00047 { 00048 this->m_res_type = string(res_type); 00049 this->m_type = type; 00050 this->m_observable = observable; 00051 this->m_res_mask = res_mask; 00052 this->m_obs_number = 0; 00053 this->m_data_wrapper = NULL; 00054 this->m_observer = NULL; 00055 this->m_maxage = DEFAULT_MAXAGE; 00056 this->m_content_format = DEFAULT_CONTENT_FORMAT; 00057 this->m_ep = NULL; 00058 this->m_res = NULL; 00059 } 00060 00061 // constructor (input initial value) 00062 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,const ResourceType type) : Resource<string>(logger,string(obj_name),string(res_name),value) 00063 { 00064 this->m_res_type = string(res_type); 00065 this->m_type = type; 00066 this->m_observable = observable; 00067 this->m_res_mask = res_mask; 00068 this->m_obs_number = 0; 00069 this->m_data_wrapper = NULL; 00070 this->m_observer = NULL; 00071 this->m_maxage = DEFAULT_MAXAGE; 00072 this->m_content_format = DEFAULT_CONTENT_FORMAT; 00073 this->m_ep = NULL; 00074 this->m_res = NULL; 00075 } 00076 00077 // constructor (strings) 00078 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,const ResourceType type) : Resource<string>(logger,obj_name,res_name,value) 00079 { 00080 this->m_res_type = res_type; 00081 this->m_type = type; 00082 this->m_observable = observable; 00083 this->m_res_mask = res_mask; 00084 this->m_obs_number = 0; 00085 this->m_data_wrapper = NULL; 00086 this->m_observer = NULL; 00087 this->m_maxage = DEFAULT_MAXAGE; 00088 this->m_content_format = DEFAULT_CONTENT_FORMAT; 00089 this->m_ep = NULL; 00090 this->m_res = NULL; 00091 } 00092 00093 // copy constructor 00094 DynamicResource::DynamicResource(const DynamicResource &resource) : Resource<string>((const Resource<string> &)resource) 00095 { 00096 this->m_res_type = resource.m_res_type; 00097 this->m_type = resource.m_type; 00098 this->m_observable = resource.m_observable; 00099 this->m_res_mask = resource.m_res_mask; 00100 this->m_obs_number = resource.m_obs_number; 00101 this->m_data_wrapper = resource.m_data_wrapper; 00102 this->m_observer = resource.m_observer; 00103 this->m_maxage = resource.m_maxage; 00104 this->m_content_format = resource.m_content_format; 00105 this->m_ep = resource.m_ep; 00106 this->m_res = resource.m_res; 00107 } 00108 00109 // destructor 00110 DynamicResource::~DynamicResource() { 00111 } 00112 00113 // bind CoAP Resource... 00114 void DynamicResource::bind(void *ep) { 00115 if (ep != NULL) { 00116 // cast 00117 Connector::Endpoint *endpoint = (Connector::Endpoint *)ep; 00118 00119 // get our ObjectInstanceManager 00120 ObjectInstanceManager *oim = endpoint->getObjectInstanceManager(); 00121 00122 // Create our Resource 00123 this->m_res = (M2MResource *)oim->createDynamicResourceInstance((char *)this->getObjName().c_str(),(char *)this->getResName().c_str(),(char *)this->m_res_type.c_str(),(int)this->m_type,this->m_observable); 00124 if (this->m_res != NULL) { 00125 // Record our Instance Number 00126 this->setInstanceNumber(oim->getLastCreatedInstanceNumber()); 00127 00128 // perform an initial get() to initialize our data value 00129 this->setValue(this->get()); 00130 00131 // now record the data value 00132 if (this->getDataWrapper() != NULL) { 00133 // wrap the data... 00134 this->getDataWrapper()->wrap((uint8_t *)this->getValue().c_str(),(int)this->getValue().size()); 00135 this->m_res->set_operation((M2MBase::Operation)this->m_res_mask); 00136 this->m_res->set_value( this->getDataWrapper()->get(),(uint8_t)this->getDataWrapper()->length()); 00137 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); 00138 } 00139 else { 00140 // do not wrap the data... 00141 this->m_res->set_operation((M2MBase::Operation)this->m_res_mask); 00142 this->m_res->set_value((uint8_t *)this->getValue().c_str(),(uint8_t)this->getValue().size()); 00143 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); 00144 } 00145 00146 // set our endpoint instance 00147 this->m_ep = (void *)ep; 00148 00149 // For POST-enabled RESOURCES (only...), we must add a callback 00150 if ((this->m_res_mask & M2MBase::POST_ALLOWED) != 0) { 00151 // add a callback for the execute function...we will just direct through process()... 00152 //this->logger()->log("DynamicResource::bind(): Setting up POST execute callback function"); 00153 this->m_res->set_execute_function(execute_callback(this, &DynamicResource::process_resource_post)); 00154 } 00155 } 00156 } 00157 else { 00158 // no instance pointer to our endpoint 00159 this->logger()->log("%s: NULL endpoint instance pointer in bind() request...",this->m_res_type.c_str()); 00160 } 00161 } 00162 00163 // get our M2MBase representation 00164 M2MResource *DynamicResource::getResource() { 00165 return this->m_res; 00166 } 00167 00168 // process inbound mbed-client POST message for a Resource 00169 void DynamicResource::process_resource_post(void *args) { 00170 // just call process() for POST and Resources... 00171 //this->logger()->log("DynamicResource::process_resource_post(): calling process(POST)"); 00172 (void)this->process(M2MBase::POST_ALLOWED,this->m_res->base_type(),args); 00173 } 00174 00175 // process inbound mbed-client message 00176 uint8_t DynamicResource::process(M2MBase::Operation op,M2MBase::BaseType type,void *args) { 00177 #if defined (HAS_EXECUTE_PARAMS) 00178 M2MResource::M2MExecuteParameter* param = NULL; 00179 00180 // cast args if present... 00181 if (args != NULL) { 00182 param = (M2MResource::M2MExecuteParameter*)args; 00183 } 00184 #endif 00185 // DEBUG 00186 //this->logger()->log("in %s::process() Operation=0x0%x Type=%x%x",this->m_res_type.c_str(),op,type); 00187 00188 // PUT() check 00189 if ((op & M2MBase::PUT_ALLOWED) != 0) { 00190 string value = this->coapDataToString(this->m_res->value(),this->m_res->value_length()); 00191 this->logger()->log("%s: put(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),value.c_str()); 00192 this->put(value.c_str()); 00193 return 0; 00194 } 00195 00196 #if defined (HAS_EXECUTE_PARAMS) 00197 // POST() check 00198 if ((op & M2MBase::POST_ALLOWED) != 0) { 00199 string value; 00200 if (param != NULL) { 00201 // use parameters 00202 String object_name = param->get_argument_object_name(); 00203 int instance_id = (int)param->get_argument_object_instance_id(); 00204 String resource_name = param->get_argument_resource_name(); 00205 value = this->coapDataToString((uint8_t *)param->get_argument_value(),param->get_argument_value_length()); 00206 this->logger()->log("%s: post(%d) [%s/%d/%s]=[%s]) called.",this->m_res_type.c_str(),type,object_name.c_str(),instance_id,resource_name.c_str(),value.c_str()); 00207 } 00208 else { 00209 // use the resource value itself 00210 value = this->coapDataToString((uint8_t *)this->m_res->value(),this->m_res->value_length()); 00211 this->logger()->log("%s: post(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),value.c_str()); 00212 } 00213 00214 // invoke 00215 this->post(args); 00216 return 0; 00217 } 00218 #else 00219 // POST() check 00220 if ((op & M2MBase::POST_ALLOWED) != 0) { 00221 if (args != NULL) { 00222 this->logger()->log("%s: post(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),(char *)args); 00223 this->post(args); 00224 } 00225 else { 00226 string value = this->coapDataToString((uint8_t *)this->m_res->value(),this->m_res->value_length()); 00227 this->logger()->log("%s: post(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),value.c_str()); 00228 this->post((void *)value.c_str()); 00229 } 00230 return 0; 00231 } 00232 #endif 00233 00234 #if defined (HAS_EXECUTE_PARAMS) 00235 // DELETE() check 00236 if ((op & M2MBase::DELETE_ALLOWED) != 0) { 00237 if (param != NULL) { 00238 // use parameters 00239 String object_name = param->get_argument_object_name(); 00240 int instance_id = (int)param->get_argument_object_instance_id(); 00241 String resource_name = param->get_argument_resource_name(); 00242 string value = this->coapDataToString((uint8_t *)param->get_argument_value(),param->get_argument_value_length()); 00243 this->logger()->log("%s: delete(%d) [%s/%d/%s]=[%s]) called.",this->m_res_type.c_str(),type,object_name.c_str(),instance_id,resource_name.c_str(),value.c_str()); 00244 } 00245 else { 00246 // use the resource value itself 00247 string value = this->coapDataToString((uint8_t *)this->m_res->value(),this->m_res->value_length()); 00248 this->logger()->log("%s: delete(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),value.c_str()); 00249 } 00250 00251 // invoke 00252 this->del(args); 00253 return 0; 00254 } 00255 #else 00256 // DELETE() check 00257 if ((op & M2MBase::DELETE_ALLOWED) != 0) { 00258 if (args != NULL) { 00259 this->logger()->log("%s: delete(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),(char *)args); 00260 this->del(args); 00261 } 00262 else { 00263 string value = this->coapDataToString((uint8_t *)this->m_res->value(),this->m_res->value_length()); 00264 this->logger()->log("%s: delete(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),value.c_str()); 00265 this->del((void *)value.c_str()); 00266 } 00267 } 00268 #endif 00269 00270 // unknown type... 00271 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()); 00272 return 1; 00273 } 00274 00275 // send the notification 00276 int DynamicResource::notify(const string data) { 00277 return this->notify((uint8_t *)data.c_str(),(int)data.length()); 00278 } 00279 00280 // send the notification 00281 int DynamicResource::notify(uint8_t *data,int data_length) { 00282 uint8_t *notify_data = NULL; 00283 int notify_data_length = 0; 00284 int status = 0; 00285 00286 // convert the string from the GET to something suitable for CoAP payloads 00287 if (this->getDataWrapper() != NULL) { 00288 // wrap the data... 00289 this->getDataWrapper()->wrap((uint8_t *)data,data_length); 00290 00291 // announce (after wrap) 00292 //this->logger()->log("Notify payload [%s]...",this->getDataWrapper()->get()); 00293 00294 // fill notify 00295 notify_data_length = this->getDataWrapper()->length(); 00296 notify_data = this->getDataWrapper()->get(); 00297 } 00298 else { 00299 // announce (no wrap) 00300 //this->logger()->log("Notify payload [%s]...",data); 00301 00302 // do not wrap the data... 00303 notify_data_length = data_length; 00304 notify_data = data; 00305 } 00306 00307 // update the resource 00308 this->m_res->set_value((uint8_t *)notify_data,(uint8_t)notify_data_length); 00309 00310 // return our status 00311 return status; 00312 } 00313 00314 // default GET (does nothing) 00315 string DynamicResource::get() 00316 { 00317 // not used by default 00318 //this->logger()->log("DynamicResource::get() invoked (NOOP)"); 00319 return string(""); 00320 } 00321 00322 // default PUT (does nothing) 00323 void DynamicResource::put(const string /* value */) 00324 { 00325 // not used by default 00326 //this->logger()->log("DynamicResource::put() invoked (NOOP)"); 00327 } 00328 00329 // default POST (does nothing) 00330 void DynamicResource::post(void * /* args */) 00331 { 00332 // not used by default 00333 //this->logger()->log("DynamicResource::post() invoked (NOOP)"); 00334 } 00335 00336 // default DELETE (does nothing) 00337 void DynamicResource::del(void * /* args */) 00338 { 00339 // not used by default 00340 //this->logger()->log("DynamicResource::del() invoked (NOOP)"); 00341 } 00342 00343 // default observe behavior 00344 void DynamicResource::observe() { 00345 if (this->m_observable == true && this->isRegistered() == true) { 00346 this->notify(this->get()); 00347 } 00348 } 00349 00350 // set the observer pointer 00351 void DynamicResource::setObserver(void *observer) { 00352 this->m_observer = observer; 00353 } 00354 00355 // set the content-format in responses 00356 void DynamicResource::setContentFormat(uint8_t content_format) { 00357 this->m_content_format = content_format; 00358 } 00359 00360 // set the max-age of responses 00361 void DynamicResource::setMaxAge(uint8_t maxage) { 00362 this->m_maxage = maxage; 00363 } 00364 00365 // convert the CoAP data pointer to a string type 00366 string DynamicResource::coapDataToString(uint8_t *coap_data_ptr,int coap_data_ptr_length) 00367 { 00368 if (coap_data_ptr != NULL && coap_data_ptr_length > 0) { 00369 if (this->getDataWrapper() != NULL) { 00370 // unwrap the data... 00371 this->getDataWrapper()->unwrap(coap_data_ptr,coap_data_ptr_length); 00372 char *buf = (char *)this->getDataWrapper()->get(); // assumes data is null terminated in DataWrapper... 00373 return string(buf); 00374 } 00375 else { 00376 // no unwrap of the data... 00377 char buf[MAX_VALUE_BUFFER_LENGTH+1]; 00378 memset(buf,0,MAX_VALUE_BUFFER_LENGTH+1); 00379 int length = coap_data_ptr_length; 00380 if (length > MAX_VALUE_BUFFER_LENGTH) { 00381 length = MAX_VALUE_BUFFER_LENGTH; 00382 this->logger()->log("DynamicResource::coapDataToString: WARNING clipped data: %d bytes to %d bytes. Increase MAX_VALUE_BUFFER_LENGTH", 00383 coap_data_ptr_length,length); 00384 } 00385 memcpy(buf,(char *)coap_data_ptr,length); 00386 return string(buf); 00387 } 00388 } 00389 return string(""); 00390 } 00391 00392 // convert the CoAP data pointer to an integer type 00393 int DynamicResource::coapDataToInteger(uint8_t *coap_data_ptr,int coap_data_ptr_length) { 00394 int value = 0; 00395 if (coap_data_ptr != NULL && coap_data_ptr_length > 0) { 00396 if (this->getDataWrapper() != NULL) { 00397 // unwrap the data... 00398 this->getDataWrapper()->unwrap(coap_data_ptr,coap_data_ptr_length); 00399 //value = (int)this->getDataWrapper()->get(); // assumes data is null terminated in DataWrapper... 00400 } 00401 else { 00402 // no unwrap of the data... 00403 //value = (int)coap_data_ptr; 00404 } 00405 } 00406 return value; 00407 } 00408 00409 // convert the CoAP data pointer to a float type 00410 float DynamicResource::coapDataToFloat(uint8_t *coap_data_ptr,int coap_data_ptr_length) { 00411 float value = 0.0; 00412 if (coap_data_ptr != NULL && coap_data_ptr_length > 0) { 00413 if (this->getDataWrapper() != NULL) { 00414 // unwrap the data... 00415 this->getDataWrapper()->unwrap(coap_data_ptr,coap_data_ptr_length); 00416 //value = (float)this->getDataWrapper()->get(); // assumes data is null terminated in DataWrapper... 00417 } 00418 else { 00419 // no unwrap of the data... 00420 //value = (float)coap_data_ptr; 00421 } 00422 } 00423 return value; 00424 } 00425 00426 // convert the CoAP data pointer to an opaque type 00427 void *DynamicResource::coapDataToOpaque(uint8_t *coap_data_ptr,int coap_data_ptr_length) { 00428 if (coap_data_ptr != NULL && coap_data_ptr_length > 0) { 00429 if (this->getDataWrapper() != NULL) { 00430 // unwrap the data... 00431 this->getDataWrapper()->unwrap(coap_data_ptr,coap_data_ptr_length); 00432 char *buf = (char *)this->getDataWrapper()->get(); // assumes data is null terminated in DataWrapper... 00433 return (void *)buf; 00434 } 00435 } 00436 return (void *)coap_data_ptr; 00437 } 00438 00439 // Determine if we are connected or not 00440 bool DynamicResource::isConnected() { 00441 bool is_connected = false; 00442 00443 // get our Endpoint 00444 Connector::Endpoint *ep = (Connector::Endpoint *)this->m_endpoint; 00445 if (ep != NULL) { 00446 is_connected = ep->isConnected(); 00447 if (is_connected) { 00448 //this->logger()->log("DynamicResource::isConnected = true"); 00449 } 00450 else { 00451 //this->logger()->log("DynamicResource::isConnected = false"); 00452 } 00453 } 00454 else { 00455 this->logger()->log("DynamicResource::isConnected = false (no endpoint)"); 00456 } 00457 00458 // return our endpoint connection state 00459 return is_connected; 00460 } 00461 00462 // Determine if we are registered or not 00463 bool DynamicResource::isRegistered() { 00464 bool is_registered = false; 00465 00466 if (this->isConnected() == true) { 00467 // get our Endpoint 00468 Connector::Endpoint *ep = (Connector::Endpoint *)this->m_endpoint; 00469 if (ep != NULL) { 00470 is_registered = ep->isRegistered(); 00471 if (is_registered) { 00472 //this->logger()->log("DynamicResource::isRegistered = true"); 00473 } 00474 else { 00475 //this->logger()->log("DynamicResource::isRegistered = false"); 00476 } 00477 } 00478 else { 00479 this->logger()->log("DynamicResource::isRegistered = false (no endpoint)"); 00480 } 00481 } 00482 00483 // return our endpoint registration state 00484 return is_registered; 00485 } 00486 00487 // get our observer 00488 void *DynamicResource::getObserver() { 00489 return this->m_observer; 00490 }
Generated on Tue Jul 12 2022 18:16:51 by
1.7.2
