Acquisitore: pagina per settare l'acquisizione (anteprima, esposizione/guadagno, stile TMF) #87

Closed
opened 2026-10-24 12:33:10 +00:00 by Adriano · 1 comment
Owner

Pagina dell'acquisitore (GET /calibrazione, porta 8765) da rendere la pagina per settare l'acquisizione in fiera. Chiesto da Adriano il 24/10/2026.

VERIFICATO (PC fiera DESKTOP-RABEHJJ, pacchetto 11c7d2e, screenshot Edge headless): la pagina fa solo calibrazione. Mancano anteprima dal vivo (fuoco, luce), esposizione e guadagno (la Itala li espone: GenicamSource.capacita/dominio/scrivi, vendor/visionsuite/packages/vs-camera/src/visionsuite/camera/genicam.py:903-1000), salvataggio dei settaggi (configurazione.salva_settaggi/carica_settaggi). Stile chiaro diverso da TMF (scuro, slate/blu). "Lato dello scacco" parte da 2 anche se la calibrazione salvata ha 1,35. Data ISO grezza. "Choose File / No file chosen" del browser.

PIANO A — servizio (scripts/camera_service.py, test in scripts/tests): rotte 1-4 del contratto sotto, /acquisizione come alias della pagina, caricamento settaggi all'apertura.
PIANO B — pagina (scripts/calibrazione_pagina.py, test in scripts/tests): titolo "Acquisizione camera"; stile scuro TMF (sfondo #0f172a, pannelli #1e293b, bordi #334155, accento #3b82f6, testo #e2e8f0, secondario #94a3b8; font di sistema "Segoe UI"); sezioni:

  1. Sorgente: select da /camera/sources, ultima scelta ricordata (localStorage in try/catch); stato calibrazione accanto ("calibrata: 71,11 px/mm" / "non calibrata").
  2. Anteprima: pulsanti Avvia/Ferma anteprima e Scatta; casella "Immagine grezza (senza correzione)"; ciclo sequenziale su POST /camera/anteprima (la richiesta dopo solo a risposta arrivata, almeno 300 ms fra due); indicatori Nitidezza (con "massimo visto" e barra, si azzera cambiando sorgente), Saturati % (rosso se > 1%), Livello medio; mirino centrale attivabile; dimensioni del frame pieno.
  3. Parametri camera: costruiti da GET /camera/parametri; numero -> cursore + casella con min/max/passo (esposizione in µs, guadagno in dB); scelta -> select; scrittura con PUT dopo 300 ms dall'ultima modifica; impostare un valore manuale mette prima l'*_auto corrispondente a "Off" se esiste; pulsante "Salva come predefiniti" (POST /camera/parametri/salva); se regolabile=false: "Questa sorgente non ha parametri regolabili".
  4. Calibrazione: come oggi, ma lato dello scacco precompilato dalla calibrazione salvata, data in formato italiano (gg/mm/aaaa hh:mm locale), pulsante file in italiano ("Scegli immagine..." con input nascosto), anteprima sospesa durante la calibrazione e ripresa dopo.
    Numeri con virgola decimale (it-IT). Errori mostrati nella pagina, mai alert().

TEST: piano A con sorgenti finte (oggetto con capacita/supporta/dominio/leggi/scrivi/salva_settaggi/carica_settaggi) e FolderCamera; piano B: la pagina contiene le rotte e gli id attesi, non usa alert(, nessun URL http esterno. Prova d'insieme del coordinatore: servizio avviato su daitarn con --folder sulle foto di Menoncin, pagina in Edge headless.
NON TOCCARE: scripts/calibrazione.py, src/ (backend, frontend, vision), contratto delle rotte esistenti.
CONTRATTO (identico per i due piani; repo TieMeasureFlow, ramo base lavoro/daitarn-tmf-dxfcal 11c7d2e)

Servizio: scripts/camera_service.py (FastAPI, porta 8765). Pagina: scripts/calibrazione_pagina.py (costante PAGINA, HTML autonomo, offline: niente CDN, niente font esterni), servita su GET /calibrazione e, nuovo, anche su GET /acquisizione (stessa PAGINA).

Rotte esistenti, invariate: GET /camera/sources, POST /camera/grab, GET/DELETE /camera/calibration, POST /camera/calibrate.

Rotte nuove:

  1. POST /camera/anteprima json {source: str, grezzo: bool=false, lato_max: int=1280 (320..4096), timeout_ms: int=5000 (1..10000)}
    -> 200 image/jpeg (qualita' 85), immagine ridotta col lato lungo <= lato_max (mai ingrandita);
    raddrizzata come /camera/grab se la sorgente ha la mappa e grezzo=false.
    Header: X-Raddrizzato: si|no; X-Larghezza, X-Altezza (dimensioni del frame PIENO);
    X-Nitidezza: varianza del Laplaciano sul frame pieno in grigio (float, 1 decimale);
    X-Saturati-Pct: % di pixel >= 250 sul frame pieno (2 decimali);
    X-Media: livello medio 0-255 (1 decimale).
    Header esposti al browser: Access-Control-Expose-Headers non serve (stessa origine).
    Errori come /camera/grab: 400 parametri, 404 sorgente, 503 camera, 504 timeout.
  2. GET /camera/parametri?source=
    -> 200 {"source": src, "regolabile": bool, "parametri": {nome: dominio}}
    nomi, in quest'ordine: "esposizione", "esposizione_auto", "guadagno", "guadagno_auto".
    dominio = quello di GenicamSource.dominio(nome): sempre "valore" e "tipo" ("numero"|"scelta");
    "numero": "min"/"max"/"passo" solo se la camera li espone; "scelta": "scelte" (lista di stringhe);
    "scrivibile" se noto. Esposizione in microsecondi (nodo ExposureTime), guadagno in dB.
    Sorgente senza capacita' (cartella, file, OpenCV senza dominio): regolabile=false, parametri={}.
    Si includono solo i nomi che la sorgente supporta (supporta(nome) True).
  3. PUT /camera/parametri json {source: str, valori: {nome: valore}}
    Scrive nell'ordine: prima *_auto, poi esposizione/guadagno, ciascuno con scrivi(nome, valore, assesta=3).
    Nome non tra i quattro -> 400. Sorgente non regolabile -> 409 "questa sorgente non ha parametri regolabili".
    Scrittura rifiutata dalla camera (CameraStateError) -> 422 col messaggio.
    -> 200 stessa forma di GET (valori riletti dalla camera).
  4. POST /camera/parametri/salva json {source: str}
    -> 200 {"source": src, "salvati": true, "file": ""}; salva_settaggi in <config_dir>/settaggi/-<sha1[:8]>.json
    (stesso schema di nome di calibrazione.Archivio._file). 409 se non regolabile.
    All'apertura di una camera nel servizio (quando _grab la apre per la prima volta), se esiste il file
    dei settaggi di quella sorgente: carica_settaggi(file); un errore si scrive nel log e non blocca l'apertura.

Tutte le rotte che toccano la camera passano dallo stesso lock per sorgente di _grab (la camera e' una sola).
Lingua di tutti i messaggi: italiano.

Pagina dell'acquisitore (GET /calibrazione, porta 8765) da rendere la pagina per settare l'acquisizione in fiera. Chiesto da Adriano il 24/10/2026. VERIFICATO (PC fiera DESKTOP-RABEHJJ, pacchetto 11c7d2e, screenshot Edge headless): la pagina fa solo calibrazione. Mancano anteprima dal vivo (fuoco, luce), esposizione e guadagno (la Itala li espone: GenicamSource.capacita/dominio/scrivi, vendor/visionsuite/packages/vs-camera/src/visionsuite/camera/genicam.py:903-1000), salvataggio dei settaggi (configurazione.salva_settaggi/carica_settaggi). Stile chiaro diverso da TMF (scuro, slate/blu). "Lato dello scacco" parte da 2 anche se la calibrazione salvata ha 1,35. Data ISO grezza. "Choose File / No file chosen" del browser. PIANO A — servizio (scripts/camera_service.py, test in scripts/tests): rotte 1-4 del contratto sotto, /acquisizione come alias della pagina, caricamento settaggi all'apertura. PIANO B — pagina (scripts/calibrazione_pagina.py, test in scripts/tests): titolo "Acquisizione camera"; stile scuro TMF (sfondo #0f172a, pannelli #1e293b, bordi #334155, accento #3b82f6, testo #e2e8f0, secondario #94a3b8; font di sistema "Segoe UI"); sezioni: 1. Sorgente: select da /camera/sources, ultima scelta ricordata (localStorage in try/catch); stato calibrazione accanto ("calibrata: 71,11 px/mm" / "non calibrata"). 2. Anteprima: pulsanti Avvia/Ferma anteprima e Scatta; casella "Immagine grezza (senza correzione)"; ciclo sequenziale su POST /camera/anteprima (la richiesta dopo solo a risposta arrivata, almeno 300 ms fra due); indicatori Nitidezza (con "massimo visto" e barra, si azzera cambiando sorgente), Saturati % (rosso se > 1%), Livello medio; mirino centrale attivabile; dimensioni del frame pieno. 3. Parametri camera: costruiti da GET /camera/parametri; numero -> cursore + casella con min/max/passo (esposizione in µs, guadagno in dB); scelta -> select; scrittura con PUT dopo 300 ms dall'ultima modifica; impostare un valore manuale mette prima l'*_auto corrispondente a "Off" se esiste; pulsante "Salva come predefiniti" (POST /camera/parametri/salva); se regolabile=false: "Questa sorgente non ha parametri regolabili". 4. Calibrazione: come oggi, ma lato dello scacco precompilato dalla calibrazione salvata, data in formato italiano (gg/mm/aaaa hh:mm locale), pulsante file in italiano ("Scegli immagine..." con input nascosto), anteprima sospesa durante la calibrazione e ripresa dopo. Numeri con virgola decimale (it-IT). Errori mostrati nella pagina, mai alert(). TEST: piano A con sorgenti finte (oggetto con capacita/supporta/dominio/leggi/scrivi/salva_settaggi/carica_settaggi) e FolderCamera; piano B: la pagina contiene le rotte e gli id attesi, non usa alert(, nessun URL http esterno. Prova d'insieme del coordinatore: servizio avviato su daitarn con --folder sulle foto di Menoncin, pagina in Edge headless. NON TOCCARE: scripts/calibrazione.py, src/ (backend, frontend, vision), contratto delle rotte esistenti. CONTRATTO (identico per i due piani; repo TieMeasureFlow, ramo base lavoro/daitarn-tmf-dxfcal 11c7d2e) Servizio: scripts/camera_service.py (FastAPI, porta 8765). Pagina: scripts/calibrazione_pagina.py (costante PAGINA, HTML autonomo, offline: niente CDN, niente font esterni), servita su GET /calibrazione e, nuovo, anche su GET /acquisizione (stessa PAGINA). Rotte esistenti, invariate: GET /camera/sources, POST /camera/grab, GET/DELETE /camera/calibration, POST /camera/calibrate. Rotte nuove: 1. POST /camera/anteprima json {source: str, grezzo: bool=false, lato_max: int=1280 (320..4096), timeout_ms: int=5000 (1..10000)} -> 200 image/jpeg (qualita' 85), immagine ridotta col lato lungo <= lato_max (mai ingrandita); raddrizzata come /camera/grab se la sorgente ha la mappa e grezzo=false. Header: X-Raddrizzato: si|no; X-Larghezza, X-Altezza (dimensioni del frame PIENO); X-Nitidezza: varianza del Laplaciano sul frame pieno in grigio (float, 1 decimale); X-Saturati-Pct: % di pixel >= 250 sul frame pieno (2 decimali); X-Media: livello medio 0-255 (1 decimale). Header esposti al browser: Access-Control-Expose-Headers non serve (stessa origine). Errori come /camera/grab: 400 parametri, 404 sorgente, 503 camera, 504 timeout. 2. GET /camera/parametri?source=<src> -> 200 {"source": src, "regolabile": bool, "parametri": {nome: dominio}} nomi, in quest'ordine: "esposizione", "esposizione_auto", "guadagno", "guadagno_auto". dominio = quello di GenicamSource.dominio(nome): sempre "valore" e "tipo" ("numero"|"scelta"); "numero": "min"/"max"/"passo" solo se la camera li espone; "scelta": "scelte" (lista di stringhe); "scrivibile" se noto. Esposizione in microsecondi (nodo ExposureTime), guadagno in dB. Sorgente senza capacita' (cartella, file, OpenCV senza dominio): regolabile=false, parametri={}. Si includono solo i nomi che la sorgente supporta (supporta(nome) True). 3. PUT /camera/parametri json {source: str, valori: {nome: valore}} Scrive nell'ordine: prima *_auto, poi esposizione/guadagno, ciascuno con scrivi(nome, valore, assesta=3). Nome non tra i quattro -> 400. Sorgente non regolabile -> 409 "questa sorgente non ha parametri regolabili". Scrittura rifiutata dalla camera (CameraStateError) -> 422 col messaggio. -> 200 stessa forma di GET (valori riletti dalla camera). 4. POST /camera/parametri/salva json {source: str} -> 200 {"source": src, "salvati": true, "file": "<nome file>"}; salva_settaggi in <config_dir>/settaggi/<nome sicuro>-<sha1[:8]>.json (stesso schema di nome di calibrazione.Archivio._file). 409 se non regolabile. All'apertura di una camera nel servizio (quando _grab la apre per la prima volta), se esiste il file dei settaggi di quella sorgente: carica_settaggi(file); un errore si scrive nel log e non blocca l'apertura. Tutte le rotte che toccano la camera passano dallo stesso lock per sorgente di _grab (la camera e' una sola). Lingua di tutti i messaggi: italiano.
Adriano added the sviluppo label 2026-10-24 12:33:10 +00:00
Author
Owner

Soluzione

ESITO: fatto
COSA: acquisitore con anteprima, parametri camera (esposizione/guadagno/auto) e settaggi predefiniti; pagina «Acquisizione camera» (stile TMF scuro, 4 sezioni) su /acquisizione e /calibrazione.
FILE: scripts/camera_service.py (9eb5942: POST /camera/anteprima, GET/PUT /camera/parametri, POST /camera/parametri/salva, settaggi caricati all'apertura); scripts/calibrazione_pagina.py (0629f1b 13eeec7 813b66d); test scripts/tests/test_camera_acquisizione.py, test_pagina_acquisizione.py. Merge in lavoro/daitarn-tmf-dxfcal 2760623.
PROVA: pytest scripts/tests -> 62 passed. Camera vera Itala ITA32 601020 via GenTL su daitarn (TMF da sorgente, packaging/windows/sviluppo.ps1 -EscludiCamere OECS): GET parametri regolabile=true; PUT esposizione 8000->media 66, 30000->media 175; guadagno 99 -> 422 con messaggio; salva -> acquisitore/settaggi/camera_601020-be257e9d.json; esposizione 5000 non salvata + riavvio -> 12000 ricaricato. Playwright su Edge: anteprima live, casella esposizione 6000 -> «Parametri applicati.».
MANCA: prova sull'exe del PC fiera (build daltanius in corso da 2760623, senza 813b66d).

**Soluzione** ESITO: fatto COSA: acquisitore con anteprima, parametri camera (esposizione/guadagno/auto) e settaggi predefiniti; pagina «Acquisizione camera» (stile TMF scuro, 4 sezioni) su /acquisizione e /calibrazione. FILE: scripts/camera_service.py (9eb5942: POST /camera/anteprima, GET/PUT /camera/parametri, POST /camera/parametri/salva, settaggi caricati all'apertura); scripts/calibrazione_pagina.py (0629f1b 13eeec7 813b66d); test scripts/tests/test_camera_acquisizione.py, test_pagina_acquisizione.py. Merge in lavoro/daitarn-tmf-dxfcal 2760623. PROVA: pytest scripts/tests -> 62 passed. Camera vera Itala ITA32 601020 via GenTL su daitarn (TMF da sorgente, packaging/windows/sviluppo.ps1 -EscludiCamere OECS): GET parametri regolabile=true; PUT esposizione 8000->media 66, 30000->media 175; guadagno 99 -> 422 con messaggio; salva -> acquisitore/settaggi/camera_601020-be257e9d.json; esposizione 5000 non salvata + riavvio -> 12000 ricaricato. Playwright su Edge: anteprima live, casella esposizione 6000 -> «Parametri applicati.». MANCA: prova sull'exe del PC fiera (build daltanius in corso da 2760623, senza 813b66d).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Adriano/TieMeasureFlow#87