Displays the current weather, date, and time

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

Welcome to the Smart Weather Clock, which uses WiFi and Bluetooth to give the user a clear date, time, and weather for the day.

This wiki serves to document

  • What components you'll need
  • How these components will be connected
  • How the code gets all the information it needs

Components

LCD Screen

Components / 4D Systems 128 by 128 Smart Color LCD uLCD-144-G2
128 by 128 Color Smart LCD with serial interface and SD card slot

The LCD screen is a 128x128 pixel full color LCD by 4D Systems. A wonderful introduction can be found here.

In the simplest case, we'll only use one screen, but we can (and perhaps should) augment the design to include two.

Import library4DGL-uLCD-SE

Fork of 4DGL lib for uLCD-144-G2. Different command values needed. See https://mbed.org/users/4180_1/notebook/ulcd-144-g2-128-by-128-color-lcd/ for instructions and demo code.

You can buy it from sparkfun.

5V Adapter

The adapter allows us to feed much more power to the MBED and, critically, decouples us from a computer. It's important to remember that on the barrel jack adapter (i.e., the part that goes in the breadboard), the pin closest to the jack is 5V, and the back pin is Ground.

You can get the adapter here, and the barrel jack adapter here

Bluetooth UART Module

This module allows us to interface with the mbed via bluetooth and the ever-helpful AdaFruit Bluetooth App. A great introduction can be found here.

We'll use it to allow the user to set some defaults and API keys. This is stored in persistent flash storage on the LPC 1768 (See the Local File System, but you'll need an SD card if you're using a different MBED device.

You can get the Bluetooth module here.

WiFi Module

The WiFi module is also from AdaFruit, like the Bluetooth module. This allows us to interface with different WiFi networks for internet connectivity. A nice introduction is here.

You can get the WiFi module here.

WiFi Interface!

The current WiFi interface (found here) has some major problems - we're using an augmented version in our code!

Connections

5V Input for MBED

Before you connect the MBED to 5V from the wall, Make sure you have connected it correctly! If you don't, you could brick the MBED.

Thankfully, this is easy to test - when you think you have hooked up the 5V Jack correctly, try lighting a single LED (with a 10K resistor in series). If it lights up - you're good!

Alternatively, you could just plug in the MBED via USB, and just not have the MBED run on the +5V. You'll still need the Wall Adapter, however.

WiFi Module

The WiFi Module has two Grounds - you must connect both!

MBED5V Barrel Jack
Vin+5V (back pin)
GndGnd (pin closest to jack)
MBEDuLCD Cable
5V5V
GndGnd
P09TX
P10RX
P11Reset
MBEDBluetooth UART
5VVin
GndGnd
GndCTS
P27TXO
P28RXI
MBEDWiFi Module
5VV+
GndGnd
GndGnd
P13RX
P14TX
P15Reset

Code

The code works in a fairly logical order:

  1. Connect to the given WiFi, and check that we have all of our API keys
  2. Get the current location via the IP API
  3. Get the current time via the TimeZoneDB
  4. Get the current weather via the OpenWeatherMap API
  5. Continually update the weather, once per minute

Some caveats:

  • Memory seems to be an issue. If I had to guess, it would be the MbedJSONValue JSON parser - instantiating a third one seems to always lead to an MBED OS Fault or an MBED Memory Allocation fault. More insight is needed here.
  • The off-the-shelf ESP8226 Interface doesn't handle receiving correctly - I had to augment the library with recv and recv2. It works in most simple practical use cases.
Committer:
alexhrao
Date:
Mon Apr 01 16:54:53 2019 +0000
Revision:
6:ec7829f7cd38
Parent:
5:b77a717feada
Child:
8:d323c6406b47
Clean up device printing and comments

Who changed what in which revision?

