Fork from Alex

Dependencies:   mbed MbedJSONValue mbed-rtos 4DGL-uLCD-SE ESP8266NodeMCUInterface

Revision:
4:55f0c303f56a
Parent:
3:7bf41989ff8f
Child:
5:b77a717feada
--- a/main.cpp	Sun Mar 31 03:08:51 2019 +0000
+++ b/main.cpp	Sun Mar 31 15:39:50 2019 +0000
@@ -32,15 +32,17 @@
 // Time
 Thread time_thread;
 
-// Weather
-Thread weather_thread;
-char weather_api_key[256];
-
 // Location
-char ip_api_key[256];
 double latitude = 0;
 double longitude = 0;
 
+// Credentials
+char ssid[256];
+char pass[256];
+char ip_api_key[256];
+char time_api_key[256];
+char weather_api_key[256];
+
 void time_updater() {
     // We're not an interrupt, so take as much time as we need. Infinite loop
     // but wait 1 second between each loop
@@ -51,9 +53,10 @@
     ltm = localtime(&now);
     
     // Buffer for time string. Max length is 23:59 + \0
-    int max_time_len = 6;
+    int max_time_len = 8;
     char ftime[max_time_len];
-    
+    ftime[0] = ' ';
+    ftime[1] = ' ';
     int min = -1;
     
     while (true) {
@@ -62,7 +65,7 @@
         ltm = localtime(&now);
         if(ltm->tm_min != min) {
             // Get the new time
-            strftime(ftime, max_time_len, "%H:%M", ltm); 
+            strftime(ftime + 2, max_time_len, "%H:%M", ltm); 
             // Update time! Lock the lcd mutex
             lcd_lock.lock();
             uLCD.text_width(2);
@@ -77,53 +80,54 @@
     }   
 }
 
+/*
 void weather_updater() {
-    // We can take as long as we want
+    // get the weather
+    // first get the current weather
+    // Weather data is _long_
+    dev.printf("Hello, World!\n");
+
+    char forecast_buf[4096];
+    TCPSocketConnection forecast_sck;
+    // http://api.openweathermap.org/data/2.5/forecast?lat=33.7485&lon=-84.3871&appid=6971e1ebfcc60f29c8dcc617c532b1b6&cnt=8
+    forecast_sck.connect("api.openweathermap.org", 80);
+    char cmd[256];
+    sprintf(cmd,
+        "GET /data/2.5/weather?lat=%0.4f&lon=%0.4f&APPID=6971e1ebfcc60f29c8dcc617c532b1b6&cnt=8\r\nHost: api.openweathermap.org\r\n\r\n",
+        latitude, longitude);
+    forecast_sck.send_all(cmd, strlen(cmd));
+    wait(10);
+    int len_read = wifi.recv(forecast_buf, 4096 - 1, 0);
+    forecast_buf[len_read] = '\0';
+    dev.printf(forecast_buf);
     return;
-    while (true) {
-        // get the weather
-        // first get the current weather
-        // Weather data is _long_
-        
-        char forecast_buf[2];
-        TCPSocketConnection sck;
-        // http://api.openweathermap.org/data/2.5/forecast?lat=33.7485&lon=-84.3871&appid=6971e1ebfcc60f29c8dcc617c532b1b6
-        sck.connect("api.openweathermap.org", 80);
-        char cmd[1024];
-        sprintf(cmd,
-            "GET /data/2.5/weather?lat=%0.4f&lon=%0.4f&APPID=%s\r\nHost: api.openweathermap.org\r\n\r\n",
-            latitude, longitude, weather_api_key);
-        sck.send_all(cmd, strlen(cmd));
-        wait(10);
-        int buf_len = wifi.recv(forecast_buf, 16384 - 1, 0);
-        forecast_buf[buf_len] = '\0';
-        
-        // Get current weather
-        char current_buf[8192];
-        sprintf(cmd,
-            "GET /data/2.5/forecast?lat=%0.4f&lon=%0.4f&APPID=%s\r\nHost: api.openweathermap.org\r\n\r\n",
-            latitude, longitude, weather_api_key);
-        sck.send_all(cmd, strlen(cmd));
-        wait(10);
-        buf_len = wifi.recv(current_buf, 8192 - 1, 0);
-        current_buf[buf_len] = '\0';
-        // we'll always want to update the LCD - don't worry about the previous
-        // weather
-        int curr_temp = 0;
-        int high_temp = 0;
-        int low_temp = 0;
-        char buf[12];
-        sprintf(buf, "%d %d/%d", curr_temp, high_temp, low_temp);
-        // lock
-        lcd_lock.lock();
-        uLCD.text_width(2);
-        uLCD.text_height(2);
-        // include null!
-        uLCD.text_string(buf, 0, 5, FONT_7X8, WHITE);
-        // done! unlock
-        lcd_lock.unlock();
-    }
+    // http://api.openweathermap.org/data/2.5/forecast?lat=33.7485&lon=-84.3871&appid=6971e1ebfcc60f29c8dcc617c532b1b6
+    // Get current weather
+    char current_buf[4096];
+    sprintf(cmd,
+        "GET /data/2.5/forecast?lat=%0.4f&lon=%0.4f&APPID=%s\r\nHost: api.openweathermap.org\r\n\r\n",
+        latitude, longitude, weather_api_key);
+    sck.send_all(cmd, strlen(cmd));
+    wait(10);
+    int buf_len = wifi.recv(current_buf, 4096 - 1, 0);
+    current_buf[buf_len] = '\0';
+    // we'll always want to update the LCD - don't worry about the previous
+    // weather
+    int curr_temp = 0;
+    int high_temp = 0;
+    int low_temp = 0;
+    char buf[12];
+    sprintf(buf, "%d %d/%d", curr_temp, high_temp, low_temp);
+    // lock
+    lcd_lock.lock();
+    uLCD.text_width(2);
+    uLCD.text_height(2);
+    // include null!
+    uLCD.text_string(buf, 0, 5, FONT_7X8, WHITE);
+    // done! unlock
+    lcd_lock.unlock();
 }
+*/
 
 void dev_recv() {
     // Continually check if we have stuff...
@@ -151,7 +155,11 @@
     }
 }
 
