Doug Anson / endpoint_mqtt

Dependents:   mbed_mqtt_endpoint_ublox_ethernet mbed_mqtt_endpoint_ublox_cellular mbed_mqtt_endpoint_nxp

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MBEDEndpoint.cpp Source File

MBEDEndpoint.cpp

00001 /* Copyright C2013 Doug Anson, MIT License
00002  *
00003  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004  * and associated documentation files the "Software", to deal in the Software without restriction,
00005  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00006  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00007  * furnished to do so, subject to the following conditions:
00008  *
00009  * The above copyright notice and this permission notice shall be included in all copies or
00010  * substantial portions of the Software.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017  */
00018  
00019  #include "MQTTTransport.h"
00020  #include "MBEDEndpoint.h"
00021  
00022  // MBED Light support
00023  #include "MBEDLight.h"
00024  
00025  // Light Personality: Emulated Light Resource Factory
00026  #include "EmulatedLightResourceFactory.h"
00027  
00028  // Light Personality: Emulated Actions we can act on with the Light personalikty
00029  #include "EmulatedLightDimmerAction.h"
00030  #include "EmulatedLightSwitchAction.h"
00031  
00032  // Salesforce Status Reporting (if enabled)
00033  #if SF_STATUS_REPORTING
00034     #include "StatusReporter.h"
00035  #endif
00036  
00037  // string support
00038  #include <stdlib.h>
00039  #include <string.h>
00040    
00041  // shutdown endpoint reference
00042  extern void closedown(int code);
00043   
00044  // default constructor
00045  MBEDEndpoint::MBEDEndpoint(Logger *logger,void *transport,void *status_reporter,void *extra) : BaseClass(logger,NULL) {
00046      bool success = true;
00047      this->m_instance_id = 0;
00048      this->m_preferences = NULL;
00049      this->m_status_reporter = status_reporter;
00050      memset(this->m_lcd_status,0,TEMP_BUFFER_LEN+1);
00051      memset(this->m_gw_address,0,PREFERENCE_VALUE_LEN+1);
00052      for(int i=0;i<NUM_TRANSPORTS;++i) this->m_transports[i] = NULL;
00053      this->logger()->setEndpoint((void *)this);
00054      this->setEndpoint(new IOCEndpoint(logger,(void *)this));
00055      if (success) this->initPreferences();
00056      if (success) this->initEndpointName();
00057      if (success) this->logger()->turnLEDBlue();
00058  #ifdef MAC_ADDRESS
00059      extern char fmt_mac[RESOURCE_VALUE_LEN+1];
00060      if (success)this->logger()->log("%s (MAC: %s)",ENDPOINT_VERSION_ANNOUNCE,fmt_mac);
00061 #else
00062      if (success)this->logger()->log(ENDPOINT_VERSION_ANNOUNCE);
00063 #endif
00064      if (success) this->initGWAddress();
00065      //if (success) this->logger()->log("IOC GW IP: %s",this->m_gw_address);
00066      if (PL_ENABLE && success) this->logger()->log("Philips Light ID: %d Philips Gateway IP: %s",PL_LIGHT_ID,PL_GW_ADDRESS);
00067 #ifdef CELLULAR_NETWORK
00068      this->m_cellular_modem = NULL;
00069      this->m_gps = NULL;
00070      this->logger()->log("initializing Cellular Modem...");
00071      if (success) success = this->initializeCellularModem(transport);
00072      //this->logger()->log("initializing GPS Receiver...");
00073      //if (success) success = this->initializeGPSReceiver(this,extra);
00074 #else
00075      if (success) success = this->initializeEthernet((EthernetInterface *)transport);
00076 #endif
00077      if (success) this->logger()->turnLEDYellow();
00078      this->logger()->log("initializing resource map...");
00079      if (success)this->m_map = new MBEDToIOCResourceMap(logger); 
00080      this->logger()->log("initializing transports...");
00081      if (success) success = this->initializeTransports();
00082      this->logger()->log("initializing personalities...");
00083      if (success) success = this->initializePersonalities();  
00084      this->logger()->log("initialization complete for endpoint...");
00085      if (success) this->logger()->turnLEDOrange();
00086      this->logger()->lcdStatusOnly(true);
00087      if (!success) closedown(2);
00088      if (success && AUTO_REGISTER_WITH_IOC) {
00089          // load up our endpoints
00090          this->loadPersonalities();
00091          this->updatePersonalities();
00092      }
00093  }
00094  
00095  // default destructor
00096  MBEDEndpoint::~MBEDEndpoint() {
00097      bool success = true;
00098      if (success) this->logger()->turnLEDYellow();
00099      if (success) success = this->closePersonalities();
00100      if (success) success = this->closeTransports();
00101 #ifdef CELLULAR_NETWORK
00102      if (success) success = this->closeCellularModem();
00103      if (success) success = this->closeGPSReceiver();
00104      if (this->m_cellular_modem != NULL) delete this->m_cellular_modem;
00105      if (this->m_gps != NULL) delete this->m_gps;
00106      if (this->m_preferences != NULL) delete this->m_preferences;
00107 #else
00108      if (success) success = this->closeEthernet();
00109 #endif
00110      if (success) this->logger()->turnLEDBlue();
00111      if (this->m_map != NULL) delete this->m_map;
00112      if (this->getEndpoint() != NULL) delete (IOCEndpoint *)this->getEndpoint();
00113  }
00114   
00115  // get the IOC <--> MBED resource map
00116  MBEDToIOCResourceMap *MBEDEndpoint::getMap() { return this->m_map; }
00117  
00118  // initialize our preferences
00119  void MBEDEndpoint::initPreferences() { 
00120     if (this->m_preferences == NULL) 
00121         this->m_preferences = new Preferences(this->logger()); 
00122     if (this->m_preferences != NULL) 
00123         this->m_preferences->fixCoordsForIOC(); 
00124  }
00125 
00126  // get our preferences
00127  Preferences *MBEDEndpoint::preferences() { return this->m_preferences; }
00128  
00129  // initialize the GW address from the configuration
00130  void MBEDEndpoint::initGWAddress() {
00131      memset(this->m_gw_address,0,PREFERENCE_VALUE_LEN+1);
00132      strcpy(this->m_gw_address,GW_IPADDRESS);
00133      if (this->m_preferences != NULL) {
00134         this->m_preferences->getPreference("gw_address",this->m_gw_address,PREFERENCE_VALUE_LEN,GW_IPADDRESS);
00135         this->m_preferences->getPreference("gw_port",this->m_gw_port,PREFERENCE_VALUE_LEN,GW_PORT);
00136         this->logger()->log("GW: %s:%s",this->m_gw_address,this->m_gw_port);
00137      }   
00138  }
00139  
00140  // get our GW address
00141  char *MBEDEndpoint::getGWAddress() { return this->m_gw_address; }
00142  
00143  // get our GW Port
00144  char *MBEDEndpoint::getGWPort() { return this->m_gw_port; }
00145  
00146  // get our LCD status
00147  char *MBEDEndpoint::getLCDStatus() {
00148      memset(this->m_lcd_status,0,TEMP_BUFFER_LEN+1);
00149      
00150      // look at Light#0 to determine the IOC linkage ID...
00151      char *ioc = this->m_personalities[0]->getResourceFactory()->getResourceValue(EXTERNAL_LINKAGE_RESOURCE);
00152      
00153      // color our LED depending on whether we have IOC linkage or not...
00154      if (ioc == NULL || strcmp(ioc,EXTERNAL_LINKAGE_UNSET) == 0) this->logger()->turnLEDOrange();
00155      else this->logger()->turnLEDGreen();
00156            
00157      sprintf(this->m_lcd_status,"Node: %s\nGW IP: %s\nIOC Link: %s",this->getEndpointName(),this->getGWAddress(),ioc);
00158      return this->m_lcd_status;
00159  }
00160  
00161  // initialize our personality
00162  bool MBEDEndpoint::initializePersonalities() {
00163  #ifdef LIGHT_PERSONALITY
00164     return this->initializeLights();
00165  #endif
00166  #ifdef COPCAR_PERSONALITY
00167     return this->initializeLights();
00168  #endif
00169  }
00170  
00171  // initialize the Lights
00172  bool MBEDEndpoint::initializeLights() {
00173      int index = PERSONALITY_NAME_INDEX;
00174      if (this->m_preferences != NULL) index = this->m_preferences->getIntPreference("endpoint_id",PERSONALITY_NAME_INDEX); 
00175      this->logger()->log("Initializing Lights...");
00176      for(int i=0;i<NUM_PERSONALITY_INSTANCES;++i) {
00177          this->m_personalities[i] = new MBEDLight(this->logger(),this->m_transports,i+index,this);
00178          ((Light *)this->m_personalities[i])->setDimmerAction(new EmulatedLightDimmerAction(this->logger(),(Light *)this->m_personalities[i]));
00179          ((Light *)this->m_personalities[i])->setSwitchAction(new EmulatedLightSwitchAction(this->logger(),(Light *)this->m_personalities[i]));
00180      }
00181      return true;
00182  }
00183  
00184  // does the input name match any of our personality instances?
00185  int MBEDEndpoint::indexOfPersonality(char *name) {
00186      bool found = false;
00187      int index = -1;
00188      
00189      for(int i=0;i<NUM_PERSONALITY_INSTANCES && !found;++i) {
00190          if (strcmp(this->m_personalities[i]->getName(),name) == 0) {
00191              found = true;
00192              index = i;
00193          }
00194      }
00195      
00196      return index;
00197  }
00198  
00199  // get a specific resources
00200  ResourceFactory *MBEDEndpoint::getResources(int index) {
00201      if (index >= 0 && index < NUM_PERSONALITY_INSTANCES) return this->m_personalities[index]->getResourceFactory();
00202      return NULL;
00203  }
00204  
00205  // initialize the ResourceFactory to fit our personality
00206  ResourceFactory *MBEDEndpoint::initResourceFactory() {
00207 #ifdef LIGHT_PERSONALITY
00208     return this->initLightResourceFactory(); 
00209 #endif
00210 #ifdef COPCAR_PERSONALITY
00211     return this->initLightResourceFactory(); 
00212 #endif
00213  }
00214  
00215  // initialize a Light Resource Factory
00216  ResourceFactory *MBEDEndpoint::initLightResourceFactory() { return new EmulatedLightResourceFactory(this->logger(),(void *)this); }
00217  
00218  // Initialize the Endpoint Name - will be the first Light resource name (and there must be one...)
00219  void MBEDEndpoint::initEndpointName() {
00220      this->m_instance_id = PERSONALITY_NAME_INDEX;
00221      memset(this->m_endpoint_name,0,PERSONALITY_NAME_LEN+1);
00222      if (this->m_preferences != NULL) 
00223         this->m_instance_id = this->m_preferences->getIntPreference("endpoint_id",PERSONALITY_NAME_INDEX);
00224      sprintf(this->m_endpoint_name,PERSONALITY_NAME,this->m_instance_id);
00225  }
00226  
00227  // get our endpoint name
00228  char *MBEDEndpoint::getEndpointName() { return this->m_endpoint_name; }
00229  
00230  // get our instance id
00231  int MBEDEndpoint::getInstanceID() { return this->m_instance_id; }
00232  
00233  // initialize a specific transport
00234  bool MBEDEndpoint::initializeTransport(int index,char *key,Transport *transport) {
00235      bool success = false;
00236      if (this->m_transports[index] == NULL) {
00237           this->logger()->log("Initializing %s Transport...", key);
00238           this->m_transports[index] = transport;
00239           if (this->m_transports[index] != NULL) success = this->m_transports[index]->connect();
00240           if (success) this->logger()->log("Transport %s initialized and connected",key);
00241       }
00242       else {
00243           this->logger()->log("%s already connected (OK)...", key);
00244           success = true;
00245       }
00246       return success;
00247  }
00248  
00249  // initialize our transports
00250  bool MBEDEndpoint::initializeTransports() {
00251       bool success = true;
00252       
00253       if (success == true) {
00254         // MQTT Initialization
00255         success = this->initializeTransport(MQTT_TRANSPORT,"MQTT",new MQTTTransport(this->logger(),this,this->getMap()));
00256       }
00257       
00258       if (success == true) {
00259           // HTTP Initialization
00260           success = this->initializeTransport(HTTP_TRANSPORT,"HTTP",new IOCHTTPTransport(this->logger(),this));
00261       }
00262       return success;
00263  }
00264  
00265  #ifdef CELLULAR_NETWORK
00266  bool MBEDEndpoint::initializeCellularModem(void *modem) {
00267      bool success = false;
00268      
00269      // initialize
00270      if (this->m_cellular_modem == NULL) this->m_cellular_modem = new MBEDUbloxCellRadio(this->logger(),(void *)this,modem);
00271      if (this->m_cellular_modem != NULL) success = this->m_cellular_modem->connect();
00272      
00273      // return our status
00274      return success;
00275  }
00276  
00277  bool MBEDEndpoint::initializeGPSReceiver(void *gps) {
00278      bool success = false;
00279      
00280      // initialize
00281      if (this->m_gps == NULL) this->m_gps = new MBEDUbloxGPS(this->logger(),(void *)this,gps);
00282      if (this->m_gps != NULL) success = this->m_gps->connect();
00283      
00284      // return our status
00285      return success;
00286  }
00287  #endif
00288  
00289  #ifndef CELLULAR_NETWORK
00290  // initialize our Ethernet 
00291  bool MBEDEndpoint::initializeEthernet(EthernetInterface *ethernet) {
00292      bool success = false;
00293      this->m_ethernet = ethernet;
00294      if (this->m_ethernet != NULL) {
00295          this->logger()->log("Initializing Ethernet...");
00296          
00297          // connect up ethernet
00298          this->m_ethernet->init();
00299          //this->m_ethernet->init("192.168.1.220","255.255.255.0","192.168.1.1");
00300          this->m_ethernet->connect();
00301          
00302          // display our IP address
00303          char *ipaddr = this->m_ethernet->getIPAddress();
00304          if (ipaddr != NULL && strlen(ipaddr) > 0) {
00305             this->logger()->log("IPAddress: %s",this->m_ethernet->getIPAddress());
00306             success = true;
00307          }
00308          else {
00309             this->logger()->log("Ethernet Not Connected...");
00310             success = false;
00311          }
00312      }
00313      else {
00314          this->logger()->log("No Ethernet instance found");
00315          success = false;
00316      }
00317      return success;
00318  }
00319  #endif
00320  
00321  // load up all personality instances into the IOC
00322  bool MBEDEndpoint::loadPersonalities() {
00323      bool success = true;
00324      this->logger()->log("Loading All Personalities into the IOC...");
00325      for(int i=0;i<NUM_PERSONALITY_INSTANCES && success;++i) success = this->loadPersonality(this->m_personalities[i]);
00326      return success;
00327  }
00328  
00329  // load up our personality to the IOC
00330  bool MBEDEndpoint::loadPersonality(Personality *instance) {      
00331      bool success = false;
00332      char result[IOC_RESULT_LEN+1];
00333      char payload[IOC_PAYLOAD_LEN+1];
00334      
00335      // initialize
00336      memset(result,0,IOC_RESULT_LEN+1);
00337      memset(payload,0,IOC_PAYLOAD_LEN+1);
00338      
00339      // DEBUG
00340      this->logger()->log("Building Payload for Personality(%s): %s...",instance->getType(),instance->getName());
00341           
00342      // build the personality payload
00343      char *data = ((IOCEndpoint *)this->getEndpoint())->buildLightPayload(payload,IOC_PAYLOAD_LEN,(Light *)instance);
00344       
00345      // issue the request
00346      if (data != NULL && strlen(data) > 0) {
00347         // DEBUG
00348         this->logger()->log("Sending Personality(%s): %s to the IOC...",instance->getType(),instance->getName());
00349      
00350         // load
00351         success = this->m_transports[LOAD_TRANSPORT]->loadEndpoint((char *)payload,strlen(payload),(char *)result,IOC_RESULT_LEN);
00352      }
00353      
00354      // DEBUG
00355      //if (success) this->logger()->log("Saving IOC ID for Light: %s...",light->getName());
00356      
00357      // update the External ID if found
00358      if (success) ((IOCEndpoint *)this->getEndpoint())->saveExternalID(instance,result);
00359      
00360      // DEBUG
00361      if (success) this->logger()->log("Personality(%s): %s IOC ID=%d sent successfully",instance->getType(),instance->getName(),instance->getExternalID());
00362      
00363      // DEBUG
00364      if (!success) {
00365          if (instance != NULL) this->logger()->log("Personality(%s): %s send FAILED",instance->getType(),instance->getName());
00366          else this->logger()->log("Personality send FAILED: NULL Personality instance");
00367      }
00368      
00369      // return our status
00370      return success;
00371  }
00372  
00373  // update all personality instances into the IOC
00374  bool MBEDEndpoint::updatePersonalities() {
00375      bool success = true;
00376      for(int i=0;i<NUM_PERSONALITY_INSTANCES && success;++i) success = this->updatePersonality(i);
00377      return success;
00378  }
00379  
00380  // update all personality instances to the IOC
00381  bool MBEDEndpoint::updatePersonality(int index) {
00382      if (index >= 0 && index < NUM_PERSONALITY_INSTANCES) return this->updatePersonality(this->m_personalities[index]);
00383      return false; 
00384  }
00385  
00386  // update our ith personality instance with the IOC
00387  bool MBEDEndpoint::updatePersonality(Personality *instance) { 
00388      bool success = false;
00389      char result[IOC_RESULT_LEN+1];
00390      char payload[IOC_PAYLOAD_LEN+1];
00391      
00392      // initialize
00393      memset(result,0,IOC_RESULT_LEN+1);
00394      memset(payload,0,IOC_PAYLOAD_LEN+1);
00395           
00396      // build the payload
00397      char *data = ((IOCEndpoint *)this->getEndpoint())->buildLightPayload(payload,IOC_PAYLOAD_LEN,(Light *)instance);
00398 
00399      // issue the request  
00400      if (data != NULL && strlen(data) > 0) {
00401         // DEBUG
00402         this->logger()->log("Updating Personality(%s): %s at the IOC...",instance->getType(),instance->getName()); 
00403         
00404         // update
00405         success = this->m_transports[LOAD_TRANSPORT]->updateEndpoint(instance->getExternalID(),(char *)payload,strlen(payload),(char *)result,IOC_RESULT_LEN);
00406      }
00407      
00408      // DEBUG
00409      if (success) this->logger()->log("Update of Personality instance to IOC successful");
00410      else this->logger()->log("Update of Personality instance to IOC FAILED");
00411           
00412      // return our status
00413      return success; 
00414  } 
00415  
00416  // close down our personalities
00417  bool MBEDEndpoint::closePersonalities() {
00418     bool success = true;
00419     this->logger()->log("Closing down Personalities...");
00420     for(int i=0;i<NUM_PERSONALITY_INSTANCES;++i)
00421         if (this->m_personalities[i] != NULL) delete this->m_personalities[i];
00422     return success;
00423  }
00424  
00425  // close a given transport
00426  bool MBEDEndpoint::closeTransport(int index,char *key) {
00427     this->logger()->log("Closing down %s Transport...", key);
00428     if (this->m_transports[index] != NULL) delete this->m_transports[index];
00429     return true;
00430  }
00431  
00432  // close down our transports
00433  bool MBEDEndpoint::closeTransports() {
00434      bool success = true;
00435      
00436      if (success) {
00437          // close MQTT
00438          success = this->closeTransport(MQTT_TRANSPORT,"MQTT");
00439      }
00440      
00441      if (success) {
00442          // close HTTP
00443          success = this->closeTransport(HTTP_TRANSPORT,"HTTP");
00444      }
00445      
00446      return success;
00447  }
00448  
00449  #ifdef CELLULAR_NETWORK
00450  bool MBEDEndpoint::closeCellularModem() {
00451      bool success = true; 
00452      if (this->m_cellular_modem != NULL) success = this->m_cellular_modem->disconnect();
00453      return success;
00454  }
00455  
00456  bool MBEDEndpoint::closeGPSReceiver() {
00457      bool success = true; 
00458      if (this->m_gps != NULL) success = this->m_gps->disconnect();
00459      return success;
00460  }
00461  #endif
00462  
00463  #ifndef CELLULAR_NETWORK
00464  // close down our Ethernet 
00465  bool MBEDEndpoint::closeEthernet() {
00466      this->logger()->log("Closing down Ethernet...");
00467      if (this->m_ethernet != NULL) this->m_ethernet->disconnect();
00468      return true;
00469  }
00470  #endif
00471    
00472  // main running loop
00473  void MBEDEndpoint::run() {
00474      this->logger()->log("Endpoint Main Loop");
00475      while(true) {
00476          // sleep a bit
00477          //this->logger()->log("Sleeping for a bit...");
00478          Thread::wait(MAIN_LOOP_SLEEP);
00479          
00480          // check for events 
00481          //this->logger()->log("Processing Events...");
00482          for(int i=0;i<NUM_TRANSPORTS;++i) this->m_transports[i]->checkAndProcess();
00483          
00484          // check for exit
00485          //this->logger()->log("Checking for exit...");
00486          this->logger()->checkForExit();
00487          
00488          // do any extra event loop activities
00489          this->extraEventLoopWork();
00490      }
00491  }
00492 
00493  // do any extra work from within the event loop
00494  void MBEDEndpoint::extraEventLoopWork() {
00495     // check and send status reporting if enabled
00496  #if SF_STATUS_REPORTING
00497     if (this->m_status_reporter != NULL) {
00498         StatusReporter *status_reporter = (StatusReporter *)this->m_status_reporter;
00499         status_reporter->checkAndReportOnStatus();
00500     }
00501  #endif
00502  }
00503