Last active
December 19, 2018 16:53
-
-
Save jamesbulpin/d25403d56798013fd5015db49d822826 to your computer and use it in GitHub Desktop.
Sketch for the Christmas countdown bauble
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Christmas tree bauble countdown timer for ESP8266 with 128x32 OLED display | |
#include <Arduino.h> | |
#include <ESP8266WiFi.h> | |
#include <ESP8266WiFiMulti.h> | |
#include <ESP8266HTTPClient.h> | |
#include "SSD1306.h" | |
#include <ArduinoJson.h> | |
#define API_ENDPOINT "https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/default/baubleblog" // TODO - set this to your API URL | |
#define API_ENDPOINT_CERT_FINGERPRINT "7b c9 47 ae f4 1e f6 79 f9 b5 40 29 07 61 7b 66 93 17 5b 68" // TODO - set this to your cert fingerprint | |
#define USE_SERIAL Serial | |
ESP8266WiFiMulti WiFiMulti; | |
SSD1306 display(0x3c, SDA, SCL, OLED_RST, GEOMETRY_128_32); | |
void startWiFi() { | |
WiFi.mode(WIFI_STA); | |
WiFi.disconnect(); | |
delay(100); | |
// From https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiScan/WiFiScan.ino | |
int n = WiFi.scanNetworks(); | |
USE_SERIAL.println("scan done"); | |
if (n == 0) { | |
USE_SERIAL.println("no networks found"); | |
} else { | |
USE_SERIAL.print(n); | |
USE_SERIAL.println(" networks found"); | |
for (int i = 0; i < n; ++i) { | |
// Print SSID and RSSI for each network found | |
USE_SERIAL.print(i + 1); | |
USE_SERIAL.print(": "); | |
USE_SERIAL.print(WiFi.SSID(i)); | |
USE_SERIAL.print(" ("); | |
USE_SERIAL.print(WiFi.RSSI(i)); | |
USE_SERIAL.print(")"); | |
USE_SERIAL.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*"); | |
delay(10); | |
} | |
} | |
USE_SERIAL.println(""); | |
delay(1000); | |
WiFiMulti.addAP("<SSID>", "<PSK>"); // TODO - fill this in | |
// Wait for WiFi connection | |
while (WiFiMulti.run() != WL_CONNECTED) { | |
delay(250); | |
USE_SERIAL.print('.'); | |
} | |
USE_SERIAL.println(); | |
USE_SERIAL.print("SSID: "); | |
USE_SERIAL.println(WiFi.SSID()); | |
USE_SERIAL.print("IP: "); | |
USE_SERIAL.println(WiFi.localIP()); | |
USE_SERIAL.print("MAC: "); | |
USE_SERIAL.println(WiFi.macAddress()); | |
} | |
void setup() { | |
USE_SERIAL.begin(115200); | |
// Initialise the OLED display and show the Citrix logo | |
display.init(); | |
display.flipScreenVertically(); | |
display.setFont(ArialMT_Plain_16); | |
display.display(); | |
delay(1000); | |
startWiFi(); | |
USE_SERIAL.print("API: "); | |
USE_SERIAL.println(API_ENDPOINT); | |
} | |
// Interval definitions | |
unsigned long intervalHTTP = 60000; | |
unsigned long prevHTTP = 0; | |
unsigned long intervalDisplay = 250; | |
unsigned long prevDisplay = 0; | |
// Target for parsing the JSON object fetched from the cloud service | |
StaticJsonBuffer<200> jsonBuffer; | |
// The time of the event we're counting down to expressed as | |
// the seconds equivalent of a call to millis() | |
unsigned long timerTarget = 0; | |
// Buffer to hold the event description string | |
char description[20]; | |
// Buffer to build strings to display | |
char remainingText[50]; | |
void loop() { | |
unsigned long currentMillis = millis(); | |
unsigned long currentSecs = currentMillis / 1000; | |
static boolean wifiConnected = false; | |
static boolean lastFlip = true; | |
// Refresh the display event 250ms | |
if (currentMillis - prevDisplay > intervalDisplay) { | |
prevDisplay = currentMillis; | |
// Only update the display if we have a valid event description and target time | |
display.clear(); | |
if ((strlen(description) > 0) && (timerTarget > 0)) { | |
// Show a countdown timer and the event description | |
unsigned long remaining = (timerTarget < currentSecs)?0:(timerTarget - currentSecs); | |
unsigned long days = remaining/86400; | |
unsigned long hours = (remaining%86400)/3600; | |
unsigned long minutes = (remaining%3600)/60; | |
unsigned long seconds = remaining%60; | |
sprintf(remainingText, "%u %s %u:%02u", days, (days==1)?"day":"days", hours, minutes); | |
display.setFont(ArialMT_Plain_16); | |
display.drawString(0, 0, remainingText); | |
int16_t x = display.getStringWidth(remainingText); | |
display.setFont(ArialMT_Plain_10); | |
sprintf(remainingText, ":%02u", seconds); | |
display.drawString(x, 3, remainingText); | |
display.drawString(0, 19, "Until"); | |
int indent = display.getStringWidth("Until "); | |
display.setFont(ArialMT_Plain_16); | |
display.drawString(indent, 16, description); | |
} | |
display.display(); | |
} | |
// Refetch the event description and remaining time every minute | |
if ((currentMillis - prevHTTP > intervalHTTP) || (prevHTTP == 0)) { | |
wifiConnected = (WiFiMulti.run() == WL_CONNECTED); | |
if (wifiConnected) { | |
USE_SERIAL.print("SSID: "); | |
USE_SERIAL.println(WiFi.SSID()); | |
USE_SERIAL.print("IP: "); | |
USE_SERIAL.println(WiFi.localIP()); | |
prevHTTP = currentMillis; | |
HTTPClient http; | |
// The second argument here is the SSL fingerprint | |
http.begin(API_ENDPOINT, API_ENDPOINT_CERT_FINGERPRINT); | |
int httpCode = http.GET(); | |
if (httpCode > 0) { | |
USE_SERIAL.printf("HTTP GET code: %d\n", httpCode); | |
if (httpCode == HTTP_CODE_OK) { | |
String payload = http.getString(); | |
USE_SERIAL.println(payload); | |
jsonBuffer.clear(); | |
// Todo - check for buffer overrun for jsonBuffer | |
JsonObject& root = jsonBuffer.parseObject(payload); | |
if (!root.success()) { | |
USE_SERIAL.println("parseObject() failed"); | |
} | |
else { | |
if (root.containsKey("description")) { | |
strncpy(description, root["description"], 19); | |
// The service returns the number of seconds until the event. Add the number of seconds | |
// returned by millis() to get our target time. This avaoid us having to know the | |
// actual time. | |
timerTarget = root["remaining"].as<unsigned long>() + currentMillis/1000; | |
display.display(); | |
} | |
} | |
} | |
} else { | |
USE_SERIAL.printf("HTTP GET failed, error: %s\n", http.errorToString(httpCode).c_str()); | |
} | |
http.end(); | |
} | |
} | |
delay(10); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment