mqtt specific components for the impact mbed endpoint library
Dependents: mbed_mqtt_endpoint_ublox_ethernet mbed_mqtt_endpoint_ublox_cellular mbed_mqtt_endpoint_nxp
MBEDEndpoint.cpp
- Committer:
- ansond
- Date:
- 2014-04-02
- Revision:
- 26:b9d74e06b3de
- Parent:
- 25:5269e8881494
- Child:
- 27:bb4253d9f1d0
File content as of revision 26:b9d74e06b3de:
/* 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" // Light Personality: Emulated Light Resource Factory #include "EmulatedLightResourceFactory.h" // Light Personality: Emulated Actions we can act on with the Light personalikty #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,void *transport,void *pinouts) : BaseClass(error_handler,NULL) { 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->logger()->setEndpoint((void *)this); this->setEndpoint(new IOCEndpoint(this->logger(),(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); #ifdef CELLULAR_NETWORK this->m_cellular_modem = NULL; this->m_gps = NULL; if (success) success = this->initializeCellularModem(transport,pinouts); if (success) success = this->initializeGPSReceiver(pinouts); #else if (success) success = this->initializeEthernet((EthernetInterface *)transport); #endif if (success) this->logger()->turnLEDYellow(); if (success)this->m_map = new MBEDToIOCResourceMap(error_handler); if (success) success = this->initializeTransports(); if (success) success = this->initializePersonalities(); 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->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; if (this->m_preferences != NULL) delete this->m_preferences; #else if (success) success = this->closeEthernet(); #endif if (success) this->logger()->turnLEDBlue(); if (this->m_map != NULL) delete this->m_map; if (this->getEndpoint() != NULL) delete (IOCEndpoint *)this->getEndpoint(); } // 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_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\nGW IP: %s\nIOC Link: %s",this->getEndpointName(),this->getGWAddress(),ioc); return this->m_lcd_status; } // initialize our personality 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 Lights..."); 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 EmulatedLightDimmerAction(this->logger(),(Light *)this->m_personalities[i])); ((Light *)this->m_personalities[i])->setSwitchAction(new EmulatedLightSwitchAction(this->logger(),(Light *)this->m_personalities[i])); } return true; } // does the input name match any of our personality instances? int MBEDEndpoint::indexOfPersonality(char *name) { bool found = false; int index = -1; for(int i=0;i<NUM_PERSONALITY_INSTANCES && !found;++i) { if (strcmp(this->m_personalities[i]->getName(),name) == 0) { found = true; index = i; } } return index; } // get a specific resources ResourceFactory *MBEDEndpoint::getResources(int index) { if (index >= 0 && index < NUM_PERSONALITY_INSTANCES) return this->m_personalities[index]->getResourceFactory(); return NULL; } // initialize the ResourceFactory to fit our personality ResourceFactory *MBEDEndpoint::initResourceFactory() { #ifdef LIGHT_PERSONALITY return this->initLightResourceFactory(); #endif #ifdef COPCAR_PERSONALITY return this->initLightResourceFactory(); #endif } // initialize a Light Resource Factory ResourceFactory *MBEDEndpoint::initLightResourceFactory() { return new EmulatedLightResourceFactory(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",PERSONALITY_NAME_INDEX); memset(this->m_endpoint_name,0,PERSONALITY_NAME_LEN+1); sprintf(this->m_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(); 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->logger(),this,this->getMap())); } if (success == true) { // HTTP Initialization success = this->initializeTransport(HTTP_TRANSPORT,"HTTP",new IOCHTTPTransport(this->logger(),this)); } return success; } #ifdef CELLULAR_NETWORK bool MBEDEndpoint::initializeCellularModem(void *transport,void *pinouts) { bool success = false; // initialize if (this->m_cellular_modem == NULL) this->m_cellular_modem = new MBEDUbloxCellRadio(this->logger(),(void *)this,(UBLOX_MODEM *)transport,(C027 *)pinouts); if (this->m_cellular_modem != NULL) success = this->m_cellular_modem->connect(); // return our status return success; } bool MBEDEndpoint::initializeGPSReceiver(void *pinouts) { bool success = false; // initialize if (this->m_gps == NULL) this->m_gps = new MBEDUbloxGPS(this->logger(),this,(C027 *)pinouts); 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(); 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 // load up all personality instances into the IOC bool MBEDEndpoint::loadPersonalities() { bool success = true; this->logger()->log("Loading All Personalities into the IOC..."); for(int i=0;i<NUM_PERSONALITY_INSTANCES && success;++i) success = this->loadPersonality(this->m_personalities[i]); return success; } // load up our personality to the IOC bool MBEDEndpoint::loadPersonality(Personality *instance) { 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 Personality(%s): %s...",instance->getType(),instance->getName()); // build the personality payload char *data = NULL; #ifdef LIGHT_PERSONALITY data = ((IOCEndpoint *)this->getEndpoint())->buildLightPayload(payload,IOC_PAYLOAD_LEN,(Light *)instance); #endif // issue the request if (data != NULL && strlen(data) > 0) { // DEBUG this->logger()->log("Sending Personality(%s): %s to the IOC...",instance->getType(),instance->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 External ID if found if (success) ((IOCEndpoint *)this->getEndpoint())->saveExternalID(instance,result); // DEBUG if (success) this->logger()->log("Personality(%s): %s IOC ID=%d sent successfully",instance->getType(),instance->getName(),instance->getExternalID()); // DEBUG if (!success) { if (instance != NULL) this->logger()->log("Personality(%s): %s send FAILED",instance->getType(),instance->getName()); else this->logger()->log("Personality send FAILED: NULL Personality instance"); } // return our status return success; } // update all personality instances into the IOC bool MBEDEndpoint::updatePersonalities() { bool success = true; for(int i=0;i<NUM_PERSONALITY_INSTANCES && success;++i) success = this->updatePersonality(i); return success; } // update all personality instances to the IOC bool MBEDEndpoint::updatePersonality(int index) { if (index >= 0 && index < NUM_PERSONALITY_INSTANCES) return this->updatePersonality(this->m_personalities[index]); return false; } // update our ith personality instance with the IOC bool MBEDEndpoint::updatePersonality(Personality *instance) { 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 = NULL; #ifdef LIGHT_PERSONALITY data = ((IOCEndpoint *)this->getEndpoint())->buildLightPayload(payload,IOC_PAYLOAD_LEN,(Light *)instance); #endif // issue the request if (data != NULL && strlen(data) > 0) { // DEBUG this->logger()->log("Updating Personality(%s): %s at the IOC...",instance->getType(),instance->getName()); // update success = this->m_transports[LOAD_TRANSPORT]->updateEndpoint(instance->getExternalID(),(char *)payload,strlen(payload),(char *)result,IOC_RESULT_LEN); } // DEBUG if (success) this->logger()->log("Update of Personality instance to IOC successful"); else this->logger()->log("Update of Personality instance to IOC FAILED"); // return our status return success; } // close down our personalities bool MBEDEndpoint::closePersonalities() { bool success = true; this->logger()->log("Closing down Personalities..."); for(int i=0;i<NUM_PERSONALITY_INSTANCES;++i) if (this->m_personalities[i] != NULL) delete this->m_personalities[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; } #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"); 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(); } }