@m-scan/device-kit-agent
v0.0.3
Published
Local native agent (Node.js) exposing network/USB/Bluetooth device access to the browser over WebSocket/HTTP
Readme
@m-scan/device-kit-agent
Agent local (Node.js) qui donne à une application web (@m-scan/device-kit) l'accès au réseau, aux queues d'impression USB et aux ports série Bluetooth — des accès qu'un navigateur ne peut pas atteindre directement.
Doit tourner en permanence sur le poste de caisse, sur le même réseau local que les imprimantes. Un hébergement cloud externe ne peut pas atteindre du matériel sur un réseau privé de magasin.
Installation et lancement
npx m-scan-device-agentOu installé globalement :
npm install -g @m-scan/device-kit-agent
m-scan-device-agentÉcoute par défaut sur http://localhost:4310. Changer le port :
M_SCAN_AGENT_PORT=4400 npx m-scan-device-agentPlateformes supportées
| Transport | Plateforme |
|---|---|
| Réseau (TCP) | Windows, Linux, macOS |
| USB | Windows, Linux, macOS (queue d'impression système : winspool.drv ou CUPS) |
| Bluetooth | Windows, Linux, macOS (port série, l'imprimante doit être appairée dans les paramètres Bluetooth de l'OS) |
Android/iOS ne sont pas supportés par l'agent (pas d'environnement Node.js persistant sur mobile) — sur tablette/téléphone, la voie prévue est une PWA qui parle directement à l'imprimante via Web Bluetooth/WebUSB dans le navigateur, sans agent (encore à implémenter).
API
Toutes les routes acceptent/répondent en JSON. { receipt: Receipt } (voir
@m-scan/device-kit-escpos) est préféré à { lines: string[] }
pour un ticket correctement formaté (colonnes alignées).
Réseau
| Route | Méthode | Body | Rôle |
|---|---|---|---|
| /api/scan | GET | ?port=9100 | Scanne le /24 local, identifie les imprimantes (SNMP/mDNS best-effort) |
| /api/connect | POST | { host, port? } | Ouvre une connexion TCP réutilisable |
| /api/print | POST | { receipt } ou { host?, port?, receipt } | Imprime (réutilise la connexion active si host omis) |
| /api/cash-drawer | POST | { host?, port? } | Pulse le tiroir-caisse |
| /api/disconnect | POST | — | Ferme toutes les connexions actives (tous transports) |
USB (préfixe /api/usb/)
Mêmes routes, avec printerName (nom de la queue d'impression système —
Get-Printer sur Windows, lpstat -v sur Linux/macOS) à la place de
host/port.
Bluetooth (préfixe /api/bluetooth/)
Mêmes routes, avec comPort (ex. "COM5") à la place de host/port.
Exemple complet
const AGENT = 'http://localhost:4310'
// Découvrir les imprimantes réseau
const { devices } = await fetch(`${AGENT}/api/scan`).then((r) => r.json())
// Se connecter à la première trouvée
await fetch(`${AGENT}/api/connect`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ host: devices[0].address, port: devices[0].meta.port }),
})
// Imprimer
await fetch(`${AGENT}/api/print`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ receipt: myReceipt }),
})Utilisation programmatique (sans CLI)
import { AgentServer } from '@m-scan/device-kit-agent'
const server = new AgentServer({ port: 4310 })
await server.start()
// ...
await server.stop()Pourquoi pas d'accès USB/Bluetooth bas niveau (WebUSB/libusb) ?
Testé et abandonné en pratique : dès qu'un pilote imprimante est installé
sur un périphérique USB, l'OS verrouille l'accès USB direct (sur Windows,
claimInterface échoue avec "incompatible driver is installed for this
device"). Passer par la queue d'impression système (winspool.drv sur
Windows, CUPS sur Linux/macOS) évite ce conflit et fonctionne avec le
pilote déjà en place.
Licence
MIT
