Last active
April 29, 2019 12:59
-
-
Save csquared/4341720 to your computer and use it in GitHub Desktop.
Heroku Status Lights Monitor - Arduino Software
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
/* | |
Heroku Office Status Monitor | |
What it is: Arduino + Ethernet Shield | |
What it does: Networked device that provides status monitoring. | |
Components: | |
- Status site monitor | |
HTTP GET to http://outage-lights.herokuapp.com/status to consume current Heroku Platform status. | |
Go to http://outage-lights.herokuapp.com/ to see if this system is currently working. | |
- Local Override | |
A simple web server that turns pin 8 on when it recieves | |
a GET request to `/on` and turns that pin off when | |
it receives a GET request to `/off`. | |
- Trigger Failure when unable to connect to the web. | |
by Chris Continanza | |
*/ | |
#include <SPI.h> | |
#include <Ethernet.h> | |
// Enter a MAC address and IP address for your controller below. | |
// The IP address will be dependent on your local network: | |
byte mac[] = { | |
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; | |
IPAddress ip(10,10,10,102); | |
//Heroku's Public raw IP endpoint FTW | |
IPAddress status_server(174,129,212,2); | |
int heartbeat_port = 80; | |
/* Deprectated: this was used when status and hearbeat were | |
* separate endonpoints. | |
int heartbeat_delay_millis = 5000; | |
int heartbeat_tolerance = 1000; | |
int last_heartbeat = 0; | |
*/ | |
int status_delay_millis = 5000; | |
int status_tolerance = 1000; | |
int last_status = 0; | |
int http_failures_limit = 25; | |
boolean http_on = false; | |
boolean status_on = false; | |
int http_failures = 0; | |
// Initialize the Ethernet server library | |
// with the IP address and port you want to use | |
// (port 80 is default for HTTP): | |
EthernetServer server(80); | |
int LED = 8; | |
void setup() | |
{ | |
pinMode(LED, OUTPUT); | |
// open the serial port | |
Serial.begin(9600); | |
/* | |
// Not using DHCP so we have a static connection | |
// start the Ethernet connection: | |
Uncomment this block to use DHCP. | |
Serial.println("Trying to get an IP address using DHCP"); | |
if (Ethernet.begin(mac) == 0) { | |
Serial.println("Failed to configure Ethernet using DHCP"); | |
} | |
*/ | |
// connect w. static ip - this is assigned at the router | |
// and makes connecting to the manual override easier. | |
Ethernet.begin(mac, ip); | |
// print your local IP address to Serial for debugging. | |
Serial.print("My IP address: "); | |
IPAddress my_ip = Ethernet.localIP(); | |
for (byte thisByte = 0; thisByte < 4; thisByte++) { | |
// print the value of each byte of the IP address: | |
Serial.print(my_ip[thisByte], DEC); | |
Serial.print("."); | |
} | |
Serial.println(); | |
// start listening for clients | |
server.begin(); | |
} | |
/* HTTP Helper method | |
takes an EthernetClient object and returns a String. | |
it reads the next HTTP Response from the client one byte at a time. | |
*/ | |
String readHTTPResponse(EthernetClient _client) { | |
// an http request ends with a blank line | |
boolean currentLineIsBlank = true; | |
boolean httpBody = false; | |
//string for fetching data from address | |
String httpRequest = ""; | |
while (_client.connected()) { | |
if (_client.available()) { | |
char c = _client.read(); | |
if(httpBody){ | |
httpRequest.concat(c); | |
} | |
if (c == '\n' && httpBody){ | |
return httpRequest; | |
} | |
if (c == '\n' && currentLineIsBlank) { | |
httpBody = true; | |
} | |
if (c == '\n') { | |
// you're starting a new lineu | |
currentLineIsBlank = true; | |
} | |
else if (c != '\r') { | |
// you've gotten a character on the current line | |
currentLineIsBlank = false; | |
} | |
} | |
} | |
} | |
/* HTTP Helper method | |
takes an EthernetClient object and returns a String. | |
it reads the next HTTP Request from the client one byte at a time. | |
*/ | |
String readHTTPRequest(EthernetClient _client) { | |
// an http request ends with a blank line | |
boolean currentLineIsBlank = true; | |
//string for fetching data from address | |
String httpRequest = ""; | |
while (_client.connected()) { | |
if (_client.available()) { | |
char c = _client.read(); | |
httpRequest.concat(c); | |
// if you've gotten to the end of the line (received a newline | |
// character) and the line is blank, the http request has ended, | |
// so you can send a reply | |
if (c == '\n' && currentLineIsBlank) { | |
return httpRequest; | |
} | |
if (c == '\n') { | |
// you're starting a new lineu | |
currentLineIsBlank = true; | |
} | |
else if (c != '\r') { | |
// you've gotten a character on the current line | |
currentLineIsBlank = false; | |
} | |
} | |
} | |
} | |
/* Application loop | |
*/ | |
void loop() | |
{ | |
int time = millis(); | |
if(status_on || http_on || http_failures > http_failures_limit){ | |
digitalWrite(LED, HIGH); // set the LED on | |
} | |
else{ | |
digitalWrite(LED, LOW); // set the LED off | |
} | |
//some delay logic | |
if((time % status_delay_millis < status_tolerance) && | |
(time - last_status > status_delay_millis)){ | |
last_status = time; | |
/* fire off a GET request to status */ | |
EthernetClient status_client; | |
status_on = false; | |
if (status_client.connect(status_server, 80)) { | |
http_failures = 0; | |
Serial.println("connected to status"); | |
// Make a HTTP request: | |
status_client.println("GET /status HTTP/1.0"); | |
status_client.println("Host: outage-lights.herokuapp.com"); | |
status_client.println("Authorization: Basic ---------------"); | |
status_client.println(); | |
String response = readHTTPResponse(status_client); | |
Serial.println(response); | |
Serial.println(response.indexOf("red")); | |
// If its red, turn the switch on. | |
// could probably make this my own response... | |
if(response.indexOf("red") == -1){ | |
Serial.println("Status clear - LED OFF"); | |
} | |
else { | |
Serial.println("Status red! - LED ON"); | |
status_on = true; | |
} | |
} | |
else { | |
//count failures cus you didn't get a connection to the server | |
http_failures++; | |
Serial.println("connection to status failed"); | |
} | |
//make sure you write all those bytes. | |
status_client.flush(); | |
//aaaaaand give it some time | |
delay(10); | |
//cleanup | |
status_client.stop(); | |
} | |
// Check if an HTTP request came in. | |
EthernetClient client = server.available(); | |
if (client) { | |
String httpRequest = readHTTPRequest(client); | |
Serial.print(httpRequest); | |
// send a standard http response header | |
client.println("HTTP/1.1 200 OK"); | |
client.println("Content-Type: text/html"); | |
client.println(); | |
//send an HTML response | |
if(httpRequest.startsWith("GET /on")){ | |
Serial.println("HTTP Request - LED ON"); | |
client.print("<h1>Outage Lights On</h1>"); | |
http_on = true; | |
} | |
else if(httpRequest.startsWith("GET /off")){ | |
Serial.println("HTTP Request - LED OFF"); | |
client.print("<h1>Outage Lights Off</h1>"); | |
http_on = false; | |
} | |
// give the web browser time to receive the data | |
delay(1); | |
// close the connection: | |
client.stop(); | |
} | |
} | |
/* | |
Deprecated: heartbeat is assumed when GET goes to /status | |
//send the Heartbet request for monitoring. | |
EthernetClient heartbeat; | |
//delay logic | |
if((time % heartbeat_delay_millis < heartbeat_tolerance) && | |
(time - last_heartbeat > heartbeat_delay_millis)){ | |
Serial.println("heartbeat"); | |
last_heartbeat = time; | |
// connect to Heroku via direct IP connection | |
// writing HTTP packet to the Socket like a boss | |
if (heartbeat.connect(heartbeat_server, heartbeat_port)) { | |
Serial.println("heartbeat connected"); | |
http_failures = 0; | |
// Make an HTTP request: | |
heartbeat.println("POST /heartbeat HTTP/1.0"); | |
heartbeat.println("Host: outage-lights-heartbeat.herokuapp.com"); | |
heartbeat.println("Content-Length: 0"); | |
heartbeat.println("Authorization: Basic -�-------------"); | |
heartbeat.println(); | |
heartbeat.println(); | |
Serial.println("heartbeat sent"); | |
} | |
else { | |
//you didn't get a connection to the server: | |
Serial.println("heartbeat connection failed"); | |
http_failures++; | |
} | |
//flush and clean up after yourself | |
heartbeat.flush(); | |
delay(50); | |
heartbeat.stop(); | |
} | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment