#undef ARDUINO_M5STACK_FIRE #define ARDUINO_M5STACK_Paper #define YAML_DISABLE_CJSON #define LGFX_M5PAPER #define LGFX_USE_V1 #define LGFX_AUTODETECT #include #include #include #include #include "display.hpp" #include "keypad.hpp" #include "input.hpp" #include "status.hpp" #include "lock.hpp" #include "touch.hpp" #include "settings.hpp" #include "mqtt.hpp" static MQTT *mqtt; static Display display; static Keypad *keypad; static Status *status; static Input *input; static Touch *touch; static Lock *keylock; void keypad_state(bool enabled) { for (int i = 0; i < 11; i++) { keypad->set_enabled(i, enabled); } keypad->set_enabled(11, !enabled); } static bool is_disarmed = false; static const int WIFI_CONNECT_RETRY_MAX = 30; void mqtt_callback(char *topic, byte *payload, unsigned int length) { payload[length] = '\0'; String state((const char *)payload); is_disarmed = state == "disarmed"; state.replace("_", " "); state[0] = toupper(state[0]); Serial.println(state); status->set(state); status->draw(&display); keypad_state(!is_disarmed); } void lock() { if (is_disarmed) { mqtt->send("ARM_AWAY"); } } void unlock() { mqtt->send("DISARM"); } void submit(String code) { if (!keylock->check(code)) { status->set("Invalid"); return; } unlock(); } bool isConnecting = false; void initWifi(Settings *settings) { if (!settings) { status->set("No settings"); return; } if (isConnecting) { status->set("Already connecting"); return; } isConnecting = true; status->set("Connecting"); WiFi.begin(settings->gettext("wifi:ssid"), settings->gettext("wifi:password")); if (WiFi.isConnected()) { WiFi.disconnect(); } Serial.print("Connecting to Wi-Fi network"); for (int cnt_retry = 0; cnt_retry < WIFI_CONNECT_RETRY_MAX && !WiFi.isConnected(); cnt_retry++) { delay(500); Serial.print("."); } Serial.println(""); if (WiFi.isConnected()) { Serial.print("Local IP: "); Serial.println(WiFi.localIP()); isConnecting = false; status->set("Connected"); } else { status->set("Failed to connect"); isConnecting = false; return; } } void p(int v) { switch (v) { case 9: input->clear(); break; case 10: input->append("0"); break; case 11: lock(); break; default: input->append(v + 1); break; } if (input->length() >= 6) { // verify input->draw(&display); // force one more redraw for the last character submit(input->get_value()); input->clear(); } } void setup() { M5.begin(); display.init(); touch = new Touch(M5.TP); status = new Status("Loading"); keypad = new Keypad(&display); keypad->addListener("pressed", p); input = new Input("", keypad->get_width(), 0, display.width() - keypad->get_width(), 115); auto settings = new Settings(); if (!settings) { status->set("Settings Error"); return; } initWifi(settings); keylock = new Lock(settings); mqtt = new MQTT(settings, mqtt_callback); mqtt->connect(); keylock->begin(); } void loop() { mqtt->loop(); auto tap = touch->tap(); if (tap.has_value()) keypad->update(tap.value()); keypad->draw(); input->draw(&display); status->draw(&display); }