diff --git a/darksky.py b/darksky.py new file mode 100755 index 0000000..0d4498e --- /dev/null +++ b/darksky.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 + +# +# Pulls out only the required pieces for the esp_time.ino arduino program +# the ESP8266 doesn't have enough RAM to parse the whole JSON object. +# substitue in api_key, run this and place the output at a web server +# adjust ds_url in esp_time.ino to point at that web server! + +import json +import urllib.request + +ds_url = "https://api.darksky.net/forecast/"; +ds_ll = "/-35.135,149.61"; +ds_opts = "?units=auto" + +api_key = "PUT YOUR API KEY HERE" + +contents = urllib.request.urlopen(ds_url + api_key + ds_ll + ds_opts) + +d = json.load(contents) + +new = {} +current = d['currently'] +today = d['daily']['data'][0] +tomorrow = d['daily']['data'][1] +day_after = d['daily']['data'][2] + +new['current'] = {} +new['current']['temp'] = current['temperature'] +new['current']['icon'] = current['icon'] +new['today'] = {} +new['today']['max'] = today['temperatureMax'] +new['today']['icon'] = today['icon'] +new['tomorrow'] = {} +new['tomorrow']['max'] = tomorrow['temperatureMax'] +new['tomorrow']['icon'] = tomorrow['icon'] +new['day_after'] = {} +new['day_after']['max'] = day_after['temperatureMax'] +new['day_after']['icon'] = day_after['icon'] + + +with open('darksky.json', 'w') as output: + output.write(json.dumps(new)) + output.close() + + + + + # OWM + # for forecast in d['list']: + # utcDate = datetime.datetime.strptime(forecast['dt_txt']+"+0000", "%Y-%m-%d %H:%M:%S%z") + + # utcDate.replace(tzinfo=UTC) + + # print("********") + # print(utcDate) + # print(utcDate.astimezone(local)) + # print(forecast['weather'][0]['description'], forecast['weather'][0]['icon'], forecast['main']['temp']) + diff --git a/esp_time.ino b/esp_time.ino index 4ec3709..71c9dfa 100644 --- a/esp_time.ino +++ b/esp_time.ino @@ -8,10 +8,12 @@ #include #include #include +#include #include "epd.h" #include "credential.h" + // Weather bits // Australian BOM bits, Belconnen is mine. @@ -20,10 +22,13 @@ //const char* bom_url = "ftp://ftp.bom.gov.au/anon/gen/fwo/IDN11060.xml"; // openweathermap, api_key from credential.h -// -// Maybe try String types? -const String owm_url = "http://api.openweathermap.org/data/2.5/weather?q=Belconnen,AU&APPID="; +// const String owm_url = "http://api.openweathermap.org/data/2.5/weather?q=Belconnen,AU&units=metric&APPID="; +// DarkSky API key from credential.h +// substitute decimal latitude and longitude in ds_ll +const String ds_url = "http://pwarren.id.au/darksky/darksky.json"; + +bool ds_done = false; // Timezone bits @@ -35,11 +40,10 @@ TimeChangeRule *tcr; // Network clients WiFiUDP ntpUDP; - HTTPClient http; - NTPClient timeClient(ntpUDP, "raspberrypi.lan", 0, 60000); //use internal ntp server, update every 10 minutes +//NTPClient timeClient(ntpUDP, "au.pool.ntp.org", 0, 60000); //use internal ntp server, update every 10 minutes // defined in "credentials.h" const char* ssid = ssid_name; // The SSID (name) of your Wi-Fi network @@ -47,14 +51,14 @@ const char* password = ssid_pass; // The password of the Wi-Fi network const int led = LED_BUILTIN; +// Font width +int dwidth = 185; + // yes this seems backwards but it works... void ledOn(void) { digitalWrite(led, LOW);} void ledOff(void) { digitalWrite(led, HIGH);} void wait(void) { delay(1500);} -// Font width -int dwidth = 185; - void setup() { pinMode(led, OUTPUT); ledOff(); @@ -78,7 +82,9 @@ void setup() { timeClient.begin(); ntpUpdate(); epd_clear(); + weatherUpdate(); printDateTime(1); + epd_update(); ledOff(); } @@ -104,8 +110,9 @@ void wifi() { } void ntpUpdate() { - timeClient.update(); - setTime(timeClient.getEpochTime()); + if (timeClient.update()) { + setTime(timeClient.getEpochTime()); + } } @@ -151,12 +158,11 @@ void disp_digit(int digit, int xpos){ epd_disp_bitmap("9.JPG", dpos, ypos); break; } + delay(500); } void disp_time(int hours, int minutes) { - epd_clear(); - // first digit of hours if (hours > 19) { disp_digit(2, 1); @@ -172,6 +178,7 @@ void disp_time(int hours, int minutes) { disp_digit(hours, 2); epd_disp_bitmap("COLO.JPG", 2 * dwidth, 0); + delay(500); // first minutes digit if (minutes > 49) { @@ -195,7 +202,7 @@ void disp_time(int hours, int minutes) { // second minutes digit disp_digit(minutes, 4); - + } @@ -203,10 +210,9 @@ void printDateTime(int update_epd) { char buf[64]; - time_t t; - + time_t t; t = ausET.toLocal(now(), &tcr); - + char m[4]; // temporary storage for month string (DateStrings.cpp uses shared buffer) strcpy(m, monthShortStr(month(t))); @@ -215,6 +221,7 @@ void printDateTime(int update_epd) if (update_epd > 0) { disp_time(hour(t), minute(t)); + wait(); } sprintf(buf, "%s %.2d %s %d %s", dayShortStr(weekday(t)), day(t), m, year(t), &tcr -> abbrev); @@ -222,29 +229,77 @@ void printDateTime(int update_epd) if (update_epd > 0) { epd_set_en_font(ASCII64); - epd_disp_string(buf, 150, 290); - epd_update(); - delay(1500); + epd_disp_string(buf, 150, 225); + delay(500); Serial.println("Screen Updated"); } } void weatherUpdate(void) { + const size_t capacity = 4*JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(4) + 150; + DynamicJsonBuffer jsonBuffer(capacity); - http.begin(owm_url + api_key); + time_t t; + + char buf[96] = {}; + const char* nstr = "Now"; + const char* tstr = "Today"; + const char* tmstr = "Tomorrow"; + + http.begin(ds_url); int httpCode = http.GET(); - + if (httpCode > 0) { + JsonObject& root = jsonBuffer.parseObject(http.getString()); + + if (!root.success()) { + Serial.print(F("parseObject() failed: ")); + return; + } + float current_temp = root["current"]["temp"]; + const char* current_icon = root["current"]["icon"]; + + float today_max = root["today"]["max"]; + const char* today_icon = root["today"]["icon"]; + + float tomorrow_max = root["tomorrow"]["max"]; + const char* tomorrow_icon = root["tomorrow"]["icon"]; + + float day_after_max = root["day_after"]["max"]; + const char* day_after_icon = root["day_after"]["icon"]; - String payload = http.getString(); - Serial.println(httpCode); - Serial.println(payload); + + epd_set_en_font(ASCII64); + + //Today + t = ausET.toLocal(now()); + epd_disp_string(dayStr(weekday(t)), 0, 536); + delay(500); + (String(today_max, 1)).toCharArray(buf,64); + epd_disp_string(buf, 0, 472); + delay(500); + + //Tomorrow + t = ausET.toLocal(now() + 86400, &tcr); + epd_disp_string(dayStr(weekday(t)), 267, 536); + delay(500); + (String(tomorrow_max, 1)).toCharArray(buf,64); + epd_disp_string(buf, 267, 472); + delay(500); + + //Day after Tomorrow + t = ausET.toLocal(now() + 86400 + 86400); + epd_disp_string(dayStr(weekday(t)), 533, 536); + delay(500); + (String(day_after_max, 1)).toCharArray(buf,64); + epd_disp_string(buf, 533, 472); + delay(500); + } else { Serial.print("Error on HTTP Request: "); Serial.println(httpCode); - - http.end(); } + http.end(); } void loop() { @@ -257,20 +312,22 @@ void loop() { } ntpUpdate(); - //weatherUpdate(); - if (second(now()) >= 49) { + if (second(now()) >= 55) { epd_wakeup(); - while (second(now()) != 0) { + while (second(now()) != 57) { delay(500); } + epd_clear(); + weatherUpdate(); printDateTime(1); - delay(4000); + epd_update(); + delay(5000); epd_enter_stopmode(); } - sleep_seconds = 49 - second(now()); + sleep_seconds = 55 - second(now()); Serial.print("Sleeping for: "); Serial.println(sleep_seconds); diff --git a/images/images.ino b/images/images.ino index de0afee..a2d0562 100644 --- a/images/images.ino +++ b/images/images.ino @@ -25,6 +25,11 @@ void setup() { epd_wakeup(); delay(1500); epd_set_memory(MEM_TF); + epd_disp_bitmap("0.jpg", 0, 0); + epd_disp_bitmap("9.jpg", 185,0); + Serial.println("Attempting to display 0 and 9"); + epd_update(); + delay(10000); epd_load_pic(); epd_set_memory(MEM_NAND); delay(1500);