mbed Connector Interface simplification API on top of mbed-client

Fork of mbedConnectorInterfaceV3 by Doug Anson

NOTE:

This repo has been replaced with https://github.com/ARMmbed/mbedConnectorInterface. No further updates will occur with this repo. Please use the github repo instead. Thanks!

Committer:
ansond
Date:
Fri Feb 19 17:32:14 2016 +0000
Revision:
0:1f1f55e73248
Child:
13:9edad7677211
initial checkin

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:1f1f55e73248 1 /**
ansond 0:1f1f55e73248 2 * @file DynamicResource.cpp
ansond 0:1f1f55e73248 3 * @brief mbed CoAP Endpoint Dynamic Resource class
ansond 0:1f1f55e73248 4 * @author Doug Anson/Chris Paola
ansond 0:1f1f55e73248 5 * @version 1.0
ansond 0:1f1f55e73248 6 * @see
ansond 0:1f1f55e73248 7 *
ansond 0:1f1f55e73248 8 * Copyright (c) 2014
ansond 0:1f1f55e73248 9 *
ansond 0:1f1f55e73248 10 * Licensed under the Apache License, Version 2.0 (the "License");
ansond 0:1f1f55e73248 11 * you may not use this file except in compliance with the License.
ansond 0:1f1f55e73248 12 * You may obtain a copy of the License at
ansond 0:1f1f55e73248 13 *
ansond 0:1f1f55e73248 14 * http://www.apache.org/licenses/LICENSE-2.0
ansond 0:1f1f55e73248 15 *
ansond 0:1f1f55e73248 16 * Unless required by applicable law or agreed to in writing, software
ansond 0:1f1f55e73248 17 * distributed under the License is distributed on an "AS IS" BASIS,
ansond 0:1f1f55e73248 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ansond 0:1f1f55e73248 19 * See the License for the specific language governing permissions and
ansond 0:1f1f55e73248 20 * limitations under the License.
ansond 0:1f1f55e73248 21 */
ansond 0:1f1f55e73248 22
ansond 0:1f1f55e73248 23 #include "mbed-connector-interface/DynamicResource.h"
ansond 0:1f1f55e73248 24
ansond 0:1f1f55e73248 25 // ResourceObserver help
ansond 0:1f1f55e73248 26 #include "mbed-connector-interface/ResourceObserver.h"
ansond 0:1f1f55e73248 27
ansond 0:1f1f55e73248 28 // Options enablement
ansond 0:1f1f55e73248 29 #include "mbed-connector-interface/Options.h"
ansond 0:1f1f55e73248 30
ansond 0:1f1f55e73248 31 // GET option that can be used to Start/Stop Observations...
ansond 0:1f1f55e73248 32 #define START_OBS 0
ansond 0:1f1f55e73248 33 #define STOP_OBS 1
ansond 0:1f1f55e73248 34
ansond 0:1f1f55e73248 35 // MaxAge support for each DynamicResource
ansond 0:1f1f55e73248 36 #define DEFAULT_MAXAGE 60
ansond 0:1f1f55e73248 37
ansond 0:1f1f55e73248 38 // ContentFormat defaults for each DynamicResource
ansond 0:1f1f55e73248 39 #define DEFAULT_CONTENT_FORMAT 0
ansond 0:1f1f55e73248 40
ansond 0:1f1f55e73248 41 // default constructor
ansond 0:1f1f55e73248 42 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(""))
ansond 0:1f1f55e73248 43 {
ansond 0:1f1f55e73248 44 this->m_res_type = string(res_type);
ansond 0:1f1f55e73248 45 this->m_observable = observable;
ansond 0:1f1f55e73248 46 this->m_res_mask = res_mask;
ansond 0:1f1f55e73248 47 this->m_obs_number = 0;
ansond 0:1f1f55e73248 48 this->m_data_wrapper = NULL;
ansond 0:1f1f55e73248 49 this->m_observer = NULL;
ansond 0:1f1f55e73248 50 this->m_maxage = DEFAULT_MAXAGE;
ansond 0:1f1f55e73248 51 this->m_content_format = DEFAULT_CONTENT_FORMAT;
ansond 0:1f1f55e73248 52 this->m_object = NULL;
ansond 0:1f1f55e73248 53 this->m_op_processor = NULL;
ansond 0:1f1f55e73248 54 }
ansond 0:1f1f55e73248 55
ansond 0:1f1f55e73248 56 // constructor (input initial value)
ansond 0:1f1f55e73248 57 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)
ansond 0:1f1f55e73248 58 {
ansond 0:1f1f55e73248 59 this->m_res_type = string(res_type);
ansond 0:1f1f55e73248 60 this->m_observable = observable;
ansond 0:1f1f55e73248 61 this->m_res_mask = res_mask;
ansond 0:1f1f55e73248 62 this->m_obs_number = 0;
ansond 0:1f1f55e73248 63 this->m_data_wrapper = NULL;
ansond 0:1f1f55e73248 64 this->m_observer = NULL;
ansond 0:1f1f55e73248 65 this->m_maxage = DEFAULT_MAXAGE;
ansond 0:1f1f55e73248 66 this->m_content_format = DEFAULT_CONTENT_FORMAT;
ansond 0:1f1f55e73248 67 this->m_object = NULL;
ansond 0:1f1f55e73248 68 this->m_op_processor = NULL;
ansond 0:1f1f55e73248 69 }
ansond 0:1f1f55e73248 70
ansond 0:1f1f55e73248 71 // constructor (strings)
ansond 0:1f1f55e73248 72 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)
ansond 0:1f1f55e73248 73 {
ansond 0:1f1f55e73248 74 this->m_res_type = res_type;
ansond 0:1f1f55e73248 75 this->m_observable = observable;
ansond 0:1f1f55e73248 76 this->m_res_mask = res_mask;
ansond 0:1f1f55e73248 77 this->m_obs_number = 0;
ansond 0:1f1f55e73248 78 this->m_data_wrapper = NULL;
ansond 0:1f1f55e73248 79 this->m_observer = NULL;
ansond 0:1f1f55e73248 80 this->m_maxage = DEFAULT_MAXAGE;
ansond 0:1f1f55e73248 81 this->m_content_format = DEFAULT_CONTENT_FORMAT;
ansond 0:1f1f55e73248 82 this->m_object = NULL;
ansond 0:1f1f55e73248 83 this->m_op_processor = NULL;
ansond 0:1f1f55e73248 84 }
ansond 0:1f1f55e73248 85
ansond 0:1f1f55e73248 86 // copy constructor
ansond 0:1f1f55e73248 87 DynamicResource::DynamicResource(const DynamicResource &resource) : Resource<string>((const Resource<string> &)resource)
ansond 0:1f1f55e73248 88 {
ansond 0:1f1f55e73248 89 this->m_res_type = resource.m_res_type;
ansond 0:1f1f55e73248 90 this->m_observable = resource.m_observable;
ansond 0:1f1f55e73248 91 this->m_res_mask = resource.m_res_mask;
ansond 0:1f1f55e73248 92 this->m_obs_number = resource.m_obs_number;
ansond 0:1f1f55e73248 93 this->m_data_wrapper = resource.m_data_wrapper;
ansond 0:1f1f55e73248 94 this->m_observer = resource.m_observer;
ansond 0:1f1f55e73248 95 this->m_maxage = resource.m_maxage;
ansond 0:1f1f55e73248 96 this->m_content_format = resource.m_content_format;
ansond 0:1f1f55e73248 97 this->m_object = resource.m_object;
ansond 0:1f1f55e73248 98 this->m_op_processor = resource.m_op_processor;
ansond 0:1f1f55e73248 99 }
ansond 0:1f1f55e73248 100
ansond 0:1f1f55e73248 101 // destructor
ansond 0:1f1f55e73248 102 DynamicResource::~DynamicResource() {
ansond 0:1f1f55e73248 103 }
ansond 0:1f1f55e73248 104
ansond 0:1f1f55e73248 105 // bind CoAP Resource...
ansond 0:1f1f55e73248 106 M2MObject *DynamicResource::bind(void *p) {
ansond 0:1f1f55e73248 107 if (p != NULL) {
ansond 0:1f1f55e73248 108 this->m_object = M2MInterfaceFactory::create_object(this->getObjName().c_str());
ansond 0:1f1f55e73248 109 if (this->m_object != NULL) {
ansond 0:1f1f55e73248 110 this->m_obj_instance = this->m_object->create_object_instance();
ansond 0:1f1f55e73248 111 if (this->m_obj_instance != NULL) {
ansond 0:1f1f55e73248 112 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);
ansond 0:1f1f55e73248 113 if (this->m_res != NULL) {
ansond 0:1f1f55e73248 114 // perform an initial get() to initialize our data value
ansond 0:1f1f55e73248 115 this->setValue(this->get());
ansond 0:1f1f55e73248 116
ansond 0:1f1f55e73248 117 // now record the data value
ansond 0:1f1f55e73248 118 if (this->getDataWrapper() != NULL) {
ansond 0:1f1f55e73248 119 // wrap the data...
ansond 0:1f1f55e73248 120 this->getDataWrapper()->wrap((uint8_t *)this->getValue().c_str(),(int)this->getValue().size());
ansond 0:1f1f55e73248 121 this->m_res->set_operation((M2MBase::Operation)this->m_res_mask);
ansond 0:1f1f55e73248 122 this->m_res->set_value( this->getDataWrapper()->get(),(uint8_t)this->getDataWrapper()->length());
ansond 0:1f1f55e73248 123 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);
ansond 0:1f1f55e73248 124 this->m_op_processor = (void *)p;
ansond 0:1f1f55e73248 125 }
ansond 0:1f1f55e73248 126 else {
ansond 0:1f1f55e73248 127 // do not wrap the data...
ansond 0:1f1f55e73248 128 this->m_res->set_operation((M2MBase::Operation)this->m_res_mask);
ansond 0:1f1f55e73248 129 this->m_res->set_value((uint8_t *)this->getValue().c_str(),(uint8_t)this->getValue().size());
ansond 0:1f1f55e73248 130 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);
ansond 0:1f1f55e73248 131 this->m_op_processor = (void *)p;
ansond 0:1f1f55e73248 132 }
ansond 0:1f1f55e73248 133
ansond 0:1f1f55e73248 134 // For POST-enabled RESOURCES (only...), we must add a callback
ansond 0:1f1f55e73248 135 if ((this->m_res_mask & M2MBase::POST_ALLOWED) != 0) {
ansond 0:1f1f55e73248 136 // add a callback for the execute function...we will just direct through process()...
ansond 0:1f1f55e73248 137 this->m_res->set_execute_function(execute_callback(this, &DynamicResource::process_resource_post));
ansond 0:1f1f55e73248 138 }
ansond 0:1f1f55e73248 139 }
ansond 0:1f1f55e73248 140 else {
ansond 0:1f1f55e73248 141 // create_dynamic_resource() failed
ansond 0:1f1f55e73248 142 this->logger()->log("%s: Unable to create dynamic resource...",this->m_res_type.c_str());
ansond 0:1f1f55e73248 143 delete this->m_object;
ansond 0:1f1f55e73248 144 this->m_object = NULL;
ansond 0:1f1f55e73248 145 }
ansond 0:1f1f55e73248 146 }
ansond 0:1f1f55e73248 147 else {
ansond 0:1f1f55e73248 148 // create_object_instance() failed...
ansond 0:1f1f55e73248 149 this->logger()->log("%s: Unable to create object instance...",this->m_res_type.c_str());
ansond 0:1f1f55e73248 150 delete this->m_object;
ansond 0:1f1f55e73248 151 this->m_object = NULL;
ansond 0:1f1f55e73248 152 }
ansond 0:1f1f55e73248 153 }
ansond 0:1f1f55e73248 154 else {
ansond 0:1f1f55e73248 155 // create_object() failed
ansond 0:1f1f55e73248 156 this->logger()->log("%s: Unable to create object...",this->m_res_type.c_str());
ansond 0:1f1f55e73248 157 }
ansond 0:1f1f55e73248 158 }
ansond 0:1f1f55e73248 159 else {
ansond 0:1f1f55e73248 160 this->logger()->log("%s: NULL value parameter in bind() request...",this->m_res_type.c_str());
ansond 0:1f1f55e73248 161 }
ansond 0:1f1f55e73248 162 return this->m_object;
ansond 0:1f1f55e73248 163 }
ansond 0:1f1f55e73248 164
ansond 0:1f1f55e73248 165 // get our M2MBase representation
ansond 0:1f1f55e73248 166 M2MBase *DynamicResource::getResource() {
ansond 0:1f1f55e73248 167 return (M2MBase *)this->m_res;
ansond 0:1f1f55e73248 168 }
ansond 0:1f1f55e73248 169
ansond 0:1f1f55e73248 170 // process inbound mbed-client POST message for a Resource
ansond 0:1f1f55e73248 171 void DynamicResource::process_resource_post(void *args) {
ansond 0:1f1f55e73248 172 // just call process() for POST and Resources...
ansond 0:1f1f55e73248 173 (void)this->process(M2MBase::POST_ALLOWED,M2MBase::Resource);
ansond 0:1f1f55e73248 174 }
ansond 0:1f1f55e73248 175
ansond 0:1f1f55e73248 176 // process inbound mbed-client message
ansond 0:1f1f55e73248 177 uint8_t DynamicResource::process(M2MBase::Operation op,M2MBase::BaseType type) {
ansond 0:1f1f55e73248 178 // DEBUG
ansond 0:1f1f55e73248 179 //this->logger()->log("in %s::process() Operation=0x0%x Type=%x%x",this->m_res_type.c_str(),op,type);
ansond 0:1f1f55e73248 180
ansond 0:1f1f55e73248 181 // PUT() check
ansond 0:1f1f55e73248 182 if ((op & M2MBase::PUT_ALLOWED) != 0) {
ansond 0:1f1f55e73248 183 string value = this->coapDataToString(this->m_res->value(),this->m_res->value_length());
ansond 0:1f1f55e73248 184 this->logger()->log("%s: Calling resource(PUT) with [%s]=[%s]",this->m_res_type.c_str(),this->getFullName().c_str(),value.c_str());
ansond 0:1f1f55e73248 185 this->put(value.c_str());
ansond 0:1f1f55e73248 186 return 0;
ansond 0:1f1f55e73248 187 }
ansond 0:1f1f55e73248 188
ansond 0:1f1f55e73248 189 // POST() check
ansond 0:1f1f55e73248 190 if ((op & M2MBase::POST_ALLOWED) != 0) {
ansond 0:1f1f55e73248 191 string value = this->coapDataToString(this->m_res->value(),this->m_res->value_length());
ansond 0:1f1f55e73248 192 this->logger()->log("%s: Calling resource(POST) with [%s]=[%s]",this->m_res_type.c_str(),this->getFullName().c_str(),value.c_str());
ansond 0:1f1f55e73248 193 this->post(value.c_str());
ansond 0:1f1f55e73248 194 return 0;
ansond 0:1f1f55e73248 195 }
ansond 0:1f1f55e73248 196
ansond 0:1f1f55e73248 197 // DELETE() check
ansond 0:1f1f55e73248 198 if ((op & M2MBase::DELETE_ALLOWED) != 0) {
ansond 0:1f1f55e73248 199 string value = this->coapDataToString(this->m_res->value(),this->m_res->value_length());
ansond 0:1f1f55e73248 200 this->logger()->log("%s: Calling resource(DELETE) with [%s]=[%s]",this->m_res_type.c_str(),this->getFullName().c_str(),value.c_str());
ansond 0:1f1f55e73248 201 this->del(value.c_str());
ansond 0:1f1f55e73248 202 return 0;
ansond 0:1f1f55e73248 203 }
ansond 0:1f1f55e73248 204
ansond 0:1f1f55e73248 205 // unknown type...
ansond 0:1f1f55e73248 206 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());
ansond 0:1f1f55e73248 207 return 1;
ansond 0:1f1f55e73248 208 }
ansond 0:1f1f55e73248 209
ansond 0:1f1f55e73248 210 // send the notification
ansond 0:1f1f55e73248 211 int DynamicResource::notify(const string data) {
ansond 0:1f1f55e73248 212 return this->notify((uint8_t *)data.c_str(),(int)data.length());
ansond 0:1f1f55e73248 213 }
ansond 0:1f1f55e73248 214
ansond 0:1f1f55e73248 215 // send the notification
ansond 0:1f1f55e73248 216 int DynamicResource::notify(uint8_t *data,int data_length) {
ansond 0:1f1f55e73248 217 uint8_t *notify_data = NULL;
ansond 0:1f1f55e73248 218 int notify_data_length = 0;
ansond 0:1f1f55e73248 219 int status = 0;
ansond 0:1f1f55e73248 220
ansond 0:1f1f55e73248 221 // convert the string from the GET to something suitable for CoAP payloads
ansond 0:1f1f55e73248 222 if (this->getDataWrapper() != NULL) {
ansond 0:1f1f55e73248 223 // wrap the data...
ansond 0:1f1f55e73248 224 this->getDataWrapper()->wrap((uint8_t *)data,data_length);
ansond 0:1f1f55e73248 225
ansond 0:1f1f55e73248 226 // announce (after wrap)
ansond 0:1f1f55e73248 227 //this->logger()->log("Notify payload [%s]...",this->getDataWrapper()->get());
ansond 0:1f1f55e73248 228
ansond 0:1f1f55e73248 229 // fill notify
ansond 0:1f1f55e73248 230 notify_data_length = this->getDataWrapper()->length();
ansond 0:1f1f55e73248 231 notify_data = this->getDataWrapper()->get();
ansond 0:1f1f55e73248 232 }
ansond 0:1f1f55e73248 233 else {
ansond 0:1f1f55e73248 234 // announce (no wrap)
ansond 0:1f1f55e73248 235 //this->logger()->log("Notify payload [%s]...",data);
ansond 0:1f1f55e73248 236
ansond 0:1f1f55e73248 237 // do not wrap the data...
ansond 0:1f1f55e73248 238 notify_data_length = data_length;
ansond 0:1f1f55e73248 239 notify_data = data;
ansond 0:1f1f55e73248 240 }
ansond 0:1f1f55e73248 241
ansond 0:1f1f55e73248 242 // update the resource
ansond 0:1f1f55e73248 243 this->m_res->set_value((uint8_t *)notify_data,(uint8_t)notify_data_length);
ansond 0:1f1f55e73248 244
ansond 0:1f1f55e73248 245 // return our status
ansond 0:1f1f55e73248 246 return status;
ansond 0:1f1f55e73248 247 }
ansond 0:1f1f55e73248 248
ansond 0:1f1f55e73248 249 // default PUT (does nothing)
ansond 0:1f1f55e73248 250 void DynamicResource::put(const string value)
ansond 0:1f1f55e73248 251 {
ansond 0:1f1f55e73248 252 // not used by default
ansond 0:1f1f55e73248 253 ;
ansond 0:1f1f55e73248 254 }
ansond 0:1f1f55e73248 255
ansond 0:1f1f55e73248 256 // default POST (does nothing)
ansond 0:1f1f55e73248 257 void DynamicResource::post(const string value)
ansond 0:1f1f55e73248 258 {
ansond 0:1f1f55e73248 259 // not used by default
ansond 0:1f1f55e73248 260 ;
ansond 0:1f1f55e73248 261 }
ansond 0:1f1f55e73248 262
ansond 0:1f1f55e73248 263 // default DELETE (does nothing)
ansond 0:1f1f55e73248 264 void DynamicResource::del(const string value)
ansond 0:1f1f55e73248 265 {
ansond 0:1f1f55e73248 266 // not used by default
ansond 0:1f1f55e73248 267 ;
ansond 0:1f1f55e73248 268 }
ansond 0:1f1f55e73248 269
ansond 0:1f1f55e73248 270 // default observe behavior
ansond 0:1f1f55e73248 271 void DynamicResource::observe() {
ansond 0:1f1f55e73248 272 if (this->m_observable == true) {
ansond 0:1f1f55e73248 273 this->notify(this->get());
ansond 0:1f1f55e73248 274 }
ansond 0:1f1f55e73248 275 }
ansond 0:1f1f55e73248 276
ansond 0:1f1f55e73248 277 // set the observer pointer
ansond 0:1f1f55e73248 278 void DynamicResource::setObserver(void *observer) {
ansond 0:1f1f55e73248 279 this->m_observer = observer;
ansond 0:1f1f55e73248 280 }
ansond 0:1f1f55e73248 281
ansond 0:1f1f55e73248 282 // set the content-format in responses
ansond 0:1f1f55e73248 283 void DynamicResource::setContentFormat(uint8_t content_format) {
ansond 0:1f1f55e73248 284 this->m_content_format = content_format;
ansond 0:1f1f55e73248 285 }
ansond 0:1f1f55e73248 286
ansond 0:1f1f55e73248 287 // set the max-age of responses
ansond 0:1f1f55e73248 288 void DynamicResource::setMaxAge(uint8_t maxage) {
ansond 0:1f1f55e73248 289 this->m_maxage = maxage;
ansond 0:1f1f55e73248 290 }
ansond 0:1f1f55e73248 291
ansond 0:1f1f55e73248 292 // convenience method to get the URI from its buffer field...
ansond 0:1f1f55e73248 293 string DynamicResource::coapDataToString(uint8_t *coap_data_ptr,int coap_data_ptr_length)
ansond 0:1f1f55e73248 294 {
ansond 0:1f1f55e73248 295 if (coap_data_ptr != NULL && coap_data_ptr_length > 0) {
ansond 0:1f1f55e73248 296 if (this->getDataWrapper() != NULL) {
ansond 0:1f1f55e73248 297 // unwrap the data...
ansond 0:1f1f55e73248 298 this->getDataWrapper()->unwrap(coap_data_ptr,coap_data_ptr_length);
ansond 0:1f1f55e73248 299 char *buf = (char *)this->getDataWrapper()->get(); // assumes data is null terminated in DataWrapper...
ansond 0:1f1f55e73248 300 return string(buf);
ansond 0:1f1f55e73248 301 }
ansond 0:1f1f55e73248 302 else {
ansond 0:1f1f55e73248 303 // no unwrap of the data...
ansond 0:1f1f55e73248 304 char buf[MAX_VALUE_BUFFER_LENGTH+1];
ansond 0:1f1f55e73248 305 memset(buf,0,MAX_VALUE_BUFFER_LENGTH+1);
ansond 0:1f1f55e73248 306 memcpy(buf,(char *)coap_data_ptr,coap_data_ptr_length);
ansond 0:1f1f55e73248 307 return string(buf);
ansond 0:1f1f55e73248 308 }
ansond 0:1f1f55e73248 309 }
ansond 0:1f1f55e73248 310 return string("");
ansond 0:1f1f55e73248 311 }
ansond 0:1f1f55e73248 312