UserRevisionLine numberNew contents of line
alexhrao 0:4ffa136585a2 1 #include "mbed.h"
alexhrao 1:0620ba35d2e8 2 #include "uLCD_4DGL.h"
alexhrao 1:0620ba35d2e8 3 #include "ESP8266Interface.h"
alexhrao 1:0620ba35d2e8 4 #include "TCPSocketConnection.h"
alexhrao 1:0620ba35d2e8 5 #include "rtos.h"
alexhrao 3:7bf41989ff8f 6 #include "MbedJSONValue.h"
alexhrao 3:7bf41989ff8f 7 #include <string>
alexhrao 3:7bf41989ff8f 8
alexhrao 3:7bf41989ff8f 9 #define BUF_SIZE 4096
alexhrao 1:0620ba35d2e8 10
alexhrao 1:0620ba35d2e8 11 // We need this for being able to reset the MBED (similar to watch dogs)
alexhrao 1:0620ba35d2e8 12 extern "C" void mbed_reset();
alexhrao 1:0620ba35d2e8 13
alexhrao 1:0620ba35d2e8 14 // LCD Screen
alexhrao 1:0620ba35d2e8 15 uLCD_4DGL uLCD(p9, p10, p11);
alexhrao 1:0620ba35d2e8 16 Mutex lcd_lock;
alexhrao 1:0620ba35d2e8 17
alexhrao 1:0620ba35d2e8 18 // File System
alexhrao 1:0620ba35d2e8 19 LocalFileSystem fs("local");
alexhrao 1:0620ba35d2e8 20
alexhrao 1:0620ba35d2e8 21 // Bluetooth
alexhrao 1:0620ba35d2e8 22 RawSerial pc(USBTX, USBRX);
alexhrao 1:0620ba35d2e8 23 RawSerial dev(p28,p27);
alexhrao 1:0620ba35d2e8 24
alexhrao 1:0620ba35d2e8 25 // Error LED
alexhrao 1:0620ba35d2e8 26 DigitalOut err_led(LED1);
alexhrao 1:0620ba35d2e8 27
alexhrao 1:0620ba35d2e8 28 // WiFi
alexhrao 1:0620ba35d2e8 29 ESP8266Interface wifi(p13, p14, p15, 9600, 10000);
alexhrao 1:0620ba35d2e8 30
alexhrao 1:0620ba35d2e8 31 // Time
alexhrao 1:0620ba35d2e8 32 Thread time_thread;
alexhrao 1:0620ba35d2e8 33
alexhrao 3:7bf41989ff8f 34 // Location
alexhrao 3:7bf41989ff8f 35 double latitude = 0;
alexhrao 3:7bf41989ff8f 36 double longitude = 0;
alexhrao 0:4ffa136585a2 37
alexhrao 4:55f0c303f56a 38 // Credentials
alexhrao 4:55f0c303f56a 39 char ssid[256];
alexhrao 4:55f0c303f56a 40 char pass[256];
alexhrao 4:55f0c303f56a 41 char ip_api_key[256];
alexhrao 4:55f0c303f56a 42 char time_api_key[256];
alexhrao 4:55f0c303f56a 43 char weather_api_key[256];
alexhrao 4:55f0c303f56a 44
alexhrao 1:0620ba35d2e8 45 void time_updater() {
alexhrao 1:0620ba35d2e8 46 // We're not an interrupt, so take as much time as we need. Infinite loop
alexhrao 1:0620ba35d2e8 47 // but wait 1 second between each loop
alexhrao 1:0620ba35d2e8 48 struct tm* ltm;
alexhrao 1:0620ba35d2e8 49 time_t now;
alexhrao 1:0620ba35d2e8 50
alexhrao 1:0620ba35d2e8 51 now = time(NULL);
alexhrao 1:0620ba35d2e8 52 ltm = localtime(&now);
alexhrao 1:0620ba35d2e8 53
alexhrao 1:0620ba35d2e8 54 // Buffer for time string. Max length is 23:59 + \0
alexhrao 4:55f0c303f56a 55 int max_time_len = 8;
alexhrao 1:0620ba35d2e8 56 char ftime[max_time_len];
alexhrao 4:55f0c303f56a 57 ftime[0] = ' ';
alexhrao 4:55f0c303f56a 58 ftime[1] = ' ';
alexhrao 1:0620ba35d2e8 59 int min = -1;
alexhrao 1:0620ba35d2e8 60
alexhrao 1:0620ba35d2e8 61 while (true) {
alexhrao 1:0620ba35d2e8 62 // if the minute has changed, update.
alexhrao 1:0620ba35d2e8 63 now = time(NULL);
alexhrao 1:0620ba35d2e8 64 ltm = localtime(&now);
alexhrao 1:0620ba35d2e8 65 if(ltm->tm_min != min) {
alexhrao 1:0620ba35d2e8 66 // Get the new time
alexhrao 4:55f0c303f56a 67 strftime(ftime + 2, max_time_len, "%H:%M", ltm);
alexhrao 1:0620ba35d2e8 68 // Update time! Lock the lcd mutex
alexhrao 1:0620ba35d2e8 69 lcd_lock.lock();
alexhrao 1:0620ba35d2e8 70 uLCD.text_width(2);
alexhrao 1:0620ba35d2e8 71 uLCD.text_height(2);
alexhrao 1:0620ba35d2e8 72 uLCD.text_string(ftime, 0, 2, FONT_8X8, GREEN);
alexhrao 1:0620ba35d2e8 73 // Done updating - unlock!
alexhrao 1:0620ba35d2e8 74 lcd_lock.unlock();
alexhrao 1:0620ba35d2e8 75 min = ltm->tm_min;
alexhrao 1:0620ba35d2e8 76 }
alexhrao 1:0620ba35d2e8 77 // Wait 1 second
alexhrao 1:0620ba35d2e8 78 Thread::wait(1.0f);
alexhrao 1:0620ba35d2e8 79 }
alexhrao 1:0620ba35d2e8 80 }
alexhrao 1:0620ba35d2e8 81
alexhrao 1:0620ba35d2e8 82 void dev_recv() {
alexhrao 1:0620ba35d2e8 83 // Continually check if we have stuff...
alexhrao 1:0620ba35d2e8 84 char buf[1024];
alexhrao 1:0620ba35d2e8 85 int ind = 0;
alexhrao 1:0620ba35d2e8 86 while (true) {
alexhrao 1:0620ba35d2e8 87 while (true) {
alexhrao 1:0620ba35d2e8 88 // get stuff. If we encounter \r or \n, that's a complete command!
alexhrao 1:0620ba35d2e8 89 char tmp = dev.getc();
alexhrao 1:0620ba35d2e8 90 if (tmp == '\n' || tmp == '\r') {
alexhrao 1:0620ba35d2e8 91 break;
alexhrao 1:0620ba35d2e8 92 }
alexhrao 1:0620ba35d2e8 93 buf[ind++] = tmp;
alexhrao 1:0620ba35d2e8 94 Thread::wait(0.01);
alexhrao 1:0620ba35d2e8 95 }
alexhrao 1:0620ba35d2e8 96 buf[ind] = '\0';
alexhrao 1:0620ba35d2e8 97 // read command and respond
alexhrao 1:0620ba35d2e8 98 if (strcmp(buf, "reset") == 0) {
alexhrao 1:0620ba35d2e8 99 dev.printf("Are you sure? y/[n]\n");
alexhrao 1:0620ba35d2e8 100 }
alexhrao 1:0620ba35d2e8 101 buf[0] = '\0';
alexhrao 1:0620ba35d2e8 102 ind = 0;
alexhrao 1:0620ba35d2e8 103 //if (strcmp(buf, "reset") != 0) {
alexhrao 1:0620ba35d2e8 104 Thread::wait(0.01);
alexhrao 1:0620ba35d2e8 105 }
alexhrao 2:f7d19812bdc5 106 }
alexhrao 0:4ffa136585a2 107
alexhrao 4:55f0c303f56a 108 int kelvin2farenheit(int temp) {
alexhrao 4:55f0c303f56a 109 return (int)((((temp - 273.15f) * 9.0f) / 5.0f) + 32.0f);
alexhrao 4:55f0c303f56a 110 }
alexhrao 4:55f0c303f56a 111
alexhrao 4:55f0c303f56a 112 void clock_init() {
alexhrao 1:0620ba35d2e8 113 // Set up bluetooth
alexhrao 1:0620ba35d2e8 114 dev.baud(9600);
alexhrao 1:0620ba35d2e8 115 pc.baud(9600);
alexhrao 2:f7d19812bdc5 116
alexhrao 1:0620ba35d2e8 117 // Tell user we're initializing...
alexhrao 1:0620ba35d2e8 118 lcd_lock.lock();
alexhrao 1:0620ba35d2e8 119 uLCD.cls();
alexhrao 1:0620ba35d2e8 120 uLCD.text_height(2);
alexhrao 6:ec7829f7cd38 121 uLCD.text_width(2);
alexhrao 6:ec7829f7cd38 122 uLCD.text_string("PLEASE", 0, 2, FONT_7X8, WHITE);
alexhrao 6:ec7829f7cd38 123 uLCD.text_string("WAIT", 0, 5, FONT_7X8, WHITE);
alexhrao 1:0620ba35d2e8 124 lcd_lock.unlock();
alexhrao 2:f7d19812bdc5 125
alexhrao 1:0620ba35d2e8 126 // Need to get wifi settings. If we don't have local file, then ask!
alexhrao 4:55f0c303f56a 127 FILE* fid = fopen("/local/settings.txt", "r");
alexhrao 3:7bf41989ff8f 128
alexhrao 4:55f0c303f56a 129 if (fid != NULL) {
alexhrao 2:f7d19812bdc5 130 // Read WiFi Settings
alexhrao 2:f7d19812bdc5 131 char settings_buf[1024];
alexhrao 4:55f0c303f56a 132 // Guaranteed to be 5 lines
alexhrao 2:f7d19812bdc5 133 //
alexhrao 2:f7d19812bdc5 134 fgets(settings_buf, 1024, fid);
alexhrao 2:f7d19812bdc5 135 // find \n
alexhrao 2:f7d19812bdc5 136 int settings_ind = 0;
alexhrao 2:f7d19812bdc5 137 int counter = 0;
alexhrao 2:f7d19812bdc5 138 while (settings_buf[counter] != '\n') {
alexhrao 2:f7d19812bdc5 139 ssid[settings_ind++] = settings_buf[counter++];
alexhrao 2:f7d19812bdc5 140 }
alexhrao 2:f7d19812bdc5 141 ssid[settings_ind] = '\0';
alexhrao 2:f7d19812bdc5 142 settings_ind = 0;
alexhrao 4:55f0c303f56a 143 fgets(settings_buf, 1024, fid);
alexhrao 4:55f0c303f56a 144 counter = 0;
alexhrao 2:f7d19812bdc5 145 while (settings_buf[counter] != '\n') {
alexhrao 2:f7d19812bdc5 146 pass[settings_ind++] = settings_buf[counter++];
alexhrao 2:f7d19812bdc5 147 }
alexhrao 2:f7d19812bdc5 148 pass[settings_ind] = '\0';
alexhrao 2:f7d19812bdc5 149 settings_ind = 0;
alexhrao 4:55f0c303f56a 150 fgets(settings_buf, 1024, fid);
alexhrao 4:55f0c303f56a 151 counter = 0;
alexhrao 4:55f0c303f56a 152 while (settings_buf[counter] != '\n') {
alexhrao 4:55f0c303f56a 153 ip_api_key[settings_ind++] = settings_buf[counter++];
alexhrao 4:55f0c303f56a 154 }
alexhrao 4:55f0c303f56a 155 ip_api_key[settings_ind] = '\0';
alexhrao 4:55f0c303f56a 156 settings_ind = 0;
alexhrao 4:55f0c303f56a 157 fgets(settings_buf, 1024, fid);
alexhrao 4:55f0c303f56a 158 counter = 0;
alexhrao 2:f7d19812bdc5 159 while (settings_buf[counter] != '\n') {
alexhrao 4:55f0c303f56a 160 time_api_key[settings_ind++] = settings_buf[counter++];
alexhrao 2:f7d19812bdc5 161 }
alexhrao 4:55f0c303f56a 162 time_api_key[settings_ind] = '\0';
alexhrao 4:55f0c303f56a 163 settings_ind = 0;
alexhrao 4:55f0c303f56a 164 fgets(settings_buf, 1024, fid);
alexhrao 4:55f0c303f56a 165 counter = 0;
alexhrao 4:55f0c303f56a 166 while (settings_buf[counter] != '\n') {
alexhrao 4:55f0c303f56a 167 weather_api_key[settings_ind++] = settings_buf[counter++];
alexhrao 4:55f0c303f56a 168 }
alexhrao 4:55f0c303f56a 169 weather_api_key[settings_ind] = '\0';
alexhrao 2:f7d19812bdc5 170 fclose(fid);
alexhrao 1:0620ba35d2e8 171 } else {
alexhrao 1:0620ba35d2e8 172 lcd_lock.lock();
alexhrao 1:0620ba35d2e8 173 uLCD.cls();
alexhrao 1:0620ba35d2e8 174 uLCD.text_height(2);
alexhrao 1:0620ba35d2e8 175 uLCD.text_width(2);
alexhrao 1:0620ba35d2e8 176 uLCD.text_string("SEE", 0, 2, FONT_7X8, RED);
alexhrao 1:0620ba35d2e8 177 uLCD.text_string("DEVICE", 0, 5, FONT_7X8, RED);
alexhrao 1:0620ba35d2e8 178 lcd_lock.unlock();
alexhrao 2:f7d19812bdc5 179
alexhrao 1:0620ba35d2e8 180 // Ask!
alexhrao 1:0620ba35d2e8 181 dev.printf("Please provide the name of a WiFi Network\n");
alexhrao 2:f7d19812bdc5 182
alexhrao 1:0620ba35d2e8 183 // Wait for them to respond
alexhrao 1:0620ba35d2e8 184 while (!dev.readable()) {
alexhrao 1:0620ba35d2e8 185 wait(0.001);
alexhrao 1:0620ba35d2e8 186 }
alexhrao 1:0620ba35d2e8 187 int ind = 0;
alexhrao 2:f7d19812bdc5 188
alexhrao 1:0620ba35d2e8 189 // Read response
alexhrao 1:0620ba35d2e8 190 while (ind < 255) {
alexhrao 1:0620ba35d2e8 191 char tmp = dev.getc();
alexhrao 1:0620ba35d2e8 192 if (tmp == '\n' || tmp == '\r') {
alexhrao 1:0620ba35d2e8 193 break;
alexhrao 1:0620ba35d2e8 194 }
alexhrao 1:0620ba35d2e8 195 ssid[ind++] = tmp;
alexhrao 1:0620ba35d2e8 196 wait(0.01);
alexhrao 1:0620ba35d2e8 197 }
alexhrao 1:0620ba35d2e8 198 ssid[ind] = '\0';
alexhrao 1:0620ba35d2e8 199
alexhrao 1:0620ba35d2e8 200 // flush device
alexhrao 1:0620ba35d2e8 201 while (dev.readable()) {
alexhrao 1:0620ba35d2e8 202 dev.getc();
alexhrao 1:0620ba35d2e8 203 wait(0.01);
alexhrao 1:0620ba35d2e8 204 }
alexhrao 1:0620ba35d2e8 205
alexhrao 2:f7d19812bdc5 206 // Get the password
alexhrao 1:0620ba35d2e8 207 dev.printf("Please provide the password\n");
alexhrao 1:0620ba35d2e8 208 while (!dev.readable()) {
alexhrao 1:0620ba35d2e8 209 wait(0.001);
alexhrao 1:0620ba35d2e8 210 }
alexhrao 1:0620ba35d2e8 211 ind = 0;
alexhrao 1:0620ba35d2e8 212 while (ind < 255) {
alexhrao 1:0620ba35d2e8 213 char tmp = dev.getc();
alexhrao 1:0620ba35d2e8 214 if (tmp == '\n' || tmp == '\r') {
alexhrao 1:0620ba35d2e8 215 break;
alexhrao 1:0620ba35d2e8 216 }
alexhrao 1:0620ba35d2e8 217 pass[ind++] = tmp;
alexhrao 1:0620ba35d2e8 218 wait(0.01);
alexhrao 1:0620ba35d2e8 219 }
alexhrao 1:0620ba35d2e8 220 pass[ind] = '\0';
alexhrao 2:f7d19812bdc5 221
alexhrao 2:f7d19812bdc5 222 // Get the API key
alexhrao 4:55f0c303f56a 223 dev.printf("Please provide the IP Stack API key\n");
alexhrao 2:f7d19812bdc5 224 while (!dev.readable()) {
alexhrao 2:f7d19812bdc5 225 wait(0.001);
alexhrao 2:f7d19812bdc5 226 }
alexhrao 2:f7d19812bdc5 227 ind = 0;
alexhrao 2:f7d19812bdc5 228 while (ind < 255) {
alexhrao 2:f7d19812bdc5 229 char tmp = dev.getc();
alexhrao 2:f7d19812bdc5 230 if (tmp == '\n' || tmp == '\r') {
alexhrao 2:f7d19812bdc5 231 break;
alexhrao 2:f7d19812bdc5 232 }
alexhrao 4:55f0c303f56a 233 ip_api_key[ind++] = tmp;
alexhrao 4:55f0c303f56a 234 wait(0.01);
alexhrao 4:55f0c303f56a 235 }
alexhrao 4:55f0c303f56a 236
alexhrao 4:55f0c303f56a 237 ip_api_key[ind] = '\0';
alexhrao 4:55f0c303f56a 238
alexhrao 4:55f0c303f56a 239 dev.printf("Please provide the TimeZoneDB API key\n");
alexhrao 4:55f0c303f56a 240 while (!dev.readable()) {
alexhrao 4:55f0c303f56a 241 wait(0.001);
alexhrao 4:55f0c303f56a 242 }
alexhrao 4:55f0c303f56a 243 ind = 0;
alexhrao 4:55f0c303f56a 244 while (ind < 255) {
alexhrao 4:55f0c303f56a 245 char tmp = dev.getc();
alexhrao 4:55f0c303f56a 246 if (tmp == '\r' || tmp == '\n') {
alexhrao 4:55f0c303f56a 247 break;
alexhrao 4:55f0c303f56a 248 }
alexhrao 4:55f0c303f56a 249 time_api_key[ind++] = tmp;
alexhrao 2:f7d19812bdc5 250 wait(0.01);
alexhrao 2:f7d19812bdc5 251 }
alexhrao 4:55f0c303f56a 252 time_api_key[ind] = '\0';
alexhrao 4:55f0c303f56a 253
alexhrao 4:55f0c303f56a 254 dev.printf("Please provide the OpenWeather API key\n");
alexhrao 4:55f0c303f56a 255 while (!dev.readable()) {
alexhrao 4:55f0c303f56a 256 wait(0.001);
alexhrao 4:55f0c303f56a 257 }
alexhrao 4:55f0c303f56a 258 ind = 0;
alexhrao 4:55f0c303f56a 259 while (ind < 255) {
alexhrao 4:55f0c303f56a 260 char tmp = dev.getc();
alexhrao 4:55f0c303f56a 261 if (tmp == '\r' || tmp == '\n') {
alexhrao 4:55f0c303f56a 262 break;
alexhrao 4:55f0c303f56a 263 }
alexhrao 4:55f0c303f56a 264 weather_api_key[ind++] = tmp;
alexhrao 4:55f0c303f56a 265 wait(0.01);
alexhrao 4:55f0c303f56a 266 }
alexhrao 4:55f0c303f56a 267 weather_api_key[ind] = '\0';
alexhrao 4:55f0c303f56a 268
alexhrao 4:55f0c303f56a 269
alexhrao 4:55f0c303f56a 270
alexhrao 1:0620ba35d2e8 271 // Because this is a simple proof of concept, we store the password in
alexhrao 1:0620ba35d2e8 272 // plaintext. It should be noted, however, that you **should never do
alexhrao 1:0620ba35d2e8 273 // this in "real life"**
alexhrao 4:55f0c303f56a 274 fid = fopen("/local/settings.txt", "w");
alexhrao 4:55f0c303f56a 275 fprintf(fid, "%s\n%s\n%s\n%s\n%s\n", ssid, pass, ip_api_key, time_api_key, weather_api_key);
alexhrao 4:55f0c303f56a 276 fclose(fid);
alexhrao 1:0620ba35d2e8 277 }
alexhrao 6:ec7829f7cd38 278 /*
alexhrao 4:55f0c303f56a 279 dev.printf("\r\n** CREDENTIALS **\r\n");
alexhrao 4:55f0c303f56a 280 dev.printf("SSID: **%s** (%d)\r\n", ssid, strlen(ssid));
alexhrao 4:55f0c303f56a 281 dev.printf("PASS: **%s** (%d)\r\n", pass, strlen(pass));
alexhrao 4:55f0c303f56a 282 dev.printf("IP STACK: **%s**\r\n", ip_api_key);
alexhrao 4:55f0c303f56a 283 dev.printf("TIMEZONEDB: **%s**\r\n", time_api_key);
alexhrao 4:55f0c303f56a 284 dev.printf("WEATHERMAP: **%s**\r\n", weather_api_key);
alexhrao 6:ec7829f7cd38 285 */
alexhrao 1:0620ba35d2e8 286 bool res = wifi.init();
alexhrao 4:55f0c303f56a 287
alexhrao 1:0620ba35d2e8 288 // Set up the WiFi Access Point
alexhrao 1:0620ba35d2e8 289 dev.printf("Connecting to WiFi %s with Password %s\n", ssid, pass);
alexhrao 4:55f0c303f56a 290
alexhrao 5:b77a717feada 291 res = wifi.connect(ssid, pass);
alexhrao 2:f7d19812bdc5 292 if (!res) {
alexhrao 2:f7d19812bdc5 293 dev.printf("Connection Failed... Resetting Device\n");
alexhrao 2:f7d19812bdc5 294 err_led = 1;
alexhrao 2:f7d19812bdc5 295 mbed_reset();
alexhrao 2:f7d19812bdc5 296 }
alexhrao 4:55f0c303f56a 297
alexhrao 2:f7d19812bdc5 298 dev.printf("Connected with IP Address: %s\n", wifi.getIPAddress());
alexhrao 2:f7d19812bdc5 299
alexhrao 4:55f0c303f56a 300 /** API REQUESTS **/
alexhrao 4:55f0c303f56a 301
alexhrao 4:55f0c303f56a 302 int header_ind = 0;
alexhrao 4:55f0c303f56a 303 int footer_ind = 0;
alexhrao 4:55f0c303f56a 304 int read_len = 0;
alexhrao 4:55f0c303f56a 305 char buffer[BUF_SIZE];
alexhrao 4:55f0c303f56a 306 char cmd[512];
alexhrao 4:55f0c303f56a 307
alexhrao 3:7bf41989ff8f 308 TCPSocketConnection tcp;
alexhrao 3:7bf41989ff8f 309 tcp.connect("api.ipstack.com", 80);
alexhrao 6:ec7829f7cd38 310
alexhrao 4:55f0c303f56a 311 sprintf(cmd,
alexhrao 4:55f0c303f56a 312 "GET /check?access_key=%s HTTP/1.1\r\nHost: api.ipstack.com\r\n\r\n",
alexhrao 4:55f0c303f56a 313 ip_api_key);
alexhrao 4:55f0c303f56a 314 tcp.send_all(cmd, strlen(cmd));
alexhrao 3:7bf41989ff8f 315
alexhrao 4:55f0c303f56a 316 wait(5);
alexhrao 3:7bf41989ff8f 317
alexhrao 4:55f0c303f56a 318 read_len = wifi.recv(buffer, BUF_SIZE - 1, 0);
alexhrao 3:7bf41989ff8f 319 buffer[read_len] = '\0';
alexhrao 3:7bf41989ff8f 320
alexhrao 4:55f0c303f56a 321 // Cleanup
alexhrao 4:55f0c303f56a 322
alexhrao 4:55f0c303f56a 323 while (header_ind < read_len) {
alexhrao 4:55f0c303f56a 324 // if we are \r, look ahead to see \n\r\n:
alexhrao 4:55f0c303f56a 325 if(buffer[header_ind] == '\r' &&
alexhrao 4:55f0c303f56a 326 buffer[header_ind+1] == '\n' &&
alexhrao 4:55f0c303f56a 327 buffer[header_ind+2] == '\r' &&
alexhrao 4:55f0c303f56a 328 buffer[header_ind+3] == '\n') {
alexhrao 4:55f0c303f56a 329 // Increment header_ind, look for JSON
alexhrao 4:55f0c303f56a 330 // Now just look for {
alexhrao 4:55f0c303f56a 331 header_ind += 4;
alexhrao 4:55f0c303f56a 332 while (header_ind < read_len) {
alexhrao 4:55f0c303f56a 333 if (buffer[header_ind] == '{') {
alexhrao 4:55f0c303f56a 334 // we got it!
alexhrao 4:55f0c303f56a 335 break;
alexhrao 4:55f0c303f56a 336 }
alexhrao 4:55f0c303f56a 337 header_ind++;
alexhrao 4:55f0c303f56a 338 }
alexhrao 4:55f0c303f56a 339 break;
alexhrao 4:55f0c303f56a 340 }
alexhrao 4:55f0c303f56a 341 header_ind++;
alexhrao 4:55f0c303f56a 342 }
alexhrao 4:55f0c303f56a 343 for (footer_ind = read_len - 1; footer_ind > header_ind; footer_ind--) {
alexhrao 4:55f0c303f56a 344 if(buffer[footer_ind] == '}') {
alexhrao 4:55f0c303f56a 345 break;
alexhrao 4:55f0c303f56a 346 }
alexhrao 4:55f0c303f56a 347 }
alexhrao 4:55f0c303f56a 348 buffer[footer_ind + 1] = '\0';
alexhrao 6:ec7829f7cd38 349
alexhrao 3:7bf41989ff8f 350 MbedJSONValue parser;
alexhrao 4:55f0c303f56a 351 parse(parser, buffer + header_ind);
alexhrao 2:f7d19812bdc5 352
alexhrao 4:55f0c303f56a 353 latitude = parser["latitude"].get<double>();
alexhrao 3:7bf41989ff8f 354 longitude = parser["longitude"].get<double>();
alexhrao 3:7bf41989ff8f 355
alexhrao 4:55f0c303f56a 356 // Get the Time
alexhrao 4:55f0c303f56a 357 TCPSocketConnection time_tcp;
alexhrao 4:55f0c303f56a 358
alexhrao 4:55f0c303f56a 359 time_tcp.connect("api.timezonedb.com", 80);
alexhrao 6:ec7829f7cd38 360
alexhrao 4:55f0c303f56a 361 sprintf(cmd,
alexhrao 4:55f0c303f56a 362 "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",
alexhrao 4:55f0c303f56a 363 time_api_key,
alexhrao 4:55f0c303f56a 364 latitude,
alexhrao 4:55f0c303f56a 365 longitude);
alexhrao 4:55f0c303f56a 366
alexhrao 4:55f0c303f56a 367 time_tcp.send_all(cmd, strlen(cmd));
alexhrao 6:ec7829f7cd38 368
alexhrao 4:55f0c303f56a 369 wait(5);
alexhrao 6:ec7829f7cd38 370
alexhrao 4:55f0c303f56a 371 read_len = wifi.recv(buffer, BUF_SIZE - 1, 0);
alexhrao 3:7bf41989ff8f 372 buffer[read_len] = '\0';
alexhrao 4:55f0c303f56a 373
alexhrao 4:55f0c303f56a 374 // Cleanup
alexhrao 4:55f0c303f56a 375
alexhrao 4:55f0c303f56a 376 // Clean up front
alexhrao 4:55f0c303f56a 377 // Read through headers (\r\n\r\n)
alexhrao 4:55f0c303f56a 378 header_ind = 0;
alexhrao 4:55f0c303f56a 379 while (header_ind < read_len) {
alexhrao 4:55f0c303f56a 380 // if we are \r, look ahead to see \n\r\n:
alexhrao 4:55f0c303f56a 381 if(buffer[header_ind] == '\r' &&
alexhrao 4:55f0c303f56a 382 buffer[header_ind+1] == '\n' &&
alexhrao 4:55f0c303f56a 383 buffer[header_ind+2] == '\r' &&
alexhrao 4:55f0c303f56a 384 buffer[header_ind+3] == '\n') {
alexhrao 4:55f0c303f56a 385 // Increment header_ind, look for JSON
alexhrao 4:55f0c303f56a 386 // Now just look for {
alexhrao 4:55f0c303f56a 387 header_ind += 4;
alexhrao 4:55f0c303f56a 388 while (header_ind < read_len) {
alexhrao 4:55f0c303f56a 389 if (buffer[header_ind] == '{') {
alexhrao 4:55f0c303f56a 390 // we got it!
alexhrao 4:55f0c303f56a 391 break;
alexhrao 4:55f0c303f56a 392 }
alexhrao 4:55f0c303f56a 393 header_ind++;
alexhrao 4:55f0c303f56a 394 }
alexhrao 4:55f0c303f56a 395 break;
alexhrao 4:55f0c303f56a 396 }
alexhrao 4:55f0c303f56a 397 header_ind++;
alexhrao 4:55f0c303f56a 398 }
alexhrao 4:55f0c303f56a 399
alexhrao 4:55f0c303f56a 400 for (footer_ind = read_len - 1; footer_ind > header_ind; footer_ind--) {
alexhrao 4:55f0c303f56a 401 if(buffer[footer_ind] == '}') {
alexhrao 4:55f0c303f56a 402 break;
alexhrao 4:55f0c303f56a 403 }
alexhrao 4:55f0c303f56a 404 }
alexhrao 4:55f0c303f56a 405 buffer[footer_ind + 1] = '\0';
alexhrao 2:f7d19812bdc5 406
alexhrao 4:55f0c303f56a 407 MbedJSONValue time_parser;
alexhrao 4:55f0c303f56a 408 parse(time_parser, buffer + header_ind);
alexhrao 4:55f0c303f56a 409
alexhrao 4:55f0c303f56a 410 // Add 5 so that we make up for the wait(5)
alexhrao 6:ec7829f7cd38 411 // Add 3 so that we make up for TCP request - empirically...
alexhrao 6:ec7829f7cd38 412 set_time(time_parser["timestamp"].get<int>() + 5 + 3);
alexhrao 4:55f0c303f56a 413 // Now that we know what time it is, set up our Time Thread
alexhrao 4:55f0c303f56a 414 time_thread.start(time_updater);
alexhrao 6:ec7829f7cd38 415
alexhrao 4:55f0c303f56a 416 TCPSocketConnection forecast_sck;
alexhrao 6:ec7829f7cd38 417
alexhrao 4:55f0c303f56a 418 forecast_sck.connect("api.openweathermap.org", 80);
alexhrao 6:ec7829f7cd38 419
alexhrao 4:55f0c303f56a 420 sprintf(cmd,
alexhrao 4:55f0c303f56a 421 "GET /data/2.5/weather?lat=%0.4f&lon=%0.4f&APPID=%s&cnt=8\r\nHost: api.openweathermap.org\r\n\r\n",
alexhrao 4:55f0c303f56a 422 latitude, longitude, weather_api_key);
alexhrao 4:55f0c303f56a 423 forecast_sck.send_all(cmd, strlen(cmd));
alexhrao 6:ec7829f7cd38 424
alexhrao 4:55f0c303f56a 425 wait(5);
alexhrao 4:55f0c303f56a 426
alexhrao 6:ec7829f7cd38 427 read_len wifi.recv(buffer, BUF_SIZE - 1, 0);
alexhrao 6:ec7829f7cd38 428 buffer[read_len] = '\0';
alexhrao 6:ec7829f7cd38 429
alexhrao 6:ec7829f7cd38 430 // We don't have enough memory for another parser (why?), so just
alexhrao 6:ec7829f7cd38 431 // look for the word "temp" 0 hopefully won't have a city named "temp"!
alexhrao 4:55f0c303f56a 432 char* ind = strstr(buffer, "temp");
alexhrao 4:55f0c303f56a 433 char num_buf[16];
alexhrao 4:55f0c303f56a 434 int num_ind = 0;
alexhrao 4:55f0c303f56a 435 // go until we find numbers
alexhrao 4:55f0c303f56a 436 while (char tmp = *ind++) {
alexhrao 4:55f0c303f56a 437 if (tmp > '0' && tmp < '9') {
alexhrao 4:55f0c303f56a 438 num_buf[num_ind++] = tmp;
alexhrao 4:55f0c303f56a 439 break;
alexhrao 4:55f0c303f56a 440 }
alexhrao 4:55f0c303f56a 441 }
alexhrao 4:55f0c303f56a 442 // Keep moving until no more numbers
alexhrao 4:55f0c303f56a 443 while (char tmp = *ind++) {
alexhrao 4:55f0c303f56a 444 if (tmp > '9' || tmp < '0') {
alexhrao 4:55f0c303f56a 445 num_buf[num_ind] = '\0';
alexhrao 4:55f0c303f56a 446 break;
alexhrao 4:55f0c303f56a 447 } else {
alexhrao 4:55f0c303f56a 448 num_buf[num_ind++] = tmp;
alexhrao 4:55f0c303f56a 449 }
alexhrao 4:55f0c303f56a 450 }
alexhrao 4:55f0c303f56a 451 int temp = atoi(num_buf);
alexhrao 4:55f0c303f56a 452 // Convert
alexhrao 6:ec7829f7cd38 453 temp = kelvin2farenheit(temp);
alexhrao 4:55f0c303f56a 454 char temp_buf[12];
alexhrao 4:55f0c303f56a 455 sprintf(temp_buf, " %dF", temp);
alexhrao 6:ec7829f7cd38 456
alexhrao 2:f7d19812bdc5 457 lcd_lock.lock();
alexhrao 4:55f0c303f56a 458 uLCD.text_width(2);
alexhrao 4:55f0c303f56a 459 uLCD.text_height(2);
alexhrao 4:55f0c303f56a 460 uLCD.text_string(temp_buf, 0, 5, FONT_8X8, WHITE);
alexhrao 2:f7d19812bdc5 461 lcd_lock.unlock();
alexhrao 6:ec7829f7cd38 462
alexhrao 6:ec7829f7cd38 463 time_t prev_time = time(NULL);
alexhrao 1:0620ba35d2e8 464 while(true) {
alexhrao 3:7bf41989ff8f 465 time_t curr_time = time(NULL);
alexhrao 6:ec7829f7cd38 466 // Wait for 60 seconds
alexhrao 6:ec7829f7cd38 467 if ((prev_time + 60) < curr_time) {
alexhrao 4:55f0c303f56a 468 sprintf(cmd,
alexhrao 4:55f0c303f56a 469 "GET /data/2.5/weather?lat=%0.4f&lon=%0.4f&APPID=%s\r\nHost: api.openweathermap.org\r\n\r\n",
alexhrao 4:55f0c303f56a 470 latitude, longitude, weather_api_key);
alexhrao 4:55f0c303f56a 471 forecast_sck.connect("api.openweathermap.org", 80);
alexhrao 4:55f0c303f56a 472 wait(10);
alexhrao 4:55f0c303f56a 473 forecast_sck.send_all(cmd, strlen(cmd));
alexhrao 4:55f0c303f56a 474 wait(5);
alexhrao 4:55f0c303f56a 475
alexhrao 6:ec7829f7cd38 476 read_len = wifi.recv(buffer, BUF_SIZE - 1, 0);
alexhrao 4:55f0c303f56a 477
alexhrao 6:ec7829f7cd38 478 buffer[read_len] = '\0';
alexhrao 4:55f0c303f56a 479
alexhrao 4:55f0c303f56a 480 ind = strstr(buffer, "temp");
alexhrao 4:55f0c303f56a 481 num_ind = 0;
alexhrao 4:55f0c303f56a 482 // go until we find numbers
alexhrao 4:55f0c303f56a 483 while (char tmp = *ind++) {
alexhrao 4:55f0c303f56a 484 if (tmp > '0' && tmp < '9') {
alexhrao 4:55f0c303f56a 485 num_buf[num_ind++] = tmp;
alexhrao 4:55f0c303f56a 486 break;
alexhrao 4:55f0c303f56a 487 }
alexhrao 4:55f0c303f56a 488 }
alexhrao 4:55f0c303f56a 489 // Keep moving until no more numbers
alexhrao 4:55f0c303f56a 490 while (char tmp = *ind++) {
alexhrao 4:55f0c303f56a 491 if (tmp > '9' || tmp < '0') {
alexhrao 4:55f0c303f56a 492 num_buf[num_ind] = '\0';
alexhrao 4:55f0c303f56a 493 break;
alexhrao 4:55f0c303f56a 494 } else {
alexhrao 4:55f0c303f56a 495 num_buf[num_ind++] = tmp;
alexhrao 4:55f0c303f56a 496 }
alexhrao 4:55f0c303f56a 497 }
alexhrao 4:55f0c303f56a 498 temp = atoi(num_buf);
alexhrao 6:ec7829f7cd38 499
alexhrao 4:55f0c303f56a 500 // Convert
alexhrao 6:ec7829f7cd38 501 temp = kelvin2farenheit(temp);
alexhrao 4:55f0c303f56a 502 sprintf(temp_buf, " %dF", temp);
alexhrao 4:55f0c303f56a 503 lcd_lock.lock();
alexhrao 4:55f0c303f56a 504 uLCD.text_width(2);
alexhrao 4:55f0c303f56a 505 uLCD.text_height(2);
alexhrao 4:55f0c303f56a 506 uLCD.text_string(temp_buf, 0, 5, FONT_8X8, WHITE);
alexhrao 4:55f0c303f56a 507 lcd_lock.unlock();
alexhrao 3:7bf41989ff8f 508 }
alexhrao 0:4ffa136585a2 509 }
alexhrao 0:4ffa136585a2 510 }
alexhrao 4:55f0c303f56a 511
alexhrao 4:55f0c303f56a 512 int main() {
alexhrao 4:55f0c303f56a 513 clock_init();
alexhrao 4:55f0c303f56a 514 }