Skip to content

Instantly share code, notes, and snippets.

@sowbug
Created December 25, 2018 06:46
Show Gist options
  • Save sowbug/cfa6d28a6f0466240a7da4fa2fb30672 to your computer and use it in GitHub Desktop.
Save sowbug/cfa6d28a6f0466240a7da4fa2fb30672 to your computer and use it in GitHub Desktop.
An Arduino sketch to turn an ESP8266 with a PIR sensor into a thing that pings IFTTT when it's time to turn a room light on and off.
// Mostly copied from http://randomnerdtutorials.com
// New stuff is the on/off logic
#include <ESP8266WiFi.h>
const char* ssid = "...";
const char* password = "...";
const char* resource_on = "/trigger/[IFTTT_APPLET_ID_TO_TURN_ON]/with/key/xxxxxxx";
const char* resource_off = "/trigger/[IFTTT_APPLET_ID_TO_TURN_OFF]/with/key/xxxxxxx";
const char* server = "maker.ifttt.com";
void initWifi() {
Serial.print("Connecting to: ");
Serial.print(ssid);
WiFi.begin(ssid, password);
int timeout = 10 * 4; // 10 seconds
while (WiFi.status() != WL_CONNECTED && (timeout-- > 0)) {
delay(250);
Serial.print(".");
}
Serial.println("");
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Failed to connect, going back to sleep");
}
Serial.print("WiFi connected in: ");
Serial.print(millis());
Serial.print(", IP address: ");
Serial.println(WiFi.localIP());
}
void setup() {
Serial.begin(115200);
initWifi();
}
// Make an HTTP request to the IFTTT web service
void makeIFTTTRequest(bool on) {
Serial.print("Connecting to ");
Serial.print(server);
WiFiClient client;
int retries = 5;
while (!!!client.connect(server, 80) && (retries-- > 0)) {
Serial.print(".");
}
Serial.println();
if (!!!client.connected()) {
Serial.println("Failed to connect, going back to sleep");
}
const char *resource = on ? resource_on : resource_off;
Serial.print("Request resource: ");
Serial.println(resource);
client.print(String("GET ") + resource +
" HTTP/1.1\r\n" +
"Host: " + server + "\r\n" +
"Connection: close\r\n\r\n");
int timeout = 5 * 10; // 5 seconds
while (!!!client.available() && (timeout-- > 0)) {
delay(100);
}
if (!!!client.available()) {
Serial.println("No response, going back to sleep");
}
while (client.available()) {
Serial.write(client.read());
}
Serial.println("\nclosing connection");
client.stop();
}
// off to on
#define MINUTES_ON_FIRST (30 * 60 * 1000)
// already in room, extending session
#define MINUTES_ON_EXTEND (5 * 60 * 1000)
const int PIR = D3;
bool current_state = false;
bool desired_state = false;
unsigned long time_to_shut_off = 0;
bool is_extended = false;
void loop() {
unsigned long now = millis();
bool sensor_on = digitalRead(PIR) == HIGH;
digitalWrite(BUILTIN_LED, sensor_on ? LOW : HIGH);
if (sensor_on) {
if (!current_state) {
time_to_shut_off = now + MINUTES_ON_FIRST;
} else {
is_extended = true;
}
desired_state = true;
}
// Every 49 days or so, there's a chance that the light will
// turn off sooner than it's supposed to.
//
// now = CLOSE_TO_32_BIT_MAX
// now + delay = SMALL_NUMBER_THAT_WRAPPED
// now >= time_to_shut_off == instantly true
//
// So to get around this, we look at the difference instead of comparing
// and use a heuristic to tell whether it wrapped.
if (now - time_to_shut_off <= (unsigned long)LONG_MAX) {
if (is_extended) {
is_extended = false;
time_to_shut_off = now + MINUTES_ON_EXTEND;
} else {
desired_state = false;
}
}
if (current_state != desired_state) {
makeIFTTTRequest(desired_state);
current_state = desired_state;
}
delay(250);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment