Fork of my original MQTTGateway

Dependencies:   mbed-http

Revision:
0:a1734fe1ec4b
diff -r 000000000000 -r a1734fe1ec4b main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,297 @@
+/* mbed main.cpp to test a secure MQTT connection using MBED TLS library 
+ * Copyright (c) 2017 Vergil Perez Cola
+ *
+ * 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.
+ */
+ 
+ /* *
+  * @note This program is derived from the MQTT sample program.
+  */
+/**
+ * @note To make this work with FRDM-K64F
+ * @note PTA0 must be disconnected from the swd clk by cutting J11.
+ * @note But to re-active SWD you need to put jumper header to J11
+ * @note so that it can be re-connected by a jumper.
+ */
+
+#include "mbed.h"
+#include "rtos.h"
+#include "XbeeMonitor.h"
+#include "easy-connect.h"
+#include "NTPClient.h"
+#include "SDBlockDevice.h"
+#include "FATFileSystem.h"
+#include "DownloadFile.h"
+#include "MQTTSManager.h"
+#include "WeatherInfo.h"
+#include "RadioCfg.h"
+#include "config.h"
+
+#include <string>
+#include <sstream>
+
+#if defined(ENABLE_LOGGING)
+#include "DigiLoggerMbedSerial.h"
+using namespace DigiLog;
+#endif
+
+#if defined(TARGET_NUCLEO_L476RG)
+//SDBlockDevice sd(D11, D12, D13, D9);
+#else
+SDBlockDevice sd(PTE3, PTE1, PTE2, PTE4);
+#endif
+
+#if !defined(TARGET_NUCLEO_L476RG)
+FATFileSystem fs("sd");
+#endif
+
+Serial pc(USBTX, USBRX, 115200);
+
+Thread xbeeThd;
+
+#if !defined(TARGET_NUCLEO_L476RG)
+static const char * radioconfigfile = "/sd/radioconfig.json";
+#endif
+
+/* List of trusted root CA certificates
+ * currently only "letsencrypt", the CA for mbedhacks.com
+ *
+ * To add more than one root, just concatenate them.
+ *
+ * TODO: Move this certificate file onto the SD card.
+ */
+static const char SSL_CA_PEM[] = "-----BEGIN CERTIFICATE-----\n"
+    "MIIFETCCA/mgAwIBAgISA2ktlb1Y6ap4GCH7dg3wS37XMA0GCSqGSIb3DQEBCwUA\n"
+    "MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD\n"
+    "ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNzAzMDkwMTQ4MDBaFw0x\n"
+    "NzA2MDcwMTQ4MDBaMBgxFjAUBgNVBAMTDW1iZWRoYWNrcy5jb20wggEiMA0GCSqG\n"
+    "SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4ppYHlH8lfB7lkWOjMSnOJGaLtCBfz57I\n"
+    "VVOd1Rngsz7nE5fg3joa7lkazRY1ZqtuC2UloS+4LYoQZX4Z887dhdug/TPA4J1A\n"
+    "GppA4xVCb2kUFODMjZ2r4pMLp+MjFFMBaHrL4cgx/n4aJUB+N9Z+HW0p2Yr5TsOQ\n"
+    "ghIOPkNxFr2q6klm49+BMUbO98hAwFwsIISLf6IbHM93gx1ltqkvb55N87ZM1hYH\n"
+    "fkq+J+YqjleiLaqRN2MVlNMNfy9MDbqM5uCyGiWGtq8eiQLaWpZkxnA2MC5zPsO/\n"
+    "fzEWiVjn2uazlXZ5xZwiK22KMxVasqWMitvETtmPOl9mocRbLQdxAgMBAAGjggIh\n"
+    "MIICHTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF\n"
+    "BwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFCsgG+z1BTjrN3K+/tF0C4k818Yv\n"
+    "MB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMHAGCCsGAQUFBwEBBGQw\n"
+    "YjAvBggrBgEFBQcwAYYjaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNyeXB0Lm9y\n"
+    "Zy8wLwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5v\n"
+    "cmcvMCsGA1UdEQQkMCKCDW1iZWRoYWNrcy5jb22CEXd3dy5tYmVkaGFja3MuY29t\n"
+    "MIH+BgNVHSAEgfYwgfMwCAYGZ4EMAQIBMIHmBgsrBgEEAYLfEwEBATCB1jAmBggr\n"
+    "BgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlwdC5vcmcwgasGCCsGAQUFBwIC\n"
+    "MIGeDIGbVGhpcyBDZXJ0aWZpY2F0ZSBtYXkgb25seSBiZSByZWxpZWQgdXBvbiBi\n"
+    "eSBSZWx5aW5nIFBhcnRpZXMgYW5kIG9ubHkgaW4gYWNjb3JkYW5jZSB3aXRoIHRo\n"
+    "ZSBDZXJ0aWZpY2F0ZSBQb2xpY3kgZm91bmQgYXQgaHR0cHM6Ly9sZXRzZW5jcnlw\n"
+    "dC5vcmcvcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBABFH6YcvHh8foHeg\n"
+    "NM7iR9HnYRqa5gSERcCtq6jm8PcTsAbsdQ/BNpIHK7AZSg2kk17kj+JFeyMuNJWq\n"
+    "lmabV0dtzdC8ejp1d7hGb/HjuQ400th/QRayvyrDVzQPfCNyJ0C82Q2DFjeUgnqv\n"
+    "oJMcV6i4ICW0boI7GUf7oeHCmrUEHKffAbeFvx3c85c39IHJEFa59UWj1linU/Tr\n"
+    "g9i5AaSKB95d706u1XRA7WLV/Hu7yunhxEjlj33bfdifBb/ZLBd0LtrXPwtXi6E8\n"
+    "r6obp+B+Ce89G7WEhdT9BX0ck1KTK+yP7uAC7tvvsiejxXOoCtVyBAumBJS7mRuv\n"
+    "I5hmKgE=\n"
+    "-----END CERTIFICATE-----\n"
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n"
+    "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
+    "DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n"
+    "SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n"
+    "GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n"
+    "AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n"
+    "q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n"
+    "SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n"
+    "Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n"
+    "a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n"
+    "/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n"
+    "AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n"
+    "CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n"
+    "bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n"
+    "c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n"
+    "VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n"
+    "ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n"
+    "MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n"
+    "Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n"
+    "AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n"
+    "uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n"
+    "wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n"
+    "X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n"
+    "PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n"
+    "KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n"
+    "-----END CERTIFICATE-----";
+
+const char * openweathermap_id = "1bfddd34faa0e0216769d688b0b0c743";
+float lastTemperature;
+
+#define BASIC_AUTH_USER         "tinong"
+#define BASIC_AUTH_PASSWORD     "tatay"
+
+template <class T>
+std::string to_string (const T& t)
+{
+    std::stringstream ss;
+    ss << t;
+    return ss.str();
+}
+
+
+void UpdateWeatherInfo(NetworkInterface* network)
+{
+    printf("Downloading weather information ...\r\n");
+    DownloadFile * wInfo = new DownloadFile(network);
+    if (wInfo)
+    {
+        std::string url = "http://api.openweathermap.org/data/2.5/weather?q=Singapore,sg&appid="; 
+        url += openweathermap_id;
+        printf("Getting weather from [%s]\r\n", url.c_str());
+        HttpResponse* result = wInfo->get_file(url.c_str());
+        if (result != NULL)
+        {
+
+            std::string content = result->get_body_as_string();
+         
+            printf("\r\n========= Weather Info =============\r\n");
+            printf("%s\r\n", content.c_str());
+            printf("==============================\r\n");
+            
+            const char * weather = content.c_str();
+            WeatherInfo info;
+            if ( parseweatherinfo(weather, info) == 0)
+            {
+                printf("Weather : %s\r\n", info.weather.c_str());
+                printf("Weather Icon : %s\r\n", info.icon.c_str());
+                printf("Current Temperature : %.2f\r\n", info.temperature - 273.15);
+                printf("Current Pressure : %.2f\r\n", info.pressure);
+                printf("Current Humidity : %.2f\r\n", info.humidity);
+        
+                // TODO: process the information and send updates
+                // to GUI  
+                lastTemperature = info.temperature - 273.15;              
+            }
+        }
+            
+        delete wInfo;
+    }
+}
+    
+int main()
+{
+    uint64_t radioID;
+    int lasthour = 0;
+    RadioCfg cfg;
+    
+#if !defined(TARGET_NUCLEO_L476RG)    
+    // Mount the SD card first!
+    printf("Mounting the filesystem on \"/sd\". ");
+    fs.mount(&sd);
+#endif
+    
+#if defined(ENABLE_LOGGING)
+    new DigiLoggerMbedSerial(&pc, LogLevelInfo);
+#endif      
+    pc.printf("Initializing XbeeMonitor ...\r\n");
+    initXbeeMonitor();
+    // TODO: get XBee radio id 
+    // and request configuration settings
+    // from the web.
+    radioID = getXbeeId();
+    cfg.radioID = radioID;
+    pc.printf("Radio ID : %llu\r\n", radioID);
+        
+    pc.printf("Connecting to ethernet ...\r\n");
+    // Get the network interface via 
+    // easy connect
+    NetworkInterface* network = easy_connect(true);
+    if (!network) {
+        return 1;
+    }
+
+    pc.printf("IP Address : %s\r\n", network->get_ip_address());
+    pc.printf("MAC Address : %s\r\n", network->get_mac_address());
+    
+    time_t ctTime;
+    ctTime = time(NULL);
+
+    printf("Getting coordinator info from the internet!...\r\n");
+#if !defined(TARGET_NUCLEO_L476RG)
+    DownloadFile * df = new DownloadFile(network, radioconfigfile, SSL_CA_PEM );
+#else
+    DownloadFile * df = new DownloadFile(network, NULL, SSL_CA_PEM );
+#endif
+    if (df)
+    {
+        std::string url = "https://www.mbedhacks.com/Garden/getconfig.php?id=";
+        url += to_string(radioID);
+        printf("Getting config from [%s]\r\n", url.c_str());
+        df->basic_auth(BASIC_AUTH_USER, BASIC_AUTH_PASSWORD);
+        HttpResponse* result = df->get_file(url.c_str());
+        if (result != NULL)
+        {
+#if defined(TARGET_NUCLEO_L476RG)                
+            std::string content = result->get_body_as_string();;
+#else
+            std::string content = df->get_file_content();
+#endif
+            printf("\r\n==========================\r\n");
+            printf("%s\r\n", content.c_str());
+            printf("==============================\r\n");
+            
+            // TODO: pass the downloaded file to the RadioCfg
+            if (parseradioconfig(content.c_str(), cfg) == 0)
+            {
+                cfg.debug();
+            }
+        }
+        delete df;
+    }
+
+    NTPClient ntp(network, cfg.utc_offset);
+    pc.printf("Initial System Time is: %s\r\n", ctime(&ctTime));
+    pc.printf("Trying to update time...\r\n");
+    if (ntp.setTime("0.pool.ntp.org") == 0) {
+        
+        pc.printf("Set time successfully\r\n");
+        pc.printf("Updated time is : %s\r\n", ctime(&ctTime));
+        
+        pc.printf("Starting the Xbee manager thread ...\r\n");
+        xbeeThd.start(runXbeeMonitor);
+        pc.printf("Starting MQTTS subscriber thread ...\r\n");
+        // Initialize MQTT
+        mqttsInit(network, SSL_CA_PEM);
+        if ( runMQTTS() != 0 )
+            pc.printf("Failed launching MQTT thread ...\r\n");
+        
+        while(true) {
+            time_t currentTime;
+            struct tm *localTime;            
+            
+            time( &currentTime );                   // Get the current time
+            localTime = localtime( &currentTime );  // Convert the current time to local time
+
+            // TODO: Update the weather information every hour ...            
+            if (lasthour != localTime->tm_hour )
+            //if (lasthour != localTime->tm_min )            
+            {
+                printf("An hour has passed!!! ...\r\n");
+                UpdateWeatherInfo(network);
+                // Update ...
+                //lasthour = localTime->tm_min;
+                lasthour = localTime->tm_hour;                
+            }
+
+            Thread::wait(10000);
+        }
+    }
+    else
+    {
+        pc.printf("Failed to setup time from NTP  ...\r\n");
+        while(true)
+        {
+            Thread::wait(100);
+        }
+    }
+}