nsp specific components for the NSP version of the impact endpoint

Dependents:   mbed_nsp_endpoint_ublox_cellular mbed_nsp_endpoint_ublox_ethernet mbed_nsp_endpoint_nxp

MBEDEndpoint.cpp

Committer:
ansond
Date:
2014-09-13
Revision:
24:b62fec3ff73c
Parent:
23:6f6e97a276b9
Child:
28:b6a7959c8be0

File content as of revision 24:b62fec3ff73c:

/* 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 "NSPTransport.h"
 #include "MBEDEndpoint.h"
 
 // Light Personality Support: MBED Light support
 #include "MBEDLight.h"
 
 // Light Personality Support: NSP Resource Factory
 #include "NSPLightResourceFactory.h"
 
 // Light Personality Support: NSP Actions we can act on
 #include "NSPLightDimmerAction.h"
 #include "NSPLightSwitchAction.h"
 
 // Salesforce Status Reporting (if enabled)
 #if SF_STATUS_REPORTING
    #include "StatusReporter.h"
 #endif
 
 // shutdown endpoint reference
 extern void closedown(int code);
  
 // default constructor
 MBEDEndpoint::MBEDEndpoint(ErrorHandler *error_handler,void *transport,void *status_reporter,void *extra) : BaseClass(error_handler,NULL) {
     bool success = true;
     this->m_preferences = NULL;
     this->m_instance_id = 0;
     this->m_status_reporter = status_reporter;
     memset(this->m_lcd_status,0,TEMP_BUFFER_LEN+1);
     memset(this->m_nsp_address,0,PREFERENCE_VALUE_LEN+1);
     memset(this->m_nsp_port_str_def,0,PREFERENCE_VALUE_LEN+1);
     sprintf(this->m_nsp_port_str_def,"%d",NSP_PORT);
     for(int i=0;i<NUM_TRANSPORTS;++i) this->m_transports[i] = NULL;
     this->logger()->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->initNSPAddress();
     if (PL_ENABLE && success) this->logger()->log("Philips Light ID: %d Philips Gateway IP: %s",PL_LIGHT_ID,PL_GW_ADDRESS);
#ifdef CELLULAR_NETWORK
     this->m_cellular_modem = NULL;
     this->m_gps = NULL;
     this->logger()->log("initializing Cellular Modem...");
     if (success) success = this->initializeCellularModem(transport);
     //this->logger()->log("initializing GPS Receiver...");
     //if (success) success = this->initializeGPSReceiver(this,extra);
#else
     if (success) success = this->initializeEthernet((EthernetInterface *)transport);
#endif
     if (success) this->logger()->turnLEDYellow();
     this->logger()->log("initializing transports...");
     if (success) success = this->initializeTransports();
     this->logger()->log("initializing personalities...");
     if (success) success = this->initializePersonalities();  
     this->logger()->log("initialization complete for endpoint...");
     if (success) this->logger()->turnLEDOrange();
     this->logger()->lcdStatusOnly(true);
     if (!success) closedown(2);
     if (success && AUTO_REGISTER_WITH_IOC) this->autoRegisterWithIOC();
 }
 
 // default destructor
 MBEDEndpoint::~MBEDEndpoint() {
     bool success = true;
     if (success) this->logger()->turnLEDYellow();
     if (success) success = this->closePersonalities();
     if (success) success = this->closeTransports();
#ifdef CELLULAR_NETWORK
     if (success) success = this->closeCellularModem();
     if (success) success = this->closeGPSReceiver();
     if (this->m_cellular_modem != NULL) delete this->m_cellular_modem;
     if (this->m_gps != NULL) delete this->m_gps;
#else
     if (success) success = this->closeEthernet();
#endif
     if (success) this->logger()->turnLEDBlue();
 }
 
 // initialize our preferences
 void MBEDEndpoint::initPreferences() { if (this->m_preferences == NULL) this->m_preferences = new Preferences(this->logger()); }

 // get our preferences
 Preferences *MBEDEndpoint::preferences() { return this->m_preferences; }
 
 // initialize the NSP address from the configuration
 void MBEDEndpoint::initNSPAddress() {
     memset(this->m_nsp_address,0,PREFERENCE_VALUE_LEN+1);
     memset(this->m_nsp_port_str,0,PREFERENCE_VALUE_LEN+1);
     if (this->m_preferences != NULL) {
        this->preferences()->getPreference("nsp_address",this->m_nsp_address,PREFERENCE_VALUE_LEN,NSP_ADDRESS);
        this->preferences()->getPreference("nsp_port",this->m_nsp_port_str,PREFERENCE_VALUE_LEN,this->m_nsp_port_str_def);
        sscanf(this->m_nsp_port_str,"%d",&(this->m_nsp_port));
        this->logger()->log("NSP: %s:%d",this->getNSPAddress(),this->getNSPPort());
     }
 }
 
 // get our NSP address
 char *MBEDEndpoint::getNSPAddress() { return this->m_nsp_address; }
 
 // get our NSP port
 int MBEDEndpoint::getNSPPort() { return this->m_nsp_port; }
 
 // 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_personalities[0]->getResourceFactory()->getResourceValue(EXTERNAL_LINKAGE_RESOURCE);
     
     // color our LED depending on whether we have IOC linkage or not...
     if (ioc == NULL || strcmp(ioc,EXTERNAL_LINKAGE_UNSET) == 0) this->logger()->turnLEDOrange();
     else this->logger()->turnLEDGreen();
           
     sprintf(this->m_lcd_status,"Node: %s\nNSP: %s:%d\nIOC Link: %s",this->getEndpointName(),this->getNSPAddress(),this->getNSPPort(),ioc);
     return this->m_lcd_status;
 }
 
 // initialize our Personalities
 bool MBEDEndpoint::initializePersonalities() {
 #ifdef LIGHT_PERSONALITY
    return this->initializeLights();
 #endif
 #ifdef COPCAR_PERSONALITY
    return this->initializeLights();
 #endif
 }
  
 // initialize the Lights
 bool MBEDEndpoint::initializeLights() {
     int index = this->preferences()->getIntPreference("endpoint_id",PERSONALITY_NAME_INDEX);     
     this->logger()->log("Initializing Personality(%s)...",PERSONALITY_TYPE);
     for(int i=0;i<NUM_PERSONALITY_INSTANCES;++i) {
         this->m_personalities[i] = new MBEDLight(this->logger(),this->m_transports,i+index,this);
         ((Light *)this->m_personalities[i])->setDimmerAction(new NSPLightDimmerAction(this->logger(),(Light *)this->m_personalities[i]));
         ((Light *)this->m_personalities[i])->setSwitchAction(new NSPLightSwitchAction(this->logger(),(Light *)this->m_personalities[i]));
     }
     return true;
 }
 
 // send any observations we may have 
 void MBEDEndpoint::sendObservations() {
     for(int i=0;i<NUM_PERSONALITY_INSTANCES;++i) {
         if (this->m_personalities[i] != NULL) {
             NSPResourceFactory *resource_factory = (NSPResourceFactory *)(this->m_personalities[i]->getResourceFactory());
             if (resource_factory != NULL) resource_factory->sendObservations();
         } 
     }
 }
 
 // initialize our ResourceFactory
 ResourceFactory *MBEDEndpoint::initResourceFactory() { 
#ifdef LIGHT_PERSONALITY
    return new NSPLightResourceFactory(this->logger(),(void *)this); 
#endif
#ifdef COPCAR_PERSONALITY
    return new NSPLightResourceFactory(this->logger(),(void *)this); 
#endif
 }
 
 // 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",PERSONALITY_NAME_INDEX);
     memset(_endpoint_name,0,PERSONALITY_NAME_LEN+1);
     memset(this->m_endpoint_name,0,PERSONALITY_NAME_LEN+1);
     sprintf(this->m_endpoint_name,PERSONALITY_NAME,this->m_instance_id);
     sprintf(_endpoint_name,PERSONALITY_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();
      }
      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) {
        // NSP Initialization
        success = this->initializeTransport(NSP_TRANSPORT,"NSP",new NSPTransport(this->logger(),this));
      }
      
      if  (success == true) {
        // HTTP Initialization
        success = this->initializeTransport(HTTP_TRANSPORT,"HTTP",new HTTPTransport(this->logger(),this));
      }
      
      return success;
 }
 
 // auto register with the IOC
 bool MBEDEndpoint::autoRegisterWithIOC() {
     bool success = false;
     char url[AUTOREGISTER_URL_LENGTH+1];
     char result[AUTOREGISTER_RESPONSE_LEN+1];
     
     // we use the HTTP transport to tell the Gateway to register us on our behalf
     HTTPTransport *http = (HTTPTransport *)this->m_transports[HTTP_TRANSPORT];
     if (http != NULL) {
         // DEBUG
         this->logger()->log("Initiating registration %s with IOC...",this->getEndpointName());
         
         // initialize buffers
         memset(url,0,AUTOREGISTER_URL_LENGTH+1);
         memset(result,0,AUTOREGISTER_RESPONSE_LEN+1);
         
         // enable basic auth
         http->basicAuth(IOC_USERNAME,IOC_PASSWORD);
        
         // build the URL
         sprintf(url,GW_AUTOREGISTER_URL,GW_IPADDRESS,GW_PORT,this->getEndpointName());
         
         // DEBUG
         //this->logger()->log("AutoRegister: %s...",url);
         
         // issue the registration request
         success = http->httpGet(url,result,AUTOREGISTER_RESPONSE_LEN,GW_AUTOREGISTER_TIMEOUT_MS);
         
         // reset basic auth
         http->basicAuth(NULL,NULL);
     }
     
     // return our status
     return success;
 }
 
 #ifdef CELLULAR_NETWORK
  bool MBEDEndpoint::initializeCellularModem(void *modem) {
     bool success = false;
     
     // initialize
     if (this->m_cellular_modem == NULL) this->m_cellular_modem = new MBEDUbloxCellRadio(this->logger(),(void *)this,modem);
     if (this->m_cellular_modem != NULL) success = this->m_cellular_modem->connect();
     
     // return our status
     return success;
 }
 
 bool MBEDEndpoint::initializeGPSReceiver(void *gps) {
     bool success = false;
     
     // initialize
     if (this->m_gps == NULL) this->m_gps = new MBEDUbloxGPS(this->logger(),(void *)this,gps);
     if (this->m_gps != NULL) success = this->m_gps->connect();
     
     // return our status
     return success;
 }
 #endif
 
 #ifndef CELLULAR_NETWORK
 // 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();  // DHCP
         //this->m_ethernet->init("192.168.1.220","255.255.255.0","192.168.1.1");
         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;
 }
 #endif
 
 // close down the Personalities
 bool MBEDEndpoint::closePersonalities() {
    bool success = true;
    this->logger()->log("Closing down Personalities...");
    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 NSP
         success = this->closeTransport(NSP_TRANSPORT,"NSP");
     }
          
     return success;
 }
 
 #ifdef CELLULAR_NETWORK
 bool MBEDEndpoint::closeCellularModem() {
     bool success = true; 
     if (this->m_cellular_modem != NULL) success = this->m_cellular_modem->disconnect();
     return success;
 }
 
 bool MBEDEndpoint::closeGPSReceiver() {
     bool success = true; 
     if (this->m_gps != NULL) success = this->m_gps->disconnect();
     return success;
 }
 #endif
 
 #ifndef CELLULAR_NETWORK
 // close down our Ethernet 
 bool MBEDEndpoint::closeEthernet() {
     this->logger()->log("Closing down Ethernet...");
     if (this->m_ethernet != NULL) this->m_ethernet->disconnect();
     return true;
 }
 #endif
 
 // main running loop
 void MBEDEndpoint::run() {
     this->logger()->log("Endpoint Main Loop");         
     this->m_transports[NSP_TRANSPORT]->checkAndProcess();
 }
 
 // do any extra work from within the event loop
 void MBEDEndpoint::extraEventLoopWork() {
    // check and send status reporting if enabled
 #if SF_STATUS_REPORTING
    if (this->m_status_reporter != NULL) {
        StatusReporter *status_reporter = (StatusReporter *)this->m_status_reporter;
        status_reporter->checkAndReportOnStatus();
    }
 #endif
 }