MBED_DEMOS / Mbed 2 deprecated mbed_mqtt_endpoint_nxp

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

MBEDEndpoint.cpp

Committer:
ansond
Date:
2014-02-27
Revision:
18:214698dbcdfa
Parent:
17:84ab108ed670
Child:
19:956b694f6542

File content as of revision 18:214698dbcdfa:

/* 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"
 
 // JSON serialization support
 #include "MbedJSONValue.h"
 #include <string>
 
 // shutdown endpoint reference
 extern void closedown(int code);
  
 // default constructor
 MBEDEndpoint::MBEDEndpoint(ErrorHandler *error_handler,EthernetInterface *ethernet) {
     this->m_ioc_id = -1;
     bool success = true;
     for(int i=0;i<NUM_TRANSPORTS;++i) this->m_transports[i] = NULL;
     this->m_error_handler = error_handler;
     this->m_map = new MBEDToIOCResourceMap(error_handler);
     this->logger()->log(ENDPOINT_VERSION_ANNOUNCE);
     if (success) this->logger()->turnLEDBlue();
     if (success) success = this->initializeEthernet(ethernet);
     if (success) this->logger()->turnLEDYellow();
     if (success) success = this->initializeLights();
     if (success) success = this->initializeTransports();
     if (success) this->logger()->turnLEDGreen();
     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;
 }
 
 // set the IOC ID
 void MBEDEndpoint::setIOCID(int ioc_id) { this->m_ioc_id = ioc_id; }
 
 // get the IOC ID
 int MBEDEndpoint::getIOCID() { return this->m_ioc_id; }
 
 // get the IOC <--> MBED resource map
 MBEDToIOCResourceMap *MBEDEndpoint::getMap() { return this->m_map; }
 
 // initialize the Lights
 bool MBEDEndpoint::initializeLights() {
     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+1,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()); }
 
 // get our endpoint name (first light name)
 char *MBEDEndpoint::getEndpointName() { return this->m_lights[0]->getName(); }
 
 // 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();
      }
      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 HTTPTransport(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("Loading Light: %s...",light->getName());
          
     // build the payload
     char *data = this->buildIOCPayload(payload,IOC_PAYLOAD_LEN,light);
     
     // DEBUG
     this->logger()->log("Sending Light: %s to the IOC...",light->getName());
 
 return true;
     
     // issue the request
     success = this->m_transports[LOAD_TRANSPORT]->loadEndpoint((char *)payload,strlen(payload),(char *)result,IOC_RESULT_LEN);
     
     // DEBUG
     this->logger()->log("Saving IOC ID for Light: %s...",light->getName());
     
     // update the IOC ID if found
     if (success) this->saveIOCID(result);
     
     // DEBUG
     this->logger()->log("Light: %s IOC ID=%d...",light->getName(),this->getIOCID());
     
     // 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   
     success = this->m_transports[LOAD_TRANSPORT]->updateEndpoint(this->getIOCID(),(char *)payload,strlen(payload),(char *)result,IOC_RESULT_LEN);
          
     // return our status
     return success; 
 } 
 
 // build out the Payload
 char *MBEDEndpoint::buildIOCPayload(char *data,int data_length,Light *light) {
     // construct the payload for Load/Updates
     ResourceFactory *factory = light->getResourceFactory();
      
     // JSON factory
     MbedJSONValue json_generator;
     
     // 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);
         
         // add to the JSON payload
         char *name = this->getMap()->endpointNameToIOCName(resource->getName());
         char *value = resource->getValue();
         std::string  str_name(name);
         std::string  str_value(value);
         
         this->logger()->log("Name: %s Value: %s",str_name.c_str(),str_value.c_str());
         json_generator[str_name] = str_value;
     }
     
     // Special Case: STARTDATETIME
     json_generator["STARTDATETIME"] = "2014-02-27T03:35:55.940Z";
     
     // Special Case: ENDDATETIME
     json_generator["ENDDATETIME"] = "2017-02-27T03:35:55.940Z";
     
     // Speical Case: LOCATION
     json_generator["LOCATION"] = "Point(65.017210,25.492411)";
     
     // now convert to JSON
     std::string str_json = json_generator.serialize();
     
     // copy over to the buffer
     strncpy(data,str_json.c_str(),this->min(str_json.length(),data_length));
          
     // DEBUG
     this->logger()->log("Loading Payload: %s",data);
     
     // return the payload
     return data;
 }
  
 // save the IOC ID
 void MBEDEndpoint::saveIOCID(char *json) {     
     // JSON factory
     MbedJSONValue parser;
     
     // parse the result 
     parse(parser,json);
     
     // look for the ID element specifically
     int ioc_id = parser[IOC_REPONSE_ID_KEY].get<int>();
     
     // save the IOC ID
     if (ioc_id > 0) this->setIOCID(ioc_id);
 }
 
 // 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();
     }
}