Compare commits

...

2 Commits

4 changed files with 99 additions and 43 deletions

View File

@ -6,7 +6,7 @@ UPLOAD_PORT ?= /dev/ttyUSB0
all: build all: build
build: build:
arduino-cli compile -b ${BOARD_NAME} smartswitch.ino arduino-cli compile -b ${BOARD_NAME} ${PWD}
upload: upload:
arduino-cli upload -b ${BOARD_NAME} -p ${UPLOAD_PORT} smartswitch.ino arduino-cli upload -b ${BOARD_NAME} -p ${UPLOAD_PORT} ${PWD}

View File

@ -37,7 +37,7 @@ only be high for a short time. 1 is for latched mode; the pin will stay high unt
## Building ## Building
**TODO** Just run `make` to build the code. You need to have `config.h` and `data/ca_cert.pem` defined.
## Webhook data ## Webhook data
@ -49,3 +49,9 @@ The webhook should always return a page in the following (JSON-compatible) forma
Where index and state are both integers. If you are expecting momentary input, you should return the Where index and state are both integers. If you are expecting momentary input, you should return the
state to '0' after the page is served / the webhook is consumed. state to '0' after the page is served / the webhook is consumed.
## Future Improvements
* make it actually work...
* use WifiManager?

View File

@ -1,6 +1,5 @@
#include "config.h" #include "config.h"
#include <ESP8266WiFi.h> #include "wifi.h"
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
// how long to delay between each request to the // how long to delay between each request to the
@ -18,32 +17,20 @@ const int OLD_HIGH = 255;
// Holds the current state of all the pins. // Holds the current state of all the pins.
// Gets written to by parse_webhook_response(). // Gets written to by parse_webhook_response().
// Gets read from by set_pins(). // Gets read from by set_pins().
int pin_states[sizeof(PIN_MAP)] = {0}; int pin_states[NUM_PINS] = {0};
// Just a static client object to avoid memory allocations.
HTTPClient client;
void init_serial() { void init_serial() {
Serial.begin(9600); Serial.begin(9600);
} }
void init_wifi() { void init_pins() {
Serial.println("Attempting to (re)connect to wifi"); for (int i = 0; i < NUM_PINS; i++) {
WiFi.disconnect(); digitalWrite(PIN_MAP[i][0], LOW);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
int elapsed = 0;
while (WiFi.status() != WL_CONNECTED) {
Serial.print("Wifi connecting for ");
Serial.print(elapsed);
Serial.println(" seconds");
elapsed++;
delay(1000);
} }
Serial.println("Wifi connected");
} }
void setup() { void setup() {
init_pins();
init_serial(); init_serial();
init_wifi(); init_wifi();
} }
@ -61,23 +48,40 @@ void loop() {
// wait the agreed upon delay and then turn them off. // wait the agreed upon delay and then turn them off.
// if any momentary data input went low, we "reset" // if any momentary data input went low, we "reset"
// the pin. // the pin.
//
// returns the time spent delaying, if any.
int handle_momentary() { int handle_momentary() {
for (int i = 0; i < sizeof(pin_states); i++) { 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 [the pin is momentary] and [it was set high this cycle]
if (PIN_MAP[i][1] == 0 && pin_states[i] == HIGH) { if (PIN_MAP[i][1] == 0 && pin_states[i] == HIGH) {
// wait for the specified amount of time, then set the pin need_delay = true;
// back to low. break;
}
}
if (!need_delay) {
return 0;
}
delay(MOMENTARY_PERIOD); delay(MOMENTARY_PERIOD);
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) {
// set the pin back to low and make it 'sticky' until we read a low again.
digitalWrite(PIN_MAP[i][0], LOW); digitalWrite(PIN_MAP[i][0], LOW);
pin_states[i] = OLD_HIGH; pin_states[i] = OLD_HIGH;
} }
} }
return MOMENTARY_PERIOD;
} }
// poll_server makes the actual HTTP request and handles // poll_server makes the actual HTTP request and handles
// the result. It returns false if an error occurred. // the result. It returns false if an error occurred.
bool poll_server() { bool poll_server() {
client.begin(WEBHOOK_URL); client.begin(transport, WEBHOOK_URL);
int status = client.GET(); int status = client.GET();
if (status < 0) { if (status < 0) {
Serial.print("Client error communicating with server: "); Serial.print("Client error communicating with server: ");
@ -94,20 +98,6 @@ bool poll_server() {
} }
void parse_webhook_response(String raw_data) { void parse_webhook_response(String raw_data) {
// int data[sizeof(PIN_MAP)] = {-1};
// // TODO: split the data and turn it into numbers
// while (raw_data.length() > 0) {
// // read to a newline
// String line = raw_data.substring(0, raw_data.indexOf('\n'));
// raw_data.remove(0, raw_data.indexOf('\n') + 1);
// // extract data from the line and add it to our incoming data array
// int index = line.substring(0, raw_data.indexOf(' ')).toInt();
// int state = line.substring(raw_data.indexOf(' ')+1).toInt();
// data[index] = state;
// }
StaticJsonDocument<256> doc; StaticJsonDocument<256> doc;
DeserializationError err = deserializeJson(doc, raw_data); DeserializationError err = deserializeJson(doc, raw_data);
@ -127,14 +117,14 @@ void parse_webhook_response(String raw_data) {
i++; i++;
} }
if (data.size() < sizeof(pin_states) / sizeof(*pin_states)) { if (data.size() < NUM_PINS) {
Serial.println("Did not receive data for all pins."); Serial.println("Did not receive data for all pins.");
} }
} }
// Uses the current pin_states to actually write to the pins // Uses the current pin_states to actually write to the pins
void set_pins() { void set_pins() {
for (int i = 0; i < sizeof(PIN_MAP); i++) { for (int i = 0; i < NUM_PINS; i++) {
if (tripped(i)) { if (tripped(i)) {
continue; continue;
} }

60
wifi.h Normal file
View File

@ -0,0 +1,60 @@
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
//#include <WifiClientSecureBearSSL.h>
#include <bearssl.h>
#include <FS.h>
HTTPClient client;
BearSSL::WifiClientSecure *transport;
BearSSL::X509List cert_list;
void init_wifi() {
transport = new WifiClientSecure();
Serial.println("Attempting to (re)connect to wifi");
WiFi.disconnect();
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
int elapsed = 0;
while (WiFi.status() != WL_CONNECTED) {
Serial.print("Wifi connecting for ");
Serial.print(elapsed);
Serial.println(" seconds");
elapsed++;
delay(1000);
}
Serial.println("Wifi connected");
sync_time();
load_ca_cert();
}
void load_ca_cert() {
// read cert from file
if (!SPIFFS.begin()) {
Serial.println("Failed to mount file system.");
return
}
File cert = SPIFFS.open("/ca_cert.pem", "r");
if (!cert) {
Serial.println("Couldn't open cert file.");
return;
}
cert_list.append(strdup(cert.readString().c_str()));
netClient->setTrustAnchors(&certList);
}
void sync_time() {
// sync time
Serial.print("Syncing time");
configTime(8 * 3600, 0, "pool.ntp.org", "time.nist.gov");
time_t now = time(nullptr);
while (now < 8 * 3600 * 2) {
delay(500);
Serial.print(".");
now = time(nullptr);
}
Serial.println("");
}