Fork of my original MQTTGateway

Dependencies:   mbed-http

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* mbed main.cpp to test a secure MQTT connection using MBED TLS library 
00002  * Copyright (c) 2017 Vergil Perez Cola
00003  *
00004  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00005  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00006  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00007  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00008  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00009  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00010  * THE SOFTWARE.
00011  */
00012  
00013  /* *
00014   * @note This program is derived from the MQTT sample program.
00015   */
00016 /**
00017  * @note To make this work with FRDM-K64F
00018  * @note PTA0 must be disconnected from the swd clk by cutting J11.
00019  * @note But to re-active SWD you need to put jumper header to J11
00020  * @note so that it can be re-connected by a jumper.
00021  */
00022 
00023 #include "mbed.h"
00024 #include "rtos.h"
00025 #include "XbeeMonitor.h"
00026 #include "easy-connect.h"
00027 #include "NTPClient.h"
00028 #include "SDBlockDevice.h"
00029 #include "FATFileSystem.h"
00030 #include "DownloadFile.h"
00031 #include "MQTTSManager.h"
00032 #include "WeatherInfo.h"
00033 #include "RadioCfg.h"
00034 #include "config.h"
00035 
00036 #include <string>
00037 #include <sstream>
00038 
00039 #if defined(ENABLE_LOGGING)
00040 #include "DigiLoggerMbedSerial.h"
00041 using namespace DigiLog;
00042 #endif
00043 
00044 #if defined(TARGET_NUCLEO_L476RG)
00045 //SDBlockDevice sd(D11, D12, D13, D9);
00046 #else
00047 SDBlockDevice sd(PTE3, PTE1, PTE2, PTE4);
00048 #endif
00049 
00050 #if !defined(TARGET_NUCLEO_L476RG)
00051 FATFileSystem fs("sd");
00052 #endif
00053 
00054 Serial pc(USBTX, USBRX, 115200);
00055 
00056 Thread xbeeThd;
00057 
00058 #if !defined(TARGET_NUCLEO_L476RG)
00059 static const char * radioconfigfile = "/sd/radioconfig.json";
00060 #endif
00061 
00062 /* List of trusted root CA certificates
00063  * currently only "letsencrypt", the CA for mbedhacks.com
00064  *
00065  * To add more than one root, just concatenate them.
00066  *
00067  * TODO: Move this certificate file onto the SD card.
00068  */
00069 static const char SSL_CA_PEM[] = "-----BEGIN CERTIFICATE-----\n"
00070     "MIIFETCCA/mgAwIBAgISA2ktlb1Y6ap4GCH7dg3wS37XMA0GCSqGSIb3DQEBCwUA\n"
00071     "MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD\n"
00072     "ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNzAzMDkwMTQ4MDBaFw0x\n"
00073     "NzA2MDcwMTQ4MDBaMBgxFjAUBgNVBAMTDW1iZWRoYWNrcy5jb20wggEiMA0GCSqG\n"
00074     "SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4ppYHlH8lfB7lkWOjMSnOJGaLtCBfz57I\n"
00075     "VVOd1Rngsz7nE5fg3joa7lkazRY1ZqtuC2UloS+4LYoQZX4Z887dhdug/TPA4J1A\n"
00076     "GppA4xVCb2kUFODMjZ2r4pMLp+MjFFMBaHrL4cgx/n4aJUB+N9Z+HW0p2Yr5TsOQ\n"
00077     "ghIOPkNxFr2q6klm49+BMUbO98hAwFwsIISLf6IbHM93gx1ltqkvb55N87ZM1hYH\n"
00078     "fkq+J+YqjleiLaqRN2MVlNMNfy9MDbqM5uCyGiWGtq8eiQLaWpZkxnA2MC5zPsO/\n"
00079     "fzEWiVjn2uazlXZ5xZwiK22KMxVasqWMitvETtmPOl9mocRbLQdxAgMBAAGjggIh\n"
00080     "MIICHTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF\n"
00081     "BwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFCsgG+z1BTjrN3K+/tF0C4k818Yv\n"
00082     "MB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMHAGCCsGAQUFBwEBBGQw\n"
00083     "YjAvBggrBgEFBQcwAYYjaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNyeXB0Lm9y\n"
00084     "Zy8wLwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5v\n"
00085     "cmcvMCsGA1UdEQQkMCKCDW1iZWRoYWNrcy5jb22CEXd3dy5tYmVkaGFja3MuY29t\n"
00086     "MIH+BgNVHSAEgfYwgfMwCAYGZ4EMAQIBMIHmBgsrBgEEAYLfEwEBATCB1jAmBggr\n"
00087     "BgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlwdC5vcmcwgasGCCsGAQUFBwIC\n"
00088     "MIGeDIGbVGhpcyBDZXJ0aWZpY2F0ZSBtYXkgb25seSBiZSByZWxpZWQgdXBvbiBi\n"
00089     "eSBSZWx5aW5nIFBhcnRpZXMgYW5kIG9ubHkgaW4gYWNjb3JkYW5jZSB3aXRoIHRo\n"
00090     "ZSBDZXJ0aWZpY2F0ZSBQb2xpY3kgZm91bmQgYXQgaHR0cHM6Ly9sZXRzZW5jcnlw\n"
00091     "dC5vcmcvcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBABFH6YcvHh8foHeg\n"
00092     "NM7iR9HnYRqa5gSERcCtq6jm8PcTsAbsdQ/BNpIHK7AZSg2kk17kj+JFeyMuNJWq\n"
00093     "lmabV0dtzdC8ejp1d7hGb/HjuQ400th/QRayvyrDVzQPfCNyJ0C82Q2DFjeUgnqv\n"
00094     "oJMcV6i4ICW0boI7GUf7oeHCmrUEHKffAbeFvx3c85c39IHJEFa59UWj1linU/Tr\n"
00095     "g9i5AaSKB95d706u1XRA7WLV/Hu7yunhxEjlj33bfdifBb/ZLBd0LtrXPwtXi6E8\n"
00096     "r6obp+B+Ce89G7WEhdT9BX0ck1KTK+yP7uAC7tvvsiejxXOoCtVyBAumBJS7mRuv\n"
00097     "I5hmKgE=\n"
00098     "-----END CERTIFICATE-----\n"
00099     "-----BEGIN CERTIFICATE-----\n"
00100     "MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n"
00101     "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
00102     "DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n"
00103     "SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n"
00104     "GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n"
00105     "AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n"
00106     "q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n"
00107     "SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n"
00108     "Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n"
00109     "a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n"
00110     "/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n"
00111     "AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n"
00112     "CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n"
00113     "bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n"
00114     "c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n"
00115     "VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n"
00116     "ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n"
00117     "MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n"
00118     "Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n"
00119     "AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n"
00120     "uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n"
00121     "wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n"
00122     "X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n"
00123     "PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n"
00124     "KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n"
00125     "-----END CERTIFICATE-----";
00126 
00127 const char * openweathermap_id = "1bfddd34faa0e0216769d688b0b0c743";
00128 float lastTemperature;
00129 
00130 #define BASIC_AUTH_USER         "tinong"
00131 #define BASIC_AUTH_PASSWORD     "tatay"
00132 
00133 template <class T>
00134 std::string to_string (const T& t)
00135 {
00136     std::stringstream ss;
00137     ss << t;
00138     return ss.str();
00139 }
00140 
00141 
00142 void UpdateWeatherInfo(NetworkInterface* network)
00143 {
00144     printf("Downloading weather information ...\r\n");
00145     DownloadFile * wInfo = new DownloadFile(network);
00146     if (wInfo)
00147     {
00148         std::string url = "http://api.openweathermap.org/data/2.5/weather?q=Singapore,sg&appid="; 
00149         url += openweathermap_id;
00150         printf("Getting weather from [%s]\r\n", url.c_str());
00151         HttpResponse* result = wInfo->get_file(url.c_str());
00152         if (result != NULL)
00153         {
00154 
00155             std::string content = result->get_body_as_string();
00156          
00157             printf("\r\n========= Weather Info =============\r\n");
00158             printf("%s\r\n", content.c_str());
00159             printf("==============================\r\n");
00160             
00161             const char * weather = content.c_str();
00162             WeatherInfo info;
00163             if ( parseweatherinfo(weather, info) == 0)
00164             {
00165                 printf("Weather : %s\r\n", info.weather.c_str());
00166                 printf("Weather Icon : %s\r\n", info.icon.c_str());
00167                 printf("Current Temperature : %.2f\r\n", info.temperature - 273.15);
00168                 printf("Current Pressure : %.2f\r\n", info.pressure);
00169                 printf("Current Humidity : %.2f\r\n", info.humidity);
00170         
00171                 // TODO: process the information and send updates
00172                 // to GUI  
00173                 lastTemperature = info.temperature - 273.15;              
00174             }
00175         }
00176             
00177         delete wInfo;
00178     }
00179 }
00180     
00181 int main()
00182 {
00183     uint64_t radioID;
00184     int lasthour = 0;
00185     RadioCfg cfg;
00186     
00187 #if !defined(TARGET_NUCLEO_L476RG)    
00188     // Mount the SD card first!
00189     printf("Mounting the filesystem on \"/sd\". ");
00190     fs.mount(&sd);
00191 #endif
00192     
00193 #if defined(ENABLE_LOGGING)
00194     new DigiLoggerMbedSerial(&pc, LogLevelInfo);
00195 #endif      
00196     pc.printf("Initializing XbeeMonitor ...\r\n");
00197     initXbeeMonitor();
00198     // TODO: get XBee radio id 
00199     // and request configuration settings
00200     // from the web.
00201     radioID = getXbeeId();
00202     cfg.radioID = radioID;
00203     pc.printf("Radio ID : %llu\r\n", radioID);
00204         
00205     pc.printf("Connecting to ethernet ...\r\n");
00206     // Get the network interface via 
00207     // easy connect
00208     NetworkInterface* network = easy_connect(true);
00209     if (!network) {
00210         return 1;
00211     }
00212 
00213     pc.printf("IP Address : %s\r\n", network->get_ip_address());
00214     pc.printf("MAC Address : %s\r\n", network->get_mac_address());
00215     
00216     time_t ctTime;
00217     ctTime = time(NULL);
00218 
00219     printf("Getting coordinator info from the internet!...\r\n");
00220 #if !defined(TARGET_NUCLEO_L476RG)
00221     DownloadFile * df = new DownloadFile(network, radioconfigfile, SSL_CA_PEM );
00222 #else
00223     DownloadFile * df = new DownloadFile(network, NULL, SSL_CA_PEM );
00224 #endif
00225     if (df)
00226     {
00227         std::string url = "https://www.mbedhacks.com/Garden/getconfig.php?id=";
00228         url += to_string(radioID);
00229         printf("Getting config from [%s]\r\n", url.c_str());
00230         df->basic_auth(BASIC_AUTH_USER, BASIC_AUTH_PASSWORD);
00231         HttpResponse* result = df->get_file(url.c_str());
00232         if (result != NULL)
00233         {
00234 #if defined(TARGET_NUCLEO_L476RG)                
00235             std::string content = result->get_body_as_string();;
00236 #else
00237             std::string content = df->get_file_content();
00238 #endif
00239             printf("\r\n==========================\r\n");
00240             printf("%s\r\n", content.c_str());
00241             printf("==============================\r\n");
00242             
00243             // TODO: pass the downloaded file to the RadioCfg
00244             if (parseradioconfig(content.c_str(), cfg) == 0)
00245             {
00246                 cfg.debug();
00247             }
00248         }
00249         delete df;
00250     }
00251 
00252     NTPClient ntp(network, cfg.utc_offset);
00253     pc.printf("Initial System Time is: %s\r\n", ctime(&ctTime));
00254     pc.printf("Trying to update time...\r\n");
00255     if (ntp.setTime("0.pool.ntp.org") == 0) {
00256         
00257         pc.printf("Set time successfully\r\n");
00258         pc.printf("Updated time is : %s\r\n", ctime(&ctTime));
00259         
00260         pc.printf("Starting the Xbee manager thread ...\r\n");
00261         xbeeThd.start(runXbeeMonitor);
00262         pc.printf("Starting MQTTS subscriber thread ...\r\n");
00263         // Initialize MQTT
00264         mqttsInit(network, SSL_CA_PEM);
00265         if ( runMQTTS() != 0 )
00266             pc.printf("Failed launching MQTT thread ...\r\n");
00267         
00268         while(true) {
00269             time_t currentTime;
00270             struct tm *localTime;            
00271             
00272             time( &currentTime );                   // Get the current time
00273             localTime = localtime( &currentTime );  // Convert the current time to local time
00274 
00275             // TODO: Update the weather information every hour ...            
00276             if (lasthour != localTime->tm_hour )
00277             //if (lasthour != localTime->tm_min )            
00278             {
00279                 printf("An hour has passed!!! ...\r\n");
00280                 UpdateWeatherInfo(network);
00281                 // Update ...
00282                 //lasthour = localTime->tm_min;
00283                 lasthour = localTime->tm_hour;                
00284             }
00285 
00286             Thread::wait(10000);
00287         }
00288     }
00289     else
00290     {
00291         pc.printf("Failed to setup time from NTP  ...\r\n");
00292         while(true)
00293         {
00294             Thread::wait(100);
00295         }
00296     }
00297 }