Skip to content

Instantly share code, notes, and snippets.

@savannahostrowski
Last active August 4, 2020 03:54
Show Gist options
  • Save savannahostrowski/3ff7c2f79b3f7ba1725043be15d2d22b to your computer and use it in GitHub Desktop.
Save savannahostrowski/3ff7c2f79b3f7ba1725043be15d2d22b to your computer and use it in GitHub Desktop.
A4 - Ambient Display
//---------------------------------------------
// Contact Switch
//---------------------------------------------
#include <ESP8266WiFi.h> // Requisite Libraries . . .
#include <PubSubClient.h>
#include <Wire.h>
#include <ArduinoJson.h>
#include "config.h" // include the configuration of credentials in the config.h file
#define MQTT_ENABLE 1 // for testing the sensor, set to 1 to enable posting data to the server
StaticJsonDocument<256> outputDoc;
//////////
//We need a 'truly' unique client ID for our esp8266, all client names on the server must be unique.
//Every device, app, other MQTT server, etc that connects to an MQTT server must have a unique client ID.
//This is the only way the server can keep every device separate and deal with them as individual devices/apps.
//The client ID is unique to the device.
//////////
char mac[6]; //A MAC address is a 'truly' unique ID for each device, lets use that as our 'truly' unique user ID!!!
char buffer[256]; // stores the data for the JSON document
unsigned long timer; // a timer for the MQTT server we don't want to flood it with data
// Create objects
WiFiClient espClient;
PubSubClient mqtt(espClient);
const int sensor = 4;
int currentDeskState = "down";
int prevDeskState = "up";
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.print("This board is running: ");
Serial.println(F(__FILE__));
Serial.print("Compiled: ");
Serial.println(F(__DATE__ " " __TIME__));
pinMode(sensor, INPUT_PULLUP);
Serial.println("hello");
if (MQTT_ENABLE) {
setup_wifi();
mqtt.setServer(MQTT_SERVER, 1883);
}
timer = millis(); // start the timer
}
void loop(){
if (millis() - timer > 5000) { //see if 5 seconds have elapsed since last message
currentDeskState = digitalRead(sensor);
String deskStateToPub = currentDeskState ? "down" : "up";
if (currentDeskState != prevDeskState) {
outputDoc["deskState"] = deskStateToPub;
prevDeskState = currentDeskState;
serializeJson(outputDoc, buffer);
timer = millis(); // reset a 5-second timer
if (MQTT_ENABLE) { // if posting is turned on, post the data
if (!mqtt.connected()) {
reconnect();
}
mqtt.publish(FEED, buffer); // post the data to the feed
Serial.println("Posted:");
serializeJsonPretty(outputDoc, Serial);
Serial.println();
mqtt.loop(); //this keeps the mqtt connection 'active'
}
}
}
}
/////SETUP_WIFI/////
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
String temp = WiFi.macAddress(); //get the unique MAC address to use as MQTT client ID, a 'truly' unique ID.
temp.toCharArray(mac, 6); //.macAddress() returns a byte array 6 bytes representing the MAC address
} //5C:CF:7F:F0:B0:C1 for example
///CONNECT/RECONNECT///// Monitor the connection to MQTT server, if down, reconnect
void reconnect() {
// Loop until we're reconnected
while (!mqtt.connected()) {
Serial.print("Attempting MQTT connection...");
if (mqtt.connect(mac, MQTT_TOKEN, MQTT_PASS)) { //<<---using MAC as client ID, always unique!!!
Serial.println("connected");
mqtt.subscribe(FEED);
} else {
Serial.print("failed, rc=");
Serial.print(mqtt.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
//---------------------------------------------
// LIGHT
//---------------------------------------------
#include <ESP8266WiFi.h> // Requisite Libraries . . .
#include <ESP8266HTTPClient.h> // HTTP Feather library
#include <PubSubClient.h>
#include <Wire.h>
#include "config.h" // include the configuration of credentials in the config.h file
//ArduinoJson can decode Unicode escape sequence, but this feature is disabled by default
//because it makes the code bigger. To enable it, you must define ARDUINOJSON_DECODE_UNICODE to 1
#define ARDUINOJSON_DECODE_UNICODE 1
#include <ArduinoJson.h>
#define MQTT_ENABLE 1 // for testing the sensor, set to 1 to enable posting data to the server
// Create objects for the ESP and MQTT clients
WiFiClient espClient;
PubSubClient mqtt(espClient);
char mac[12]; //A MAC address is a 'truly' unique ID for each device, lets use that as our 'truly' unique user ID!!!
unsigned long cbTimer; //A timer we will use for checking how long we've been sitting
int minsFactor = 60000; // This is used to convert milliseconds to minutes
// Configures the pins for the RGB LED
uint8_t bluePin = D5;
uint8_t greenPin = D6;
uint8_t redPin = D7;
// Stores all the RGB values for the LED
int colours[6][3] = {
{255, 0, 0}, //red
{0, 255, 0}, //green
{204, 204, 0}, //yellow
{0, 0, 255}, //blue
{80, 0, 80}, // purple
{0, 255, 255} // aqua
};
String currentDeskState = "down"; // My desk is always down at the beginning of the day
String prevDeskState; //We will use this to see if the desk state has changed
int dayOfWeek; // Used to store the day of the week
int currentColourIdx = 1; // We will always start the colour of the light at green
// A function that takes in the RGB values to render a colour to set the pins on the LED
void setColour(int arr[3])
{
analogWrite(redPin, arr[0]); // Grabs the 0th index in the array (the red value)
analogWrite(greenPin, arr[1]); // Grabs the 1st index in the array (the green value)
analogWrite(bluePin, arr[2]); // Grabs the 2nd index in the array (the blue value)
};
void setup() {
Serial.begin(115200); // Set the data rate in bits per second for serial data transmission and print that the program is starting
Serial.println("Starting!");
//If MQTT is enabled
if (MQTT_ENABLE) {
setup_wifi(); //Set up WiFi
mqtt.setServer(MQTT_SERVER, 1883); //Set up server
mqtt.setCallback(callback); //Set up callback to be called when we received data from the subscribed MQTT feed
}
// Set up pins for the RGB LED
pinMode(redPin, OUTPUT); // red LED
pinMode(bluePin, OUTPUT); // blue LED
pinMode(greenPin, OUTPUT); // green LED
// Get the day of the week
dayOfWeek = getDayOfWeek();
//If the day of the week is Saturday or Sunday
if(dayOfWeek == 0 or dayOfWeek == 6) {
// We do fun things!
cycleThroughColours();
}
// Set the timer
cbTimer = millis();
}
void loop() {
//If we haven't connected to MQTT, try again
if (!mqtt.connected()) {
reconnect();
}
// If it's Saturday or Sunday, we want to don't want to do anything because we are cycling through colours!
if(dayOfWeek == 0 or dayOfWeek == 6) {
return;
}
// If it's a weekday then we check if the desk is up
if (currentDeskState == "up") {
setColour(colours[1]); //Set to green
}
else if (currentDeskState == "down") { //If the current desk state is down
if (millis() - cbTimer <= 15 * minsFactor) { //If the desk has been up for less than or equal to 15 mins
setColour(colours[1]); //Set to green
}
else if (millis() - cbTimer <= 45 * minsFactor) { //If the desk has been up for less than or equal to 30 mins
setColour(colours[2]); //Set to yellow
}
else if (millis() - cbTimer > 45 * minsFactor) { //If the desk has been up for less than or equal to 45 mins
setColour(colours[0]); //Set to red; time to stand!
}
}
mqtt.loop(); //this keeps the mqtt connection 'active'
}
// Called when we get data from the feed
void callback(char* topic, byte* payload, unsigned int length) {
StaticJsonDocument<256> doc;
// A better way, with error reporting too!
DeserializationError err = deserializeJson(doc, payload, length);
if (err) { //well what was it?
Serial.println("deserializeJson() failed, are you sure this message is JSON formatted?");
Serial.print("Error code: ");
Serial.println(err.c_str());
return;
}
// If a message is received on the topic esp32/output, you check if the message is either "on" or "off".
// Changes the output state according to the message
if (strcmp(topic, FEED) == 0) {
serializeJson(doc["deskState"], Serial); //Serialize the JSON to get the current desk state
prevDeskState = currentDeskState; //Set the previous state to the current state
currentDeskState = doc["deskState"].as<String>(); // Get the new desk state
cbTimer = millis(); //Reset the timer
}
}
/////SETUP_WIFI/////
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
String temp = WiFi.macAddress(); //get the unique MAC address to use as MQTT client ID, a 'truly' unique ID.
temp.toCharArray(mac, 12); //.macAddress() returns a byte array 12 bytes representing the MAC address
} //5C:CF:7F:F0:B0:C1 for example
///CONNECT/RECONNECT///// Monitor the connection to MQTT server, if down, reconnect
void reconnect() {
// Loop until we're reconnected
while (!mqtt.connected()) {
Serial.print("Attempting MQTT connection...");
if (mqtt.connect(mac, MQTT_TOKEN, MQTT_PASS)) { //<<---using MAC as client ID, always unique!!!
Serial.println("connected");
mqtt.subscribe(FEED); //we are subscribing to 'theTopic' and all subtopics below that topic
} else {
Serial.print("failed, rc=");
Serial.print(mqtt.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
// Helper that gets us the day of the week
int getDayOfWeek() {
// Instantiates a client object
HTTPClient theClient;
theClient.begin(DAY_OF_WEEK_URL);
// Make a GET request to the client
int httpCode = theClient.GET();
Serial.println(httpCode);
// If we have a status code
if (httpCode > 0)
{
// Status code is 200; request was successful
if (httpCode == 200)
{
//Print to serial monitor that we got data from the endpoint
Serial.println("Received HTTP payload.");
// Instantiate the object to store the JSON document/blob
StaticJsonDocument<1024> doc;
// Get the JSON blob back from the endpoint (it's serialized at this point)
String payload = theClient.getString();
Serial.println("Parsing...");
// Derialize the payload into the doc variable
deserializeJson(doc, payload);
// Instantiates an error variable which we will check in the next line
DeserializationError error = deserializeJson(doc, payload);
// If there was an error
if (error)
{
//Print that deserialization failed to the serial monitor
Serial.print("deserializeJson() failed with error code ");
// Derialization failed so we print the error
Serial.println(error.c_str());
return -1;
}
// Get the day of the week by parsing the JSON
dayOfWeek = doc["day_of_week"].as<int>();
}
else
{
// Print that there's something wrong with the endpoint to the serial monitor
Serial.println("Something went wrong with connecting to the endpoint.");
}
}
// Return the day of the week
return dayOfWeek;
}
// A helper function to cycle colours
void cycleThroughColours() {
// Standard for loop; for each colour in the list of colours
for(int i = 0; i < sizeof(colours); i++) {
setColour(colours[i]); // Set the colour of the RGB LED to the colour
delay(2 * minsFactor); //Delay for 2 minutes before iterating again
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment