MBED_DEMOS / Mbed 2 deprecated mbed_mqtt_endpoint_nxp

Dependencies:   C12832_lcd EthernetInterface StatusReporter LM75B MQTT-ansond endpoint_core endpoint_mqtt mbed-rtos mbed

Committer:
ansond
Date:
Thu Feb 27 04:09:39 2014 +0000
Revision:
14:0a6497a380a4
Parent:
13:25448d92c205
Child:
15:e44d75d95b38
updates

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:ae2a45502448 1 /* Copyright C2013 Doug Anson, MIT License
ansond 0:ae2a45502448 2 *
ansond 0:ae2a45502448 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
ansond 0:ae2a45502448 4 * and associated documentation files the "Software", to deal in the Software without restriction,
ansond 0:ae2a45502448 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
ansond 0:ae2a45502448 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
ansond 0:ae2a45502448 7 * furnished to do so, subject to the following conditions:
ansond 0:ae2a45502448 8 *
ansond 0:ae2a45502448 9 * The above copyright notice and this permission notice shall be included in all copies or
ansond 0:ae2a45502448 10 * substantial portions of the Software.
ansond 0:ae2a45502448 11 *
ansond 0:ae2a45502448 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
ansond 0:ae2a45502448 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
ansond 0:ae2a45502448 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
ansond 0:ae2a45502448 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
ansond 0:ae2a45502448 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
ansond 0:ae2a45502448 17 */
ansond 0:ae2a45502448 18
ansond 0:ae2a45502448 19 #include "MQTTTransport.h"
ansond 0:ae2a45502448 20 #include "MBEDEndpoint.h"
ansond 0:ae2a45502448 21
ansond 0:ae2a45502448 22 // MBED Light support
ansond 0:ae2a45502448 23 #include "MBEDLight.h"
ansond 0:ae2a45502448 24
ansond 2:90a84a216c58 25 // Emulated Resource Factory
ansond 2:90a84a216c58 26 #include "EmulatedResourceFactory.h"
ansond 2:90a84a216c58 27
ansond 0:ae2a45502448 28 // Emulated Actions we can act on
ansond 0:ae2a45502448 29 #include "EmulatedLightDimmerAction.h"
ansond 0:ae2a45502448 30 #include "EmulatedLightSwitchAction.h"
ansond 7:f570eb3f38cd 31
ansond 13:25448d92c205 32 // JSON serialization support
ansond 13:25448d92c205 33 #include "MbedJSONValue.h"
ansond 13:25448d92c205 34
ansond 7:f570eb3f38cd 35 // shutdown endpoint reference
ansond 7:f570eb3f38cd 36 extern void closedown(int code);
ansond 0:ae2a45502448 37
ansond 0:ae2a45502448 38 // default constructor
ansond 0:ae2a45502448 39 MBEDEndpoint::MBEDEndpoint(ErrorHandler *error_handler,EthernetInterface *ethernet) {
ansond 10:748fc7052e61 40 this->m_ioc_id = -1;
ansond 0:ae2a45502448 41 bool success = true;
ansond 0:ae2a45502448 42 for(int i=0;i<NUM_TRANSPORTS;++i) this->m_transports[i] = NULL;
ansond 0:ae2a45502448 43 this->m_error_handler = error_handler;
ansond 0:ae2a45502448 44 this->logger()->log(ENDPOINT_VERSION_ANNOUNCE);
ansond 0:ae2a45502448 45 if (success) this->logger()->turnLEDBlue();
ansond 0:ae2a45502448 46 if (success) success = this->initializeEthernet(ethernet);
ansond 0:ae2a45502448 47 if (success) this->logger()->turnLEDYellow();
ansond 8:45f9a920e82c 48 if (success) success = this->initializeLights();
ansond 0:ae2a45502448 49 if (success) success = this->initializeTransports();
ansond 0:ae2a45502448 50 if (success) this->logger()->turnLEDGreen();
ansond 7:f570eb3f38cd 51 if (!success) closedown(2);
ansond 0:ae2a45502448 52 }
ansond 0:ae2a45502448 53
ansond 0:ae2a45502448 54 // default destructor
ansond 0:ae2a45502448 55 MBEDEndpoint::~MBEDEndpoint() {
ansond 0:ae2a45502448 56 bool success = true;
ansond 0:ae2a45502448 57 if (success) this->logger()->turnLEDYellow();
ansond 0:ae2a45502448 58 if (success) success = this->closeLights();
ansond 0:ae2a45502448 59 if (success) success = this->closeTransports();
ansond 0:ae2a45502448 60 if (success) success = this->closeEthernet();
ansond 0:ae2a45502448 61 if (success) this->logger()->turnLEDBlue();
ansond 0:ae2a45502448 62 }
ansond 0:ae2a45502448 63
ansond 10:748fc7052e61 64 // set the IOC ID
ansond 10:748fc7052e61 65 void MBEDEndpoint::setIOCID(int ioc_id) { this->m_ioc_id = ioc_id; }
ansond 10:748fc7052e61 66
ansond 10:748fc7052e61 67 // get the IOC ID
ansond 10:748fc7052e61 68 int MBEDEndpoint::getIOCID() { return this->m_ioc_id; }
ansond 10:748fc7052e61 69
ansond 0:ae2a45502448 70 // initialize the Lights
ansond 0:ae2a45502448 71 bool MBEDEndpoint::initializeLights() {
ansond 0:ae2a45502448 72 this->logger()->log("Initializing Lights...");
ansond 0:ae2a45502448 73 for(int i=0;i<NUM_LIGHTS;++i) {
ansond 0:ae2a45502448 74 this->m_lights[i] = new MBEDLight(this->logger(),this->m_transports,i+1,this);
ansond 0:ae2a45502448 75 this->m_lights[i]->setDimmerAction(new EmulatedLightDimmerAction(this->logger(),this->m_lights[i]));
ansond 0:ae2a45502448 76 this->m_lights[i]->setSwitchAction(new EmulatedLightSwitchAction(this->logger(),this->m_lights[i]));
ansond 0:ae2a45502448 77 }
ansond 0:ae2a45502448 78 return true;
ansond 0:ae2a45502448 79 }
ansond 0:ae2a45502448 80
ansond 0:ae2a45502448 81 // does the input name match any of our light resources?
ansond 0:ae2a45502448 82 int MBEDEndpoint::indexOfLight(char *name) {
ansond 0:ae2a45502448 83 bool found = false;
ansond 0:ae2a45502448 84 int index = -1;
ansond 0:ae2a45502448 85
ansond 0:ae2a45502448 86 for(int i=0;i<NUM_LIGHTS && !found;++i) {
ansond 0:ae2a45502448 87 if (strcmp(this->m_lights[i]->getName(),name) == 0) {
ansond 0:ae2a45502448 88 found = true;
ansond 0:ae2a45502448 89 index = i;
ansond 0:ae2a45502448 90 }
ansond 0:ae2a45502448 91 }
ansond 0:ae2a45502448 92
ansond 0:ae2a45502448 93 return index;
ansond 0:ae2a45502448 94 }
ansond 0:ae2a45502448 95
ansond 0:ae2a45502448 96 // get a specific resources
ansond 0:ae2a45502448 97 ResourceFactory *MBEDEndpoint::getResources(int index) {
ansond 0:ae2a45502448 98 if (index >= 0 && index < NUM_LIGHTS) return this->m_lights[index]->resources();
ansond 0:ae2a45502448 99 return NULL;
ansond 0:ae2a45502448 100 }
ansond 0:ae2a45502448 101
ansond 0:ae2a45502448 102 // initialize our ResourceFactory
ansond 2:90a84a216c58 103 ResourceFactory *MBEDEndpoint::initResourceFactory() { return new EmulatedResourceFactory(this->logger()); }
ansond 2:90a84a216c58 104
ansond 2:90a84a216c58 105 // get our endpoint name (first light name)
ansond 6:34c07e145caa 106 char *MBEDEndpoint::getEndpointName() { return this->m_lights[0]->getName(); }
ansond 0:ae2a45502448 107
ansond 0:ae2a45502448 108 // initialize a specific transport
ansond 0:ae2a45502448 109 bool MBEDEndpoint::initializeTransport(int index,char *key,Transport *transport) {
ansond 0:ae2a45502448 110 bool success = false;
ansond 0:ae2a45502448 111 if (this->m_transports[index] == NULL) {
ansond 0:ae2a45502448 112 this->logger()->log("Initializing %s Transport...", key);
ansond 0:ae2a45502448 113 this->m_transports[index] = transport;
ansond 0:ae2a45502448 114 if (this->m_transports[index] != NULL) success = this->m_transports[index]->connect();
ansond 0:ae2a45502448 115 }
ansond 0:ae2a45502448 116 else {
ansond 0:ae2a45502448 117 this->logger()->log("%s already connected (OK)...", key);
ansond 0:ae2a45502448 118 success = true;
ansond 0:ae2a45502448 119 }
ansond 0:ae2a45502448 120 return success;
ansond 0:ae2a45502448 121 }
ansond 0:ae2a45502448 122
ansond 0:ae2a45502448 123 // initialize our transports
ansond 0:ae2a45502448 124 bool MBEDEndpoint::initializeTransports() {
ansond 0:ae2a45502448 125 bool success = true;
ansond 0:ae2a45502448 126
ansond 0:ae2a45502448 127 if (success == true) {
ansond 0:ae2a45502448 128 // MQTT Initialization
ansond 7:f570eb3f38cd 129 success = this->initializeTransport(MQTT_TRANSPORT,"MQTT",new MQTTTransport(this->m_error_handler,this));
ansond 0:ae2a45502448 130 }
ansond 0:ae2a45502448 131
ansond 0:ae2a45502448 132 if (success == true) {
ansond 0:ae2a45502448 133 // HTTP Initialization
ansond 7:f570eb3f38cd 134 success = this->initializeTransport(HTTP_TRANSPORT,"HTTP",new HTTPTransport(this->m_error_handler,this));
ansond 0:ae2a45502448 135 }
ansond 0:ae2a45502448 136 return success;
ansond 0:ae2a45502448 137 }
ansond 0:ae2a45502448 138
ansond 0:ae2a45502448 139 // initialize our Ethernet
ansond 0:ae2a45502448 140 bool MBEDEndpoint::initializeEthernet(EthernetInterface *ethernet) {
ansond 0:ae2a45502448 141 bool success = false;
ansond 0:ae2a45502448 142 this->m_ethernet = ethernet;
ansond 0:ae2a45502448 143 if (this->m_ethernet != NULL) {
ansond 0:ae2a45502448 144 this->logger()->log("Initializing Ethernet...");
ansond 0:ae2a45502448 145
ansond 0:ae2a45502448 146 // connect up ethernet
ansond 0:ae2a45502448 147 this->m_ethernet->init();
ansond 0:ae2a45502448 148 this->m_ethernet->connect();
ansond 0:ae2a45502448 149
ansond 0:ae2a45502448 150 // display our IP address
ansond 0:ae2a45502448 151 char *ipaddr = this->m_ethernet->getIPAddress();
ansond 0:ae2a45502448 152 if (ipaddr != NULL && strlen(ipaddr) > 0) {
ansond 0:ae2a45502448 153 this->logger()->log("IPAddress: %s",this->m_ethernet->getIPAddress());
ansond 0:ae2a45502448 154 success = true;
ansond 0:ae2a45502448 155 }
ansond 0:ae2a45502448 156 else {
ansond 0:ae2a45502448 157 this->logger()->log("Ethernet Not Connected...");
ansond 0:ae2a45502448 158 success = false;
ansond 0:ae2a45502448 159 }
ansond 0:ae2a45502448 160 }
ansond 0:ae2a45502448 161 else {
ansond 0:ae2a45502448 162 this->logger()->log("No Ethernet instance found");
ansond 0:ae2a45502448 163 success = false;
ansond 0:ae2a45502448 164 }
ansond 0:ae2a45502448 165 return success;
ansond 0:ae2a45502448 166 }
ansond 0:ae2a45502448 167
ansond 13:25448d92c205 168 // load up all endpoints into the IOC
ansond 13:25448d92c205 169 bool MBEDEndpoint::loadEndpoints() {
ansond 13:25448d92c205 170 bool success = true;
ansond 13:25448d92c205 171 for(int i=0;i<NUM_LIGHTS && success;++i) success = this->loadEndpoint(this->m_lights[i]);
ansond 13:25448d92c205 172 return success;
ansond 13:25448d92c205 173 }
ansond 13:25448d92c205 174
ansond 0:ae2a45502448 175 // load up our endpoint to the IOC
ansond 13:25448d92c205 176 bool MBEDEndpoint::loadEndpoint(Light *light) {
ansond 11:59ee476fda24 177 bool success = false;
ansond 11:59ee476fda24 178 char result[IOC_RESULT_LEN+1];
ansond 11:59ee476fda24 179 char payload[IOC_PAYLOAD_LEN+1];
ansond 11:59ee476fda24 180
ansond 11:59ee476fda24 181 // initialize
ansond 11:59ee476fda24 182 memset(result,0,IOC_RESULT_LEN+1);
ansond 12:952dce085876 183 memset(payload,0,IOC_PAYLOAD_LEN+1);
ansond 12:952dce085876 184
ansond 11:59ee476fda24 185 // build the payload
ansond 14:0a6497a380a4 186 char *data = this->buildIOCPayload(payload,IOC_PAYLOAD_LEN,light);
ansond 11:59ee476fda24 187
ansond 11:59ee476fda24 188 // issue the request
ansond 12:952dce085876 189 success = this->m_transports[LOAD_TRANSPORT]->loadEndpoint((char *)payload,strlen(payload),(char *)result,IOC_RESULT_LEN);
ansond 11:59ee476fda24 190
ansond 11:59ee476fda24 191 // update the IOC ID if found
ansond 11:59ee476fda24 192 if (success) this->saveIOCID(result);
ansond 11:59ee476fda24 193
ansond 11:59ee476fda24 194 // return our status
ansond 11:59ee476fda24 195 return success;
ansond 11:59ee476fda24 196 }
ansond 0:ae2a45502448 197
ansond 13:25448d92c205 198 // update all endpoints to the IOC
ansond 13:25448d92c205 199 bool MBEDEndpoint::updateEndpoints() {
ansond 13:25448d92c205 200 bool success = true;
ansond 13:25448d92c205 201 for(int i=0;i<NUM_LIGHTS && success;++i) success = this->updateEndpoints(i);
ansond 13:25448d92c205 202 return success;
ansond 13:25448d92c205 203 }
ansond 13:25448d92c205 204
ansond 13:25448d92c205 205 // update all endpoints to the IOC
ansond 13:25448d92c205 206 bool MBEDEndpoint::updateEndpoints(int index) {
ansond 13:25448d92c205 207 if (index >= 0 && index < NUM_LIGHTS) return this->updateEndpoint(this->m_lights[index]);
ansond 13:25448d92c205 208 return false;
ansond 13:25448d92c205 209 }
ansond 13:25448d92c205 210
ansond 0:ae2a45502448 211 // update our endpoint with the IOC
ansond 13:25448d92c205 212 bool MBEDEndpoint::updateEndpoint(Light *light) {
ansond 11:59ee476fda24 213 bool success = false;
ansond 11:59ee476fda24 214 char result[IOC_RESULT_LEN+1];
ansond 11:59ee476fda24 215 char payload[IOC_PAYLOAD_LEN+1];
ansond 11:59ee476fda24 216
ansond 11:59ee476fda24 217 // initialize
ansond 11:59ee476fda24 218 memset(result,0,IOC_RESULT_LEN+1);
ansond 12:952dce085876 219 memset(payload,0,IOC_PAYLOAD_LEN+1);
ansond 12:952dce085876 220
ansond 11:59ee476fda24 221 // build the payload
ansond 14:0a6497a380a4 222 char *data = this->buildIOCPayload(payload,IOC_PAYLOAD_LEN,light);
ansond 11:59ee476fda24 223
ansond 11:59ee476fda24 224 // issue the request
ansond 12:952dce085876 225 success = this->m_transports[LOAD_TRANSPORT]->updateEndpoint(this->getIOCID(),(char *)payload,strlen(payload),(char *)result,IOC_RESULT_LEN);
ansond 11:59ee476fda24 226
ansond 11:59ee476fda24 227 // return our status
ansond 11:59ee476fda24 228 return success;
ansond 11:59ee476fda24 229 }
ansond 11:59ee476fda24 230
ansond 11:59ee476fda24 231 // build out the Payload
ansond 13:25448d92c205 232 char *MBEDEndpoint::buildIOCPayload(char *data,int data_length,Light *light) {
ansond 11:59ee476fda24 233 // construct the payload for Load/Updates
ansond 13:25448d92c205 234 ResourceFactory *factory = light->getResourceFactory();
ansond 13:25448d92c205 235 MBEDToIOCResourceMap *map = new MBEDToIOCResourceMap(this->logger());
ansond 13:25448d92c205 236
ansond 13:25448d92c205 237 // JSON factory
ansond 13:25448d92c205 238 MbedJSONValue json;
ansond 13:25448d92c205 239
ansond 13:25448d92c205 240 // loop through the resources and build a JSON representation for the payload
ansond 13:25448d92c205 241 for(int i=0;i<factory->numResources();++i) {
ansond 13:25448d92c205 242 // get the ith resource
ansond 13:25448d92c205 243 Resource *resource = factory->getResource(i);
ansond 13:25448d92c205 244
ansond 13:25448d92c205 245 // add to the JSON payload
ansond 13:25448d92c205 246 json[map->endpointNameToIOCName(resource->getName())] = resource->getValue();
ansond 13:25448d92c205 247 }
ansond 13:25448d92c205 248
ansond 13:25448d92c205 249 // now convert to JSON
ansond 13:25448d92c205 250 std::string str_json = json.serialize();
ansond 13:25448d92c205 251
ansond 13:25448d92c205 252 // copy over to the buffer
ansond 13:25448d92c205 253 strncpy(data,str_json.c_str(),this->min(str_json.length(),data_length));
ansond 13:25448d92c205 254
ansond 13:25448d92c205 255 // clean up
ansond 13:25448d92c205 256 if (map != NULL) delete map;
ansond 13:25448d92c205 257
ansond 13:25448d92c205 258 // DEBUG
ansond 13:25448d92c205 259 this->logger()->log("Loading Payload: %s",data);
ansond 11:59ee476fda24 260
ansond 11:59ee476fda24 261 // return the payload
ansond 12:952dce085876 262 return data;
ansond 11:59ee476fda24 263 }
ansond 11:59ee476fda24 264
ansond 11:59ee476fda24 265 // save the IOC ID
ansond 13:25448d92c205 266 void MBEDEndpoint::saveIOCID(char *json) {
ansond 13:25448d92c205 267 // JSON factory
ansond 13:25448d92c205 268 MbedJSONValue parser;
ansond 11:59ee476fda24 269
ansond 13:25448d92c205 270 // parse the result
ansond 13:25448d92c205 271 parse(parser,json);
ansond 13:25448d92c205 272
ansond 13:25448d92c205 273 // look for the ID element specifically
ansond 13:25448d92c205 274 int ioc_id = parser[IOC_REPONSE_ID_KEY].get<int>();
ansond 11:59ee476fda24 275
ansond 11:59ee476fda24 276 // save the IOC ID
ansond 11:59ee476fda24 277 if (ioc_id > 0) this->setIOCID(ioc_id);
ansond 11:59ee476fda24 278 }
ansond 0:ae2a45502448 279
ansond 0:ae2a45502448 280 // close down the Lights
ansond 0:ae2a45502448 281 bool MBEDEndpoint::closeLights() {
ansond 0:ae2a45502448 282 bool success = true;
ansond 0:ae2a45502448 283 this->logger()->log("Closing down Lights...");
ansond 0:ae2a45502448 284 return success;
ansond 0:ae2a45502448 285 }
ansond 0:ae2a45502448 286
ansond 0:ae2a45502448 287 // close a given transport
ansond 0:ae2a45502448 288 bool MBEDEndpoint::closeTransport(int index,char *key) {
ansond 0:ae2a45502448 289 this->logger()->log("Closing down %s Transport...", key);
ansond 0:ae2a45502448 290 if (this->m_transports[index] != NULL) delete this->m_transports[index];
ansond 0:ae2a45502448 291 return true;
ansond 0:ae2a45502448 292 }
ansond 0:ae2a45502448 293
ansond 0:ae2a45502448 294 // close down our transports
ansond 0:ae2a45502448 295 bool MBEDEndpoint::closeTransports() {
ansond 0:ae2a45502448 296 bool success = true;
ansond 0:ae2a45502448 297
ansond 0:ae2a45502448 298 if (success) {
ansond 0:ae2a45502448 299 // close MQTT
ansond 0:ae2a45502448 300 success = this->closeTransport(MQTT_TRANSPORT,"MQTT");
ansond 0:ae2a45502448 301 }
ansond 0:ae2a45502448 302
ansond 0:ae2a45502448 303 if (success) {
ansond 0:ae2a45502448 304 // close HTTP
ansond 0:ae2a45502448 305 success = this->closeTransport(HTTP_TRANSPORT,"HTTP");
ansond 0:ae2a45502448 306 }
ansond 0:ae2a45502448 307
ansond 0:ae2a45502448 308 return success;
ansond 0:ae2a45502448 309 }
ansond 0:ae2a45502448 310
ansond 0:ae2a45502448 311 // close down our Ethernet
ansond 0:ae2a45502448 312 bool MBEDEndpoint::closeEthernet() {
ansond 0:ae2a45502448 313 this->logger()->log("Closing down Ethernet...");
ansond 0:ae2a45502448 314 if (this->m_ethernet != NULL) this->m_ethernet->disconnect();
ansond 0:ae2a45502448 315 return true;
ansond 0:ae2a45502448 316 }
ansond 0:ae2a45502448 317
ansond 13:25448d92c205 318 // min function
ansond 13:25448d92c205 319 int MBEDEndpoint::min(int value1,int value2) {
ansond 13:25448d92c205 320 if (value1 < value2) return value1;
ansond 13:25448d92c205 321 return value2;
ansond 13:25448d92c205 322 }
ansond 13:25448d92c205 323
ansond 0:ae2a45502448 324 // get our error handler
ansond 0:ae2a45502448 325 ErrorHandler *MBEDEndpoint::logger() { return this->m_error_handler; }
ansond 0:ae2a45502448 326
ansond 0:ae2a45502448 327 // main running loop
ansond 0:ae2a45502448 328 void MBEDEndpoint::run() {
ansond 0:ae2a45502448 329 this->logger()->log("Endpoint Main Loop");
ansond 0:ae2a45502448 330 while(true) {
ansond 0:ae2a45502448 331 // sleep a bit
ansond 0:ae2a45502448 332 //this->logger()->log("Sleeping for a bit...");
ansond 0:ae2a45502448 333 wait_ms(MAIN_LOOP_SLEEP);
ansond 0:ae2a45502448 334
ansond 0:ae2a45502448 335 // check for events
ansond 0:ae2a45502448 336 //this->logger()->log("Processing Events...");
ansond 0:ae2a45502448 337 for(int i=0;i<NUM_TRANSPORTS;++i) this->m_transports[i]->checkAndProcess();
ansond 0:ae2a45502448 338
ansond 0:ae2a45502448 339 // check for exit
ansond 0:ae2a45502448 340 //this->logger()->log("Checking for exit...");
ansond 0:ae2a45502448 341 this->logger()->checkForExit();
ansond 0:ae2a45502448 342 }
ansond 0:ae2a45502448 343 }
ansond 0:ae2a45502448 344