#pragma once #include #include #include #include #include #include #include #include "Config.h" #include "ScreenData.h" class DoorbellLogic { public: void begin(); // Boot sequence (called individually so .ino can render between steps) void beginWiFi(); void connectWiFiBlocking(); void finishBoot(); void update(); const ScreenState& getScreenState() const { return _screen; } // Input events from the outside void onTouch(const TouchEvent& evt); void onSerialCommand(const String& cmd); private: ScreenState _screen; // State DeviceState _state = DeviceState::SILENT; String _currentMessage = ""; unsigned long _bootTime = 0; bool _inBootGrace = true; bool _networkOK = false; // Dedup String _lastAlertId; String _lastSilenceId; String _lastAdminId; // Timing unsigned long _lastPoll = 0; unsigned long _lastBlink = 0; unsigned long _alertStart = 0; unsigned long _wakeStart = 0; unsigned long _lastHeartbeat = 0; bool _blinkState = false; // Stale silence protection time_t _alertMsgEpoch = 0; // ntfy timestamp of the alert that started ALERTING time_t _lastParsedMsgEpoch = 0; // ntfy timestamp of message currently being handled // Deferred status publish bool _pendingStatus = false; String _pendStatusState; String _pendStatusMsg; // NTP — pointer because NTPClient has no default constructor WiFiUDP _ntpUDP; NTPClient* _timeClient = nullptr; bool _ntpSynced = false; time_t _lastEpoch = 0; // WiFi WiFiMulti _wifiMulti; // Methods void checkNetwork(); void syncNTP(); void pollTopics(); void pollTopic(const char* url, void (DoorbellLogic::*handler)(const String&), const char* name, String& lastId); void parseMessages(String& response, const char* name, void (DoorbellLogic::*handler)(const String&), String& lastId); void handleAlert(const String& msg); void handleSilence(const String& msg); void handleAdmin(const String& msg); void transitionTo(DeviceState newState); void queueStatus(const char* state, const String& msg); void flushStatus(); void updateScreenState(); static DoorbellLogic* _instance; // for static event callback static void onWiFiEvent(WiFiEvent_t event); };