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
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
Generated on Thu Jul 14 2022 16:49:25 by
 1.7.2