Skip to content
This repository was archived by the owner on Jul 31, 2026. It is now read-only.

Commit 30cded5

Browse files
feat: smart scan exit + correct phase messages across workflow
Workflow phases now correct end-to-end: 1. 📡 Scanning RFID... (WF_SCANNING — motor rotating, no UID yet) 2. [background] container + twin fetch in parallel, also waiting for 2nd UID 2bis. Early exit SCANNING if twin found in Firestore + container ready → no need to wait for 2nd physical reader (reason=twin_firestore) 3. ⚖️ Stabilizing... (WF_STABLE_WAIT — UID found, weight settling) 4. ⏳ Sending... (WF_SENDING) 5. ✓ Sent (success) Bug fixed: gTwinFetchDone was consumed by display pickup → pushWeightToCloud fell through to a duplicate sync readInventoryDocTwinTag. Now display pickup reads gTwinFetchResult without clearing the flag — pushWeightToCloud is the sole consumer of gTwinFetchDone. sendPhase values: "scanning" → "stabilizing" → "send" → "success"/"error" WS values: "scanning:N" → "stable:N" → "send" → "success"/"error" Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent a922a79 commit 30cded5

2 files changed

Lines changed: 42 additions & 26 deletions

File tree

‎data/www/script.js‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ const translations = {
103103
sendError: '✗ Erreur',
104104
sendIn: 'Envoi dans',
105105
scanningRfid: '📡 Lecture RFID...',
106+
stabilizing: '⚖️ Stabilisation...',
106107
// Weight breakdown
107108
containerLabel: 'Bobine',
108109
filamentLabel: 'Filament',
@@ -202,6 +203,7 @@ const translations = {
202203
sendError: '✗ Error',
203204
sendIn: 'Sending in',
204205
scanningRfid: '📡 Scanning RFID...',
206+
stabilizing: '⚖️ Stabilizing...',
205207
// Weight breakdown
206208
containerLabel: 'Spool',
207209
filamentLabel: 'Filament',
@@ -934,10 +936,13 @@ function applyStatusSnapshot(s) {
934936
setSendState(t('sendError'), 'rgba(245,101,101,0.3)');
935937
setTimeout(() => setSendState(''), 2000);
936938
} else if (v.startsWith('scanning:')) {
937-
// WF_SCANNING — RFID not yet detected, motor rotating
939+
// WF_SCANNING — motor rotating, waiting for RFID tag
938940
setSendState(t('scanningRfid'), 'rgba(255,255,255,0.12)');
941+
} else if (v.startsWith('stable:')) {
942+
// WF_STABLE_WAIT — UID found, weight stabilizing
943+
setSendState(t('stabilizing'), 'rgba(255,255,255,0.18)');
939944
} else if (/^\d+$/.test(v)) {
940-
// WF_STABLE_WAIT — UID found, weight stabilizing before send
945+
// legacy fallback
941946
setSendState(t('sendIn') + ' ' + v + 's', 'rgba(255,255,255,0.2)');
942947
}
943948
}

‎src/main.cpp‎

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,18 @@
2121
// §12 FIRESTORE SCALE HEARTBEAT & SYNC 1110– 2040
2222
// §13 WEBSOCKET 2041– 2067
2323
// §14 5 — CLOUD WORKER TASK (non-blocking Firestore on core 0) 2068– 2138
24-
// §15 5 — UNIFIED WS FRAME BUILDER 2139– 2183
25-
// §16 WEIGHT FILTER HELPERS 2184– 2198
26-
// §17 POST-SEND STATE RESET (shared by all send paths) 2199– 2217
27-
// §18 SHARED WEIGHT PUSH HANDLER (used by /api/weight and /api/push-weight) 2218– 2290
28-
// §19 WEB SERVER 2291– 2992
29-
// §20 CLOUD COMMUNICATION 2993– 3175
30-
// §21 WEIGH WORKFLOW (IDLE → SCANNING → STABLE_WAIT → SENDING) 3176– 3426
31-
// §22 mDNS 3427– 3464
32-
// §23 SCALE 3465– 3556
33-
// §24 RFID 3557– 3886
34-
// §25 OTA — Over-the-air firmware + filesystem update 3887– 4255
35-
// §26 SETUP & LOOP 4256– 4657
24+
// §15 5 — UNIFIED WS FRAME BUILDER 2139– 2184
25+
// §16 WEIGHT FILTER HELPERS 2185– 2199
26+
// §17 POST-SEND STATE RESET (shared by all send paths) 2200– 2218
27+
// §18 SHARED WEIGHT PUSH HANDLER (used by /api/weight and /api/push-weight) 2219– 2291
28+
// §19 WEB SERVER 2292– 2994
29+
// §20 CLOUD COMMUNICATION 2995– 3177
30+
// §21 WEIGH WORKFLOW (IDLE → SCANNING → STABLE_WAIT → SENDING) 3178– 3437
31+
// §22 mDNS 3438– 3475
32+
// §23 SCALE 3476– 3567
33+
// §24 RFID 3568– 3897
34+
// §25 OTA — Over-the-air firmware + filesystem update 3898– 4266
35+
// §26 SETUP & LOOP 4267– 4668
3636
//
3737
// To regenerate this block: ./scripts/update_toc.sh
3838
// ─── TOC END ───────────────────────────────────────────────
@@ -2146,8 +2146,9 @@ static void twinWorkerTask(void* /*param*/) {
21462146

21472147
static String buildWsFrame(float weight) {
21482148
String stcWs;
2149-
if (sendPhase == "scanning" && sendCountdown >= 0) stcWs = "scanning:" + String(sendCountdown);
2150-
else if (sendPhase == "countdown" && sendCountdown >= 0) stcWs = String(sendCountdown);
2149+
if (sendPhase == "scanning" && sendCountdown >= 0) stcWs = "scanning:" + String(sendCountdown);
2150+
else if (sendPhase == "stabilizing" && sendCountdown >= 0) stcWs = "stable:" + String(sendCountdown);
2151+
else if (sendPhase == "countdown" && sendCountdown >= 0) stcWs = String(sendCountdown);
21512152
else if (sendPhase == "send") stcWs = "send";
21522153
else if (sendPhase == "success") stcWs = "success";
21532154
else if (sendPhase == "error") stcWs = "error";
@@ -2437,8 +2438,9 @@ void setupWebServer() {
24372438
if (gOtaMessage.length()) doc["ota_message"] = gOtaMessage;
24382439
if (gOtaLatestVer.length()) doc["ota_latest"] = gOtaLatestVer;
24392440
String stc;
2440-
if (sendPhase == "scanning" && sendCountdown >= 0) stc = "scanning:" + String(sendCountdown);
2441-
else if (sendPhase == "countdown" && sendCountdown >= 0) stc = String(sendCountdown);
2441+
if (sendPhase == "scanning" && sendCountdown >= 0) stc = "scanning:" + String(sendCountdown);
2442+
else if (sendPhase == "stabilizing" && sendCountdown >= 0) stc = "stable:" + String(sendCountdown);
2443+
else if (sendPhase == "countdown" && sendCountdown >= 0) stc = String(sendCountdown);
24422444
else if (sendPhase == "send") stc = "send";
24432445
else if (sendPhase == "success") stc = "success";
24442446
else if (sendPhase == "error") stc = "error";
@@ -3286,11 +3288,11 @@ void handleWeighWorkflow(float w) {
32863288
gContainerFetchDone = false;
32873289
gLastContainer = wfContainerWeight; // immediate OLED/WS update
32883290
}
3289-
// Pick up twin display result independently — twin fetch completes AFTER container.
3290-
// Check separately so we don't miss it if SCANNING exits before twin is ready.
3291+
// Pick up twin for display — do NOT clear gTwinFetchDone here.
3292+
// pushWeightToCloud is the sole consumer of gTwinFetchDone.
3293+
// Clearing it here would cause a duplicate sync fetch during SENDING.
32913294
if (gTwinFetchDone && lastUID2.length() == 0 && lastUIDTwin.length() == 0) {
3292-
lastUIDTwin = gTwinFetchResult;
3293-
gTwinFetchDone = false;
3295+
lastUIDTwin = gTwinFetchResult;
32943296
netLog("TWIN display=" + (lastUIDTwin.length() > 0 ? lastUIDTwin : "none (no twin in DB)"));
32953297
}
32963298

@@ -3299,9 +3301,17 @@ void handleWeighWorkflow(float w) {
32993301
if (secsLeft < 0) secsLeft = 0;
33003302
if (secsLeft != sendCountdown) sendCountdown = secsLeft;
33013303

3302-
// Sortie anticipée si les 2 UIDs sont capturés
3303-
bool bothUidsReady = (lastUID.length() > 0 && lastUID2.length() > 0);
3304-
if (bothUidsReady || now - wfScanStartMs >= scanDuration) {
3304+
// Sortie anticipée :
3305+
// A) 2 UIDs physiques capturés
3306+
// B) Twin fetché depuis Firestore ET container prêt → inutile d'attendre le 2ème lecteur
3307+
// C) Timeout du scan
3308+
bool bothUidsReady = (lastUID.length() > 0 && lastUID2.length() > 0);
3309+
bool twinReadyNoScan = (gTwinFetchDone && gTwinFetchResult.length() > 0
3310+
&& wfContainerFetched && lastUID2.length() == 0);
3311+
String exitReason = bothUidsReady ? "both_uid"
3312+
: twinReadyNoScan ? "twin_firestore"
3313+
: "timeout";
3314+
if (bothUidsReady || twinReadyNoScan || now - wfScanStartMs >= scanDuration) {
33053315
stopServoSearch();
33063316
if (lastUID.length() == 0) {
33073317
wfPhase = WF_IDLE; sendPhase = ""; sendCountdown = -1;
@@ -3310,9 +3320,10 @@ void handleWeighWorkflow(float w) {
33103320
wfPhase = WF_STABLE_WAIT;
33113321
stableCandidate = NAN; stableSinceMs = 0;
33123322
wfStableWaitStartMs = now;
3323+
sendPhase = "stabilizing";
33133324
sendCountdown = (int)((STABLE_WINDOW_MS + 999) / 1000);
33143325
netLog("WF SCANNING→STABLE_WAIT uid=" + lastUID + " uid2=" + lastUID2
3315-
+ " reason=" + (bothUidsReady ? "both" : "timeout"));
3326+
+ " reason=" + exitReason);
33163327
}
33173328
}
33183329
return;

0 commit comments

Comments
 (0)