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 mbedConnectorInterfaceWithDM 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(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(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(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(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(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(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 memcpy(buf,(char *)coap_data_ptr,coap_data_ptr_length); 00380 return string(buf); 00381 } 00382 } 00383 return string(""); 00384 } 00385 00386 // convert the CoAP data pointer to an integer type 00387 int DynamicResource::coapDataToInteger(uint8_t *coap_data_ptr,int coap_data_ptr_length) { 00388 int value = 0; 00389 if (coap_data_ptr != NULL && coap_data_ptr_length > 0) { 00390 if (this->getDataWrapper() != NULL) { 00391 // unwrap the data... 00392 this->getDataWrapper()->unwrap(coap_data_ptr,coap_data_ptr_length); 00393 //value = (int)this->getDataWrapper()->get(); // assumes data is null terminated in DataWrapper... 00394 } 00395 else { 00396 // no unwrap of the data... 00397 //value = (int)coap_data_ptr; 00398 } 00399 } 00400 return value; 00401 } 00402 00403 // convert the CoAP data pointer to a float type 00404 float DynamicResource::coapDataToFloat(uint8_t *coap_data_ptr,int coap_data_ptr_length) { 00405 float value = 0.0; 00406 if (coap_data_ptr != NULL && coap_data_ptr_length > 0) { 00407 if (this->getDataWrapper() != NULL) { 00408 // unwrap the data... 00409 this->getDataWrapper()->unwrap(coap_data_ptr,coap_data_ptr_length); 00410 //value = (float)this->getDataWrapper()->get(); // assumes data is null terminated in DataWrapper... 00411 } 00412 else { 00413 // no unwrap of the data... 00414 //value = (float)coap_data_ptr; 00415 } 00416 } 00417 return value; 00418 } 00419 00420 // convert the CoAP data pointer to an opaque type 00421 void *DynamicResource::coapDataToOpaque(uint8_t *coap_data_ptr,int coap_data_ptr_length) { 00422 if (coap_data_ptr != NULL && coap_data_ptr_length > 0) { 00423 if (this->getDataWrapper() != NULL) { 00424 // unwrap the data... 00425 this->getDataWrapper()->unwrap(coap_data_ptr,coap_data_ptr_length); 00426 char *buf = (char *)this->getDataWrapper()->get(); // assumes data is null terminated in DataWrapper... 00427 return (void *)buf; 00428 } 00429 } 00430 return (void *)coap_data_ptr; 00431 } 00432 00433 // Determine if we are connected or not 00434 bool DynamicResource::isConnected() { 00435 bool is_connected = false; 00436 00437 // get our Endpoint 00438 Connector::Endpoint *ep = (Connector::Endpoint *)this->m_endpoint; 00439 if (ep != NULL) { 00440 is_connected = ep->isConnected(); 00441 if (is_connected) { 00442 //this->logger()->log("DynamicResource::isConnected = true"); 00443 } 00444 else { 00445 //this->logger()->log("DynamicResource::isConnected = false"); 00446 } 00447 } 00448 else { 00449 this->logger()->log("DynamicResource::isConnected = false (no endpoint)"); 00450 } 00451 00452 // return our endpoint connection state 00453 return is_connected; 00454 } 00455 00456 // Determine if we are registered or not 00457 bool DynamicResource::isRegistered() { 00458 bool is_registered = false; 00459 00460 if (this->isConnected() == true) { 00461 // get our Endpoint 00462 Connector::Endpoint *ep = (Connector::Endpoint *)this->m_endpoint; 00463 if (ep != NULL) { 00464 is_registered = ep->isRegistered(); 00465 if (is_registered) { 00466 //this->logger()->log("DynamicResource::isRegistered = true"); 00467 } 00468 else { 00469 //this->logger()->log("DynamicResource::isRegistered = false"); 00470 } 00471 } 00472 else { 00473 this->logger()->log("DynamicResource::isRegistered = false (no endpoint)"); 00474 } 00475 } 00476 00477 // return our endpoint registration state 00478 return is_registered; 00479 } 00480 00481 // get our observer 00482 void *DynamicResource::getObserver() { 00483 return this->m_observer; 00484 }
Generated on Wed Jul 13 2022 01:24:02 by
1.7.2
