2019-11-22 19:34:26 +11:00
/*
* Copyright Paul Warren 2019 < pwarren @ pwarren . id . au >
*
* Released under the terms of the GPLv3 license .
2020-01-05 13:58:23 +11:00
*
* D1Mini : Colour : UART Module
* D5 : White : DOUT
* D6 : Green : DIN
* D7 : Yellow : Wake Up
* D8 : Blue : Reset
*
*
2019-11-22 19:34:26 +11:00
*/
# include <ESP8266HTTPClient.h>
# include <ESP8266WiFi.h>
# include <WiFiUdp.h>
# include <NTPClient.h>
# include <Timezone.h>
2019-11-23 20:21:10 +11:00
# include <ArduinoJson.h>
2019-11-22 19:34:26 +11:00
# include "epd.h"
# include "credential.h"
2019-11-23 20:21:10 +11:00
2022-01-28 22:59:56 +11:00
// BOM, see bom_rrd2.py
2019-11-26 23:42:01 +11:00
const String ds_url = " http://pwarren.id.au/darksky/bom.json " ;
2019-11-22 19:34:26 +11:00
2019-11-23 20:21:10 +11:00
bool ds_done = false ;
2019-11-22 19:34:26 +11:00
// Timezone bits
// Australia Eastern Time Zone (Sydney, Melbourne)
TimeChangeRule aEDT = { " AEDT " , First , Sun , Oct , 2 , 660 } ; // UTC + 11 hours
TimeChangeRule aEST = { " AEST " , First , Sun , Apr , 3 , 600 } ; // UTC + 10 hours
Timezone ausET ( aEDT , aEST ) ;
TimeChangeRule * tcr ;
2022-01-28 22:59:56 +11:00
// when to wake up the display and get going
int wakeup_seconds = 50 ;
2019-11-22 19:34:26 +11:00
// Network clients
2022-01-28 22:59:56 +11:00
WiFiClient wfclient ;
2019-11-22 19:34:26 +11:00
WiFiUDP ntpUDP ;
HTTPClient http ;
2022-01-28 22:59:56 +11:00
NTPClient timeClient ( ntpUDP , " pi.lan " , 0 , 60000 ) ; //use internal ntp server, update every 10 minutes, taking in to account the 9 seconds it takes to update the screen for the current time
2019-11-22 19:34:26 +11:00
2022-12-06 22:41:37 +11:00
//NTPClient timeClient(ntpUDP, "au.pool.ntp.org", 0, 60000); //use external ntp server, update every 10 minutes
2019-11-22 19:34:26 +11:00
// defined in "credentials.h"
const char * ssid = ssid_name ; // The SSID (name) of your Wi-Fi network
const char * password = ssid_pass ; // The password of the Wi-Fi network
const int led = LED_BUILTIN ;
2019-11-23 20:21:10 +11:00
// Font width
int dwidth = 185 ;
2019-11-22 19:34:26 +11:00
// yes this seems backwards but it works...
void ledOn ( void ) { digitalWrite ( led , LOW ) ; }
void ledOff ( void ) { digitalWrite ( led , HIGH ) ; }
void wait ( void ) { delay ( 1500 ) ; }
2019-12-30 15:54:43 +11:00
// globals for the temperature :(
2019-12-30 19:13:01 +11:00
const char * current_outside ;
const char * current_bedroom ;
const char * current_lounge ;
2019-12-30 15:54:43 +11:00
2019-11-22 19:34:26 +11:00
void setup ( ) {
pinMode ( led , OUTPUT ) ;
ledOff ( ) ;
wifi_set_sleep_type ( LIGHT_SLEEP_T ) ;
epd_init ( ) ;
epd_wakeup ( ) ;
epd_set_memory ( MEM_NAND ) ;
epd_set_color ( BLACK , WHITE ) ;
epd_set_en_font ( ASCII64 ) ;
epd_clear ( ) ;
Serial . begin ( 115200 ) ; // Start serial communication
Serial . setTimeout ( 2000 ) ;
while ( ! Serial ) { }
Serial . println ( " \r \n \r \n STARTING \r \n " ) ;
wifi ( ) ;
timeClient . begin ( ) ;
ntpUpdate ( ) ;
2022-01-28 22:59:56 +11:00
/* weatherUpdate();
2019-11-22 19:34:26 +11:00
printDateTime ( 1 ) ;
2022-01-28 22:59:56 +11:00
2019-11-23 20:21:10 +11:00
epd_update ( ) ;
2022-01-28 22:59:56 +11:00
wait ( ) ; */
2019-11-22 19:34:26 +11:00
ledOff ( ) ;
}
void wifi ( ) {
WiFi . persistent ( false ) ;
WiFi . mode ( WIFI_OFF ) ;
WiFi . mode ( WIFI_STA ) ;
WiFi . begin ( ssid , password ) ; // Access WiFi
Serial . print ( " Connecting to " ) ;
Serial . print ( ssid ) ;
Serial . print ( " ... " ) ;
while ( WiFi . status ( ) ! = WL_CONNECTED ) { // Wait for WiFi to connect
delay ( 250 ) ;
Serial . print ( " . " ) ;
}
Serial . println ( ' \n ' ) ;
Serial . println ( " WiFi connection established " ) ;
Serial . print ( " Device's IP address is " ) ;
Serial . println ( WiFi . localIP ( ) ) ; // Show device's IP address
}
void ntpUpdate ( ) {
2019-11-23 20:21:10 +11:00
if ( timeClient . update ( ) ) {
setTime ( timeClient . getEpochTime ( ) ) ;
}
2019-11-22 19:34:26 +11:00
}
void disp_digit ( int digit , int xpos ) {
// digit: digit to display
// xpos: X digit position, indexed at 1
int dpos = 0 ;
int ypos = 0 ;
dpos = ( ( xpos - 1 ) * dwidth ) ;
if ( xpos > 2 ) {
dpos + = 60 ; // account for colon
}
switch ( digit ) {
case 0 :
epd_disp_bitmap ( " 0.JPG " , dpos , ypos ) ;
break ;
case 1 :
epd_disp_bitmap ( " 1.JPG " , dpos , ypos ) ;
break ;
case 2 :
epd_disp_bitmap ( " 2.JPG " , dpos , ypos ) ;
break ;
case 3 :
epd_disp_bitmap ( " 3.JPG " , dpos , ypos ) ;
break ;
case 4 :
epd_disp_bitmap ( " 4.JPG " , dpos , ypos ) ;
break ;
case 5 :
epd_disp_bitmap ( " 5.JPG " , dpos , ypos ) ;
break ;
case 6 :
epd_disp_bitmap ( " 6.JPG " , dpos , ypos ) ;
break ;
case 7 :
epd_disp_bitmap ( " 7.JPG " , dpos , ypos ) ;
break ;
case 8 :
epd_disp_bitmap ( " 8.JPG " , dpos , ypos ) ;
break ;
case 9 :
epd_disp_bitmap ( " 9.JPG " , dpos , ypos ) ;
break ;
}
2022-01-28 22:59:56 +11:00
// wait();
2019-11-22 19:34:26 +11:00
}
void disp_time ( int hours , int minutes ) {
// first digit of hours
if ( hours > 19 ) {
disp_digit ( 2 , 1 ) ;
hours - = 20 ;
} else if ( hours > 9 ) {
disp_digit ( 1 , 1 ) ;
hours - = 10 ;
} else {
disp_digit ( 0 , 1 ) ;
}
// second hours digit
disp_digit ( hours , 2 ) ;
epd_disp_bitmap ( " COLO.JPG " , 2 * dwidth , 0 ) ;
2019-11-23 20:21:10 +11:00
delay ( 500 ) ;
2019-11-22 19:34:26 +11:00
// first minutes digit
if ( minutes > 49 ) {
disp_digit ( 5 , 3 ) ;
minutes - = 50 ;
} else if ( minutes > 39 ) {
disp_digit ( 4 , 3 ) ;
minutes - = 40 ;
} else if ( minutes > 29 ) {
disp_digit ( 3 , 3 ) ;
minutes - = 30 ;
} else if ( minutes > 19 ) {
disp_digit ( 2 , 3 ) ;
minutes - = 20 ;
} else if ( minutes > 9 ) {
disp_digit ( 1 , 3 ) ;
minutes - = 10 ;
} else {
disp_digit ( 0 , 3 ) ;
}
// second minutes digit
disp_digit ( minutes , 4 ) ;
2019-11-23 20:21:10 +11:00
2019-11-22 19:34:26 +11:00
}
void printDateTime ( int update_epd )
{
char buf [ 64 ] ;
2019-11-23 20:21:10 +11:00
time_t t ;
2022-01-28 22:59:56 +11:00
t = ausET . toLocal ( now ( ) + 60 , & tcr ) ;
2019-11-23 20:21:10 +11:00
2019-11-22 19:34:26 +11:00
char m [ 4 ] ; // temporary storage for month string (DateStrings.cpp uses shared buffer)
2022-01-28 22:59:56 +11:00
strncpy ( m , monthShortStr ( month ( t ) ) , 4 ) ;
2019-11-22 19:34:26 +11:00
sprintf ( buf , " %.2d:%.2d:%.2d " , hour ( t ) , minute ( t ) , second ( t ) ) ;
Serial . print ( buf ) ; Serial . print ( " " ) ;
if ( update_epd > 0 ) {
2022-01-28 22:59:56 +11:00
Serial . println ( " Adding Time " ) ;
2019-11-22 19:34:26 +11:00
disp_time ( hour ( t ) , minute ( t ) ) ;
}
2019-12-30 19:13:01 +11:00
sprintf ( buf , " %s %.2d %s %d " ,
2019-12-30 15:54:43 +11:00
dayShortStr ( weekday ( t ) ) ,
day ( t ) ,
m ,
2019-12-30 19:13:01 +11:00
year ( t ) ) ;
2019-11-22 19:34:26 +11:00
Serial . println ( buf ) ;
if ( update_epd > 0 ) {
2022-01-28 22:59:56 +11:00
Serial . println ( " Adding Date " ) ;
2019-11-22 19:34:26 +11:00
epd_set_en_font ( ASCII64 ) ;
2022-01-28 22:59:56 +11:00
epd_disp_string ( buf , 50 , 225 ) ;
}
2019-11-22 19:34:26 +11:00
}
void weatherUpdate ( void ) {
2022-01-28 22:59:56 +11:00
char buf [ 64 ] ;
2019-12-30 19:13:01 +11:00
const size_t capacity = 4 * JSON_OBJECT_SIZE ( 3 ) + JSON_OBJECT_SIZE ( 4 ) + 150 ;
2022-12-06 22:41:37 +11:00
DynamicJsonDocument jsonBuffer ( capacity ) ;
2022-01-28 22:59:56 +11:00
http . begin ( wfclient , ds_url ) ;
2019-11-22 19:34:26 +11:00
int httpCode = http . GET ( ) ;
2019-11-23 20:21:10 +11:00
2019-11-22 19:34:26 +11:00
if ( httpCode > 0 ) {
2022-12-06 22:41:37 +11:00
auto error = deserializeJson ( jsonBuffer , http . getString ( ) ) ;
if ( error ) {
Serial . print ( " Failed to parse json " ) ;
2019-11-23 20:21:10 +11:00
return ;
2022-12-06 22:41:37 +11:00
}
2019-11-26 23:42:01 +11:00
http . end ( ) ;
2019-11-23 20:21:10 +11:00
2022-12-06 22:41:37 +11:00
const char * today_day = jsonBuffer [ " today " ] [ " day " ] ; // "Wednesday"
const char * today_icon = jsonBuffer [ " today " ] [ " icon " ] ; // "sunny.jpg"
2022-12-07 23:11:58 +11:00
int today_max = jsonBuffer [ " today " ] [ " max " ] ; // "27"
2022-12-06 22:41:37 +11:00
const char * tomorrow_day = jsonBuffer [ " tomorrow " ] [ " day " ] ; // "Thursday"
const char * tomorrow_icon = jsonBuffer [ " tomorrow " ] [ " icon " ] ; // "sunny.jpg"
2022-12-07 23:11:58 +11:00
int tomorrow_max = jsonBuffer [ " tomorrow " ] [ " max " ] ; // "31"
2022-12-06 22:41:37 +11:00
const char * day_after_day = jsonBuffer [ " day_after " ] [ " day " ] ; // "Friday"
const char * day_after_icon = jsonBuffer [ " day_after " ] [ " icon " ] ; // "pcloud.jpg"
2022-12-07 23:11:58 +11:00
int day_after_max = jsonBuffer [ " day_after " ] [ " max " ] ; // "33"
2022-12-06 22:41:37 +11:00
2022-12-07 23:11:58 +11:00
int current_outside = jsonBuffer [ " current " ] [ " outside " ] ;
int current_bedroom = jsonBuffer [ " current " ] [ " bedroom " ] ;
int current_lounge = jsonBuffer [ " current " ] [ " lounge " ] ;
2019-11-23 20:21:10 +11:00
2019-12-30 19:13:01 +11:00
Serial . println ( " Updating EPD with weather " ) ;
2022-12-06 22:41:37 +11:00
2019-11-23 20:21:10 +11:00
epd_set_en_font ( ASCII64 ) ;
2022-12-06 22:41:37 +11:00
2019-11-23 20:21:10 +11:00
//Today
2022-12-07 23:11:58 +11:00
epd_disp_bitmap ( today_icon , 0 , 290 ) ;
2019-12-01 19:18:20 +11:00
epd_disp_string ( today_day , 0 , 536 ) ;
2022-12-07 23:11:58 +11:00
sprintf ( buf , " %d " , today_max ) ;
epd_disp_string ( buf , 75 , 460 ) ;
2019-11-23 20:21:10 +11:00
//Tomorrow
2019-12-01 19:18:20 +11:00
epd_disp_bitmap ( tomorrow_icon , 267 , 290 ) ;
epd_disp_string ( tomorrow_day , 260 , 536 ) ;
2022-12-07 23:11:58 +11:00
sprintf ( buf , " %d " , tomorrow_max ) ;
epd_disp_string ( buf , 352 , 460 ) ;
2022-12-06 22:41:37 +11:00
2019-11-26 23:42:01 +11:00
//Day After
2019-12-01 19:18:20 +11:00
epd_disp_bitmap ( day_after_icon , 533 , 290 ) ;
epd_disp_string ( day_after_day , 533 , 536 ) ;
2022-12-07 23:11:58 +11:00
sprintf ( buf , " %d " , day_after_max ) ;
epd_disp_string ( buf , 615 , 460 ) ;
//Serial.println("Adding Temps");
sprintf ( buf , " E: %d I: %d " ,
2022-12-06 22:41:37 +11:00
current_outside ,
current_lounge ) ;
2022-12-07 23:11:58 +11:00
//Serial.println(buf);
epd_disp_string ( buf , 500 , 225 ) ;
2022-12-06 22:41:37 +11:00
2019-11-22 19:34:26 +11:00
} else {
Serial . print ( " Error on HTTP Request: " ) ;
Serial . println ( httpCode ) ;
}
2022-12-06 22:41:37 +11:00
2019-11-22 19:34:26 +11:00
}
void loop ( ) {
int sleep_seconds = 0 ;
Serial . println ( " Back from sleep! " ) ;
if ( WiFi . status ( ) ! = WL_CONNECTED ) {
wifi ( ) ;
}
ntpUpdate ( ) ;
2019-11-26 23:42:01 +11:00
if ( second ( now ( ) ) > = wakeup_seconds ) {
2022-01-28 22:59:56 +11:00
epd_wakeup ( ) ;
2019-11-23 20:21:10 +11:00
epd_clear ( ) ;
2022-01-29 07:58:34 +11:00
weatherUpdate ( ) ;
Serial . print ( " Weather details sent: " ) ;
2019-11-26 23:42:01 +11:00
Serial . println ( second ( now ( ) ) ) ;
2022-01-28 22:59:56 +11:00
printDateTime ( 1 ) ;
2022-12-07 23:11:58 +11:00
Serial . println ( " Waiting on minute to change " ) ;
2019-11-26 23:42:01 +11:00
while ( second ( now ( ) ) ! = 0 ) {
delay ( 500 ) ;
}
2022-01-28 22:59:56 +11:00
2019-11-22 19:34:26 +11:00
}
2022-12-07 23:11:58 +11:00
Serial . println ( " EPD Update " ) ;
2022-01-28 22:59:56 +11:00
epd_update ( ) ;
2022-12-07 23:11:58 +11:00
delay ( 4000 ) ;
Serial . println ( " EPD Stop " ) ;
2022-01-28 22:59:56 +11:00
epd_enter_stopmode ( ) ;
2019-11-22 19:34:26 +11:00
2019-11-26 23:42:01 +11:00
sleep_seconds = wakeup_seconds - second ( now ( ) ) ;
2022-12-07 23:11:58 +11:00
if ( sleep_seconds < 0 ) {
sleep_seconds = 10 ;
}
2019-11-26 23:42:01 +11:00
2019-11-22 19:34:26 +11:00
Serial . print ( " Sleeping for: " ) ;
Serial . println ( sleep_seconds ) ;
delay ( sleep_seconds * 1000 ) ;
}