Created
December 25, 2018 06:46
-
-
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.
This file contains hidden or 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
// 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