snapshot
This commit is contained in:
@@ -78,6 +78,10 @@ void DoorbellLogic::finishBoot() {
|
|||||||
flushStatus();
|
flushStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Serial.printf("[CONFIG] ALERT_URL: %s\n", ALERT_URL);
|
||||||
|
Serial.printf("[CONFIG] SILENCE_URL: %s\n", SILENCE_URL);
|
||||||
|
Serial.printf("[CONFIG] ADMIN_URL: %s\n", ADMIN_URL);
|
||||||
|
|
||||||
transitionTo(DeviceState::SILENT);
|
transitionTo(DeviceState::SILENT);
|
||||||
Serial.printf("[BOOT] Grace period: %d ms\n", BOOT_GRACE_MS);
|
Serial.printf("[BOOT] Grace period: %d ms\n", BOOT_GRACE_MS);
|
||||||
}
|
}
|
||||||
@@ -223,7 +227,7 @@ void DoorbellLogic::transitionTo(DeviceState newState) {
|
|||||||
switch (newState) {
|
switch (newState) {
|
||||||
case DeviceState::SILENT:
|
case DeviceState::SILENT:
|
||||||
_screen.screen = ScreenID::OFF;
|
_screen.screen = ScreenID::OFF;
|
||||||
_alertStartEpoch = 0; // <-- ADD: clear on silence
|
_alertMsgEpoch = 0;
|
||||||
Serial.println("-> SILENT");
|
Serial.println("-> SILENT");
|
||||||
break;
|
break;
|
||||||
case DeviceState::ALERTING:
|
case DeviceState::ALERTING:
|
||||||
@@ -248,24 +252,31 @@ void DoorbellLogic::transitionTo(DeviceState newState) {
|
|||||||
void DoorbellLogic::handleAlert(const String& msg) {
|
void DoorbellLogic::handleAlert(const String& msg) {
|
||||||
if (_state == DeviceState::ALERTING && _currentMessage == msg) return;
|
if (_state == DeviceState::ALERTING && _currentMessage == msg) return;
|
||||||
_currentMessage = msg;
|
_currentMessage = msg;
|
||||||
|
_alertMsgEpoch = _lastParsedMsgEpoch; // store ntfy server time of this alert
|
||||||
|
Serial.printf("[ALERT] Accepted. ntfy time=%ld\n", (long)_alertMsgEpoch);
|
||||||
transitionTo(DeviceState::ALERTING);
|
transitionTo(DeviceState::ALERTING);
|
||||||
queueStatus("ALERTING", msg);
|
queueStatus("ALERTING", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoorbellLogic::handleSilence(const String& msg) {
|
void DoorbellLogic::handleSilence(const String& msg) {
|
||||||
// When called from ntfy poll, reject silence messages that predate the current alert.
|
if (_state != DeviceState::ALERTING) {
|
||||||
// This prevents stale silence messages from immediately canceling new alerts.
|
Serial.println("[SILENCE] Ignored — not alerting");
|
||||||
// When called from touch/admin/timeout, _lastParsedMsgEpoch is 0 → bypass check.
|
|
||||||
if (_state == DeviceState::ALERTING &&
|
|
||||||
_lastParsedMsgEpoch > 0 &&
|
|
||||||
_alertStartEpoch > 0 &&
|
|
||||||
_lastParsedMsgEpoch <= _alertStartEpoch) {
|
|
||||||
Serial.printf("[SILENCE] Ignored — predates alert (msg:%ld alert:%ld)\n",
|
|
||||||
(long)_lastParsedMsgEpoch, (long)_alertStartEpoch);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this came from ntfy poll (_lastParsedMsgEpoch > 0), reject if it
|
||||||
|
// predates or equals the alert. Both timestamps are from ntfy's server clock.
|
||||||
|
if (_lastParsedMsgEpoch > 0 && _alertMsgEpoch > 0 &&
|
||||||
|
_lastParsedMsgEpoch <= _alertMsgEpoch) {
|
||||||
|
Serial.printf("[SILENCE] Ignored — predates alert (silence:%ld <= alert:%ld)\n",
|
||||||
|
(long)_lastParsedMsgEpoch, (long)_alertMsgEpoch);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf("[SILENCE] Accepted (silence:%ld > alert:%ld)\n",
|
||||||
|
(long)_lastParsedMsgEpoch, (long)_alertMsgEpoch);
|
||||||
_currentMessage = "";
|
_currentMessage = "";
|
||||||
|
_alertMsgEpoch = 0;
|
||||||
transitionTo(DeviceState::SILENT);
|
transitionTo(DeviceState::SILENT);
|
||||||
queueStatus("SILENT", "silenced");
|
queueStatus("SILENT", "silenced");
|
||||||
}
|
}
|
||||||
@@ -363,38 +374,64 @@ void DoorbellLogic::checkNetwork() {
|
|||||||
// ntfy Polling
|
// ntfy Polling
|
||||||
// =====================================================================
|
// =====================================================================
|
||||||
void DoorbellLogic::pollTopics() {
|
void DoorbellLogic::pollTopics() {
|
||||||
Serial.println("[POLL] Starting poll cycle...");
|
Serial.printf("[POLL] Starting poll cycle... WiFi:%s NTP:%d Grace:%d\n",
|
||||||
|
WiFi.isConnected() ? "OK" : "DOWN", _ntpSynced, _inBootGrace);
|
||||||
|
|
||||||
pollTopic(ALERT_URL, &DoorbellLogic::handleAlert, "ALERT", _lastAlertId);
|
pollTopic(ALERT_URL, &DoorbellLogic::handleAlert, "ALERT", _lastAlertId);
|
||||||
yield(); // ← MISSING
|
yield();
|
||||||
pollTopic(SILENCE_URL, &DoorbellLogic::handleSilence, "SILENCE", _lastSilenceId);
|
pollTopic(SILENCE_URL, &DoorbellLogic::handleSilence, "SILENCE", _lastSilenceId);
|
||||||
yield(); // ← MISSING
|
yield();
|
||||||
pollTopic(ADMIN_URL, &DoorbellLogic::handleAdmin, "ADMIN", _lastAdminId);
|
pollTopic(ADMIN_URL, &DoorbellLogic::handleAdmin, "ADMIN", _lastAdminId);
|
||||||
Serial.printf("[POLL] Done. Heap: %dKB\n", ESP.getFreeHeap() / 1024); // ← MISSING
|
|
||||||
|
Serial.printf("[POLL] Done. Heap: %dKB\n", ESP.getFreeHeap() / 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoorbellLogic::pollTopic(const char* url,
|
void DoorbellLogic::pollTopic(const char* url,
|
||||||
void (DoorbellLogic::*handler)(const String&),
|
void (DoorbellLogic::*handler)(const String&),
|
||||||
const char* name, String& lastId) {
|
const char* name, String& lastId) {
|
||||||
if (!WiFi.isConnected()) { // ← MISSING
|
Serial.printf("[%s] Polling: %s\n", name, url);
|
||||||
Serial.printf("[%s] Skipped — WiFi down\n", name);
|
|
||||||
|
if (!WiFi.isConnected()) {
|
||||||
|
Serial.printf("[%s] SKIPPED — WiFi down\n", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFiClientSecure client;
|
WiFiClientSecure client;
|
||||||
client.setInsecure();
|
client.setInsecure();
|
||||||
client.setTimeout(10); // ← MISSING
|
client.setTimeout(10);
|
||||||
|
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||||
http.setTimeout(10000);
|
http.setTimeout(10000);
|
||||||
http.setReuse(false); // ← MISSING
|
http.setReuse(false);
|
||||||
|
|
||||||
// ... rest of method ...
|
if (!http.begin(client, url)) {
|
||||||
|
Serial.printf("[%s] begin() FAILED\n", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int code = http.GET();
|
||||||
|
Serial.printf("[%s] HTTP %d\n", name, code);
|
||||||
|
|
||||||
|
if (code == HTTP_CODE_OK) {
|
||||||
|
String response = http.getString();
|
||||||
|
Serial.printf("[%s] %d bytes\n", name, response.length());
|
||||||
|
if (response.length() > 0) {
|
||||||
|
parseMessages(response, name, handler, lastId);
|
||||||
|
} else {
|
||||||
|
Serial.printf("[%s] Empty response\n", name);
|
||||||
|
}
|
||||||
|
} else if (code < 0) {
|
||||||
|
Serial.printf("[%s] ERROR: %s\n", name, http.errorToString(code).c_str());
|
||||||
|
_networkOK = false;
|
||||||
|
} else {
|
||||||
|
Serial.printf("[%s] Unexpected code: %d\n", name, code);
|
||||||
|
}
|
||||||
|
|
||||||
http.end();
|
http.end();
|
||||||
client.stop(); // ← MISSING
|
client.stop();
|
||||||
|
|
||||||
yield(); // ← MISSING
|
yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoorbellLogic::parseMessages(String& response, const char* name,
|
void DoorbellLogic::parseMessages(String& response, const char* name,
|
||||||
|
|||||||
@@ -49,9 +49,6 @@ private:
|
|||||||
unsigned long _lastHeartbeat = 0;
|
unsigned long _lastHeartbeat = 0;
|
||||||
bool _blinkState = false;
|
bool _blinkState = false;
|
||||||
|
|
||||||
time_t _lastParsedMsgEpoch = 0; // <-- ADD
|
|
||||||
time_t _alertStartEpoch = 0; // <-- ADD
|
|
||||||
|
|
||||||
// Deferred status publish
|
// Deferred status publish
|
||||||
bool _pendingStatus = false;
|
bool _pendingStatus = false;
|
||||||
String _pendStatusState;
|
String _pendStatusState;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[tools]
|
[tools]
|
||||||
arduino-cli = "latest"
|
arduino-cli = "latest"
|
||||||
lazygit = "latest"
|
lazygit = "latest"
|
||||||
|
python = "latest"
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
FQBN = "esp32:esp32:esp32:UploadSpeed=921600,CPUFreq=240,FlashFreq=80,FlashMode=qio,FlashSize=4M,PartitionScheme=default,DebugLevel=info,EraseFlash=none"
|
FQBN = "esp32:esp32:esp32:UploadSpeed=921600,CPUFreq=240,FlashFreq=80,FlashMode=qio,FlashSize=4M,PartitionScheme=default,DebugLevel=info,EraseFlash=none"
|
||||||
@@ -24,7 +25,7 @@ depends = ["compile"]
|
|||||||
run = "arduino-cli upload --fqbn $FQBN -p $(arduino-cli board list | grep -i 'esp32\\|usb\\|ttyUSB\\|CP210\\|CH340' | head -1 | awk '{print $1}') ."
|
run = "arduino-cli upload --fqbn $FQBN -p $(arduino-cli board list | grep -i 'esp32\\|usb\\|ttyUSB\\|CP210\\|CH340' | head -1 | awk '{print $1}') ."
|
||||||
|
|
||||||
[tasks.monitor]
|
[tasks.monitor]
|
||||||
run = "tio /dev/ttyUSB0"
|
run = "arduino-cli monitor --port /dev/ttyUSB0 -c 115200"
|
||||||
|
|
||||||
[tasks.all]
|
[tasks.all]
|
||||||
depends = ["upload"]
|
depends = ["upload"]
|
||||||
|
|||||||
Reference in New Issue
Block a user