diff --git a/config.h.example b/config.h.example index ef45f82..f65469e 100644 --- a/config.h.example +++ b/config.h.example @@ -1,3 +1,7 @@ +// Do not edit these two lines +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + #define WIFI_SSID "myNetwork" #define WIFI_PASSWORD "myPassword" #define WEBHOOK_URL "example.com/aoeuhtns" @@ -12,8 +16,54 @@ // // to activate the momentary switch, (pin 5) deactivate the first // latched switch, (pin 8) and activate the second latched switch. (pin 10) -const int PIN_MAP[][2] = { +const int NUM_PINS = 3; +const int PIN_MAP[NUM_PINS][2] = { {5, 1}, {8, 1}, {10, 1} }; + +// The signing/root certificate for your webhook site. +// For internal installations this might be a self-signing cert. +// For public installations, acquire the root cert for the CA and +// place it here. You can get this for your target domain with: +// +// sudo openssl s_client -connect sss.annabunch.es:443 -showcerts +// +// Be sure that you copy the cert that is described as a "Root CA" or +// "Root Trust" certificate. +// +// The provided example is for letsencrypt.org +static const char ca_cert[] PROGMEM = R"EOF( +-----BEGIN CERTIFICATE----- +MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow +SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT +GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF +q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8 +SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0 +Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA +a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj +/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T +AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG +CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv +bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k +c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw +VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC +ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz +MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu +Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF +AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo +uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/ +wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu +X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG +PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 +KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== +-----END CERTIFICATE----- +)EOF"; + + +// Do not edit this line +#endif diff --git a/smartswitch.ino b/smartswitch.ino index ad11834..5f3b7a6 100644 --- a/smartswitch.ino +++ b/smartswitch.ino @@ -19,31 +19,6 @@ const int OLD_HIGH = 255; // Gets read from by set_pins(). int pin_states[NUM_PINS] = {0}; -void init_serial() { - Serial.begin(9600); -} - -void init_pins() { - for (int i = 0; i < NUM_PINS; i++) { - digitalWrite(PIN_MAP[i][0], LOW); - } -} - -void setup() { - init_pins(); - init_serial(); - init_wifi(); -} - -void loop() { - poll_server(); - set_pins(); - int elapsed = handle_momentary(); - - Serial.flush(); - delay(REQUEST_RATE - elapsed); -} - // 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" @@ -81,20 +56,10 @@ int handle_momentary() { // poll_server makes the actual HTTP request and handles // the result. It returns false if an error occurred. bool poll_server() { - client.begin(transport, WEBHOOK_URL); - int status = client.GET(); - if (status < 0) { - Serial.print("Client error communicating with server: "); - Serial.println(status); - return false; - } - if (status <= 400) { - Serial.print("Received HTTP status code "); - Serial.println(status); - return false; - } - - parse_webhook_response(client.getString()); + String data = FetchURL(WEBHOOK_URL); + if (data == "") return false; + parse_webhook_response(data); + return true; } void parse_webhook_response(String raw_data) { @@ -122,8 +87,18 @@ void parse_webhook_response(String raw_data) { } } +// 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); + } + +} + // Uses the current pin_states to actually write to the pins -void set_pins() { +void writePins() { for (int i = 0; i < NUM_PINS; i++) { if (tripped(i)) { continue; @@ -139,3 +114,18 @@ void set_pins() { bool tripped(int i) { return PIN_MAP[i][1] == 0 && pin_states[i] == OLD_HIGH; } + +void setup() { + Serial.begin(9600); + initPins(); + InitWifi(); +} + +void loop() { + poll_server(); + writePins(); + int elapsed = handle_momentary(); + + Serial.flush(); + delay(REQUEST_RATE - elapsed); +} diff --git a/wifi.h b/wifi.h index f59af8b..2365ad5 100644 --- a/wifi.h +++ b/wifi.h @@ -1,17 +1,39 @@ +#include "config.h" #include #include -//#include -#include -#include +#include HTTPClient client; -BearSSL::WifiClientSecure *transport; +BearSSL::WiFiClientSecure *secure_transport; +BearSSL::Session *tls_session; BearSSL::X509List cert_list; -void init_wifi() { - transport = new WifiClientSecure(); +void syncTime() { + // 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(""); +} - Serial.println("Attempting to (re)connect to wifi"); +void initTLS() { + secure_transport = new BearSSL::WiFiClientSecure(); + + syncTime(); + cert_list.append(ca_cert); + secure_transport->setTrustAnchors(&cert_list); + + tls_session = new BearSSL::Session(); + secure_transport->setSession(tls_session); +} + +void InitWifi() { + Serial.println("Attempting to connect to wifi"); WiFi.disconnect(); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); int elapsed = 0; @@ -25,36 +47,23 @@ void init_wifi() { Serial.println("Wifi connected"); - sync_time(); - load_ca_cert(); + initTLS(); } -void load_ca_cert() { - // read cert from file - if (!SPIFFS.begin()) { - Serial.println("Failed to mount file system."); - return +String FetchURL(const char *path) { + client.begin(*secure_transport, WEBHOOK_URL); + + int status = client.GET(); + if (status < 0) { + Serial.print("Client error communicating with server: "); + Serial.println(status); + return ""; + } + if (status >= 400) { + Serial.print("Received HTTP status code "); + Serial.println(status); + 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(""); + return client.getString(); }