Sample program showing how to connect GR-PEACH into Watson IoT through mbed Connector and Watson's Connector Bridge

Dependencies:   AsciiFont DisplayApp GR-PEACH_video LCD_shield_config LWIPBP3595Interface_STA_for_mbed-os USBDevice

Overview

This sample program shows how to connect GR-PEACH into Watson IoT through mbed Connector and Watson's Connector Bridge. Note that this program is derived from https://github.com/ARMmbed/mbed-ethernet-sample-techcon2016.

In this program, at first, the barcode data input from camera is decoded on GR-PEACH using ZXing which is an open-source, multi-format 1D/2D barcode image processing library. Then, the decoded string is sent to Watson IoT via mbed Device Connector and Watson's Connector Bridge. At last, the delivered string is confirmed via NodeRED flow.

Required hardware

Application setup

  1. Select the connection type. For details, please refer to the following wiki:
    https://developer.mbed.org/teams/Renesas/code/mbed-os_Watson-IoT_ZXing_sample/wiki/Connection-type.
  2. Set the client credentials. For details, please refer to the following wiki:
    https://developer.mbed.org/teams/Renesas/code/mbed-os_Watson-IoT_ZXing_sample/wiki/Client-credentials.
  3. Change Ethernet settings. For details, please refer to the following wiki:
    https://developer.mbed.org/teams/Renesas/code/mbed-os_Watson-IoT_ZXing_sample/wiki/Ethernet-settings.
  4. Change Wifi settings. For details, please refer to the following wiki:
    https://developer.mbed.org/teams/Renesas/code/mbed-os_Watson-IoT_ZXing_sample/wiki/Wifi-settings.

Building this sample program

  1. Import this sample program onto mbed Compiler.
  2. Configure this sample program in accordance with Application setup.
  3. Compile the example on mbed Compiler and download the resultant binary file.
  4. Plug the Ethernet cable into GR-PEACH if you are using Ethernet mode. /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen7.png
  5. Plug the micro-USB cable into the OpenSDA port with lies on the next to the RESET button.
  6. Copy the binary previously downloaded to your PC to GR-PEACH to flash this sample program. When the copy is successfully completed, the board is ready to work.
  7. Press the RESET button on the board to run this sample program.
  8. For verification, please refer to the following wiki:
    https://developer.mbed.org/teams/Renesas/code/mbed-os_Watson-IoT_ZXing_sample/wiki/Monitoring-the-application.

Application resources

This sample program exposes two resources listed below:

  1. /311/0/5850 : Trigger to toggle LED on GR-PEACH (PUT). When "1" is sent to this resource by PUT method, LED should be turned off. Otherwise, LED should be turned on.
  2. /888/0/7700: Decode result of barcode data input from camera (GET)

