/* * 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 reed sensor and * push these values to a server. The code is make to run on a NodeMCU with * ESP8266 chip. */ #include #include #include #include "config.h" #include "certs.h" #include "credentials.h" const int LED_PIN = 16; // D0 const int REED_PIN = 5; // D1 typedef enum { DOOR_CLOSED = 0, DOOR_OPEN = 1 } door_state; door_state current_door_state = DOOR_CLOSED; BearSSL::WiFiClientSecure client; void blink_led(int blink_count, int 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(int i=0; i!= blink_count; ++i) { 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(); Serial.println("[Srl] Serial interface initialized"); } void init_pins() { /* * set gpio for reed sensor and led */ pinMode(REED_PIN, INPUT_PULLUP); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); Serial.println("[Pin] LED and REED initialized"); } void init_wifi() { /* * Creates the ssl context. Turns wifi off and than into * access point mode. * TODO: is 'turn of' needed! */ ESP8266WiFiMulti wifi; WiFi.mode(WIFI_OFF); WiFi.mode(WIFI_STA); wifi.addAP(SSID_1, PSK_1); wifi.addAP(SSID_2, NULL); Serial.println("[Wifi] Wifi initialized"); wifi.run(); if (WiFi.status() == WL_CONNECTED) { Serial.print("[Wif] Connected to "); Serial.println(WiFi.SSID()); Serial.print("[Wifi] IP: "); Serial.println(WiFi.localIP()); set_clock(); } else { Serial.println("[Wifi] Error: Failed to connect"); blink_led(3, 500); } } door_state read_door_state() { /* * die initialisierung des reed-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 -> reed geschlossen -> low * geöffnete tür -> reed offen -> high */ if (digitalRead(REED_PIN) == HIGH) { return DOOR_OPEN; } return DOOR_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); while (now < 8 * 3600 * 2) { delay(500); Serial.print("."); now = time(nullptr); } Serial.println(""); struct tm timeinfo; gmtime_r(&now, &timeinfo); Serial.print("[Clock] Current time: "); Serial.println(asctime(&timeinfo)); } int send_status(door_state state) { /* * Inits wifi (if needed) and send the status */ char status[2] = ""; if (state == DOOR_CLOSED) { strncpy(status, "0", 1); } else if (state == DOOR_OPEN) { strncpy(status, "1", 1); } else { return 1; } BearSSL::X509List server_cert(SERVER_CERT); BearSSL::X509List client_cert(CLIENT_CERT); BearSSL::PrivateKey client_key(CLIENT_KEY); client.setTrustAnchors(&server_cert); client.setClientRSACert(&client_cert, &client_key); Serial.println("[Ctx] SSL Context initialized"); Serial.printf("[Send] Connect to %s:%i\n", SERVER_URL, SERVER_PORT); client.connect(SERVER_URL, SERVER_PORT); if (!client.connected()) { Serial.println("[Send] Can't connect to server"); Serial.print("[Send] SSL Error: "); Serial.println(client.getLastSSLError()); client.stop(); return 1; } else { 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 0; } 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) == 0) { current_door_state = new_door_state; blink_led(5, 100); } else { blink_led(5, 500); } } delay(FREQUENCY); }