TKK_E32232028/updater.py

223 lines
8.2 KiB
Python

import re
with open('esp32_serial_backend/esp32_serial_backend.ino', 'r', encoding='utf8') as f:
content = f.read()
# 1. Globals
content = content.replace(
'''bool gPendingRecog = false;
unsigned long gRecogCaptureAt = 0; // millis() when to actually capture''',
'''// Auto-retry RECOG / ENROLL state
String gKeepTryingCmd = "";
unsigned long gKeepTryingUntil = 0;
bool gLastActionSuccess = false;''')
# 2. RFID Trigger
old_rfid = ''' // Set pending RECOG - kamera preview akan tampil dulu 3 detik di loop()
gPendingRecog = true;
gRecogCaptureAt = millis() + 3000; // capture setelah 3 detik
gCameraActive = true; // tampilkan kamera preview mulai sekarang'''
new_rfid = ''' // Mulai proses pengenalan wajah terus-menerus selama 15 detik
gKeepTryingCmd = "RECOG";
gKeepTryingUntil = millis() + 15000;
gLastActionSuccess = false;
gCameraActive = true; // tampilkan kamera preview mulai sekarang'''
content = content.replace(old_rfid, new_rfid)
# 3. Web Job Trigger (ENROLL)
old_enroll_job = ''' if (type == "ENROLL")
{
showStatus("TAKE ENROLL", TFT_CYAN);
Serial.println(String("[JOB] ENROLL start name=") + name);
bool enrollOk = handleCommand(String("ENROLL ") + name);
String result = "{\\"from\\":\\"esp32\\",\\"type\\":\\"ENROLL\\",\\"name\\":\\"" + name + "\\",\\"ok\\":" + (enrollOk ? "true" : "false");
if (uid.length())
result += ",\\"uid\\":\\"" + uid + "\\"";
if (personId.length())
result += ",\\"person_id\\":\\"" + personId + "\\"";
result += "}";
String jr = postJson(String(SERVER_BASE) + "/job/result", result, 6000);
Serial.println(String("[JOB] ENROLL result post=") + jr);
if (jr.startsWith("HTTP") || jr.startsWith("WIFI"))
showStatus("JOB RESULT FAIL\\n" + jr, TFT_YELLOW);
return;
}'''
new_enroll_job = ''' if (type == "ENROLL")
{
showStatus("START ENROLL", TFT_CYAN);
Serial.println(String("[JOB] ENROLL start name=") + name);
// Aktifkan continuous capture
gKeepTryingCmd = String("ENROLL ") + name;
gKeepTryingUntil = millis() + 15000;
gLastActionSuccess = false;
gCameraActive = true;
// We notify the server immediately that we took the job.
String result = "{\\"from\\":\\"esp32\\",\\"type\\":\\"ENROLL\\",\\"name\\":\\"" + name + "\\",\\"ok\\":true";
if (uid.length())
result += ",\\"uid\\":\\"" + uid + "\\"";
if (personId.length())
result += ",\\"person_id\\":\\"" + personId + "\\"";
result += "}";
postJson(String(SERVER_BASE) + "/job/result", result, 6000);
return;
}'''
content = content.replace(old_enroll_job, new_enroll_job)
# 4. Web Job Trigger (RECOG)
old_recog_job = ''' if (type == "RECOG")
{
// Save job params so /recognize uses same threshold+uid as the web request.
gJobRecogThreshold = thr;
gJobRecogUid = uid;
gJobPersonId = personId;
showStatus("TAKE RECOG", TFT_CYAN);
Serial.println(String("[JOB] RECOG start thr=") + String(thr, 2) + String(" uid=") + uid);
Serial.println(String("[JOB] WiFi=") + (WiFi.status() == WL_CONNECTED ? "OK" : "DISCONNECTED"));
showStatus("RECOG...", TFT_CYAN);
bool recogOk = handleCommand("RECOG");
String result = String("{\\"from\\":\\"esp32\\",\\"type\\":\\"RECOG\\",\\"threshold\\":") + String(thr, 2) + String(",\\"uid\\":\\"") + uid + String("\\",\\"ok\\":") + (recogOk ? "true" : "false") + String("}");
String jr = postJson(String(SERVER_BASE) + "/job/result", result, 6000);
Serial.println(String("[JOB] RECOG result post=") + jr);
if (jr.startsWith("HTTP") || jr.startsWith("WIFI"))
showStatus("JOB RES:\\n" + jr, TFT_YELLOW);
return;
}'''
new_recog_job = ''' if (type == "RECOG")
{
gJobRecogThreshold = thr;
gJobRecogUid = uid;
gJobPersonId = personId;
showStatus("START RECOG", TFT_CYAN);
Serial.println(String("[JOB] RECOG start thr=") + String(thr, 2) + String(" uid=") + uid);
// Aktifkan continuous capture
gKeepTryingCmd = "RECOG";
gKeepTryingUntil = millis() + 15000;
gLastActionSuccess = false;
gCameraActive = true;
String result = String("{\\"from\\":\\"esp32\\",\\"type\\":\\"RECOG\\",\\"threshold\\":") + String(thr, 2) + String(",\\"uid\\":\\"") + uid + String("\\",\\"ok\\":true}");
postJson(String(SERVER_BASE) + "/job/result", result, 6000);
return;
}'''
content = content.replace(old_recog_job, new_recog_job)
# 5. Success detection in handleCommand(ENROLL)
old_enroll_resp = ''' String resp = postFrameWithRetry(url, fb, 60000);
showStatus(resp, TFT_CYAN);'''
new_enroll_resp = ''' String resp = postFrameWithRetry(url, fb, 60000);
if (!resp.startsWith("HTTP ERR") && !resp.startsWith("HTTP 4") && !resp.startsWith("HTTP 5") && !resp.startsWith("WIFI")) {
gLastActionSuccess = true;
}
showStatus(resp, TFT_CYAN);'''
content = content.replace(old_enroll_resp, new_enroll_resp)
# 6. Success detection in handleCommand(RECOG)
old_recog_resp = ''' if (respLower.indexOf(expLower) >= 0)
{
showStatus("OK: " + gExpectedName, TFT_GREEN);
}
else
{
showStatus("FAIL: " + gExpectedName, TFT_RED);
}'''
new_recog_resp = ''' if (respLower.indexOf(expLower) >= 0 || respLower.indexOf("\\"match\\":true") >= 0 || respLower.indexOf("\\"match\\": true") >= 0)
{
showStatus("OK: " + gExpectedName, TFT_GREEN);
gLastActionSuccess = true;
}
else
{
showStatus("FAIL: " + gExpectedName, TFT_RED);
}'''
content = content.replace(old_recog_resp, new_recog_resp)
# 7. Add fallback success for RECOG when no ExpectedName is set (e.g. from Web Job)
old_recog_resp_fallback = ''' else
{
showStatus(resp, TFT_CYAN);
}'''
new_recog_resp_fallback = ''' else
{
String respLower = resp;
respLower.toLowerCase();
if (respLower.indexOf("\\"match\\":true") >= 0 || respLower.indexOf("\\"match\\": true") >= 0) {
gLastActionSuccess = true;
showStatus("Dikenali", TFT_GREEN);
} else {
showStatus(resp, TFT_CYAN);
}
}'''
content = content.replace(old_recog_resp_fallback, new_recog_resp_fallback)
# 8. Loop logic
old_loop_broken = '''// ===== PENDING RECOG (dipicu oleh RFID) =====
// Kamera sudah aktif (gCameraActive=true), tampilkan preview + overlay countdown
// Saat timer habis, jalankan capture
if (gPendingRecog && !gBusy)
{
if (now >= gRecogCaptureAt)
{
// Waktu habis - jalankan RECOG sekarang
gPendingRecog = false;
gCameraActive = false;
showStatus("MEMPROSES...", TFT_CYAN, "", 8000);
Serial.println("[RFID] Countdown habis - jalankan RECOG");
bool attendOk = handleCommand("RECOG");
gCameraActive = false;
Serial.println(String("[RFID] auto attendance result=") + (attendOk ? "OK" : "FAIL"));
}
else
{
// Tampilkan countdown di overlay (tapi biarkan kamera preview tetap jalan)
int secsLeft = (int)((gRecogCaptureAt - now) / 1000) + 1;
Serial.println("[RECOG] Executing delayed capture...");
handleCommand("RECOG");
lastJobPoll = millis(); // Reset penanda waktu poll setelah proses RECOG
gBusy = false;
}
else
{
// Tampilkan hitung mundur
int secsLeft = (gRecogCaptureAt - now) / 1000 + 1;
showOverlayMessage(String("Siap-siap absen..."),
String("Capture dalam ") + secsLeft + "s...", 4000);
}
}'''
new_loop_continuous = '''// ===== CONTINUOUS CAPTURE (Auto-Retry) =====
if (gKeepTryingCmd.length() > 0 && !gBusy)
{
if (now >= gKeepTryingUntil)
{
// Timeout
gKeepTryingCmd = "";
gCameraActive = false;
showStatus("TIMEOUT", TFT_RED, "Wajah tidak dikenali", 3000);
}
else
{
Serial.println(String("[AUTO] Executing ") + gKeepTryingCmd);
showOverlayMessage("MEMPROSES...", "Jangan bergerak", 2000);
handleCommand(gKeepTryingCmd);
lastJobPoll = millis(); // Reset poll timer
if (gLastActionSuccess)
{
gKeepTryingCmd = ""; // Stop trying
gCameraActive = false; // Turn off camera on success
showStatus("BERHASIL", TFT_GREEN, "", 3000);
}
}
}'''
content = content.replace(old_loop_broken, new_loop_continuous)
with open('esp32_serial_backend/esp32_serial_backend.ino', 'w', encoding='utf8') as f:
f.write(content)
print("Update complete")