Setup of Watson IoT

  1. You should create Watson IoT Instance by the following procedure:
    • Login IBM Bluemix from https://console.ng.bluemix.net/ and login it.
    • Select Services as follows: /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen6.png
    • Select Internet of Things" as follows: /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen7_1.png
    • Press Get Started as follows: /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen8.png
    • Configure Watson IoT Instance
      • Leave unbound /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen9.png
      • Select the Free plan, then click Create /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen10.png

  2. You should create Watson IoT Application Credentials Once you successfully create Watson IoT Instance, you should see the following Watson IoT dashboard: /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen11.png
    • On dashboard, launch the Connect your devices dashboard /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen12.png
    • Click APPS /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen13.png
    • Click Generate API Key /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen14_1.png
    • Record the API Key and Authenticatoin Token. Then click Generate after adding a comment /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen15.png Note that these two values will be needed in the later step.
  3. Watson IoT NodeRED Application should be created in accordance with the following procedure:
    • Go back to your Bluemix Dashboard: https://console.ng.bluemix.net
    • Click Create Application /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen16.png
    • Select Node-RED Starter /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen17.png
    • Enter a unique App name and Click Create /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen18.png
    • Application will Stage after a few minutes
    • Application will report app is running when the staging has completed
  4. Watson NodeRED Application should be binded to Watson IoT instance
    • You can now see the dashboard below: /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen19.png
    • Click Connections. Then, press Connect Existing /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen20.png
    • Click on Watson IoT Instance badge. Then, press Connect /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen21.png
    • NodeRED application will restage. This will take a while. Please wait for Your app is running state /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen22.png /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen23.png
  5. You should acquire mbed Device Connector DOMAIN value
    • Go to the mbed Device Connector Dashboard: https://connector.mbed.com and log in /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen41.png
    • Select Access Key in order to create a new token /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen42.png
    • Click CREATE NEW ACCESS KEY and enter a unique name. Then, push ADD bution /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen43.png
    • an API token is generated. Need to save the generated string for later steps /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen44.png
  1. You should configure Watson IoT ARM mbed Connector Bridge
    • Go back to the Watson IoT Dashboard and select Extensions /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen24.png
    • Press Add Extension /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen25.png
    • Add ARM mbed Connector /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen26_1.png
    • Setup the bridge /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen27.png
    • Enter your Connector API Token to Access Key and MBED_DOMAIN to Domain Id, respectively. Then, click Check Connection /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen28.png
    • If the connection is successfully established, you can see Connection Established. Then, press Done /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen29.png
  2. NodeRED Flow Example should be imported
    • Open NODEFLOW_GR-PEACH.txt
    • Navigate to the URL that you recorded earlier for your Watson IoT NodeRED Application (i.e. http://<app name>.mybluemix.net) and Select Go to your NodeRED flow editor /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen30.png
    • Select menu, Import and Clipboard /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen31.png
    • Paste the entire contents of JSON code described in NODEFLOW_GR-PEACH.txt and click Import /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen32.png
  3. Watson IoT Application Node Flow should be configured
    • Double-click input node and link them to your Watson IoT instance. /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen33.png
    • Click on the edit button /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen34.png
    • First enter arbitrary name. Then, Watson API Key and Watson Auth Token previously acquired. Finally, press Add to save /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen35.png
    • Enter MBED_ENDPOINT_NAME in security.h as Device ID. Then, press Done to save /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen36.png
    • Double-click output node /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen37.png
    • Edit API Key and Device Id in the same manner as that for input node
    • Click LED OFF and LED ON node and replace MBED_ENDPOINT_NAME_GOES_HERE with MBED_ENDPOINT_NAME as shown below: /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen38.png
    • Click Deproy to deploy NodeRED application /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen39.png
  4. Invoke sample program
    • Press the reset button on GR-PEACH
    • The decode result of barcode data should be shown in debug window /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen40_1.png
    • Also, you can toggle LED by clicking Turn LED OFF and Turn LED ON injection node /media/uploads/HinoNaka/mbed-os_watson-iot_zxing_sample_screen40_2.png
Revision:
0:ad834d403a8c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbedConnectorInterface/source/DynamicResource.cpp	Thu Nov 24 13:59:16 2016 +0900
@@ -0,0 +1,484 @@
+/**
+ * @file    DynamicResource.cpp
+ * @brief   mbed CoAP Endpoint Dynamic Resource class
+ * @author  Doug Anson/Chris Paola
+ * @version 1.0
+ * @see
+ *
+ * Copyright (c) 2014
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Class support
+#include "mbed-connector-interface/DynamicResource.h"
+
+// ResourceObserver help
+#include "mbed-connector-interface/ResourceObserver.h"
+
+// Options enablement
+#include "mbed-connector-interface/Options.h"
+
+// Endpoint 
+#include "mbed-connector-interface/ConnectorEndpoint.h"
+
+// GET option that can be used to Start/Stop Observations...
+#define START_OBS 0
+#define STOP_OBS  1
+
+// MaxAge support for each DynamicResource
+#define DEFAULT_MAXAGE 60
+
+// ContentFormat defaults for each DynamicResource
+#define DEFAULT_CONTENT_FORMAT 0
+
+// default constructor
+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(""))
+{
+    this->m_res_type = string(res_type);
+    this->m_type = type;
+    this->m_observable = observable;
+    this->m_res_mask = res_mask;
+    this->m_obs_number = 0;
+    this->m_data_wrapper = NULL;
+    this->m_observer = NULL;
+    this->m_maxage = DEFAULT_MAXAGE;
+    this->m_content_format = DEFAULT_CONTENT_FORMAT;
+    this->m_ep = NULL;
+    this->m_res = NULL;
+}
+
+// constructor (input initial value)
+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)
+{
+    this->m_res_type = string(res_type);
+    this->m_type = type;
+    this->m_observable = observable;
+    this->m_res_mask = res_mask;
+    this->m_obs_number = 0;
+    this->m_data_wrapper = NULL;
+    this->m_observer = NULL;
+    this->m_maxage = DEFAULT_MAXAGE;
+    this->m_content_format = DEFAULT_CONTENT_FORMAT;
+    this->m_ep = NULL;
+    this->m_res = NULL;
+}
+
+// constructor (strings)
+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)
+{
+    this->m_res_type = res_type;
+    this->m_type = type;
+    this->m_observable = observable;
+    this->m_res_mask = res_mask;
+    this->m_obs_number = 0;
+    this->m_data_wrapper = NULL;
+    this->m_observer = NULL;
+    this->m_maxage = DEFAULT_MAXAGE;
+    this->m_content_format = DEFAULT_CONTENT_FORMAT;
+    this->m_ep = NULL;
+    this->m_res = NULL;
+}
+
+// copy constructor
+DynamicResource::DynamicResource(const DynamicResource &resource) : Resource<string>((const Resource<string> &)resource)
+{
+    this->m_res_type = resource.m_res_type;
+    this->m_type = resource.m_type;
+    this->m_observable = resource.m_observable;
+    this->m_res_mask = resource.m_res_mask;
+    this->m_obs_number = resource.m_obs_number;
+    this->m_data_wrapper = resource.m_data_wrapper;
+    this->m_observer = resource.m_observer;
+    this->m_maxage = resource.m_maxage;
+    this->m_content_format = resource.m_content_format;
+    this->m_ep = resource.m_ep;
+    this->m_res = resource.m_res;
+}
+
+// destructor
+DynamicResource::~DynamicResource() {
+}
+
+// bind CoAP Resource...
+void DynamicResource::bind(void *ep) {
+	if (ep != NULL) {
+		// cast
+		Connector::Endpoint *endpoint = (Connector::Endpoint *)ep;
+		
+		// get our ObjectInstanceManager
+		ObjectInstanceManager *oim = endpoint->getObjectInstanceManager();
+		
+		// Create our Resource
+		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);
+		if (this->m_res != NULL) {
+			// Record our Instance Number
+			this->setInstanceNumber(oim->getLastCreatedInstanceNumber());
+			   
+			// perform an initial get() to initialize our data value
+			this->setValue(this->get());
+			
+			// now record the data value         			
+			if (this->getDataWrapper() != NULL) {
+				// wrap the data...
+				this->getDataWrapper()->wrap((uint8_t *)this->getValue().c_str(),(int)this->getValue().size());
+				this->m_res->set_operation((M2MBase::Operation)this->m_res_mask);
+				this->m_res->set_value( this->getDataWrapper()->get(),(uint8_t)this->getDataWrapper()->length());
+				this->logger()->logging("%s: [%s] value: [%s] bound (observable: %d)",this->m_res_type.c_str(),this->getFullName().c_str(),this->getDataWrapper()->get(),this->m_observable);
+			}
+			else {
+				// do not wrap the data...
+				this->m_res->set_operation((M2MBase::Operation)this->m_res_mask);
+				this->m_res->set_value((uint8_t *)this->getValue().c_str(),(uint8_t)this->getValue().size());
+ 				this->logger()->logging("%s: [%s] value: [%s] bound (observable: %d)",this->m_res_type.c_str(),this->getFullName().c_str(),this->getValue().c_str(),this->m_observable);
+			}
+			
+			// set our endpoint instance
+			this->m_ep = (void *)ep;
+			
+			// For POST-enabled  RESOURCES (only...), we must add a callback
+			if ((this->m_res_mask & M2MBase::POST_ALLOWED)  != 0) { 
+				// add a callback for the execute function...we will just direct through process()...
+				//this->logger()->logging("DynamicResource::bind(): Setting up POST execute callback function");
+				this->m_res->set_execute_function(execute_callback(this, &DynamicResource::process_resource_post));
+			}    		
+		}		
+	}
+	else {
+		// no instance pointer to our endpoint
+      	this->logger()->logging("%s: NULL endpoint instance pointer in bind() request...",this->m_res_type.c_str());
+    }
+}
+
+// get our M2MBase representation
+M2MResource *DynamicResource::getResource() {
+	return this->m_res;
+}
+
+// process inbound mbed-client POST message for a Resource
+void DynamicResource::process_resource_post(void *args) {
+		// just call process() for POST and Resources...
+		//this->logger()->logging("DynamicResource::process_resource_post(): calling process(POST)");
+		(void)this->process(M2MBase::POST_ALLOWED,this->m_res->base_type(),args);
+}
+
+// process inbound mbed-client message
+uint8_t DynamicResource::process(M2MBase::Operation op,M2MBase::BaseType type,void *args) {
+#if defined (HAS_EXECUTE_PARAMS)
+     M2MResource::M2MExecuteParameter* param = NULL;
+     
+     // cast args if present...
+	 if (args != NULL) {
+     	param = (M2MResource::M2MExecuteParameter*)args;
+     }
+#endif	
+	// DEBUG
+	//this->logger()->logging("in %s::process()  Operation=0x0%x Type=%x%x",this->m_res_type.c_str(),op,type);
+	
+	// PUT() check
+	if ((op & M2MBase::PUT_ALLOWED) != 0) {
+		string value = this->coapDataToString(this->m_res->value(),this->m_res->value_length());
+	 	this->logger()->logging("%s: put(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),value.c_str());
+     	this->put(value.c_str());
+     	return 0;
+    }
+ 
+#if defined (HAS_EXECUTE_PARAMS)   
+    // POST() check
+	if ((op & M2MBase::POST_ALLOWED) != 0) {
+	    string value;
+	    if (param != NULL) {
+	    	// use parameters
+	    	String object_name = param->get_argument_object_name();
+	    	int instance_id = (int)param->get_argument_object_instance_id();
+	    	String resource_name = param->get_argument_resource_name();
+	    	value = this->coapDataToString(param->get_argument_value(),param->get_argument_value_length());
+	    	this->logger()->logging("%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());
+	    }
+	    else {
+	    	// use the resource value itself
+			value = this->coapDataToString(this->m_res->value(),this->m_res->value_length());
+	 		this->logger()->logging("%s: post(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),value.c_str());
+     	}
+     	
+     	// invoke
+     	this->post(args);
+     	return 0;
+    }
+#else  
+    // POST() check
+	if ((op & M2MBase::POST_ALLOWED) != 0) {
+		if (args != NULL) {
+			this->logger()->logging("%s: post(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),(char *)args);
+	     	this->post(args);
+     	}
+     	else {
+     		string value = this->coapDataToString(this->m_res->value(),this->m_res->value_length());
+		 	this->logger()->logging("%s: post(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),value.c_str());
+	     	this->post((void *)value.c_str());
+     	}
+     	return 0;
+    }
+#endif
+
+#if defined (HAS_EXECUTE_PARAMS)
+	// DELETE() check
+	if ((op & M2MBase::DELETE_ALLOWED) != 0) {
+		if (param != NULL) {
+	    	// use parameters
+	    	String object_name = param->get_argument_object_name();
+	    	int instance_id = (int)param->get_argument_object_instance_id();
+	    	String resource_name = param->get_argument_resource_name();
+	    	string value = this->coapDataToString(param->get_argument_value(),param->get_argument_value_length());
+	    	this->logger()->logging("%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());
+	    }
+	    else {
+	    	// use the resource value itself
+			string value = this->coapDataToString(this->m_res->value(),this->m_res->value_length());
+	 		this->logger()->logging("%s: delete(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),value.c_str());
+     	}
+     	
+     	// invoke
+     	this->del(args);
+     	return 0;
+    }
+#else     
+    // DELETE() check
+	if ((op & M2MBase::DELETE_ALLOWED) != 0) {
+		if (args != NULL) {
+			this->logger()->logging("%s: delete(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),(char *)args);
+	     	this->del(args);
+     	}
+     	else {
+     		string value = this->coapDataToString(this->m_res->value(),this->m_res->value_length());
+		 	this->logger()->logging("%s: delete(%d) [%s]=[%s] called.",this->m_res_type.c_str(),type,this->getFullName().c_str(),value.c_str());
+	     	this->del((void *)value.c_str());
+     	}
+     }
+#endif
+     
+     // unknown type...
+     this->logger()->logging("%s: Unknown Operation (0x%x) for [%s]=[%s]... FAILED.",op,this->m_res_type.c_str(),this->getFullName().c_str(),this->m_res->value());
+     return 1;
+}
+
+// send the notification
+int DynamicResource::notify(const string data) {
+    return this->notify((uint8_t *)data.c_str(),(int)data.length());
+}
+
+// send the notification
+int DynamicResource::notify(uint8_t *data,int data_length) {
+    uint8_t *notify_data = NULL;
+    int notify_data_length = 0;
+    int status = 0;
+
+    // convert the string from the GET to something suitable for CoAP payloads
+    if (this->getDataWrapper() != NULL) {
+        // wrap the data...
+        this->getDataWrapper()->wrap((uint8_t *)data,data_length);
+
+        // announce (after wrap)
+        //this->logger()->logging("Notify payload [%s]...",this->getDataWrapper()->get());
+
+        // fill notify
+        notify_data_length = this->getDataWrapper()->length();
+        notify_data = this->getDataWrapper()->get();
+    }
+    else {
+        // announce (no wrap)
+        //this->logger()->logging("Notify payload [%s]...",data);
+
+        // do not wrap the data...
+        notify_data_length = data_length;
+        notify_data = data;
+    }
+    
+    // update the resource
+    this->m_res->set_value((uint8_t *)notify_data,(uint8_t)notify_data_length);
+
+    // return our status
+    return status;
+}
+
+// default GET (does nothing)
+string DynamicResource::get()
+{
+    // not used by default
+    //this->logger()->logging("DynamicResource::get() invoked (NOOP)");
+    return string("");
+}
+
+// default PUT (does nothing)
+void DynamicResource::put(const string /* value */)
+{
+    // not used by default
+    //this->logger()->logging("DynamicResource::put() invoked (NOOP)");
+}
+
+// default POST (does nothing)
+void DynamicResource::post(void * /* args */)
+{
+    // not used by default
+    //this->logger()->logging("DynamicResource::post() invoked (NOOP)");
+}
+
+// default DELETE (does nothing)
+void DynamicResource::del(void * /* args */)
+{
+    // not used by default
+    //this->logger()->logging("DynamicResource::del() invoked (NOOP)");
+}
+
+// default observe behavior
+void DynamicResource::observe() {
+    if (this->m_observable == true && this->isRegistered() == true) {
+        this->notify(this->get());
+    }
+}
+
+// set the observer pointer
+void DynamicResource::setObserver(void *observer) {
+    this->m_observer = observer;
+}
+
+// set the content-format in responses
+void DynamicResource::setContentFormat(uint8_t content_format) {
+    this->m_content_format = content_format;
+}
+
+// set the max-age of responses
+void DynamicResource::setMaxAge(uint8_t maxage) {
+    this->m_maxage = maxage;
+}
+
+// convert the CoAP data pointer to a string type
+string DynamicResource::coapDataToString(uint8_t *coap_data_ptr,int coap_data_ptr_length)
+{
+    if (coap_data_ptr != NULL && coap_data_ptr_length > 0) {
+        if (this->getDataWrapper() != NULL) {
+            // unwrap the data...
+            this->getDataWrapper()->unwrap(coap_data_ptr,coap_data_ptr_length);
+            char *buf = (char *)this->getDataWrapper()->get();                  // assumes data is null terminated in DataWrapper...
+            return string(buf);
+        }
+        else {
+            // no unwrap of the data...
+            char buf[MAX_VALUE_BUFFER_LENGTH+1];
+            memset(buf,0,MAX_VALUE_BUFFER_LENGTH+1);
+            memcpy(buf,(char *)coap_data_ptr,coap_data_ptr_length);
+            return string(buf);
+        }
+    }
+    return string("");
+}
+
+// convert the CoAP data pointer to an integer type
+int DynamicResource::coapDataToInteger(uint8_t *coap_data_ptr,int coap_data_ptr_length) {
+	int value = 0;
+	if (coap_data_ptr != NULL && coap_data_ptr_length > 0) {
+        if (this->getDataWrapper() != NULL) {
+            // unwrap the data...
+            this->getDataWrapper()->unwrap(coap_data_ptr,coap_data_ptr_length);
+            //value = (int)this->getDataWrapper()->get();                  // assumes data is null terminated in DataWrapper...
+        }
+        else {
+            // no unwrap of the data...
+            //value = (int)coap_data_ptr;
+        }
+    }
+    return value;
+}
+
+// convert the CoAP data pointer to a float type
+float DynamicResource::coapDataToFloat(uint8_t *coap_data_ptr,int coap_data_ptr_length) {
+	float value = 0.0;
+	if (coap_data_ptr != NULL && coap_data_ptr_length > 0) {
+        if (this->getDataWrapper() != NULL) {
+            // unwrap the data...
+            this->getDataWrapper()->unwrap(coap_data_ptr,coap_data_ptr_length);
+            //value = (float)this->getDataWrapper()->get();                  // assumes data is null terminated in DataWrapper...
+        }
+        else {
+            // no unwrap of the data...
+            //value = (float)coap_data_ptr;
+        }
+    }
+    return value;
+}
+
+// convert the CoAP data pointer to an opaque type
+void *DynamicResource::coapDataToOpaque(uint8_t *coap_data_ptr,int coap_data_ptr_length) {
+	if (coap_data_ptr != NULL && coap_data_ptr_length > 0) {
+        if (this->getDataWrapper() != NULL) {
+            // unwrap the data...
+            this->getDataWrapper()->unwrap(coap_data_ptr,coap_data_ptr_length);
+            char *buf = (char *)this->getDataWrapper()->get();                  // assumes data is null terminated in DataWrapper...
+            return (void *)buf;
+        }
+    }
+    return (void *)coap_data_ptr;
+}
+
+// Determine if we are connected or not
+bool DynamicResource::isConnected() {
+	bool is_connected = false;
+	
+	// get our Endpoint
+	Connector::Endpoint *ep = (Connector::Endpoint *)this->m_endpoint;
+	if (ep != NULL)  {
+		is_connected = ep->isConnected();
+		if (is_connected) {
+			//this->logger()->logging("DynamicResource::isConnected = true");
+		}
+		else { 
+			//this->logger()->logging("DynamicResource::isConnected = false");
+		}
+	}
+	else {
+		this->logger()->logging("DynamicResource::isConnected = false (no endpoint)");
+	}
+	
+	// return our endpoint connection state
+	return is_connected;
+}
+
+// Determine if we are registered or not
+bool DynamicResource::isRegistered() {
+	bool is_registered = false;
+	
+	if (this->isConnected() == true) {
+		// get our Endpoint
+		Connector::Endpoint *ep = (Connector::Endpoint *)this->m_endpoint;
+		if (ep != NULL)  {
+			is_registered = ep->isRegistered();
+			if (is_registered) {
+				//this->logger()->logging("DynamicResource::isRegistered = true");
+			}
+			else { 
+				//this->logger()->logging("DynamicResource::isRegistered = false");
+			}
+		}
+		else {
+			this->logger()->logging("DynamicResource::isRegistered = false (no endpoint)");
+		}
+	}
+	
+	// return our endpoint registration state
+	return is_registered;
+}
+
+// get our observer
+void *DynamicResource::getObserver() {
+	return this->m_observer;
+}
\ No newline at end of file