mbedConnectorInterface back port from mbedOS v3 using mbed-client C++ call interface
Embed:
(wiki syntax)
Show/hide line numbers
DynamicResource.cpp
Go to the documentation of this file.
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