diff --git a/scripts/calibrazione_pagina.py b/scripts/calibrazione_pagina.py index a9fbae0..810d548 100644 --- a/scripts/calibrazione_pagina.py +++ b/scripts/calibrazione_pagina.py @@ -459,7 +459,7 @@ function cambioSorgente(salva) { // ---- Anteprima (#87) // #91: ris = {w, h} dell'ultimo frame; #92: calAttiva = la sorgente ha una calibrazione attiva (null = non nota), bloccoCal = un 409 ha fermato le richieste calibrata; urlCal/seqCal = riquadro calibrata, bloccata/sorgenteBloccata/urlBlocco/seqBlocco = #94 immagine bloccata per il calcolo (il riquadro della tab Calibrazione non segue piu' il ciclo), lato = ultimo lato_max -var A = { attiva: false, gen: 0, inVolo: false, url: null, urlCal: null, seqCal: 0, bloccata: false, sorgenteBloccata: null, urlBlocco: null, seqBlocco: 0, lato: 1280, calAttiva: null, bloccoCal: false, nitMax: 0, ris: null }; +var A = { attiva: false, gen: 0, inVolo: false, url: null, urlCal: null, seqCal: 0, bloccata: false, bloccando: 0, sorgenteBloccata: null, urlBlocco: null, seqBlocco: 0, lato: 1280, calAttiva: null, bloccoCal: false, nitMax: 0, ris: null }; function azzeraIndicatori() { A.nitMax = 0; @@ -612,6 +612,8 @@ async function unaAnteprima(lato) { async function ciclo(g) { while (A.inVolo) await pausa(50); while (A.attiva && g === A.gen) { + while (A.bloccando) await pausa(20); // #94: durante «Blocca immagine» nessuna nuova anteprima + if (!A.attiva || g !== A.gen) return; var t0 = Date.now(); var esito = await unaAnteprima(1280); if (g !== A.gen) return; @@ -640,6 +642,7 @@ async function scatta() { $("scatta").disabled = $("scattaCal").disabled = true; // #94: anche il «Scatta» della tab Calibrazione dire("msgAnteprima", "Scatto in corso...", ""); while (A.inVolo) await pausa(50); + while (A.bloccando) await pausa(20); // #94: niente scatto mentre si blocca l'immagine await unaAnteprima(4096); $("scatta").disabled = false; $("scattaCal").disabled = A.bloccata; // #94: con l'immagine bloccata resta spento @@ -673,11 +676,17 @@ $("bloccaImg").onchange = async function () { } A.bloccata = true; // subito: il riquadro smette di seguire il ciclo A.sorgenteBloccata = sorgente; - A.urlBlocco = A.url; + A.urlBlocco = null; // #94: lo si fissa dopo l'attesa, sul frame davvero mostrato var n = ++A.seqBlocco; $("scattaCal").disabled = true; dire("msgBlocco", "Blocco in corso...", ""); + A.bloccando++; // #94: il ciclo e «Scatta» non chiedono nuove anteprime finche' la copia non e' fatta try { + for (var k = 0; A.inVolo && k < 150; k++) await pausa(20); // #94: attende l'anteprima in volo (max 3 s): il frame copiato e' l'ultimo mostrato + if (n !== A.seqBlocco) return; // spenta o cambiata sorgente durante l'attesa: niente copia + if (A.inVolo) { sbloccaLocale(); dire("msgBlocco", "Anteprima ancora in corso: riprovare.", "errore"); return; } + A.urlBlocco = A.url; // #94: il frame mostrato in questo momento e' quello che il servizio copia + mostraInTabCal(A.url); var r = await fetch("/camera/blocca", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ source: sorgente }) }); if (n !== A.seqBlocco) { // spenta o cambiata sorgente nel frattempo: la copia appena fatta si toglie if (r.ok) fetch("/camera/blocca?source=" + encodeURIComponent(sorgente), { method: "DELETE" }).catch(function () { /* niente da fare */ }); @@ -688,6 +697,8 @@ $("bloccaImg").onchange = async function () { dire("msgBlocco", "Immagine bloccata " + b.larghezza + "×" + b.altezza + ": «Calcola» usa questa.", "ok"); } catch (e) { if (n === A.seqBlocco) { sbloccaLocale(); dire("msgBlocco", "Servizio non raggiungibile.", "errore"); } + } finally { + A.bloccando--; // #94: anche su errore o uscita anticipata } }; diff --git a/scripts/tests/test_blocca_immagine.py b/scripts/tests/test_blocca_immagine.py index affbf0e..203affa 100644 --- a/scripts/tests/test_blocca_immagine.py +++ b/scripts/tests/test_blocca_immagine.py @@ -142,3 +142,15 @@ def test_pagina_blocco_rotte_e_cambio_sorgente(): cambio = PAGINA.split("function cambioSorgente")[1].split("// ---- Anteprima")[0] assert "rilasciaBlocco()" in cambio assert cambio.index("rilasciaBlocco()") < cambio.index("svuotaRiquadri()") + + +def test_pagina_blocco_attende_l_anteprima_in_volo(): + # #94: il frame bloccato e' quello mostrato: flag A.bloccando, attesa di A.inVolo (20 ms, max 3 s), poi POST, flag tolto in finally + blocco = PAGINA.split('$("bloccaImg").onchange')[1].split('$("avvia").onclick')[0] + assert "A.bloccando++" in blocco and "A.bloccando--" in blocco and "finally" in blocco + assert "k < 150" in blocco and "pausa(20)" in blocco + assert blocco.index("A.inVolo") < blocco.index('fetch("/camera/blocca"') + ciclo = PAGINA.split("async function ciclo")[1].split("function avviaAnteprima")[0] + assert "while (A.bloccando)" in ciclo and ciclo.index("A.bloccando") < ciclo.index("unaAnteprima(1280)") + scatta = PAGINA.split("async function scatta")[1].split("// #94: «Blocca immagine»")[0] + assert "while (A.bloccando)" in scatta and scatta.index("A.bloccando") < scatta.index("unaAnteprima(4096)")