Driver unico multi-modello KX60 + SK1-311 #1

Merged
Max merged 4 commits from feature/driver-custom-kx60 into main 2026-07-23 13:53:32 +00:00
Contributor

Pacchetto printer_driver unificato, entrambi i profili verificati su hardware.

Pacchetto printer_driver unificato, entrambi i profili verificati su hardware.
Unifica i due driver separati in un solo pacchetto printer_driver. Il modello
si sceglie con PRINTER_MODEL o viene rilevato dal bus USB.

Il codice che crea il biglietto resta invariato per qualunque modello:
ticket.py riceve una larghezza e restituisce un'immagine, importa solo PIL,
e non esiste un percorso di codice diverso per stampante. Aggiungere un
modello costa un file in models/, caricato automaticamente.

Quattro difetti corretti, trovati sulla KX60 e validi per tutti i modelli
perche' stavano nel percorso condiviso. Tre erano invisibili dai log: il
software riportava successo e il difetto si vedeva solo sulla carta.

- Interlinea mai impostata: il LF dopo ogni banda da 24 dot avanzava di ~34
  dot (default 1/6 di pollice), lasciando 10 dot di bianco fra le bande.
  Risolto con ESC 3 24 prima delle bande e ESC 2 dopo.
- GS V 66 n esegue il taglio ma ignora l'avanzamento su firmware KX60 1.02:
  la lama cadeva dentro il contenuto e tranciava l'ultima riga. Avanzamento
  ora esplicito con ESC J.
- Device chiuso prima dello svuotamento: il taglio, accodato dietro
  l'immagine, si perdeva in modo intermittente e proporzionale alla lunghezza
  del biglietto. Attesa ora calcolata sulla carta accodata invece di un
  sleep fisso.
- Stato letto al contrario: decodifica Epson invece di quella CUSTOM, e
  valori ottimisti mai corretti quando i registri ammutoliscono. A carta
  finita il driver dichiarava "pronta".

Riconoscimento USB per VID:PID invece che per stringhe, con il motivo del
match visibile in printer-cli info.

Valori MISURATI su KX60 firmware 1.02: testina 448 dot (56mm), distanza
testina-lama 56 dot (7mm), fine carta DLE EOT 2 bit 0, esaurimento bit 3.

Il profilo sk1 NON e' verificato su hardware: nessuna SK1 disponibile durante
lo sviluppo. I valori sono ereditati dal driver precedente e vanno confermati
con calibrate, cutcal e watch. Il pacchetto lo dichiara a ogni avvio.
test_stampante.py non importa piu sk1_driver: usa il rilevamento
multi-modello e segnala i profili non verificati.

test_protocollo.py verifica il flusso ESC/POS senza consumare carta:
interlinea, ordine init/immagine/taglio, larghezza delle bande, rifiuto a
carta finita col protocollo reale misurato, e stampa comunque tentata su
stampante muta.
install_printer.sh sceglie la stampante invece di assumere la SK1.

Il rilevamento e' delegato al pacchetto tramite `printer-cli detect --shell`:
la lista dei VID:PID non e' duplicata in bash. Una lista duplicata nello
script divergerebbe al primo modello aggiunto, in silenzio.

- --model forza il modello, con avviso se sul bus ce n'e' un altro
- --list-models elenca i modelli ed esce
- --dry-run mostra il .env che scriverebbe senza toccare apt, udev o systemd
- --yes per installazioni non interattive
- un profilo non verificato viene segnalato e chiede conferma

Il .env generato contiene ora PRINTER_MODEL, PRINT_WIDTH_DOTS,
HEAD_TO_CUTTER_DOTS, TAIL_MARGIN_DOTS e NEAR_END_SENSOR, ognuno con il
commento su come si misura. Backup del .env preesistente prima di
sovrascriverlo.

La regola udev e' ora generata sul VID:PID rilevato in 99-kiosk-printer.rules
e la vecchia 99-sk1.rules viene rimossa: restava a puntare a un dispositivo
che su una macchina con KX60 non esiste. Permessi 0660 group lp invece di
0666, perche' il driver usa /dev/usb/lp0 e non serve accesso a chiunque.

Corretti due difetti trovati provando lo script:

- un modello inesistente non veniva rifiutato: `eval "$(... || true)"`
  inghiottiva l'exit code e le variabili del rilevamento precedente
  restavano, producendo un .env con il nome sbagliato e i parametri di
  un'altra stampante. L'esito e' ora catturato e verificato prima di eval.
- `printer-cli detect --model X` ignorava --model e restituiva i parametri
  della stampante rilevata invece di quelli del modello richiesto.
SK1-311 provata su raspberrypi 172.16.50.75 (firmware V3.13, id USB
_SANEI / _SK1-311). Il profilo passa da ereditato-non-verificato a misurato.

- Larghezza 576 dot / 72mm. Attenzione all'equivoco: la SK1 e' una
  stampante "80mm", ma 80mm e' la carta; l'area di stampa e' 72mm/576 dot.
  Prendere gli 80mm come larghezza in dot stampa oltre il bordo utile.
- Distanza testina-lama 80 dot / 10mm, misurata con cutcal. Il driver
  precedente tagliava con avanzamento 0: con la lama a 10mm tranciava gli
  ultimi 10mm di OGNI biglietto. Ora l'avanzamento e' 104 dot / 13mm e il
  footer resta intero.
- Stato letto da GS r 1 (0x00 carta presente, 0x0C assente) e confermato
  con ESC v. Su questo firmware DLE EOT e' muto, all'opposto della KX60
  dove e' l'unico registro affidabile: e' la dimostrazione concreta del
  perche' il decodificatore di stato deve essere per-modello. decode_sanei
  verificato in tutti gli stati, transitorio di reinserimento incluso (letto
  come "non verificabile", non finto-presente).

Stato in JSON, per consumo da altri programmi:
    python -m printer_driver.report      (anche --compact)
    printer-cli json
Riporta modello, larghezza e taglio in dot e mm, presenza carta,
esaurimento, errore/inceppamento. I campi che la stampante non espone
valgono null (non conosciuto), mai un valore inventato: error_detectable
dice se il modello sa distinguere un errore generale. Su SK1 e KX60
l'errore/jam non e' rilevabile (DLE EOT muto o mai osservato) ed e' null;
l'esaurimento e' rilevabile solo su KX60.

detects_error aggiunto a ModelProfile: separa "nessun errore" da "errore
non misurabile su questo modello".
Max merged commit 9223de22f7 into main 2026-07-23 13:53:32 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
s.moretti/dlq_printer!1
No description provided.