mqtt specific components for the impact mbed endpoint library

Dependents:   mbed_mqtt_endpoint_ublox_ethernet mbed_mqtt_endpoint_ublox_cellular mbed_mqtt_endpoint_nxp

Files at this revision

API Documentation at this revision

Comitter:
ansond
Date:
Wed Mar 26 19:48:35 2014 +0000
Child:
1:5976e067b32a
Commit message:
updates

Changed in this revision

Definitions.h Show annotated file Show diff for this revision Revisions of this file
EmulatedLightDimmerAction.cpp Show annotated file Show diff for this revision Revisions of this file
EmulatedLightDimmerAction.h Show annotated file Show diff for this revision Revisions of this file
EmulatedLightSwitchAction.cpp Show annotated file Show diff for this revision Revisions of this file
EmulatedLightSwitchAction.h Show annotated file Show diff for this revision Revisions of this file
EmulatedResourceFactory.cpp Show annotated file Show diff for this revision Revisions of this file
EmulatedResourceFactory.h Show annotated file Show diff for this revision Revisions of this file
IOCHTTPTransport.cpp Show annotated file Show diff for this revision Revisions of this file
IOCHTTPTransport.h Show annotated file Show diff for this revision Revisions of this file
MBEDEndpoint.cpp Show annotated file Show diff for this revision Revisions of this file
MBEDEndpoint.h Show annotated file Show diff for this revision Revisions of this file
MQTTTransport.cpp Show annotated file Show diff for this revision Revisions of this file
MQTTTransport.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Definitions.h	Wed Mar 26 19:48:35 2014 +0000
@@ -0,0 +1,130 @@
+/* Copyright C2013 Doug Anson, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+#ifndef _DEFINITIONS_H_
+#define _DEFINITIONS_H_
+
+// platform
+#include "mbed.h"
+
+// include common definitions
+#include "CommonDefinitions.h"
+
+// Until we get HTTPS with BasicAuth working in MBED...
+#define GW_IPADDRESS                "192.168.1.220"     // gateway IP address (default)
+#define USE_GW_HTTP_REDIRECTOR      true                // true - make http calls to IOC via GW, false - make http calls directly to IOC
+
+// Gateway REST API URL
+#define GW_REDIRECT_URL             "http://%s:8888/NSP-IOC-Gateway/IOCRestAPI"
+
+// Memory Debug Enable/Disable
+// #define ENABLE_MEMORY_DEBUG         true             // false - disable, true - enable
+
+// Hush Logging
+//#define HUSH_LOG                     true             // false - logging output, true - no logging
+
+// Hush LED usage
+//define HUSH_LEDS                     true             // false - enable LEDs, true - disable LEDs
+
+// Our Endpoint Version Annoucement
+#define ENDPOINT_VERSION_ANNOUNCE "\r\nMBED IMPACT(MQTT) Endpoint v1.0"
+
+// Preference File Configuration
+#define PREFERENCES_FILE            "/local/mqtt.cfg"               // preferences file for endpoint  
+
+// our MAC address
+//#define MAC_ADDRESS                   0xa0,0x12,0xAB,0xE3,0x4F,0x56
+
+// Light Configuration
+#define LIGHT_NAME                  "light-mqtt-%d"                 // name of each light in this endpoint
+#define LIGHT_BLINK_WAIT_MS         1000                            // time between blinks (ms)
+#define LIGHT_NAME_INDEX            1                               // start index for the ID of the light name
+
+// Philips Light Config
+#define PL_ENABLE                   false                           // true - enable for endpoint light, false - disable
+#define PL_LIGHT_ID                 PL_LIGHT_ID_BILL                // Default light for Philips Light
+
+// External LED Light Configuration
+#define EXT_LED_ENABLE              true                            // true - enable external LED endpoint light, false - disable
+#define EXT_LED_PIN                 p21                             // pin to use for external LED cathode 
+
+// Endpoint GPS Coordinates/Location
+#define ENDPOINT_LOCATION           "Las Vegas Country Club"         // Where this light/endpoint lives
+#define ENDPOINT_GPS_COORDS         "-115.143470 36.131916"          // golf course -115.143470 36.131916 
+
+// MBED doesnt have a good notion of time - so we code it here
+#define ENDPOINT_STARTTIME          "\"STARTDATETIME\":\"2014-03-09T22:03:06-07:00\","
+#define ENDPOINT_STOPTIME           "\"ENDDATETIME\":\"2015-03-10T03:35:55-07:00\","
+#define ENDPOINT_TIMEZONE           "\"TIMEZONEOFFSET\":\"-07:00\""
+
+// Keyword Definitions for MQTT packets
+#define IOC_REQUEST_LOAD_ALL_VERB   "load"
+#define IOC_REQUEST_UPDATE_ALL_VERB "update"
+#define IOC_ENDPOINT_VERB           "Endpoint"
+#define IOC_ENDPOINT_ALL_VERB       "all"
+#define IOC_CHANGE_VERB             "Change"
+#define IOC_REQUEST_VALUE_VERB      "Get"
+#define IOC_RESPONSE_VERB           "response"
+#define IOC_REPONSE_ID_KEY          "id"
+#define IOC_DATASOURCE_ID           "229"
+
+// IOC REST Buffer Lengths
+#define IOC_REST_URL_LEN            128
+#define IOC_RESULT_LEN              1024
+#define IOC_PAYLOAD_LEN             768
+#define IOC_IOC_ID_LEN              16
+
+// IOC REST URL for Load/Updates
+#define IOC_USERNAME                "anson"
+#define IOC_PASSWORD                "savetheplanet1"
+#define IOC_HOST_NAME               "iocweb.bcu.ac.uk"              // IOC Web - iocweb.bcu.ac.uk
+#define IOC_REST_URL                "https://%s/ibm/ioc/api/data-injection-service/datablocks/%s/dataitems%s"
+#define IOC_RESPONSE_TEMPLATE       "%s:{ENDPOINT=%s RESOURCE=%s VALUE=%s}:%s"
+#define IOC_RESPONSE_OK             "OK"
+#define IOC_RESPONSE_FAILED         "FAILED"
+
+// Transport Configuration
+#define NUM_TRANSPORTS              2                               // MQTT, HTTP
+#define MQTT_TRANSPORT              0                               // MQTT Transport index
+#define HTTP_TRANSPORT              1                               // HTTP Transport index
+
+// Index for Transport to use for Update/Load
+#define LOAD_TRANSPORT              1                               // 0 - MQTT, 1 - HTTP
+
+// largest MQTT message that PubSubClient will send
+#define MAX_MQTT_MESSAGE_LENGTH     128
+
+// MQTT connect information
+#define MQTT_HOSTNAME               "iocana.bcu.ac.uk"              // IOC MQTT Broker Host - iocana.bcu.ac.uk
+#define MQTT_HOSTPORT               1883                            // IOC MQTT Broker Port
+#define MQTT_ENDPOINT_ID            "mbed%d%d"                      // IOC MQTT Endpoint ID template
+#define MQTT_MAXID_VALUE            99                              // IOC MQTT Endpoint ID maximum integer value
+#define MQTT_ENDPOINT_IDLEN         64                              // IOC MQTT Endpoint ID length (max)
+#define MQTT_IOC_TOPIC              "ARM/sensinode/control/%s"      // IOC MQTT Topic 
+#define MQTT_IOC_ALL_TOPIC          "ARM/sensinode/control/all"     // IOC MQTT Topic (broadcast)
+#define MQTT_PING_SEND_TOPIC        "ARM/sensinode/ping"            // IOC MQTT Ping Send Topic
+#define MQTT_IOC_ALL_ENDPOINT       "all"                           // must be the same as the last element of MATT_IOC_ANNOUNCE_TOPIC
+#define MQTT_IOC_TOPIC_LEN          64                              // max length for the topic string
+#define MQTT_PAYLOAD_SEGMENT_LEN    64                              // max length for a segment of the payload
+#define MQTT_USERNAME               ""                              // IOC MQTT Username
+#define MQTT_PASSWORD               ""                              // IOC MQTT Password
+#define MQTT_PING_VERB_LEN          10                              // Ping or Pong
+#define MQTT_PING_COUNTDOWN         1200                            // Send ping to GW every 1200'th 250ms iterations (5 minutes)
+#define MQTT_MAX_COUNTER            32768                           // largest Ping counter before reset back to 1
+
+#endif // _DEFINITIONS_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EmulatedLightDimmerAction.cpp	Wed Mar 26 19:48:35 2014 +0000
@@ -0,0 +1,41 @@
+/* Copyright C2013 Doug Anson, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+ #include "EmulatedLightDimmerAction.h"
+ 
+  // Our instance
+ EmulatedLightDimmerAction *_dimmerAction = NULL;
+ 
+ // static callback for Dimming operations
+ void emulated_light_dimming_cb() {
+     if (_dimmerAction != NULL) ((LightDimmerAction *)_dimmerAction)->dim();
+ }
+ 
+ // default constructor
+ EmulatedLightDimmerAction::EmulatedLightDimmerAction(ErrorHandler *error_handler,Light *light) : LightDimmerAction(error_handler,light) {
+     _dimmerAction = this;
+ }
+ 
+ // destructor
+ EmulatedLightDimmerAction::~EmulatedLightDimmerAction() {
+ }
+
+ // DIM the light
+ void EmulatedLightDimmerAction::dim(int value) { 
+    if (this->light() != NULL) ((LightDimmerAction *)this)->light()->dim(value); 
+ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EmulatedLightDimmerAction.h	Wed Mar 26 19:48:35 2014 +0000
@@ -0,0 +1,33 @@
+/* Copyright C2013 Doug Anson, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+#ifndef _EMULATED_LIGHT_DIMMER_ACTION_H_
+#define _EMULATED_LIGHT_DIMMER_ACTION_H_
+
+// Base class
+#include "LightDimmerAction.h"
+
+class EmulatedLightDimmerAction : public LightDimmerAction {        
+    public:
+        EmulatedLightDimmerAction(ErrorHandler *error_handler,Light *light);
+        virtual ~EmulatedLightDimmerAction(); 
+        
+        void dim(int value);       
+};
+
+#endif // _LIGHT_DIMMER_ACTION_H_
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EmulatedLightSwitchAction.cpp	Wed Mar 26 19:48:35 2014 +0000
@@ -0,0 +1,46 @@
+/* Copyright C2013 Doug Anson, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+ #include "EmulatedLightSwitchAction.h"
+  
+ // Our instance
+ EmulatedLightSwitchAction *_switchAction = NULL;
+ 
+ // static callback for Switching operations
+ void emulated_light_switch_cb() {
+     if (_switchAction != NULL) ((LightSwitchAction *)_switchAction)->toggle();
+ }
+ 
+ // default constructor
+ EmulatedLightSwitchAction::EmulatedLightSwitchAction(ErrorHandler *error_handler,Light *light) : LightSwitchAction(error_handler,light) {
+    _switchAction = this;
+ }
+ 
+ // destructor
+ EmulatedLightSwitchAction::~EmulatedLightSwitchAction() {
+ }
+
+ // Light turned ON
+ void EmulatedLightSwitchAction::on() { 
+    if (this->light() != NULL) ((LightSwitchAction *)this)->light()->on(); 
+ }
+ 
+ // Light turned OFF
+ void EmulatedLightSwitchAction::off() { 
+    if (this->light() != NULL) ((LightSwitchAction *)this)->light()->off(); 
+ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EmulatedLightSwitchAction.h	Wed Mar 26 19:48:35 2014 +0000
@@ -0,0 +1,34 @@
+/* Copyright C2013 Doug Anson, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+#ifndef _EMULATED_LIGHT_SWITCH_ACTION_H_
+#define _EMULATED_LIGHT_SWITCH_ACTION_H_
+
+// Base class
+#include "LightSwitchAction.h"
+
+class EmulatedLightSwitchAction : public LightSwitchAction {        
+    public:
+        EmulatedLightSwitchAction(ErrorHandler *error_handler,Light *light);
+        virtual ~EmulatedLightSwitchAction(); 
+        
+        void on();
+        void off();       
+};
+
+#endif // _LIGHT_SWITCH_ACTION_H_
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EmulatedResourceFactory.cpp	Wed Mar 26 19:48:35 2014 +0000
@@ -0,0 +1,148 @@
+/* Copyright C2013 Doug Anson, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+ // class definition
+ #include "EmulatedResourceFactory.h"
+ 
+ // MBEDEndpoint support
+ #include "MBEDEndpoint.h"
+ 
+ // MBED supports Battery Emulation
+ #include "MBEDBattery.h"
+ 
+ // MBED supports Current Emulation
+ #include "MBEDCurrent.h"
+ 
+ // MBED supports Temperature Sensing
+ #include "MBEDTemperature.h"
+ 
+ // MBED supports GPS Emulation
+ #include "MBEDgps.h"
+ 
+ // MBED supports RSSI Emulation
+ #include "MBEDrssi.h"
+ 
+ // MBED supports Voltage Emulation
+ #include "MBEDVoltage.h"
+ 
+ // MBED supports Wattage Emulation
+ #include "MBEDWattage.h"
+ 
+ // Initializers
+ void init_battery(Resource *resource) { if (resource != NULL) new MBEDBattery(resource->logger(),resource); }
+ void init_current(Resource *resource) { if (resource != NULL) new MBEDCurrent(resource->logger(),resource); }
+ void init_gps(Resource *resource) { if (resource != NULL) new MBEDgps(resource->logger(),resource); }
+ void init_rssi(Resource *resource) { if (resource != NULL) new MBEDrssi(resource->logger(),resource); }
+ void init_temperature(Resource *resource) { if (resource != NULL) new MBEDTemperature(resource->logger(),resource); }
+ void init_voltage(Resource *resource) { if (resource != NULL) new MBEDVoltage(resource->logger(),resource); }
+ void init_wattage(Resource *resource) { if (resource != NULL) new MBEDWattage(resource->logger(),resource); }
+  
+ // Ethernet
+ #include "EthernetInterface.h"
+ extern EthernetInterface ethernet;
+ 
+ // NSP supports Light Dimming
+ extern void emulated_light_dimming_cb();
+ 
+ // NSP supports Light Switch 
+ extern void emulated_light_switch_cb();
+ 
+ // default constructor
+ EmulatedResourceFactory::EmulatedResourceFactory(ErrorHandler *error_handler,void *endpoint) : ResourceFactory(error_handler,endpoint) {  
+    this->initGPSCoords();
+ }
+ 
+ // default destructor
+ EmulatedResourceFactory::~EmulatedResourceFactory() {
+ }
+ 
+ // initialize our GPS coords
+ void EmulatedResourceFactory::initGPSCoords() {
+     memset(this->m_gps_coords,0,PREFERENCE_VALUE_LEN+1);
+     MBEDEndpoint *endpoint = (MBEDEndpoint *)this->m_endpoint;
+     endpoint->preferences()->getPreference("coords",this->m_gps_coords,PREFERENCE_VALUE_LEN,ENDPOINT_GPS_COORDS);
+ }
+ 
+ // get our GPS coords from preferences
+ char *EmulatedResourceFactory::getGPSCoords() { return this->m_gps_coords; }
+ 
+ // create resources
+ void EmulatedResourceFactory::createResources(char *endpoint_name) {
+    // create all of the resources we expect for this endpoint
+    this->createResource("/dev/addldata","id:0");
+    this->createResource("/dev/location",ENDPOINT_LOCATION);
+    this->createResource("/fw/devtype","Light");
+    this->createResource("/dev/bat","5.0V",(void *)&init_battery,NULL);
+    this->createResource("/sen/I","0.1A",(void *)&init_current,NULL);
+    this->createResource("/dev/I","0.1A",(void *)&init_current,NULL);
+    this->createResource("/nw/ipaddr",ethernet.getIPAddress());
+    this->createResource(endpoint_name,"/lt/0/dim","25",(void *)&emulated_light_dimming_cb);          // Action: dim/brighten light
+    this->createResource("/nw/eripaddr","N/A");
+    this->createResource(endpoint_name,"/lt/0/on","1",(void *)&emulated_light_switch_cb);             // Action: light on/off
+    this->createResource(endpoint_name,"/lt/0/ctr","1",(void *)&emulated_light_switch_cb);             // Action: light on/off
+    this->createResource("/dev/mdl","MQTT MBED Light");
+    this->createResource("/dev/mfg","NXP MBED");
+    this->createResource("/gps/int","60");
+    this->createResource("/gps/fix","1");
+    this->createResource("/nw/pipaddr","N/A");
+    this->createResource("/dev/W","0.1W",(void *)&init_wattage,NULL);
+    this->createResource("/nw/prssi","-75",(void *)&init_rssi,NULL);
+    this->createResource("/sen/temp","10.0C",(void *)&init_temperature,NULL);
+    this->createResource("/dev/t","10.0C",(void *)&init_temperature,NULL);
+    this->createResource("/sen/V","5.0V",(void *)&init_voltage,NULL);
+    this->createResource("/dev/V","5.0V",(void *)&init_voltage,NULL);
+    this->createResource("/gps/loc",this->getGPSCoords(),(void *)&init_gps,NULL);
+    this->createResource("/ns/nspaddr","(NA)");
+    this->createResource(endpoint_name,"/dev/panic","0",(void *)&emulated_light_switch_cb);             // Action: light on/off
+    
+#ifdef MAC_ADDRESS
+    extern char fmt_mac[RESOURCE_VALUE_LEN+1];
+    this->createResource("/nw/macaddr",fmt_mac);
+#else
+    this->createResource("/nw/macaddr","00:00:00:00:00");
+#endif
+ } 
+ 
+ void EmulatedResourceFactory::createResource(char *name,char *value) { ResourceFactory::createResource(name,value); }
+ void EmulatedResourceFactory::createResource(char *ep_name,char *name,char *value,void *cb) { ResourceFactory::createResource(ep_name,name,value,cb); }
+ void EmulatedResourceFactory::createResource(char *name,char *value,void *io,void *notused) {
+     MBEDEndpoint *endpoint = (MBEDEndpoint *)this->m_endpoint;
+     char *ep_name = NULL; if (endpoint != NULL) ep_name = endpoint->getEndpointName();
+     this->m_list[this->m_count] = new Resource(this->logger(),ep_name,name,value,NULL);
+     if (io != NULL && this->m_list[this->m_count] != NULL) {
+        resourceInitializer initializer = (resourceInitializer)io;
+        (initializer)(this->m_list[this->m_count]);
+     }
+     if (this->m_list[this->m_count] != NULL) ++this->m_count;
+ }
+  
+ // set a resource value (AND trigger the Emulated actions if registered)
+ bool EmulatedResourceFactory::setResourceValue(char *name, char *value) {
+     // set the resource value
+     bool success = ResourceFactory::setResourceValue(name,value);
+     if (success) {
+         // invoke an action if registered
+         EmulatedCallbackPointer cb = (EmulatedCallbackPointer)this->getCallbackPointer(name);
+         if (cb != NULL) {
+             // invoke the callback
+             this->logger()->log("Invoking Action...");
+             cb();
+         }
+     }
+     return success;
+ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EmulatedResourceFactory.h	Wed Mar 26 19:48:35 2014 +0000
@@ -0,0 +1,57 @@
+/* Copyright C2013 Doug Anson, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+#ifndef _EMULATED_RESOURCE_FACTORY_H_
+#define _EMULATED_RESOURCE_FACTORY_H_
+
+// Base Class
+#include "ResourceFactory.h"
+
+// Emulated callback structure
+typedef void (*EmulatedCallbackPointer)();
+
+// ErrorHandler support
+#include "ErrorHandler.h"
+
+// Resource Initializer callback structure
+typedef void (*resourceInitializer)(Resource *);
+
+class EmulatedResourceFactory : public ResourceFactory {    
+    private:
+        char m_gps_coords[PREFERENCE_VALUE_LEN+1];
+        
+    public:
+        EmulatedResourceFactory(ErrorHandler *error_handler,void *endpoint);
+        virtual ~EmulatedResourceFactory();
+                      
+        virtual void createResources(char *endpoint_name);
+        
+        bool setResourceValue(char *name, char *value);
+    
+    protected:
+        virtual void createResource(char *endpoint_name,char *name,char *value,void *cb);
+        virtual void createResource(char *name,char *value);
+        void createResource(char *name,char *value,void *io,void *notused);
+        
+    private:
+        void initGPSCoords();
+        char *getGPSCoords();
+ };
+
+
+#endif // _EMULATED_RESOURCE_FACTORY_H_
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IOCHTTPTransport.cpp	Wed Mar 26 19:48:35 2014 +0000
@@ -0,0 +1,104 @@
+/* Copyright C2013 Doug Anson, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+ #include "IOCHTTPTransport.h"
+   
+ // default constructor
+ IOCHTTPTransport::IOCHTTPTransport(ErrorHandler *error_handler,void *endpoint) : HTTPTransport(error_handler,endpoint) {
+     memset(this->m_url_buffer,0,IOC_REST_URL_LEN+1);
+ }
+ 
+ // default destructor
+ IOCHTTPTransport::~IOCHTTPTransport() {
+ }
+ 
+ // package up data
+ char *IOCHTTPTransport::packageData(char *verb,char *data,int ioc_id) {
+     char buffer[IOC_PAYLOAD_LEN+1];
+     memset(buffer,0,IOC_PAYLOAD_LEN+1);
+     if (USE_GW_HTTP_REDIRECTOR == false) {
+         // just use the data
+         return data;
+     }
+     else {
+         // repackage into format: VERB;USER;PASS;AUTHDOMAIN;CONTENTTYPE;JSON;URL
+         sprintf(buffer,"%s;%s;%s;_none_;%s;%s;%s ",verb,IOC_USERNAME,IOC_PASSWORD,"application/json",data,this->createIOCUpdateURL(ioc_id,false));
+         memcpy(data,buffer,strlen(buffer));
+         return data;
+     }
+ }
+ 
+ // Load up our endpoint into the IOC
+ bool IOCHTTPTransport::loadEndpoint(char *data,int data_length,char *result,int result_length) {
+    data = this->packageData("POST",data,0);    // must be first as it will first write into the common URL buffer
+    char *url = this->createIOCLoadURL();       // resets the common URL buffer to point to the IOC GW 
+    return this->httpPost(url,data,strlen(data),result,result_length); 
+ }
+ 
+ // update our endpoint with the IOC
+ bool IOCHTTPTransport::updateEndpoint(int ioc_id,char *data,int data_length,char *result,int result_length) { 
+    //this->logger()->log("updateEndpoint: %s",data);
+    data = this->packageData("PUT",data,ioc_id);
+    return this->httpPut(this->createIOCUpdateURL(ioc_id),data,strlen(data),result,result_length); 
+ }
+ 
+ // create the IOC load URL
+ char *IOCHTTPTransport::createIOCLoadURL() { return this->createIOCUpdateURL(0); }
+ 
+ // create the IOC update URL
+ char *IOCHTTPTransport::createIOCUpdateURL(int ioc_id) { return this->createIOCUpdateURL(ioc_id,USE_GW_HTTP_REDIRECTOR); }
+ char *IOCHTTPTransport::createIOCUpdateURL(int ioc_id,bool useRedirector) {
+     if (useRedirector == false) {
+         // make HTTP calls directly
+         char ioc_id_str[IOC_IOC_ID_LEN+1];
+         memset(ioc_id_str,0,IOC_IOC_ID_LEN+1);
+         if (ioc_id > 0) sprintf(ioc_id_str,"/%d",ioc_id);
+         memset(this->m_url_buffer,0,IOC_REST_URL_LEN+1);
+         sprintf(this->m_url_buffer,IOC_REST_URL,IOC_HOST_NAME,IOC_DATASOURCE_ID,ioc_id_str);
+     }
+     else {
+         // use the GW HTTP redirector
+         memset(this->m_url_buffer,0,IOC_REST_URL_LEN+1);
+         sprintf(this->m_url_buffer,GW_REDIRECT_URL,GW_IPADDRESS);
+     }
+     return this->m_url_buffer;
+ }    
+ 
+ // HTTP Get
+ bool IOCHTTPTransport::httpGet(char *url,char *result,int result_length) {
+    this->m_http->basicAuth(IOC_USERNAME,IOC_PASSWORD);
+    return HTTPTransport::httpGet(url,result,result_length);
+ }
+ 
+ // HTTP Put
+ bool IOCHTTPTransport::httpPut(char *url,char *data,int data_length,char *result,int result_length) {
+     this->m_http->basicAuth(IOC_USERNAME,IOC_PASSWORD);
+     return HTTPTransport::httpPut(url,data,data_length,result,result_length);
+ }
+ 
+ // HTTP Post
+ bool IOCHTTPTransport::httpPost(char *url,char *data,int data_length,char *result,int result_length) {
+     this->m_http->basicAuth(IOC_USERNAME,IOC_PASSWORD);
+     return HTTPTransport::httpPost(url,data,data_length,result,result_length);
+ }
+ 
+ // HTTP Delete
+  bool IOCHTTPTransport::httpDelete(char *url,char *data,int data_length) {
+    this->m_http->basicAuth(IOC_USERNAME,IOC_PASSWORD);
+    return HTTPTransport::httpDelete(url,data,data_length);
+ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IOCHTTPTransport.h	Wed Mar 26 19:48:35 2014 +0000
@@ -0,0 +1,48 @@
+/* Copyright C2013 Doug Anson, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+#ifndef _IOC_HTTP_TRANSPORT_H_
+#define _IOC_HTTP_TRANSPORT_H_
+
+// Base Class
+#include "HTTPTransport.h"
+
+class IOCHTTPTransport : public HTTPTransport {
+    private:
+        char        m_url_buffer[IOC_REST_URL_LEN+1];
+
+    public:
+        IOCHTTPTransport(ErrorHandler *error_handler,void *endpoint);
+        virtual ~IOCHTTPTransport();
+        
+        virtual bool httpGet(char *url,char *result,int result_length);
+        virtual bool httpPut(char *url,char *data,int data_length,char *result,int result_length);
+        virtual bool httpPost(char *url,char *data,int data_length,char *result,int result_length);
+        virtual bool httpDelete(char *url,char *data,int data_length);
+        
+        virtual bool loadEndpoint(char *data,int data_length,char *result,int result_length);
+        virtual bool updateEndpoint(int ioc_id,char *data,int data_length,char *result,int result_length); 
+                
+    private:
+        char *createIOCLoadURL();
+        char *packageData(char *verb,char *data,int ioc_id);
+        char *createIOCUpdateURL(int ioc_id);
+        char *createIOCUpdateURL(int ioc_id,bool useRedirector);
+ };
+
+#endif // _IOC_HTTP_TRANSPORT_H_
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MBEDEndpoint.cpp	Wed Mar 26 19:48:35 2014 +0000
@@ -0,0 +1,494 @@
+/* Copyright C2013 Doug Anson, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+ #include "MQTTTransport.h"
+ #include "MBEDEndpoint.h"
+ 
+ // MBED Light support
+ #include "MBEDLight.h"
+ 
+ // Emulated Resource Factory
+ #include "EmulatedResourceFactory.h"
+ 
+ // Emulated Actions we can act on
+ #include "EmulatedLightDimmerAction.h"
+ #include "EmulatedLightSwitchAction.h"
+ 
+ // string support
+ #include <stdlib.h>
+ #include <string.h>
+   
+ // shutdown endpoint reference
+ extern void closedown(int code);
+  
+ // default constructor
+ MBEDEndpoint::MBEDEndpoint(ErrorHandler *error_handler,EthernetInterface *ethernet) {
+     bool success = true;
+     this->m_instance_id = 0;
+     this->m_preferences = NULL;
+     memset(this->m_lcd_status,0,TEMP_BUFFER_LEN+1);
+     memset(this->m_gw_address,0,PREFERENCE_VALUE_LEN+1);
+     for(int i=0;i<NUM_TRANSPORTS;++i) this->m_transports[i] = NULL;
+     this->m_error_handler = error_handler;
+     this->m_error_handler->setEndpoint((void *)this);
+     if (success) this->initPreferences();
+     if (success) this->initEndpointName();
+     if (success) this->logger()->turnLEDBlue();
+#ifdef MAC_ADDRESS
+     extern char fmt_mac[RESOURCE_VALUE_LEN+1];
+     if (success)this->logger()->log("%s (MAC: %s)",ENDPOINT_VERSION_ANNOUNCE,fmt_mac);
+#else
+     if (success)this->logger()->log(ENDPOINT_VERSION_ANNOUNCE);
+#endif
+     if (success) this->initGWAddress();
+     if (success) this->logger()->log("IOC GW IP: %s",GW_IPADDRESS);
+     if (PL_ENABLE && success) this->logger()->log("Philips Light ID: %d Philips Gateway IP: %s",PL_LIGHT_ID,PL_GW_ADDRESS);
+     if (success) success = this->initializeEthernet(ethernet);
+     if (success) this->logger()->turnLEDYellow();
+     if (success)this->m_map = new MBEDToIOCResourceMap(error_handler); 
+     if (success) success = this->initializeTransports();
+     if (success) success = this->initializeLights();   
+     if (success) this->logger()->turnLEDOrange();
+     this->logger()->lcdStatusOnly(true);
+     if (!success) closedown(2);
+ }
+ 
+ // default destructor
+ MBEDEndpoint::~MBEDEndpoint() {
+     bool success = true;
+     if (success) this->logger()->turnLEDYellow();
+     if (success) success = this->closeLights();
+     if (success) success = this->closeTransports();
+     if (success) success = this->closeEthernet();
+     if (success) this->logger()->turnLEDBlue();
+     if (this->m_map != NULL) delete this->m_map;
+ }
+  
+ // get the IOC <--> MBED resource map
+ MBEDToIOCResourceMap *MBEDEndpoint::getMap() { return this->m_map; }
+ 
+ // initialize our preferences
+ void MBEDEndpoint::initPreferences() { if (this->m_preferences == NULL) this->m_preferences = new Preferences(this->logger()); if (this->m_preferences != NULL) this->m_preferences->fixCoordsForIOC(); }
+
+ // get our preferences
+ Preferences *MBEDEndpoint::preferences() { return this->m_preferences; }
+ 
+ // initialize the GW address from the configuration
+ void MBEDEndpoint::initGWAddress() {
+     memset(this->m_gw_address,0,PREFERENCE_VALUE_LEN+1);
+     this->preferences()->getPreference("gw_address",this->m_gw_address,PREFERENCE_VALUE_LEN,GW_IPADDRESS);
+     this->logger()->log("GW IP: %s",this->getGWAddress());
+ }
+ 
+ // get our GW address
+ char *MBEDEndpoint::getGWAddress() { return this->m_gw_address; }
+ 
+ // get our LCD status
+ char *MBEDEndpoint::getLCDStatus() {
+     memset(this->m_lcd_status,0,TEMP_BUFFER_LEN+1);
+     
+     // look at Light#0 to determine the IOC linkage ID...
+     char *ioc = this->m_lights[0]->getResourceFactory()->getResourceValue(IOC_LINKAGE_RESOURCE);
+     
+     // color our LED depending on whether we have IOC linkage or not...
+     if (ioc == NULL || strcmp(ioc,IOC_LINKAGE_UNSET) == 0) this->logger()->turnLEDOrange();
+     else this->logger()->turnLEDGreen();
+           
+     sprintf(this->m_lcd_status,"Node: %s\nGW IP: %s\nIOC Link: %s",this->getEndpointName(),this->getGWAddress(),ioc);
+     return this->m_lcd_status;
+ }
+ 
+ // initialize the Lights
+ bool MBEDEndpoint::initializeLights() {
+     int index = this->preferences()->getIntPreference("endpoint_id",LIGHT_NAME_INDEX); 
+     this->logger()->log("Initializing Lights...");
+     for(int i=0;i<NUM_LIGHTS;++i) {
+         this->m_lights[i] = new MBEDLight(this->logger(),this->m_transports,i+index,this);
+         this->m_lights[i]->setDimmerAction(new EmulatedLightDimmerAction(this->logger(),this->m_lights[i]));
+         this->m_lights[i]->setSwitchAction(new EmulatedLightSwitchAction(this->logger(),this->m_lights[i]));
+     }
+     return true;
+ }
+ 
+ // does the input name match any of our light resources?
+ int MBEDEndpoint::indexOfLight(char *name) {
+     bool found = false;
+     int index = -1;
+     
+     for(int i=0;i<NUM_LIGHTS && !found;++i) {
+         if (strcmp(this->m_lights[i]->getName(),name) == 0) {
+             found = true;
+             index = i;
+         }
+     }
+     
+     return index;
+ }
+ 
+ // get a specific resources
+ ResourceFactory *MBEDEndpoint::getResources(int index) {
+     if (index >= 0 && index < NUM_LIGHTS) return this->m_lights[index]->resources();
+     return NULL;
+ }
+ 
+ // initialize our ResourceFactory
+ ResourceFactory *MBEDEndpoint::initResourceFactory() { return new EmulatedResourceFactory(this->logger(),(void *)this); }
+ 
+ // Initialize the Endpoint Name - will be the first Light resource name (and there must be one...)
+ void MBEDEndpoint::initEndpointName() {
+     this->m_instance_id = this->preferences()->getIntPreference("endpoint_id",LIGHT_NAME_INDEX);
+     memset(this->m_endpoint_name,0,LIGHT_NAME_LEN+1);
+     sprintf(this->m_endpoint_name,LIGHT_NAME,this->m_instance_id);
+ }
+ 
+ // get our endpoint name
+ char *MBEDEndpoint::getEndpointName() { return this->m_endpoint_name; }
+ 
+ // get our instance id
+ int MBEDEndpoint::getInstanceID() { return this->m_instance_id; }
+ 
+ // initialize a specific transport
+ bool MBEDEndpoint::initializeTransport(int index,char *key,Transport *transport) {
+     bool success = false;
+     if (this->m_transports[index] == NULL) {
+          this->logger()->log("Initializing %s Transport...", key);
+          this->m_transports[index] = transport;
+          if (this->m_transports[index] != NULL) success = this->m_transports[index]->connect();
+          if (success) this->logger()->log("Transport %s initialized and connected",key);
+      }
+      else {
+          this->logger()->log("%s already connected (OK)...", key);
+          success = true;
+      }
+      return success;
+ }
+ 
+ // initialize our transports
+ bool MBEDEndpoint::initializeTransports() {
+      bool success = true;
+      
+      if (success == true) {
+        // MQTT Initialization
+        success = this->initializeTransport(MQTT_TRANSPORT,"MQTT",new MQTTTransport(this->m_error_handler,this,this->getMap()));
+      }
+      
+      if (success == true) {
+          // HTTP Initialization
+          success = this->initializeTransport(HTTP_TRANSPORT,"HTTP",new IOCHTTPTransport(this->m_error_handler,this));
+      }
+      return success;
+ }
+ 
+ // initialize our Ethernet 
+ bool MBEDEndpoint::initializeEthernet(EthernetInterface *ethernet) {
+     bool success = false;
+     this->m_ethernet = ethernet;
+     if (this->m_ethernet != NULL) {
+         this->logger()->log("Initializing Ethernet...");
+         
+         // connect up ethernet
+         this->m_ethernet->init();
+         this->m_ethernet->connect();
+         
+         // display our IP address
+         char *ipaddr = this->m_ethernet->getIPAddress();
+         if (ipaddr != NULL && strlen(ipaddr) > 0) {
+            this->logger()->log("IPAddress: %s",this->m_ethernet->getIPAddress());
+            success = true;
+         }
+         else {
+            this->logger()->log("Ethernet Not Connected...");
+            success = false;
+         }
+     }
+     else {
+         this->logger()->log("No Ethernet instance found");
+         success = false;
+     }
+     return success;
+ }
+ 
+ // load up all endpoints into the IOC
+ bool MBEDEndpoint::loadEndpoints() {
+     bool success = true;
+     this->logger()->log("Loading All Endpoints to IOC...");
+     for(int i=0;i<NUM_LIGHTS && success;++i) success = this->loadEndpoint(this->m_lights[i]);
+     return success;
+ }
+ 
+ // load up our endpoint to the IOC
+ bool MBEDEndpoint::loadEndpoint(Light *light) {      
+     bool success = false;
+     char result[IOC_RESULT_LEN+1];
+     char payload[IOC_PAYLOAD_LEN+1];
+     
+     // initialize
+     memset(result,0,IOC_RESULT_LEN+1);
+     memset(payload,0,IOC_PAYLOAD_LEN+1);
+     
+     // DEBUG
+     this->logger()->log("Building Payload for Light: %s...",light->getName());
+          
+     // build the payload
+     char *data = this->buildIOCPayload(payload,IOC_PAYLOAD_LEN,light);
+      
+     // issue the request
+     if (data != NULL && strlen(data) > 0) {
+        // DEBUG
+        this->logger()->log("Sending Light: %s to the IOC...",light->getName());
+     
+        // load
+        success = this->m_transports[LOAD_TRANSPORT]->loadEndpoint((char *)payload,strlen(payload),(char *)result,IOC_RESULT_LEN);
+     }
+     
+     // DEBUG
+     //if (success) this->logger()->log("Saving IOC ID for Light: %s...",light->getName());
+     
+     // update the IOC ID if found
+     if (success) this->saveIOCID(light,result);
+     
+     // DEBUG
+     if (success) this->logger()->log("Light: %s IOC ID=%d sent successfully",light->getName(),light->getIOCID());
+     
+     // DEBUG
+     if (!success) {
+         if (light != NULL) this->logger()->log("Light: %s send FAILED",light->getName());
+         else this->logger()->log("Light: send FAILED (NULL LIGHT)");
+     }
+     
+     // return our status
+     return success;
+ }
+ 
+ // update all endpoints to the IOC
+ bool MBEDEndpoint::updateEndpoints() {
+     bool success = true;
+     for(int i=0;i<NUM_LIGHTS && success;++i) success = this->updateEndpoints(i);
+     return success;
+ }
+ 
+ // update all endpoints to the IOC
+ bool MBEDEndpoint::updateEndpoints(int index) {
+     if (index >= 0 && index < NUM_LIGHTS) return this->updateEndpoint(this->m_lights[index]);
+     return false; 
+ }
+ 
+ // update our endpoint with the IOC
+ bool MBEDEndpoint::updateEndpoint(Light *light) { 
+     bool success = false;
+     char result[IOC_RESULT_LEN+1];
+     char payload[IOC_PAYLOAD_LEN+1];
+     
+     // initialize
+     memset(result,0,IOC_RESULT_LEN+1);
+     memset(payload,0,IOC_PAYLOAD_LEN+1);
+          
+     // build the payload
+     char *data = this->buildIOCPayload(payload,IOC_PAYLOAD_LEN,light);
+     
+     // issue the request  
+     if (data != NULL && strlen(data) > 0) {
+        // DEBUG
+        this->logger()->log("Updating Light: %s at the IOC...",light->getName()); 
+        
+        // update
+        success = this->m_transports[LOAD_TRANSPORT]->updateEndpoint(light->getIOCID(),(char *)payload,strlen(payload),(char *)result,IOC_RESULT_LEN);
+     }
+     
+     // DEBUG
+     if (success) this->logger()->log("Update of Endpoint to IOC successful");
+     else this->logger()->log("Update of Endpoint to IOC FAILED");
+          
+     // return our status
+     return success; 
+ } 
+ 
+ // build out the Payload
+ char *MBEDEndpoint::buildIOCPayload(char *data,int data_length,Light *light) {
+     char tmp[TEMP_BUFFER_LEN+1];
+      
+     // construct the payload for Load/Updates
+     ResourceFactory *factory = light->getResourceFactory();
+     
+     // start the buffer
+     strcat(data,"{");
+     
+     // loop through the resources and build a JSON representation for the payload
+     for(int i=0;i<factory->numResources();++i) {
+         // get the ith resource
+         Resource *resource = factory->getResource(i);
+         if (resource != NULL) {
+             // add to the JSON payload
+             char *name = this->getMap()->endpointNameToIOCName(resource->getName());
+             char *value = resource->getValue();
+             
+             // make sure that we have a positive IOC resource match for the NSP resource 
+             if (name != NULL && strlen(name) > 0) {
+                 // Handle LOCATION a special way
+                 if (strcmp(name,"LOCATION") != 0) {
+                     // standard name,value for IOC
+                     sprintf(tmp, "\"%s\":\"%s\",",name,value); 
+                  }
+                 else {
+                     // IOC expects "Point(X,Y)" for LOCATION
+                     sprintf(tmp, "\"%s\":\"Point(%s)\",",name,value); 
+                 }   
+                 strcat(data,tmp);
+            
+                 // Handle /dev/addldata 
+                 char *dev_addldata = this->getMap()->endpointNameToIOCName("/dev/addldata");
+                 if (dev_addldata != NULL && strcmp(name,dev_addldata) == 0 && light != NULL && light->getIOCID() > 0) {
+                     char buf[IOC_IOC_ID_LEN+1]; memset(buf,0,IOC_IOC_ID_LEN+1); sprintf(buf,"%d",light->getIOCID());
+                     sprintf(tmp,"\"%s\":\"id:%s\",",name,buf);
+                     strcat(data,tmp);
+                 }
+             }
+         }
+     }
+     
+     // Special Case: STARTDATETIME
+     strcat(data,ENDPOINT_STARTTIME);
+     
+     // Special Case: ENDDATETIME
+     strcat(data,ENDPOINT_STOPTIME);
+                
+     // Special Case: NAME
+     sprintf(tmp,"\"NAME\":\"%s\",",light->getName());
+     strcat(data,tmp);
+          
+     // Special Case: TIMEZONEOFFSET
+     strcat(data,ENDPOINT_TIMEZONE);
+          
+     // close
+     strcat(data,"}");
+     
+     // DEBUG
+     //this->logger()->log("Loading Payload: %s",data);
+     
+     // return the payload
+     return data;
+ }
+  
+ // save the IOC ID
+ void MBEDEndpoint::saveIOCID(Light *light,char *json) {
+     if (json != NULL) {          
+         //this->logger()->log("RESULT: %s",json);
+         
+         // look for "id":
+         char *check = "\"id\":";
+         char *pos1 = strstr(json,check);
+         if (pos1 != NULL) {
+             char *pos2 = strstr(pos1,","); 
+             if (pos1 != NULL && pos2 != NULL && pos2 > pos1) {
+                 pos1 += strlen(check);
+                 int length = pos2 - pos1;  
+                 char str_ioc_id[IOC_IOC_ID_LEN+1];
+                 memset(str_ioc_id,0,IOC_IOC_ID_LEN+1);
+                 strncpy(str_ioc_id,pos1,length);
+                 
+                 // DEBUG
+                 //this->logger()->log("IOC ID found: %s",str_ioc_id);
+                 
+                 // parse into int  
+                 int ioc_id = 0;             
+                 sscanf(str_ioc_id,"%d",&ioc_id);
+                          
+                 // save the IOC ID
+                 if (ioc_id > 0) light->setIOCID(ioc_id);
+             }
+             else {
+                 // cannot find the ID tag in the result JSON
+                 this->logger()->log("Cannot find the IOC ID in the JSON result");
+                 this->logger()->log("JSON: %s",json);
+             }
+         }
+         else {
+             // cannot find the ID tag in the result JSON
+             this->logger()->log("Cannot find the IOC ID in the JSON result");
+             this->logger()->log("JSON: %s",json);
+        }
+     }
+ }
+ 
+ // close down the Lights
+ bool MBEDEndpoint::closeLights() {
+    bool success = true;
+    this->logger()->log("Closing down Lights...");
+    for(int i=0;i<NUM_LIGHTS;++i)
+        if (this->m_lights[i] != NULL) delete this->m_lights[i];
+    return success;
+ }
+ 
+ // close a given transport
+ bool MBEDEndpoint::closeTransport(int index,char *key) {
+    this->logger()->log("Closing down %s Transport...", key);
+    if (this->m_transports[index] != NULL) delete this->m_transports[index];
+    return true;
+ }
+ 
+ // close down our transports
+ bool MBEDEndpoint::closeTransports() {
+     bool success = true;
+     
+     if (success) {
+         // close MQTT
+         success = this->closeTransport(MQTT_TRANSPORT,"MQTT");
+     }
+     
+     if (success) {
+         // close HTTP
+         success = this->closeTransport(HTTP_TRANSPORT,"HTTP");
+     }
+     
+     return success;
+ }
+ 
+ // close down our Ethernet 
+ bool MBEDEndpoint::closeEthernet() {
+     this->logger()->log("Closing down Ethernet...");
+     if (this->m_ethernet != NULL) this->m_ethernet->disconnect();
+     return true;
+ }
+ 
+ // min function
+ int MBEDEndpoint::min(int value1,int value2) {
+    if (value1 < value2) return value1;
+    return value2;
+ }
+ 
+ // get our error handler
+ ErrorHandler *MBEDEndpoint::logger() { return this->m_error_handler; }
+ 
+ // main running loop
+ void MBEDEndpoint::run() {
+     this->logger()->log("Endpoint Main Loop");
+     while(true) {
+         // sleep a bit
+         //this->logger()->log("Sleeping for a bit...");
+         wait_ms(MAIN_LOOP_SLEEP);
+         
+         // check for events 
+         //this->logger()->log("Processing Events...");
+         for(int i=0;i<NUM_TRANSPORTS;++i) this->m_transports[i]->checkAndProcess();
+         
+         // check for exit
+         //this->logger()->log("Checking for exit...");
+         this->logger()->checkForExit();
+     }
+}
+ 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MBEDEndpoint.h	Wed Mar 26 19:48:35 2014 +0000
@@ -0,0 +1,102 @@
+/* Copyright C2013 Doug Anson, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+#ifndef _MBED_ENDPOINT_H_
+#define _MBED_ENDPOINT_H_
+
+// Ethernet Interface
+#include "EthernetInterface.h"
+
+// ErrorHandler support
+#include "ErrorHandler.h"
+
+// MBED to IOC Resource Map
+#include "MBEDToIOCResourceMap.h"
+
+// Transport support
+#include "MQTTTransport.h"
+#include "IOCHTTPTransport.h"
+
+// Light Support
+#include "Light.h"
+
+// ResourceFactory Support
+#include "ResourceFactory.h"
+
+// Preferences Support
+#include "Preferences.h"
+  
+class MBEDEndpoint {
+    private:
+        EthernetInterface    *m_ethernet;                              // ethernet interface
+        ErrorHandler         *m_error_handler;                         // our error handler
+        Transport            *m_transports[NUM_TRANSPORTS];            // our transport
+        Light                *m_lights[NUM_LIGHTS];                    // our lights (at least 1)
+        char                  m_endpoint_name[LIGHT_NAME_LEN+1];       // our endpoint name (light[0])
+        MBEDToIOCResourceMap *m_map;                                   // IOC <--> MBED resource mapping
+        Preferences          *m_preferences;                           // preference support
+        char                  m_lcd_status[TEMP_BUFFER_LEN+1];         // LCD status buffer
+        char                  m_gw_address[PREFERENCE_VALUE_LEN+1];    // GW address buffer
+        int                   m_instance_id;                           // instance ID for this endpoint
+         
+    public:
+        MBEDEndpoint(ErrorHandler *error_handler,EthernetInterface *ethernet);
+       ~MBEDEndpoint();
+        ResourceFactory *initResourceFactory();
+        void run();
+        
+        int indexOfLight(char *name);
+        ResourceFactory *getResources(int index);
+        
+        bool loadEndpoints();
+        bool updateEndpoints();
+        bool updateEndpoints(int index);
+        
+        char *getEndpointName();
+        char *getGWAddress();
+        Preferences *preferences();
+        
+        char *getLCDStatus();
+        
+        int getInstanceID();
+                
+        MBEDToIOCResourceMap *getMap();
+    
+    protected:
+    
+    private:
+        void initPreferences();
+        void initGWAddress();
+        void initEndpointName();
+        bool initializeLights();
+        bool initializeTransport(int index,char *key,Transport *transport);
+        bool initializeTransports();
+        bool initializeEthernet(EthernetInterface *ethernet);
+        bool loadEndpoint(Light *light);
+        bool updateEndpoint(Light *light);
+        char *buildIOCPayload(char *data,int data_length,Light *light);
+        void saveIOCID(Light *light,char *data);
+        bool closeLights();
+        bool closeTransport(int index,char *key);
+        bool closeTransports();
+        bool closeEthernet(); 
+        ErrorHandler *logger(); 
+        int min(int value1, int value2);
+};
+
+#endif // _MBED_ENDPOINT_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTTransport.cpp	Wed Mar 26 19:48:35 2014 +0000
@@ -0,0 +1,468 @@
+/* Copyright C2013 Doug Anson, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+ #include "mbed.h"
+ #include "rtos.h"
+ 
+ #include "MQTTTransport.h"
+ 
+ // Endpoint Support
+ #include "MBEDEndpoint.h"
+ 
+ // EmulatedResourceFactory support
+ #include "EmulatedResourceFactory.h"
+ 
+ // Network mutex
+ extern Mutex *network_mutex;
+  
+ // our transmitt instance 
+ MQTTTransport *_mqtt_instance =  NULL;
+
+ // MQTT callback to handle received messages
+ void _mqtt_message_handler(char *topic,char *payload,unsigned int length) {
+    char buffer[MAX_MQTT_MESSAGE_LENGTH+1];
+    char rcv_topic[MQTT_IOC_TOPIC_LEN+1];
+    
+    memset(buffer,0,MAX_MQTT_MESSAGE_LENGTH+1);
+    memset(rcv_topic,0,MQTT_IOC_TOPIC_LEN+1);
+    memcpy(buffer,payload,length);
+    strcpy(rcv_topic,topic);
+    
+    if (_mqtt_instance != NULL) {
+        if (_mqtt_instance->isPongMessage(rcv_topic,buffer,length)) {
+            _mqtt_instance->processPongMessage(buffer,length);
+        }
+        else {
+            memset(buffer,0,MAX_MQTT_MESSAGE_LENGTH+1);
+            memset(rcv_topic,0,MQTT_IOC_TOPIC_LEN+1);
+            memcpy(buffer,payload,length);
+            strcpy(rcv_topic,topic);
+            _mqtt_instance->processMessage(_mqtt_instance->getEndpointNameFromTopic(rcv_topic),buffer,length);
+        }
+    }
+ }
+ 
+ // our MQTT client endpoint
+ PubSubClient _mqtt(MQTT_HOSTNAME,MQTT_HOSTPORT,_mqtt_message_handler);
+  
+ // default constructor
+ MQTTTransport::MQTTTransport(ErrorHandler *error_handler,void *endpoint,MBEDToIOCResourceMap *map) : Transport(error_handler,endpoint) {
+     this->m_mqtt = NULL;
+     _mqtt_instance = this;
+     this->m_map = map;
+     this->m_ping_counter = 1;
+     this->m_ping_countdown = MQTT_PING_COUNTDOWN;
+     this->initTopic();
+ }
+ 
+ // default destructor
+ MQTTTransport::~MQTTTransport() {
+     this->disconnect();
+ }
+  
+ // init our topic
+ void MQTTTransport::initTopic() {
+     MBEDEndpoint *endpoint = (MBEDEndpoint *)this->getEndpoint();
+     char *endpoint_name = endpoint->getEndpointName();
+     memset(this->m_topic,0,MQTT_IOC_TOPIC_LEN+1);
+     sprintf(this->m_topic,MQTT_IOC_TOPIC,endpoint_name);
+ }
+ 
+ // get our topic
+ char *MQTTTransport::getTopic() { return this->m_topic; }
+ 
+ // get the IOC <--> MBED resource map
+ MBEDToIOCResourceMap *MQTTTransport::getMap() { return this->m_map; }
+ 
+ // pull the endpoint name from the MQTT topic
+ char *MQTTTransport::getEndpointNameFromTopic(char *topic) {
+     if (topic != NULL) {
+         memset(this->m_endpoint_name,0,LIGHT_NAME_LEN+1);
+         char trash[MQTT_IOC_TOPIC_LEN+1];
+         char ep[MQTT_IOC_TOPIC_LEN+1];
+         memset(trash,0,MQTT_IOC_TOPIC_LEN+1);
+         memset(ep,0,MQTT_IOC_TOPIC_LEN+1);
+         bool done = false;
+         int length = 0; if (topic != NULL) length = strlen(topic);
+         for(int i=length-1;i>=0 && !done;--i) if (topic[i] == '/') { topic[i] = ' ' ; done = true; }
+         sscanf(topic,"%s%s",trash,ep);
+         //this->logger()->log("MQTT: Topic:[%s] trash:[%s] ep:[%s]",topic,trash,ep);
+         if (strlen(ep) > 0) {
+               if (strcmp(ep,MQTT_IOC_ALL_ENDPOINT) != 0) {
+                   // just insert the name and let the parser determine if its for us or not...
+                   strncpy(this->m_endpoint_name,ep,strlen(ep));
+               }
+               else {
+                   // this is a broadcast message - so we need to process it
+                   MBEDEndpoint *endpoint = (MBEDEndpoint *)this->getEndpoint();
+                   char *endpoint_name = endpoint->getEndpointName();
+                   strcpy(this->m_endpoint_name,endpoint_name);
+               }
+          }
+          //this->logger()->log("MQTT Topic (discovered): %s  Original: %s",this->m_endpoint_name,topic);
+          return this->m_endpoint_name;
+       }
+       //this->logger()->log("MQTT Topic (discovered): NULL  Original: %s",topic);
+       return NULL;
+ }
+ 
+ // process a MQTT Message
+ void MQTTTransport::processMessage(char *message_name,char *payload, unsigned int payload_length) {
+     char message_type[MQTT_PAYLOAD_SEGMENT_LEN+1];
+     char message_verb[MQTT_PAYLOAD_SEGMENT_LEN+1];
+     char message_value[MQTT_PAYLOAD_SEGMENT_LEN+1];
+     char message_opt[MQTT_PAYLOAD_SEGMENT_LEN+1];
+     
+     // initialize
+     memset(message_type,0,MQTT_PAYLOAD_SEGMENT_LEN+1);
+     memset(message_verb,0,MQTT_PAYLOAD_SEGMENT_LEN+1);
+     memset(message_value,0,MQTT_PAYLOAD_SEGMENT_LEN+1);
+     memset(message_opt,0,MQTT_PAYLOAD_SEGMENT_LEN+1);
+      
+     // get our endpoint
+     MBEDEndpoint *endpoint = (MBEDEndpoint *)this->getEndpoint();
+     char *endpoint_name = endpoint->getEndpointName();
+     
+     // DEBUG
+     //this->logger()->log("Endpoint:[%s] Target: [%s]",endpoint_name,message_name);
+
+     // only respond if its for our node
+     if (strcmp(endpoint_name,message_name) == 0) {                  
+         // format of the MQTT message:   message_type:verb|Parameter_X:value|keyword:optional_data  
+         char buffer[MAX_MQTT_MESSAGE_LENGTH+1];
+         memset(buffer,0,MAX_MQTT_MESSAGE_LENGTH+1); 
+         memcpy(buffer,payload,payload_length); 
+         int count = 0; for(int i=0;i<payload_length;++i) if (payload[i] == ':') ++count;
+         for(int i=0;i<payload_length;++i) {
+             if (buffer[i] == ':') {
+                 if (i < (payload_length-1)) buffer[i] = ' ';
+                 else buffer[i] = '\0';
+             }
+         }     
+         if (count == 1) sscanf(buffer,"%s%s",message_type,message_verb);
+         if (count == 2) sscanf(buffer,"%s%s%s",message_type,message_verb,message_value);
+         if (count == 3) sscanf(buffer,"%s%s%s%s",message_type,message_verb,message_value,message_opt);
+                        
+         // DEBUG
+         //this->logger()->log("Raw Payload: %s, length: %d",payload,payload_length);
+         //this->logger()->log("Buffer: %s, length: %d",buffer,strlen(buffer));
+         //this->logger()->log("Parsed Payload: Type: [%s] Name: [%s] Verb: [%s] Value: [%s]",message_type,message_name,message_verb,message_value);
+                          
+         // load endpoints
+         if (message_type != NULL && strcmp(message_type,IOC_ENDPOINT_VERB) == 0) {                 // Endpoint
+             if (message_verb != NULL && strcmp(message_verb,IOC_REQUEST_LOAD_ALL_VERB) == 0) {     // load
+                 if (message_value != NULL && strcmp(message_value,IOC_ENDPOINT_ALL_VERB) == 0) {   // all
+                    // load up our endpoints
+                    endpoint->loadEndpoints();
+                    endpoint->updateEndpoints();
+                 }
+                 else if (message_value != NULL && strcmp(message_value,this->m_endpoint_name) == 0) {
+                    // load up our endpoints (us only)
+                    endpoint->loadEndpoints();
+                    endpoint->updateEndpoints();
+                 }
+             }
+             
+             else if (message_verb != NULL && strcmp(message_verb,IOC_REQUEST_UPDATE_ALL_VERB) == 0) {  // update
+                 if (message_value != NULL && strcmp(message_value,IOC_ENDPOINT_ALL_VERB) == 0) {       // all
+                     // update our endpoints
+                     endpoint->updateEndpoints();
+                 }
+                 else {
+                     // update just our endpoint
+                     int index = -1;
+                     if (message_name != NULL) {
+                         index = endpoint->indexOfLight((char *)message_name);
+                         if (index >= 0) {
+                             if (message_verb != NULL && strcmp(message_verb,IOC_REQUEST_UPDATE_ALL_VERB) == 0) {
+                                // update our endpoint
+                                endpoint->updateEndpoints(index);
+                             }
+                         }
+                     }
+                 }
+             }
+         }
+         
+         // change a resource value
+         if (message_type != NULL && strcmp(message_type,IOC_CHANGE_VERB) == 0) {
+              if (message_name != NULL) {
+                 // destined for our lights?
+                 int index = endpoint->indexOfLight((char *)message_name);
+                 if (index >= 0) {
+                     if (message_verb != NULL) {
+                         // map the parameter to one of ours
+                         char *mapped_resource = this->mapIOCResourceToEndpointResource((char *)message_verb);
+                         if (mapped_resource != NULL) {
+                             if (message_value != NULL) {
+                                 EmulatedResourceFactory *factory = (EmulatedResourceFactory *)endpoint->getResources(index);
+                                 bool success = factory->setResourceValue(mapped_resource,message_value);
+                                 
+                                 // end the resource value back over MQTT
+                                 this->sendResult(message_name,message_verb,message_value,success);
+                             }
+                         }
+                     }
+                 }
+             }
+         }
+         
+         // get a resource value
+         if (message_type != NULL && strcmp(message_type,IOC_REQUEST_VALUE_VERB) == 0) {
+             if (message_name != NULL) {
+                 // destined for our lights?
+                 int index = endpoint->indexOfLight((char *)message_name);
+                 if (index >= 0) {
+                     if (message_verb != NULL) {
+                         // map the parameter to one of ours
+                         char *mapped_resource = this->mapIOCResourceToEndpointResource((char *)message_verb);
+                         if (mapped_resource != NULL) {
+                             EmulatedResourceFactory *factory = (EmulatedResourceFactory *)endpoint->getResources(index);
+                             strcpy(message_value,factory->getResourceValue((char *)mapped_resource));
+                             bool success = false; if (message_value != NULL) success = true;
+                             
+                             // log resource get
+                             if (success) this->logger()->log("Resource: %s (%s) Value: %s",message_verb,mapped_resource,message_value);
+                             
+                             // end the resource value back over MQTT
+                             this->sendResult(message_name,message_verb,message_value,success);
+                         }
+                     }
+                 }
+             }
+         }
+     }
+     else {
+         // message not bound for our node
+         //this->logger()->log("MQTT Message: %s not for us: %s... ignoring...",payload,endpoint_name);
+         ;
+     }     
+ }
+ 
+ // send result back to MQTT
+ void MQTTTransport::sendResult(char *endpoint_name,char *resource_name,char *value,bool success) {
+     if (this->m_connected == true) {
+         // send the response back to MQTT
+         this->logger()->log("Sending Response back to MQTT...");
+         char message[MAX_MQTT_MESSAGE_LENGTH+1];
+         memset(message,0,MAX_MQTT_MESSAGE_LENGTH+1);
+         char *str_success = IOC_RESPONSE_OK; if (!success) str_success = IOC_RESPONSE_FAILED;
+         sprintf(message,IOC_RESPONSE_TEMPLATE,IOC_RESPONSE_VERB,endpoint_name,resource_name,value,str_success);
+         if (network_mutex != NULL) network_mutex->lock();
+         bool sent = this->m_mqtt->publish(this->getTopic(),message,strlen(message));
+         if (network_mutex != NULL) network_mutex->unlock();
+         if (sent) {
+             this->logger()->log("Result sent successfully");
+             this->logger()->blinkTransportTxLED();
+         }
+         else {
+             this->logger()->log("Result send FAILED");
+         }
+     }
+     else {
+         // unable to send the response 
+         this->logger()->log("Unable to send response back to MQTT. Not connected.");
+     }
+ }
+ 
+ char *MQTTTransport::mapIOCResourceToEndpointResource(char *ioc_name) { return this->getMap()->iocNameToEndpointName(ioc_name); }
+ 
+ char *MQTTTransport::makeID(char *id_template,char *buffer) {
+     MBEDEndpoint *endpoint = (MBEDEndpoint *)this->getEndpoint();
+     int instance_id = rand()%100;
+     if (endpoint != NULL) instance_id = endpoint->getInstanceID();
+     srand(time(0));
+     srand(rand());
+     sprintf(buffer,id_template,rand()%MQTT_MAXID_VALUE,instance_id);
+     return buffer;
+ }
+ 
+ // is this message a PONG message?
+ bool MQTTTransport::isPongMessage(char *topic,char *payload,int payload_length) {
+     bool isPong = false;
+     char verb[MQTT_PING_VERB_LEN+1];
+     char end[MQTT_PING_VERB_LEN+1];
+     int counter = 0;
+     
+     // clean
+     memset(verb,0,MQTT_PING_VERB_LEN+1);
+     memset(end,0,MQTT_PING_VERB_LEN+1);
+         
+     // make sure this is for us...
+     char *topic_ep_name = this->getEndpointNameFromTopic(topic);
+     if (topic_ep_name != NULL && strcmp(topic_ep_name,this->m_endpoint_name) == 0) {
+         // parse the payload
+         for(int i=0;payload != NULL && i<payload_length;++i) if (payload[i] == ':') payload[i] = ' ';
+         sscanf(payload,"%s%d",verb,&counter);
+         
+         // check the contents to make sure its for us...
+         //this->logger()->log("isPongMessage: verb: %s counter %d ping_counter: %d",verb,counter,this->m_ping_counter);
+         if (strcmp(verb,"pong") == 0 && counter == this->m_ping_counter) {     
+             // its a PONG message to our PING... 
+             isPong = true;
+         }
+     }
+     
+     // return isPong status
+     return isPong;
+ }
+ 
+ 
+ // process this PONG message
+ void MQTTTransport::processPongMessage(char *payload,int payload_length) {
+     // DEBUG
+     //this->logger()->log("Received PONG: counter=%d",this->m_ping_counter);
+             
+     // simply increment the counter
+     ++this->m_ping_counter;
+     
+     // reset counter if maxed 
+     if (this->m_ping_counter >= MQTT_MAX_COUNTER) this->m_ping_counter = 1;
+ }
+ 
+ // send a PING message
+ bool MQTTTransport::sendPingMessage() {
+     bool sent = false;
+     char message[MAX_MQTT_MESSAGE_LENGTH+1];
+     
+     // initialize...
+     memset(message,0,MAX_MQTT_MESSAGE_LENGTH+1);
+     
+     // build message
+     sprintf(message,"ping:%s:%d:",this->m_endpoint_name,this->m_ping_counter);
+     
+     // send the message over the ping/pong topic
+     //this->logger()->log("Sending PING: counter=%d",this->m_ping_counter);
+     if (network_mutex != NULL) network_mutex->lock();
+     sent = this->m_mqtt->publish(MQTT_PING_SEND_TOPIC,message,strlen(message));
+     if (network_mutex != NULL) network_mutex->unlock();
+     if (sent) {
+         // send succeeded
+         //this->logger()->log("PING %d sent successfully",this->m_ping_counter);
+         this->logger()->blinkTransportTxLED();
+         
+         // wait for 1 second
+         wait_ms(1000);
+     }
+     else {
+         // send failed! - reconnect
+         this->logger()->log("PING send %d FAILED... (re)connecting...",this->m_ping_counter);
+         
+         // attempt reconnect
+         this->logger()->log("PING send failed - re-connecting MQTT...");
+         this->disconnect();
+         sent = this->connect();
+         if (sent) this->logger()->log("PING %d: MQTT reconnection successful...",this->m_ping_counter);
+         else this->logger()->log("PING %d: resend failed giving up...",this->m_ping_counter);
+     }
+     
+     // return our status
+     return sent;
+ }
+ 
+ // connect up MQTT
+ bool MQTTTransport::connect() {
+     if (network_mutex != NULL) network_mutex->lock();
+     char mqtt_id[MQTT_ENDPOINT_IDLEN+1];
+     memset(mqtt_id,0,(MQTT_ENDPOINT_IDLEN+1));
+     if (this->m_connected == false) {
+         this->logger()->log("MQTT Init: %s:%d...",MQTT_HOSTNAME,MQTT_HOSTPORT);
+         this->m_mqtt = &_mqtt;
+         if (this->m_mqtt != NULL) {
+             char *id = this->makeID(MQTT_ENDPOINT_ID,mqtt_id);
+             this->logger()->log("MQTT Connect: ID: %s...",id);
+             if (this->m_mqtt->connect(id)) {
+                 this->logger()->log("MQTT Subscribe: Topic: %s...",this->getTopic());
+                 if (this->m_mqtt->subscribe(this->getTopic())) {
+                    if (this->m_mqtt->subscribe(MQTT_IOC_ALL_TOPIC)) {
+                        this->logger()->log("MQTT CONNECTED.");
+                        this->m_connected = true;
+                    }
+                    else {
+                        this->logger()->log("MQTT Subscribe: Topic: %s FAILED",MQTT_IOC_ALL_TOPIC);
+                        this->logger()->turnLEDRed();
+                        this->m_connected = false;
+                    }
+                 }
+                 else {
+                     this->logger()->log("MQTT Subscribe: Topic: %s FAILED",this->getTopic());
+                     this->logger()->turnLEDRed();
+                     this->m_connected = false;
+                 }
+             }
+             else {
+                 this->logger()->log("MQTT Connect: ID: %s FAILED",id);
+                 this->logger()->turnLEDRed();
+                 this->m_connected = false;
+             }
+         }
+         else {
+             this->logger()->log("MQTT Unable to allocate new instance");
+             this->logger()->turnLEDRed();
+             this->m_connected = false;
+         }
+     }
+     else {
+         this->logger()->log("MQTT already connected (OK)");
+     }
+     if (network_mutex != NULL) network_mutex->unlock();
+     return this->m_connected;
+ }
+ 
+ // disconnect from MQTT
+ bool MQTTTransport::disconnect() {
+     if (this->m_mqtt != NULL) {
+         this->logger()->log("MQTT Unsubscribing from: %s...",this->getTopic());
+         if (network_mutex != NULL) network_mutex->lock();
+         this->m_mqtt->unsubscribe(this->getTopic());
+         if (network_mutex != NULL) network_mutex->unlock();
+         this->logger()->log("MQTT Disconnecting...");
+         this->m_mqtt->disconnect();
+     }
+     else {
+         this->logger()->log("MQTT already disconnected (OK)");
+     }
+     this->m_connected = false;
+     return true;
+ }
+ 
+ // check transport and process stuff
+ void MQTTTransport::checkAndProcess() {
+     // process any MQTT messages
+     if (this->m_mqtt != NULL && this->m_connected == true) {
+         if (network_mutex != NULL) network_mutex->lock();
+         bool connected = this->m_mqtt->loop();
+         if (network_mutex != NULL) network_mutex->unlock();
+         if (connected) {
+            this->logger()->blinkTransportRxLED();
+         }
+         else {
+            this->logger()->log("Attempting reconnection to MQTT in checkAndProcess...");
+            this->disconnect();
+            this->connect();
+         }
+     }
+     
+     // send a PING if time for it
+     --this->m_ping_countdown;
+     if (this->m_ping_countdown <= 0) {
+         //this->logger()->log("MQTT: Sending PING...");
+         this->m_ping_countdown = MQTT_PING_COUNTDOWN;
+         this->sendPingMessage();
+     }
+ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTTransport.h	Wed Mar 26 19:48:35 2014 +0000
@@ -0,0 +1,67 @@
+/* Copyright C2013 Doug Anson, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+#ifndef ___MQTTTRANSPORT_H_
+#define ___MQTTTRANSPORT_H_
+
+// Base Class
+#include "Transport.h"
+
+// MQTT Support
+#include "PubSubClient.h"
+
+// MBED to IOC Resource Map
+#include "MBEDToIOCResourceMap.h"
+
+class MQTTTransport : public Transport {
+    private:
+        PubSubClient         *m_mqtt;
+        MBEDToIOCResourceMap *m_map;
+        char                  m_topic[MQTT_IOC_TOPIC_LEN+1];
+        char                  m_endpoint_name[LIGHT_NAME_LEN+1];
+        int                   m_ping_counter;
+        int                   m_ping_countdown;
+        
+    public:
+        MQTTTransport(ErrorHandler *error_handler,void *endpoint,MBEDToIOCResourceMap *map);
+        virtual ~MQTTTransport();
+       
+        void processMessage(char *message_name,char *payload, unsigned int payload_length);
+    
+        virtual bool connect();
+        virtual bool disconnect();
+        
+        virtual void checkAndProcess();
+ 
+        char *getEndpointNameFromTopic(char *topic);
+        
+        bool isPongMessage(char *topic,char *payload,int payload_length);
+        void processPongMessage(char *payload,int payload_length);
+        
+    private:
+        char *makeID(char *id_template, char *buffer);
+        void initTopic();
+        char *getTopic();
+        char *mapIOCResourceToEndpointResource(char *ioc_name);
+        void sendResult(char *endpoint_name,char *parameter_name,char *value,bool success);
+        MBEDToIOCResourceMap *getMap();
+        
+        bool sendPingMessage();
+};
+
+#endif // ___MQTTTRANSPORT_H_
\ No newline at end of file