2020-05-06 21:05:51 +00:00
|
|
|
#include "config.h"
|
2020-05-13 06:15:44 +00:00
|
|
|
#include "wifi.h"
|
2020-05-11 17:01:12 +00:00
|
|
|
#include <ArduinoJson.h>
|
2020-05-06 21:05:51 +00:00
|
|
|
|
|
|
|
// how long to delay between each request to the
|
|
|
|
// server, in ms.
|
|
|
|
const int REQUEST_RATE = 1500;
|
|
|
|
|
|
|
|
// how long to keep a momentary switch high.
|
|
|
|
// results approximate, and must be shorter than REQUEST_RATE.
|
|
|
|
const int MOMENTARY_PERIOD = 250;
|
|
|
|
|
|
|
|
// Custom pin status for momentary switch that shouldn't
|
|
|
|
// get toggled again yet.
|
|
|
|
const int OLD_HIGH = 255;
|
|
|
|
|
|
|
|
// Holds the current state of all the pins.
|
|
|
|
// Gets written to by parse_webhook_response().
|
|
|
|
// Gets read from by set_pins().
|
2020-05-13 06:15:44 +00:00
|
|
|
int pin_states[NUM_PINS] = {0};
|
2020-05-06 21:05:51 +00:00
|
|
|
|
|
|
|
// if any momentary pins went high this loop, we
|
|
|
|
// wait the agreed upon delay and then turn them off.
|
|
|
|
// if any momentary data input went low, we "reset"
|
|
|
|
// the pin.
|
2020-05-13 06:15:44 +00:00
|
|
|
//
|
|
|
|
// returns the time spent delaying, if any.
|
2020-05-06 21:05:51 +00:00
|
|
|
int handle_momentary() {
|
2020-05-13 06:15:44 +00:00
|
|
|
bool need_delay = false;
|
|
|
|
for (int i = 0; i < NUM_PINS; i++) {
|
|
|
|
// if [the pin is momentary] and [it was set high this cycle]
|
|
|
|
if (PIN_MAP[i][1] == 0 && pin_states[i] == HIGH) {
|
|
|
|
need_delay = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!need_delay) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
delay(MOMENTARY_PERIOD);
|
|
|
|
|
|
|
|
for (int i = 0; i < NUM_PINS; i++) {
|
2020-05-06 21:05:51 +00:00
|
|
|
// if [the pin is momentary] and [it was set high this cycle]
|
|
|
|
if (PIN_MAP[i][1] == 0 && pin_states[i] == HIGH) {
|
2020-05-13 06:15:44 +00:00
|
|
|
// set the pin back to low and make it 'sticky' until we read a low again.
|
2020-05-06 21:05:51 +00:00
|
|
|
digitalWrite(PIN_MAP[i][0], LOW);
|
|
|
|
pin_states[i] = OLD_HIGH;
|
|
|
|
}
|
|
|
|
}
|
2020-05-13 06:15:44 +00:00
|
|
|
|
|
|
|
return MOMENTARY_PERIOD;
|
2020-05-06 21:05:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// poll_server makes the actual HTTP request and handles
|
|
|
|
// the result. It returns false if an error occurred.
|
|
|
|
bool poll_server() {
|
2020-05-14 18:26:02 +00:00
|
|
|
String data = FetchURL(WEBHOOK_URL);
|
|
|
|
if (data == "") return false;
|
|
|
|
parse_webhook_response(data);
|
|
|
|
return true;
|
2020-05-06 21:05:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void parse_webhook_response(String raw_data) {
|
2020-05-11 17:01:12 +00:00
|
|
|
StaticJsonDocument<256> doc;
|
|
|
|
DeserializationError err = deserializeJson(doc, raw_data);
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
Serial.print("Couldn't parse json data. Error code: ");
|
|
|
|
Serial.println(err.c_str());
|
2020-05-06 21:05:51 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 17:01:12 +00:00
|
|
|
JsonArray data = doc.as<JsonArray>();
|
|
|
|
int i = 0;
|
|
|
|
for (JsonVariant item : data) {
|
2020-05-06 21:05:51 +00:00
|
|
|
if (tripped(i) && data[i] == HIGH) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-05-11 17:01:12 +00:00
|
|
|
pin_states[i] = item;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
2020-05-13 06:15:44 +00:00
|
|
|
if (data.size() < NUM_PINS) {
|
2020-05-11 17:01:12 +00:00
|
|
|
Serial.println("Did not receive data for all pins.");
|
2020-05-06 21:05:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-14 18:26:02 +00:00
|
|
|
// Set the pins to the right state, and set them all to high during
|
|
|
|
// initialization.
|
|
|
|
void initPins() {
|
|
|
|
for (int i = 0; i < NUM_PINS; i++) {
|
|
|
|
pinMode(PIN_MAP[i][0], OUTPUT);
|
|
|
|
digitalWrite(PIN_MAP[i][0], HIGH);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-05-06 21:05:51 +00:00
|
|
|
// Uses the current pin_states to actually write to the pins
|
2020-05-14 18:26:02 +00:00
|
|
|
void writePins() {
|
2020-05-13 06:15:44 +00:00
|
|
|
for (int i = 0; i < NUM_PINS; i++) {
|
2020-05-06 21:05:51 +00:00
|
|
|
if (tripped(i)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
digitalWrite(PIN_MAP[i][0], pin_states[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns true if pin at map index i (not pinout numbering) is momentary
|
|
|
|
// and has been tripped (received a 1 without a subsequent 0 yet)
|
|
|
|
// returns false otherwise
|
|
|
|
bool tripped(int i) {
|
|
|
|
return PIN_MAP[i][1] == 0 && pin_states[i] == OLD_HIGH;
|
|
|
|
}
|
2020-05-14 18:26:02 +00:00
|
|
|
|
|
|
|
void setup() {
|
|
|
|
Serial.begin(9600);
|
|
|
|
initPins();
|
|
|
|
InitWifi();
|
|
|
|
}
|
|
|
|
|
|
|
|
void loop() {
|
|
|
|
poll_server();
|
|
|
|
writePins();
|
|
|
|
int elapsed = handle_momentary();
|
|
|
|
|
|
|
|
Serial.flush();
|
|
|
|
delay(REQUEST_RATE - elapsed);
|
|
|
|
}
|