Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed_mqtt_endpoint_ublox_ethernet mbed_mqtt_endpoint_ublox_cellular mbed_mqtt_endpoint_nxp
MBEDEndpoint.cpp
- Committer:
- ansond
- Date:
- 2014-07-01
- Revision:
- 46:32a7545dde45
- Parent:
- 44:2740794b059a
- Child:
- 47:b775f5453b5d
File content as of revision 46:32a7545dde45:
/* 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 *extra) : 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(error_handler,(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",this->m_gw_address);
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 resource map...");
if (success)this->m_map = new MBEDToIOCResourceMap(error_handler);
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);
}
// 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);
strcpy(this->m_gw_address,GW_IPADDRESS);
if (this->m_preferences != NULL) {
this->m_preferences->getPreference("gw_address",this->m_gw_address,PREFERENCE_VALUE_LEN,GW_IPADDRESS);
this->m_preferences->getPreference("gw_port",this->m_gw_port,PREFERENCE_VALUE_LEN,GW_PORT);
this->logger()->log("GW: %s:%s",this->m_gw_address,this->m_gw_port);
}
}
// get our GW address
char *MBEDEndpoint::getGWAddress() { return this->m_gw_address; }
// get our GW Port
char *MBEDEndpoint::getGWPort() { return this->m_gw_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\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 = PERSONALITY_NAME_INDEX;
if (this->m_preferences != NULL) index = this->m_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 = PERSONALITY_NAME_INDEX;
memset(this->m_endpoint_name,0,PERSONALITY_NAME_LEN+1);
if (this->m_preferences != NULL)
this->m_instance_id = this->m_preferences->getIntPreference("endpoint_id",PERSONALITY_NAME_INDEX);
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 *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();
//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
// 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 = ((IOCEndpoint *)this->getEndpoint())->buildLightPayload(payload,IOC_PAYLOAD_LEN,(Light *)instance);
// 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 = ((IOCEndpoint *)this->getEndpoint())->buildLightPayload(payload,IOC_PAYLOAD_LEN,(Light *)instance);
// 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();
}
}