Fork from Alex

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

main.cpp

Committer:
alexhrao
Date:
2019-03-31
Revision:
3:7bf41989ff8f
Parent:
2:f7d19812bdc5
Child:
4:55f0c303f56a

File content as of revision 3:7bf41989ff8f:

#include "mbed.h"
#include "uLCD_4DGL.h"
#include "ESP8266Interface.h"
#include "TCPSocketConnection.h"
#include "rtos.h"
#include "MbedJSONValue.h"
#include <string>

#define BUF_SIZE 4096

// We need this for being able to reset the MBED (similar to watch dogs)
extern "C" void mbed_reset();

// LCD Screen
uLCD_4DGL uLCD(p9, p10, p11);
Mutex lcd_lock;

// File System
LocalFileSystem fs("local");

// Bluetooth
RawSerial pc(USBTX, USBRX);
RawSerial dev(p28,p27);
Thread dev_thread;

// Error LED
DigitalOut err_led(LED1);

// WiFi
ESP8266Interface wifi(p13, p14, p15, 9600, 10000);

// 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;

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
    struct tm* ltm;
    time_t now;
    
    now = time(NULL);
    ltm = localtime(&now);
    
    // Buffer for time string. Max length is 23:59 + \0
    int max_time_len = 6;
    char ftime[max_time_len];
    
    int min = -1;
    
    while (true) {
        // if the minute has changed, update.
        now = time(NULL);
        ltm = localtime(&now);
        if(ltm->tm_min != min) {
            // Get the new time
            strftime(ftime, max_time_len, "%H:%M", ltm); 
            // Update time! Lock the lcd mutex
            lcd_lock.lock();
            uLCD.text_width(2);
            uLCD.text_height(2);
            uLCD.text_string(ftime, 0, 2, FONT_8X8, GREEN);
            // Done updating - unlock!
            lcd_lock.unlock();
            min = ltm->tm_min;
        }
        // Wait 1 second
        Thread::wait(1.0f);
    }   
}

void weather_updater() {
    // We can take as long as we want
    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();
    }
}

void dev_recv() {
    // Continually check if we have stuff...
    char buf[1024];
    int ind = 0;
    while (true) {
        while (true) {
            // get stuff. If we encounter \r or \n, that's a complete command!
            char tmp = dev.getc();
            if (tmp == '\n' || tmp == '\r') {
                break;
            }
            buf[ind++] = tmp;
            Thread::wait(0.01);
        }
        buf[ind] = '\0';
        // read command and respond
        if (strcmp(buf, "reset") == 0) {
            dev.printf("Are you sure? y/[n]\n");
        }
        buf[0] = '\0';
        ind = 0;
        //if (strcmp(buf, "reset") != 0) {
        Thread::wait(0.01);
    }
}

int main() {
    // Set up bluetooth
    dev.baud(9600);
    pc.baud(9600);
    
    // Tell user we're initializing...
    lcd_lock.lock();
    uLCD.cls();
    uLCD.text_height(2);
    uLCD.text_string("PLEASE WAIT", 0, 2, FONT_7X8, WHITE);
    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];
    
    if (true) {
        
    } else if (fid != NULL) {
        // Read WiFi Settings
        char settings_buf[1024];
        // Guaranteed to be 256, 256, 512 AT MOST + two new lines
        // 
        fgets(settings_buf, 1024, fid);
        // find \n
        int settings_ind = 0;
        int counter = 0;
        while (settings_buf[counter] != '\n') {
            ssid[settings_ind++] = settings_buf[counter++];
        }
        ssid[settings_ind] = '\0';
        settings_ind = 0;
        counter++;
        while (settings_buf[counter] != '\n') {
            pass[settings_ind++] = settings_buf[counter++];
        }
        pass[settings_ind] = '\0';
        settings_ind = 0;
        counter++;
        while (settings_buf[counter] != '\n') {
            api_key[settings_ind++] = settings_buf[counter++];
        }
        api_key[settings_ind] = '\0';
        fclose(fid);
    } else {
        lcd_lock.lock();
        uLCD.cls();
        uLCD.text_height(2);
        uLCD.text_width(2);
        uLCD.text_string("SEE", 0, 2, FONT_7X8, RED);
        uLCD.text_string("DEVICE", 0, 5, FONT_7X8, RED);
        lcd_lock.unlock();
        
        // Ask!
        dev.printf("Please provide the name of a WiFi Network\n");
        
        // Wait for them to respond
        while (!dev.readable()) {
            wait(0.001);
        }
        int ind = 0;
        
        // Read response
        while (ind < 255) {
            char tmp = dev.getc();
            if (tmp == '\n' || tmp == '\r') {
                break;
            }
            ssid[ind++] = tmp;
            wait(0.01);
        }
        ssid[ind] = '\0';
        
        // flush device
        while (dev.readable()) {
            dev.getc();
            wait(0.01);
        }
        
        // Get the password
        dev.printf("Please provide the password\n");
        while (!dev.readable()) {
            wait(0.001);
        }
        ind = 0;
        while (ind < 255) {
            char tmp = dev.getc();
            if (tmp == '\n' || tmp == '\r') {
                break;
            }
            pass[ind++] = tmp;
            wait(0.01);
        }
        pass[ind] = '\0';
        
        // Get the API key
        dev.printf("Please provide the API key\n");
        while (!dev.readable()) {
            wait(0.001);
        }
        ind = 0;
        while (ind < 255) {
            char tmp = dev.getc();
            if (tmp == '\n' || tmp == '\r') {
                break;
            }
            api_key[ind++] = tmp;
            wait(0.01);
        }
        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);
    }
    char* tmp = "af9319bf6435ddd9bb640f763ff64d34";
    for (int i = 0; i < strlen(tmp); i++) {
        api_key[i] = tmp[i];
    }
    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
    dev.printf("Getting the current location...\n");
    TCPSocketConnection tcp;
    tcp.connect("api.ipstack.com", 80);
    
    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(10);
    
    char buffer[BUF_SIZE];
    int read_len = wifi.recv(buffer, BUF_SIZE - 1, 0);
    buffer[read_len] = '\0';
    
    MbedJSONValue parser;
    parse(parser, buffer);
    // for now, just print...
    
    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);
    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);
    
    // Clear the LCD Screen first
    lcd_lock.lock();
    uLCD.cls();
    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);
    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;
        }
        err_led = !err_led;
        //dev.printf("Connection Status: %d\n", wifi.is_connected());
        wait(0.5);
    }
}