A weather station that uses GPS and WiFi to get the weather where you are. Almost better than actually going outside!

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

main.cpp

Committer:
krbng4180
Date:
2016-03-14
Revision:
1:fc07d1430053
Parent:
0:c4da54879553

File content as of revision 1:fc07d1430053:

#include "mbed.h"
#include "GPS.h"
#include "ESP8266Interface.h"
#include "MbedJSONValue.h"
#include "uLCD_4DGL.h"

#define DEBUG_MODE

#ifdef DEBUG_MODE
# define DEBUG(msg) pc.printf(msg)
# define DEBUGF(msgf) pc.printf msgf
#else
# define DEBUG(msg)
# define DEBUGF(msgf)
#endif

/* Lua code comes from here:
 *   https://learn.adafruit.com/adafruit-huzzah-esp8266-breakout/using-nodemcu-lua
 */
#define LUA(x) #x

#define SSID "ThisIsWiFi"
#define PWD "benandjerrys101"
#define API_KEY "f99ab4720b04e9a5"
#define FORECAST_API_KEY "9cfbfbf425552305838467b4b838b426"
#define WWO_API_KEY "43911d834dc04583b4e221235161303"

/*
 * The GPS unit continuously transmits data over serial in standard ASCII text.
 * Using this API, we call `gps.sample()` to get the most recent longitude and
 * latitude. To then read those values, we call `gps.longitude` and `gps.latitude`.
 *
 * Important:
 *      It is worth noting that `gps.sample()` is synchronous and blocking; because
 *      the GPS continously transmits data, `gps.sample()` can take a varying amount
 *      of time. The worst case scenario is that the GPS unit *just* transmitted the
 *      relevant information right before we call `gps.sample()`.  If we needed GPS
 *      information frequently, it would be prudent to move this to a separate thread
 *      and interface with that thread via mutex-protected global variables for 
 *      latitude and longitude.  
 */
GPS gps(p13, p14);

/*
 * Serial communications with the computer. Used for debugging.
 */
Serial pc(USBTX, USBRX);

/*
 * We communicate with the wifi firmware over serial. The firmware accepts
 * Lua commands, so we send those over serial.
 */
//Serial wifi(p9, p10);
ESP8266Interface esp(p9, p10, p8, 9600, 7000);

uLCD_4DGL uLCD(p28,p27,p30);

#define REQ_TEMPLATE_WWO "GET /free/v2/weather.ashx?key=%s&format=json&cc=yes&fx=no&q=%f,%f HTTP/1.1\r\nHost: api.worldweatheronline.com\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n"
#define REQ_TEMPLATE_WU "GET /api/%s/geolookup/q/%f,%f.json HTTP/1.1\r\nHost: api.wunderground.com\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n"
#define REQ_TEMPLATE "GET /forecast/%s/%f,%f?exclude=minutely,hourly,daily,alerts,flags HTTP/1.1\r\nHost: api.forecast.io\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n" 
static char http_request_buf[512] = { 0 };

#define RESP_LEN 2048
static char http_response_buf[RESP_LEN] = { 0 };
static int http_response_len = RESP_LEN;

/*
 * Prints to LCD, theoretically.  It's not very pretty.
*/

void draw_values (const char * weather, const char * temp) {
    uLCD.printf("\n Current Conditions:");
    uLCD.text_width(2);
    uLCD.text_height(2);
    uLCD.printf(temp);
    uLCD.printf(" F\n");
    uLCD.text_width(1);
    uLCD.text_height(1);
    uLCD.printf(weather);
}

/*
 * Parse location from geolocation response.
*/

void parse_response (char * resp_buff) {
    MbedJSONValue parsed;
    parse(parsed, resp_buff);
    MbedJSONValue &inst = parsed["data"]["current_condition"][0];
//    const string &citystate = inst["city"].get<string>() + ", " + inst["state"].get<string>();
//    string[2] ar;
    const char* weather = inst["wetherDesc"][0]["value"].get<string>().c_str();
    const char* temp = inst["temp_f"].get<string>().c_str();
    //if we want an icon, inst["weatherIconUrl"][0]["value"].get<string>(); gets the URL
    draw_values(weather, temp);
}

static char * get_weather_json(double latitude, double longitude)
{
    int http_request_len = sprintf(http_request_buf, REQ_TEMPLATE_WWO, WWO_API_KEY, latitude, longitude);
    /* Send HTTP request */
    bool sent = false;
    do {
        sent = esp.send(http_request_buf, http_request_len);
        DEBUGF(("Request sent: %d\n\r", sent));
    } while (!sent);
    
    DEBUGF(("%s", http_request_buf));
    
    wait(3);
    
    bool recv = false;
    do {
        http_response_len = RESP_LEN;
        recv = esp.recv(http_response_buf, &http_response_len);
        DEBUGF(("Request recv: %d\n\r", recv));
        DEBUGF(("Response: %s\n\r", http_response_buf));
        DEBUGF(("Response Length: %d\n\r", http_response_len));
        wait(2);
    } while (!recv);
    
    return http_response_buf;
}

int main() {
    
    //wifi.attach(&wifi_rx_handler, Serial::RxIrq);
    //wifi.attach(&wifi_tx_handler, Serial::TxIrq);
    
    //wifi.baud(9600);
    pc.baud(9600);
    pc.printf("HELLO WORLD\n\r");
    /*
     * Intialize connection to AP.
     */
    esp.init();
    
    bool connected = false;
    do {
        connected = esp.connect(SSID, PWD);
        DEBUGF(("Connected to AP: %d\n\r", connected));
    } while (!connected);
    
    /* Perform DNS lookup */
    
    char ip[12] = { 0 };
    bool dns_success = false;
    do {
        dns_success = esp.getHostByName("api.worldweatheronline.com", ip);
        DEBUGF(("IP: %s\n\r", ip));
    } while (!dns_success);
    
    /* Open connection */
    
    bool opened = false;
    do {
        opened = esp.open(1, ip, 80);
        DEBUGF(("Connection opened: %d\n\r", opened));
    } while (!opened);
    
    /* Generate HTTP request */
    gps.sample();
    get_weather_json(gps.latitude, gps.longitude + 56);
    //int http_request_len = sprintf(http_request_buf, REQ_TEMPLATE_WWO, WWO_API_KEY, gps.latitude, gps.longitude + 56);
//    /* Send HTTP request */
//    bool sent = false;
//    do {
//        sent = esp.send(http_request_buf, http_request_len);
//        DEBUGF(("Request sent: %d\n\r", sent));
//    } while (!sent);
//    
//    DEBUGF(("%s", http_request_buf));
//    
//    wait(3);
//    
//    bool recv = false;
//    do {
//        http_response_len = RESP_LEN;
//        recv = esp.recv(http_response_buf, &http_response_len);
//        DEBUGF(("Request recv: %d\n\r", recv));
//        DEBUGF(("Response: %s\n\r", http_response_buf));
//        DEBUGF(("Response Length: %d\n\r", http_response_len));
//        wait(2);
//    } while (!recv);
    
    while (1) {
    }
        
}