forked from Krautspace/doorstatus
Ludwig Behm
78e31e52a1
- Fix init_wifi: removed `ESP8266WiFiMulti`; replaced with simple wifi ap connection - Fix send_status: refactored return type into `bool` - Fix send_status: optimized if-branch for calculation of `status` into array access - Fix send_status: removed `client.connected()` => `client.connect(...)` is enough - Fix: renamed `reed` into `read` - Cleanup: changed int variables into uint8_t - Cleanup: moved static data (`ca_certs`, `client_cert/key` into global data - Style: changed typedef enum into scoped enum (enum class decl) - Style: changed int const definitions into anonymous enum constants - Style: reorderd headers alphabetically
188 lines
5.1 KiB
C++
188 lines
5.1 KiB
C++
/*
|
|
* file: statusclient.ino
|
|
* desc: This file is part of the Krautspace Doorstatus project. It's the
|
|
* main file for a client, who deals with the input from a read sensor and
|
|
* push these values to a server. The code is make to run on a NodeMCU with
|
|
* ESP8266 chip.
|
|
*/
|
|
|
|
#include <time.h>
|
|
#include <ESP8266WiFi.h>
|
|
#include <WiFiClientSecure.h>
|
|
|
|
#include "certs.h"
|
|
#include "config.h"
|
|
#include "credentials.h"
|
|
|
|
// cpp23 utility
|
|
namespace cpp23 {
|
|
template <typename Enum>
|
|
constexpr std::underlying_type_t<Enum> to_underlying(Enum e) noexcept { return static_cast<std::underlying_type_t<Enum>>(e);}
|
|
}
|
|
|
|
// defining some constants
|
|
enum : int {
|
|
LED_PIN = 16, // D0
|
|
READ_PIN = 5 // D1
|
|
};
|
|
|
|
enum class door_state {
|
|
closed = 0,
|
|
open = 1
|
|
};
|
|
|
|
// defining some globals
|
|
static inline door_state current_door_state = door_state::closed;
|
|
constexpr static inline std::array<char const[2], 2> state_str {{"0", "1"}};
|
|
|
|
// initializing
|
|
static inline BearSSL::X509List const ca_certs { CA_CERTS };
|
|
static inline BearSSL::X509List const client_cert { CLIENT_CERT };
|
|
static inline BearSSL::PrivateKey const client_key { CLIENT_KEY };
|
|
|
|
void blink_led(uint8_t blink_count, uint8_t delay_time) {
|
|
/*
|
|
* zur ausgabe von meldungen blinkt die interne led.
|
|
* erfolgreichesmeldungen werden durch kurze blinkzeichen angezeigt,
|
|
* fehlermeldungen sind durch eine lange sequenz gekennzeichnet.
|
|
* Signale:
|
|
* status der tür hat sich geändert: 2x kurz
|
|
* änderung erfolgreich gesendet: 5x kurz
|
|
* es konnte keine wifi aufgebaut werden: 3x lang
|
|
* senden des status fehlgeschlagen: 5x lang
|
|
*
|
|
* param 1: integer
|
|
* param 2: integer
|
|
*/
|
|
for (; blink_count; --blink_count) {
|
|
digitalWrite(LED_PIN, LOW);
|
|
delay(delay_time);
|
|
digitalWrite(LED_PIN, HIGH);
|
|
delay(delay_time);
|
|
}
|
|
}
|
|
|
|
void init_serial() {
|
|
/*
|
|
* set baudrate and debug modus
|
|
*/
|
|
Serial.begin(BAUD_RATE);
|
|
Serial.setDebugOutput(DEBUG);
|
|
Serial.println("\n[Srl] Serial interface initialized");
|
|
}
|
|
|
|
void init_pins() {
|
|
/*
|
|
* set gpio for read sensor and led
|
|
*/
|
|
pinMode(READ_PIN, INPUT_PULLUP);
|
|
pinMode(LED_PIN, OUTPUT);
|
|
digitalWrite(LED_PIN, HIGH);
|
|
Serial.println("[Pin] LED and READ initialized");
|
|
}
|
|
|
|
void init_wifi() {
|
|
WiFi.begin(SSID, PSK);
|
|
Serial.println("[WiFi] Wifi initialized");
|
|
|
|
while (WiFi.status() != WL_CONNECTED) {
|
|
Serial.println("[WiFi] Error: Failed to connect");
|
|
blink_led(3, 500);
|
|
}
|
|
|
|
Serial.printf("[WiFi] Connected to %s\n", WiFi.SSID());
|
|
Serial.print("[WiFi] IP: ");
|
|
Serial.println(WiFi.localIP());
|
|
|
|
set_clock();
|
|
}
|
|
|
|
door_state read_door_state() {
|
|
/*
|
|
* die initialisierung des read-pin mit pullup bewirkt, daß am pin
|
|
* 3,3 volt anliegen. die verbindung des pins mit GND sorgt dafür,
|
|
* daß die spannung "abfließen" kann. dadurch hat der pin dann den
|
|
* status 'low'.
|
|
* geschlossene tür -> read geschlossen -> low
|
|
* geöffnete tür -> read offen -> high
|
|
*/
|
|
return (digitalRead(READ_PIN) == HIGH) ? door_state::open : door_state::closed;
|
|
}
|
|
|
|
void set_clock() {
|
|
/*
|
|
* We need time for certificate authorization
|
|
*/
|
|
configTime(TZ_STRING, NTP_URL);
|
|
|
|
Serial.print("[Clock] Waiting for NTP time sync");
|
|
time_t now = time(nullptr);
|
|
for (; now < 16 * 3600; now = time(nullptr)) { // 16 hours
|
|
delay(500);
|
|
Serial.print(".");
|
|
}
|
|
Serial.println("");
|
|
struct tm timeinfo;
|
|
gmtime_r(&now, &timeinfo);
|
|
Serial.printf("[Clock] Current time: %s\n", asctime(&timeinfo));
|
|
}
|
|
|
|
bool send_status(door_state state) {
|
|
/*
|
|
* Inits wifi (if needed) and send the status
|
|
*/
|
|
char const* const status = state_str[cpp23::to_underlying(state)];
|
|
|
|
BearSSL::WiFiClientSecure client;
|
|
client.setTrustAnchors(&ca_certs);
|
|
client.setClientRSACert(&client_cert, &client_key);
|
|
|
|
Serial.println("[Ctx] SSL Context initialized");
|
|
Serial.printf("[Send] Connect to %s:%i\n", SERVER_URL, SERVER_PORT);
|
|
|
|
if (!client.connect(SERVER_URL, SERVER_PORT)) {
|
|
Serial.println("[Send] Can't connect to server");
|
|
Serial.printf("[Send] SSL Error: %d\n", client.getLastSSLError());
|
|
client.stop();
|
|
return false;
|
|
}
|
|
|
|
// ESP.resetFreeContStack();
|
|
// uint32_t freeStackStart = ESP.getFreeContStack();
|
|
Serial.println("[Send] Connection successful established");
|
|
Serial.printf("[Send] Send status: %s\n", status);
|
|
client.write(status);
|
|
client.stop();
|
|
|
|
return true;
|
|
}
|
|
|
|
void setup() {
|
|
|
|
/*
|
|
* things to do once at boot time
|
|
*/
|
|
init_serial();
|
|
init_pins();
|
|
init_wifi();
|
|
}
|
|
|
|
void loop() {
|
|
|
|
/*
|
|
* things are running in a endless loop
|
|
*/
|
|
door_state new_door_state = read_door_state();
|
|
if (new_door_state != current_door_state) {
|
|
Serial.printf("[Loop] Status has changed to %i\n", new_door_state);
|
|
blink_led(2, 100);
|
|
if (send_status(new_door_state)) {
|
|
current_door_state = new_door_state;
|
|
blink_led(5, 100);
|
|
} else {
|
|
blink_led(5, 500);
|
|
}
|
|
}
|
|
|
|
delay(FREQUENCY);
|
|
}
|