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) { } }