Lettore di codici a barre nelle applicazioni web: emulazione tastiera, WebHID, Web Serial e fotocamera
Nel browser un lettore in emulazione tastiera funziona senza codice aggiuntivo: scrive nel campo con il focus e, con il suffisso Invio, invia il modulo. Per letture senza focus puoi riconoscere il lettore dalla velocità delle battute. In alternativa, solo su browser basati su Chromium, WebHID e Web Serial leggono il dispositivo direttamente; con la fotocamera si usa BarcodeDetector o una libreria.
Quattro approcci a confronto
| Approccio | Modalità del lettore | Browser | Quando usarlo |
|---|---|---|---|
| Campo di input con focus | HID tastiera | Tutti | Moduli semplici, ricerca articolo |
| Ascolto globale della tastiera con rilevamento per tempi | HID tastiera | Tutti | Pagine senza un campo dedicato, cassa web |
| Web Serial API | COM virtuale o seriale | Chromium desktop (Chrome, Edge, Opera) | Dati esatti, caratteri di controllo GS1 |
| WebHID API | HID POS o HID non tastiera | Chromium desktop | Integrazioni avanzate, lettori in modalità HID POS |
| Fotocamera (BarcodeDetector o libreria JS) | Nessun lettore | BarcodeDetector: supporto parziale, soprattutto Chromium su Android e macOS | Letture saltuarie da smartphone |
Safari e Firefox non supportano WebHID e Web Serial. Se la web app deve funzionare ovunque, la base resta l'emulazione tastiera; le API dirette sono un'aggiunta progressiva.
Il caso semplice: un campo che riceve il codice
Con il lettore impostato su emulazione tastiera e suffisso Invio, un <form> con un solo campo invia il codice a ogni lettura. Accorgimenti che evitano molti ticket:
- metti l'
autofocussul campo e riportalo lì dopo ogni invio; - disattiva completamento automatico e correttore:
autocomplete="off",autocorrect="off",spellcheck="false", perché i suggerimenti del browser possono intercettare l'Invio; - se il campo accetta solo cifre, non usare
type="number": elimina gli zeri iniziali in alcuni passaggi e non accetta lettere; usatype="text"coninputmode="numeric"; - gestisci l'Invio esplicitamente se il campo è in un modulo più grande, per evitare invii prematuri.
Se l'Invio non arriva, vedi lettore che non invia Invio; se arrivano simboli sbagliati, è il layout tastiera (caratteri sbagliati).
Rilevare il lettore dalla velocità delle battute
Un lettore digita molto più velocemente di una persona: tipicamente pochi millisecondi tra un carattere e l'altro, contro decine o centinaia per un umano. Puoi sfruttarlo per catturare le letture ovunque nella pagina:
let buffer = '';
let last = 0;
const MAX_GAP = 30; // ms tra caratteri: da tarare sul tuo lettore
const MIN_LEN = 6; // lunghezza minima di un codice valido
document.addEventListener('keydown', (e) => {
const now = performance.now();
if (now - last > MAX_GAP) buffer = ''; // pausa lunga: nuova sequenza
last = now;
if (e.key === 'Enter') {
if (buffer.length >= MIN_LEN) {
e.preventDefault();
onScan(buffer);
}
buffer = '';
return;
}
if (e.key.length === 1) buffer += e.key; // ignora Shift, Ctrl, ecc.
});
function onScan(code) {
console.log('Letto:', code);
}
Note pratiche:
- misura il tuo lettore con il test del lettore, che mostra i tempi tra i caratteri, e tara la soglia; con lettori wireless o con ritardo tra caratteri attivo i tempi aumentano;
- se l'utente sta scrivendo in un campo, decidi se lasciare passare i caratteri o bloccarli: il codice sopra li lascia arrivare anche al campo;
- un'alternativa più robusta è configurare sul lettore un prefisso personalizzato raro come marcatore di inizio lettura.
e.key riflette il layout tastiera del sistema. Se lettore e sistema hanno layout diversi, i simboli arrivano trasformati anche nel tuo JavaScript: e.code dà la posizione fisica del tasto, ma non risolve il problema in modo generale. La soluzione resta allineare il layout (vedi impostare la tastiera italiana).
Web Serial: leggere un lettore in COM virtuale
Con il lettore in porta COM virtuale, la Web Serial API permette alla pagina di leggere i byte esatti, inclusi i separatori GS dei codici GS1. Richiede un contesto sicuro (HTTPS) e un gesto dell'utente per scegliere la porta:
button.addEventListener('click', async () => {
const port = await navigator.serial.requestPort();
await port.open({ baudRate: 9600 });
const reader = port.readable.getReader();
const dec = new TextDecoder();
let buf = '';
while (true) {
const { value, done } = await reader.read();
if (done) break;
buf += dec.decode(value);
let i;
while ((i = buf.indexOf('\r')) >= 0) { // terminatore CR
onScan(buf.slice(0, i));
buf = buf.slice(i + 1).replace(/^\n/, '');
}
}
});
Il carattere GS arriva come \x1D: puoi passarlo alla tua logica o provare la stringa nel decodificatore GS1. Vedi anche carattere GS e FNC1.
WebHID: lettori in modalità HID POS
WebHID dà accesso a dispositivi HID che non sono tastiere, come i lettori in modalità HID POS. Il browser blocca l'accesso alle tastiere tramite WebHID, quindi non serve per un lettore in emulazione tastiera. Il formato dei report HID POS è definito dalle USB HID Usage Tables, ma i dettagli (report ID, posizione dei dati) vanno verificati sulla documentazione del lettore:
const [dev] = await navigator.hid.requestDevice({ filters: [] });
await dev.open();
dev.addEventListener('inputreport', (e) => {
const bytes = new Uint8Array(e.data.buffer);
console.log(e.reportId, bytes); // interpreta secondo il manuale
});
Fotocamera: BarcodeDetector e alternative
L'API BarcodeDetector (Shape Detection API) decodifica codici da immagini o fotogrammi video. Il supporto è disomogeneo: verifica sempre la presenza dell'API e prevedi una libreria JavaScript come ripiego.
if ('BarcodeDetector' in window) {
const formats = await BarcodeDetector.getSupportedFormats();
const det = new BarcodeDetector({ formats: ['ean_13', 'qr_code', 'code_128'] });
const codes = await det.detect(videoElement);
codes.forEach(c => console.log(c.format, c.rawValue));
} else {
// ripiego: libreria JS di decodifica
}
La fotocamera è comoda per letture occasionali, molto meno per volumi alti o etichette piccole. Puoi provare l'esperienza con il nostro lettore online con fotocamera e valutare il confronto in smartphone o lettore dedicato.
Errori comuni nelle web app
- Zeri iniziali persi: il codice trattato come numero (in JavaScript o nel database). Conserva sempre i codici come stringhe.
- Doppio invio: suffisso Invio sul lettore più invio automatico nello script. Scegli uno dei due.
- Caratteri persi su pagine pesanti: handler lenti su
input. Accumula nel buffer e lavora alla fine; vedi caratteri mancanti o letture doppie. - Codici con prefissi AIM (es.
]E0) arrivati per errore: vedi identificatore di simbologia AIM.