-int main() {
+int kelvin2farenheit(int temp) {
+     return (int)((((temp - 273.15f) * 9.0f) / 5.0f) + 32.0f);
+}
+
+void clock_init() {
     // Set up bluetooth
     dev.baud(9600);
     pc.baud(9600);
@@ -164,17 +172,12 @@
     lcd_lock.unlock();
     
     // Need to get wifi settings. If we don't have local file, then ask!
-    FILE* fid = NULL;//fopen("/local/settings.txt", "r");
-    char ssid[256];
-    char pass[256];
-    char api_key[256];
+    FILE* fid = fopen("/local/settings.txt", "r");
     
-    if (true) {
-        
-    } else if (fid != NULL) {
+    if (fid != NULL) {
         // Read WiFi Settings
         char settings_buf[1024];
-        // Guaranteed to be 256, 256, 512 AT MOST + two new lines
+        // Guaranteed to be 5 lines
         // 
         fgets(settings_buf, 1024, fid);
         // find \n
@@ -185,17 +188,33 @@
         }
         ssid[settings_ind] = '\0';
         settings_ind = 0;
-        counter++;
+        fgets(settings_buf, 1024, fid);
+        counter = 0;
         while (settings_buf[counter] != '\n') {
             pass[settings_ind++] = settings_buf[counter++];
         }
         pass[settings_ind] = '\0';
         settings_ind = 0;
-        counter++;
+        fgets(settings_buf, 1024, fid);
+        counter = 0;
+        while (settings_buf[counter] != '\n') {
+            ip_api_key[settings_ind++] = settings_buf[counter++];
+        }
+        ip_api_key[settings_ind] = '\0';
+        settings_ind = 0;
+        fgets(settings_buf, 1024, fid);
+        counter = 0;
         while (settings_buf[counter] != '\n') {
-            api_key[settings_ind++] = settings_buf[counter++];
+            time_api_key[settings_ind++] = settings_buf[counter++];
         }
-        api_key[settings_ind] = '\0';
+        time_api_key[settings_ind] = '\0';
+        settings_ind = 0;
+        fgets(settings_buf, 1024, fid);
+        counter = 0;
+        while (settings_buf[counter] != '\n') {
+            weather_api_key[settings_ind++] = settings_buf[counter++];
+        }
+        weather_api_key[settings_ind] = '\0';
         fclose(fid);
     } else {
         lcd_lock.lock();
@@ -249,7 +268,7 @@
         pass[ind] = '\0';
         
         // Get the API key
-        dev.printf("Please provide the API key\n");
+        dev.printf("Please provide the IP Stack API key\n");
         while (!dev.readable()) {
             wait(0.001);
         }
@@ -259,117 +278,298 @@
             if (tmp == '\n' || tmp == '\r') {
                 break;
             }
-            api_key[ind++] = tmp;
+            ip_api_key[ind++] = tmp;
+            wait(0.01);
+        }
+
+        ip_api_key[ind] = '\0';
+        
+        dev.printf("Please provide the TimeZoneDB API key\n");
+        while (!dev.readable()) {
+            wait(0.001);
+        }
+        ind = 0;
+        while (ind < 255) {
+            char tmp = dev.getc();
+            if (tmp == '\r' || tmp == '\n') {
+                break;
+            }
+            time_api_key[ind++] = tmp;
             wait(0.01);
         }
-        api_key[ind] = '\0';
+        time_api_key[ind] = '\0';
+        
+        dev.printf("Please provide the OpenWeather API key\n");
+        while (!dev.readable()) {
+            wait(0.001);
+        }
+        ind = 0;
+        while (ind < 255) {
+            char tmp = dev.getc();
+            if (tmp == '\r' || tmp == '\n') {
+                break;
+            }
+            weather_api_key[ind++] = tmp;
+            wait(0.01);
+        }
+        weather_api_key[ind] = '\0';
+
+        
+        
         // Because this is a simple proof of concept, we store the password in 
         // plaintext. It should be noted, however, that you **should never do 
         // this in "real life"**
-        //fid = fopen("/local/settings.txt", "w");
-        //fprintf(fid, "%s\n%s\n%s\n", ssid, pass, api_key);
-        //fclose(fid);
+        fid = fopen("/local/settings.txt", "w");
+        fprintf(fid, "%s\n%s\n%s\n%s\n%s\n", ssid, pass, ip_api_key, time_api_key, weather_api_key);
+        fclose(fid);
     }
-    char* tmp = "af9319bf6435ddd9bb640f763ff64d34";
-    for (int i = 0; i < strlen(tmp); i++) {
-        api_key[i] = tmp[i];
-    }
+    
+    dev.printf("\r\n** CREDENTIALS **\r\n");
+    dev.printf("SSID: **%s** (%d)\r\n", ssid, strlen(ssid));
+    dev.printf("PASS: **%s** (%d)\r\n", pass, strlen(pass));
+    dev.printf("IP STACK: **%s**\r\n", ip_api_key);
+    dev.printf("TIMEZONEDB: **%s**\r\n", time_api_key);
+    dev.printf("WEATHERMAP: **%s**\r\n", weather_api_key);
+    
     bool res = wifi.init();
-    //dev.printf("Reset: %d\n", res);
+
     // Set up the WiFi Access Point
     dev.printf("Connecting to WiFi %s with Password %s\n", ssid, pass);
+    
     res = wifi.connect("Alex's iPhone", "mbedlookhere");
     if (!res) {
         dev.printf("Connection Failed... Resetting Device\n");
         err_led = 1;
         mbed_reset();
     }
+    
     dev.printf("Connected with IP Address: %s\n", wifi.getIPAddress());
     
-    // Get the time & location
+    /** API REQUESTS **/
+    
+    int header_ind = 0;
+    int footer_ind = 0;
+    int read_len = 0;
+    char buffer[BUF_SIZE];
+    char cmd[512];
+
     dev.printf("Getting the current location...\n");
     TCPSocketConnection tcp;
     tcp.connect("api.ipstack.com", 80);
+    //af9319bf6435ddd9bb640f763ff64d34
+    sprintf(cmd, 
+        "GET /check?access_key=%s HTTP/1.1\r\nHost: api.ipstack.com\r\n\r\n",
+        ip_api_key);
+    tcp.send_all(cmd, strlen(cmd));
     
-    char tcp_cmd[256];
-    sprintf(tcp_cmd, 
-        "GET /check?access_key=af9319bf6435ddd9bb640f763ff64d34 HTTP/1.1\r\nHost: api.ipstack.com\r\n\r\n");
-    tcp.send_all(tcp_cmd, strlen(tcp_cmd));
+    wait(5);
     
-    wait(10);
-    
-    char buffer[BUF_SIZE];
-    int read_len = wifi.recv(buffer, BUF_SIZE - 1, 0);
+    read_len = wifi.recv(buffer, BUF_SIZE - 1, 0);
     buffer[read_len] = '\0';
     
+    // Cleanup
+    
+    while (header_ind < read_len) {
+        // if we are \r, look ahead to see \n\r\n:
+        if(buffer[header_ind] == '\r' &&
+           buffer[header_ind+1] == '\n' &&
+           buffer[header_ind+2] == '\r' &&
+           buffer[header_ind+3] == '\n') {
+            // Increment header_ind, look for JSON
+            // Now just look for {
+            header_ind += 4;
+            while (header_ind < read_len) {
+                if (buffer[header_ind] == '{') {
+                    // we got it!
+                    break;
+                }
+                header_ind++;
+            }
+            break;
+        }
+        header_ind++;
+    }
+    for (footer_ind = read_len - 1; footer_ind > header_ind; footer_ind--) {
+        if(buffer[footer_ind] == '}') {
+            break;
+        }
+    }
+    buffer[footer_ind + 1] = '\0';
+    dev.printf(buffer);
     MbedJSONValue parser;
-    parse(parser, buffer);
-    // for now, just print...
+    parse(parser, buffer + header_ind);
     
-    latitude = parser["latitude"].get<double>();
+    latitude =  parser["latitude"].get<double>();
     longitude = parser["longitude"].get<double>();
 
-    /*
-    TCPSocketConnection weather_sck;
-    //http://api.openweathermap.org/data/2.5/weather?q=London,uk&APPID=6971e1ebfcc60f29c8dcc617c532b1b6
-    //http://api.openweathermap.org/data/2.5/forecast?lat=33.7485&lon=-84.3871&appid=6971e1ebfcc60f29c8dcc617c532b1b6
-    weather_sck.connect("api.openweathermap.org", 80);
-    sprintf(tcp_cmd,
-        "GET /data/2.5/weather?lat=%0.4f&lon=%0.4f&APPID=%s\r\nHost: api.openweathermap.org\r\n\r\n",
-        lat, lng, "6971e1ebfcc60f29c8dcc617c532b1b6");
-    sprintf(weather_api_key,
-        "%s", "6971e1ebfcc60f29c8dcc617c532b1b6");
-    weather_sck.send_all(tcp_cmd, strlen(tcp_cmd));
-    wait(15);
-    int read_len = wifi.recv(buffer, BUF_SIZE - 1, 0);
+    // Get the Time
+    TCPSocketConnection time_tcp;
+
+    //http://api.timezonedb.com/v2.1/get-time-zone?key=YOUR_API_KEY&format=json&by=zone&zone=America/Chicago
+    time_tcp.connect("api.timezonedb.com", 80);
+    //VFHNS0FSUJVN
+    sprintf(cmd,
+        "GET /v2.1/get-time-zone?key=%s&format=json&by=position&lat=%0.4f&lng=%0.4f HTTP/1.1\r\nHost: api.timezonedb.com\r\n\r\n",
+        time_api_key,
+        latitude,
+        longitude);
+
+    time_tcp.send_all(cmd, strlen(cmd));
+    wait(5);
+    read_len = wifi.recv(buffer, BUF_SIZE - 1, 0);
     buffer[read_len] = '\0';
-    dev.printf(buffer);
-    */
-    // dev.printf("Connection: %d\n", con_res);
-    //sprintf
-    //int con_res = weather_sck.connect("api.weather.gov", 443);
-    //    dev.printf("Connection: %d\n", con_res);
-    //sprintf(tcp_cmd,
-    //    "GET /points/%0.4f,%0.4f HTTP/1.1\r\nHost: api.weather.gov\r\n\r\n",
-    //    lat, lng);
-    //weather_sck.send_all(tcp_cmd, strlen(tcp_cmd));
-    //wait(5);
-    //wait(10);
-    //int read_len = wifi.recv(buffer, BUF_SIZE - 1, 0);
-    //buffer[read_len] = '\0';
-    //dev.printf(buffer);
-    set_time(1256729737);
+    
+    // Cleanup
+    
+    // Clean up front
+    // Read through headers (\r\n\r\n)
+    header_ind = 0;
+    while (header_ind < read_len) {
+        // if we are \r, look ahead to see \n\r\n:
+        if(buffer[header_ind] == '\r' &&
+           buffer[header_ind+1] == '\n' &&
+           buffer[header_ind+2] == '\r' &&
+           buffer[header_ind+3] == '\n') {
+            // Increment header_ind, look for JSON
+            // Now just look for {
+            header_ind += 4;
+            while (header_ind < read_len) {
+                if (buffer[header_ind] == '{') {
+                    // we got it!
+                    break;
+                }
+                header_ind++;
+            }
+            break;
+        }
+        header_ind++;
+    }
+
+    for (footer_ind = read_len - 1; footer_ind > header_ind; footer_ind--) {
+        if(buffer[footer_ind] == '}') {
+            break;
+        }
+    }
+    buffer[footer_ind + 1] = '\0';
     
-    // Clear the LCD Screen first
+    MbedJSONValue time_parser;
+    parse(time_parser, buffer + header_ind);
+
+    // Add 5 so that we make up for the wait(5)
+    set_time(time_parser["timestamp"].get<int>() + 5);
+    // Now that we know what time it is, set up our Time Thread
+    time_thread.start(time_updater);
+    TCPSocketConnection forecast_sck;
+    // http://api.openweathermap.org/data/2.5/forecast?lat=33.7485&lon=-84.3871&appid=6971e1ebfcc60f29c8dcc617c532b1b6&cnt=8
+    forecast_sck.connect("api.openweathermap.org", 80);
+    //6971e1ebfcc60f29c8dcc617c532b1b6
+    sprintf(cmd,
+        "GET /data/2.5/weather?lat=%0.4f&lon=%0.4f&APPID=%s&cnt=8\r\nHost: api.openweathermap.org\r\n\r\n",
+        latitude, longitude, weather_api_key);
+    forecast_sck.send_all(cmd, strlen(cmd));
+    wait(5);
+    int len_read = wifi.recv(buffer, BUF_SIZE - 1, 0);
+    buffer[len_read] = '\0';
+    
+
+    //buffer[footer_ind + 1] = '\0';
+    char* ind = strstr(buffer, "temp");
+    for (int m = 0; m < 15; m++) {
+        dev.putc(ind[m]);
+    }
+    char num_buf[16];
+    int num_ind = 0;
+    // go until we find numbers
+    while (char tmp = *ind++) {
+        if (tmp > '0' && tmp < '9') {
+            num_buf[num_ind++] = tmp;
+            break;
+        }
+    }
+    // Keep moving until no more numbers
+    while (char tmp = *ind++) {
+        if (tmp > '9' || tmp < '0') {
+            num_buf[num_ind] = '\0';
+            break;
+        } else {
+            num_buf[num_ind++] = tmp;
+        }
+    }
+    int temp = atoi(num_buf);
+    // Convert
+    temp = (((temp - 273.15f) * 9.0f) / 5.0f) + 32.0f;
+    char temp_buf[12];
+    sprintf(temp_buf, "   %dF", temp);
     lcd_lock.lock();
-    uLCD.cls();
+    uLCD.text_width(2);
+    uLCD.text_height(2);
+    uLCD.text_string(temp_buf, 0, 5, FONT_8X8, WHITE);
+    // done! unlock
     lcd_lock.unlock();
     
-    // Now that we know what time it is, set up our Time Thread
-    time_thread.start(time_updater);
-    
-    // Make the request to get the forecast link
-
-    // Now, make a single request to nws and get the forecast link - we can 
-    // store this link for later!
     
     // Start up weather service!
     //weather_thread.start(weather_updater);
     
-    //weather_ticker.attach(&weather_tick, 900000.0f);
     // Listen on bluetooth.
-    dev_thread.start(dev_recv);
-    dev.printf("Hello, World!\n");
-    time_t prev_time = time(NULL);
+    //dev_thread.start(dev_recv);
     while(true) {
         time_t curr_time = time(NULL);
-        // if it's been an hour (divide by 3600 >= 60), pause and get weather:
-        if (((int)(curr_time - prev_time) / 3600) >= 60) {
-            //weather_updater();
-            prev_time = curr_time;
+        if (true) {
+            sprintf(cmd,
+                "GET /data/2.5/weather?lat=%0.4f&lon=%0.4f&APPID=%s\r\nHost: api.openweathermap.org\r\n\r\n",
+                latitude, longitude, weather_api_key);
+            forecast_sck.connect("api.openweathermap.org", 80);
+            wait(10);
+            forecast_sck.send_all(cmd, strlen(cmd));
+            wait(5);
+
+            len_read = wifi.recv(buffer, BUF_SIZE - 1, 0);
+
+            buffer[len_read] = '\0';
+
+    
+            dev.printf(buffer);
+
+            ind = strstr(buffer, "temp");
+            for (int m = 0; m < 15; m++) {
+                dev.putc(ind[m]);
+            }
+            num_ind = 0;
+            // go until we find numbers
+            while (char tmp = *ind++) {
+                dev.printf("CHAR: %c\r\n", tmp);
+                if (tmp > '0' && tmp < '9') {
+                    num_buf[num_ind++] = tmp;
+                    break;
+                }
+            }
+            // Keep moving until no more numbers
+            while (char tmp = *ind++) {
+                if (tmp > '9' || tmp < '0') {
+                    num_buf[num_ind] = '\0';
+                    break;
+                } else {
+                    num_buf[num_ind++] = tmp;
+                }
+            }
+            temp = atoi(num_buf);
+            dev.printf("Temperature: %s (%d)\r\n", num_buf, temp);
+            // Convert
+            temp = (((temp - 273.15f) * 9.0f) / 5.0f) + 32.0f;
+            sprintf(temp_buf, "   %dF", temp);
+            lcd_lock.lock();
+            uLCD.text_width(2);
+            uLCD.text_height(2);
+            uLCD.text_string(temp_buf, 0, 5, FONT_8X8, WHITE);
+            // done! unlock
+            lcd_lock.unlock();
         }
+
         err_led = !err_led;
-        //dev.printf("Connection Status: %d\n", wifi.is_connected());
-        wait(0.5);
     }
 }
+
+int main() {
+    clock_init();
+}