Simplify agent to backend-driven printing
This commit is contained in:
@@ -1,143 +1,149 @@
|
||||
# LabelPrintAgent
|
||||
|
||||
Windows-Tray-Anwendung zum Rendern und Drucken von Etiketten über installierte Windows-Drucker, z. B. einen Dymo LabelWriter.
|
||||
Windows-Tray-Connector für den PaperlessManager.
|
||||
|
||||
## Aktueller Stand
|
||||
Der Agent speichert keine Layouts, keine Nummernserver-Regeln und keine MySQL-Queue-Logik mehr. Das Backend entscheidet, welche Etiketten gedruckt werden, rendert bzw. liefert das fertige Etikett als Bild, und der Agent druckt dieses Bild über einen installierten Windows-Drucker.
|
||||
|
||||
Der Agent arbeitet jetzt mit lokalen `LabelTemplates` in `C:\ProgramData\LabelPrintAgent\settings.json`.
|
||||
|
||||
Ein Queue-Job enthält nur noch:
|
||||
|
||||
- `barcode_template_id`
|
||||
- `payload_json`
|
||||
|
||||
Die alte Zuordnung über `layout_key` gibt es nicht mehr. Stattdessen gilt:
|
||||
## Ablauf
|
||||
|
||||
```text
|
||||
label_print_queue.barcode_template_id
|
||||
-> lokales LabelTemplate im LabelPrintAgent
|
||||
-> darin enthaltenes Layout rendern
|
||||
LabelPrintAgent
|
||||
-> fragt alle X Sekunden PaperlessManager-Backend
|
||||
-> erhält einen druckfertigen Etikettenjob
|
||||
-> lädt/liest das Etikettbild
|
||||
-> druckt über Windows-Drucker
|
||||
-> meldet Erfolg oder Fehler ans Backend zurück
|
||||
```
|
||||
|
||||
Die Tabelle `barcode_templates` wird nicht verändert. Sie bleibt nur die fachliche Referenz für die `barcode_template_id`.
|
||||
Optional kann später statt Polling Server-Sent Events ergänzt werden. Der aktuelle Stand nutzt bewusst Polling, weil es robuster und einfacher zu betreiben ist.
|
||||
|
||||
## LabelTemplates
|
||||
## Backend-Vertrag
|
||||
|
||||
Ein lokales LabelTemplate enthält:
|
||||
Der Agent fragt standardmäßig:
|
||||
|
||||
- `barcodeTemplateId`
|
||||
- `name`
|
||||
- `getNumberUrl`
|
||||
- `numberPrintedUrl`
|
||||
- `reservedNumberPayloadKey`
|
||||
- `qrTemplate`
|
||||
- `layout`
|
||||
```http
|
||||
GET /api/label-print-agent/jobs/next?agentId={agentId}
|
||||
Authorization: Bearer {apiToken}
|
||||
```
|
||||
|
||||
Das Layout liegt vollständig eingebettet im Template. Es gibt keine separate Layout-Datei und keinen `layoutKey` mehr.
|
||||
Wenn nichts zu drucken ist:
|
||||
|
||||
## Nummernserver
|
||||
```http
|
||||
204 No Content
|
||||
```
|
||||
|
||||
`getNumberUrl` wird per HTTP GET aufgerufen und gibt Plain Text zurück, z. B.:
|
||||
Wenn ein Etikett vorhanden ist:
|
||||
|
||||
```json
|
||||
{
|
||||
"jobId": "12345",
|
||||
"labelImageBase64": "...",
|
||||
"labelImageContentType": "image/png",
|
||||
"labelWidthMm": 57,
|
||||
"labelHeightMm": 32
|
||||
}
|
||||
```
|
||||
|
||||
Alternativ darf das Backend statt `labelImageBase64` eine URL liefern:
|
||||
|
||||
```json
|
||||
{
|
||||
"jobId": "12345",
|
||||
"labelImageUrl": "/api/label-print-agent/jobs/12345/image",
|
||||
"labelImageContentType": "image/png",
|
||||
"labelWidthMm": 57,
|
||||
"labelHeightMm": 32
|
||||
}
|
||||
```
|
||||
|
||||
Der Agent meldet Erfolg:
|
||||
|
||||
```http
|
||||
POST /api/label-print-agent/jobs/{jobId}/printed
|
||||
Authorization: Bearer {apiToken}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"agentId": "PC-BUERO",
|
||||
"printerName": "DYMO LabelWriter 450"
|
||||
}
|
||||
```
|
||||
|
||||
Der Agent meldet Fehler:
|
||||
|
||||
```http
|
||||
POST /api/label-print-agent/jobs/{jobId}/error
|
||||
Authorization: Bearer {apiToken}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"agentId": "PC-BUERO",
|
||||
"printerName": "DYMO LabelWriter 450",
|
||||
"errorMessage": "Drucker ist nicht verfügbar."
|
||||
}
|
||||
```
|
||||
|
||||
## Lokale Einstellungen
|
||||
|
||||
Die Einstellungen liegen unter:
|
||||
|
||||
```text
|
||||
123
|
||||
C:\ProgramData\LabelPrintAgent\settings.json
|
||||
```
|
||||
|
||||
Der Nummernserver liefert keine führenden Nullen. Die Datenbank speichert `reserved_number` als `BIGINT`, also z. B. `123`.
|
||||
|
||||
Führende Nullen entstehen nur über Formatierung im Template:
|
||||
|
||||
```text
|
||||
{reservedNumber:0000000} -> 0000123
|
||||
{nummer:0000000} -> 0000123
|
||||
```
|
||||
|
||||
Nach erfolgreichem Windows-Druck wird `numberPrintedUrl` aufgerufen. Erst wenn diese Bestätigung erfolgreich war, darf der Job als `printed` markiert werden.
|
||||
|
||||
Wenn der Druck erfolgreich war, aber `numberPrintedUrl` fehlschlägt, bleibt `reserved_number` erhalten und der Job geht auf `error`. Beim erneuten Drucken wird dieselbe Nummer wiederverwendet; es wird keine neue Nummer reserviert.
|
||||
|
||||
## Payload-Erweiterung
|
||||
|
||||
Vor dem Rendern wird `payload_json` erweitert:
|
||||
|
||||
- `reservedNumber`
|
||||
- der konfigurierte `reservedNumberPayloadKey`, z. B. `nummer`
|
||||
- `qr`, wenn `qrTemplate` gesetzt ist
|
||||
- `jobId`
|
||||
- `barcodeTemplateId`
|
||||
|
||||
Beispiel:
|
||||
|
||||
```json
|
||||
{
|
||||
"reservedNumber": 123,
|
||||
"nummer": 123,
|
||||
"qr": "bjoernprivat 0000123"
|
||||
"backend": {
|
||||
"baseUrl": "https://paperlessmanager.local",
|
||||
"agentId": "PC-BUERO",
|
||||
"encryptedApiToken": "",
|
||||
"nextJobPath": "/api/label-print-agent/jobs/next",
|
||||
"reportSuccessPath": "/api/label-print-agent/jobs/{jobId}/printed",
|
||||
"reportErrorPath": "/api/label-print-agent/jobs/{jobId}/error"
|
||||
},
|
||||
"printer": {
|
||||
"printerName": "DYMO LabelWriter 450",
|
||||
"labelWidthMm": 57,
|
||||
"labelHeightMm": 32,
|
||||
"dpi": 300
|
||||
},
|
||||
"worker": {
|
||||
"enabled": true,
|
||||
"pollIntervalSeconds": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Oberfläche
|
||||
Der API-Token wird lokal mit Windows DPAPI verschlüsselt gespeichert.
|
||||
|
||||
Im Einstellungsdialog gibt es den Tab `Label-Templates`.
|
||||
## Dymo-Druck
|
||||
|
||||
Dort kannst du:
|
||||
Der Dymo LabelWriter muss in Windows als normaler Drucker eingerichtet sein. Das Backend liefert ein fertiges Bild für das Etikett, typischerweise PNG in `57 x 32 mm`.
|
||||
|
||||
- Templates anlegen
|
||||
- Templates löschen
|
||||
- `barcodeTemplateId` bearbeiten
|
||||
- Nummernserver-URLs bearbeiten
|
||||
- QR-Template bearbeiten
|
||||
- eingebettetes Layout-JSON bearbeiten
|
||||
- validieren
|
||||
- Vorschau erzeugen
|
||||
- Testdruck auslösen
|
||||
Wichtig:
|
||||
|
||||
Die Vorschau verwendet eine Dummy-Nummer `123` und reserviert keine Nummer beim Nummernserver.
|
||||
- Der Agent verwendet `PrintDocument`.
|
||||
- Es wird kein ZPL, EPL oder TSPL verwendet.
|
||||
- Das Bild wird auf die komplette Papierfläche gedruckt.
|
||||
- Der Dymo-Treiber sollte auf das passende Etikettenformat eingestellt sein.
|
||||
|
||||
## Dymo-Testdruck
|
||||
## Bedienung
|
||||
|
||||
Für den Dymo LabelWriter muss der Drucker in Windows als normaler Drucker eingerichtet sein. Stelle im Dymo-Treiber möglichst das passende Etikettenformat `57 x 32 mm` ein.
|
||||
1. Anwendung starten.
|
||||
2. Tray-Symbol öffnen.
|
||||
3. Im Tab `Backend` BaseUrl, AgentId und optional API-Token eintragen.
|
||||
4. Im Tab `Drucker` den Dymo LabelWriter auswählen.
|
||||
5. Im Tab `Allgemein` Polling aktivieren und Intervall setzen.
|
||||
6. Mit `Jetzt prüfen` kann sofort ein einzelner Backend-Poll ausgelöst werden.
|
||||
|
||||
Testdruck:
|
||||
## Nicht mehr im Agent
|
||||
|
||||
1. Im Tab `Drucker` den Dymo LabelWriter auswählen.
|
||||
2. `Speichern` klicken.
|
||||
3. Im Tab `Label-Templates` ein Template auswählen.
|
||||
4. `Vorschau` prüfen.
|
||||
5. `Testdruck` klicken.
|
||||
- keine Layout-JSON-Verwaltung
|
||||
- keine lokalen LabelTemplates
|
||||
- keine MySQL-Verbindung
|
||||
- keine Nummernserver-URLs
|
||||
- keine Nummernreservierung im Agent
|
||||
|
||||
Typische Fehler:
|
||||
|
||||
- Falscher Drucker gewählt.
|
||||
- Falsches Etikettenformat im Dymo-Treiber.
|
||||
- Treiber skaliert auf A4/Letter.
|
||||
- Etikett ist gedreht: Dymo-Treiber-Labelgröße und physische Orientierung prüfen.
|
||||
|
||||
## Datenbank
|
||||
|
||||
Die SQL-Datei liegt unter:
|
||||
|
||||
```text
|
||||
sql/create_label_print_queue.sql
|
||||
```
|
||||
|
||||
Beispiel-Insert:
|
||||
|
||||
```sql
|
||||
INSERT INTO label_print_queue
|
||||
(barcode_template_id, payload_json, status)
|
||||
VALUES
|
||||
(
|
||||
1,
|
||||
JSON_OBJECT(
|
||||
'titel', 'Beleg privat',
|
||||
'beschreibung', 'Tankbeleg',
|
||||
'datum', '2026-05-07'
|
||||
),
|
||||
'pending'
|
||||
);
|
||||
```
|
||||
|
||||
## Noch offen
|
||||
|
||||
Der automatische MySQL-Worker ist noch nicht aktiv verdrahtet. Die dafür benötigten Modell-, Repository-, Nummernserver- und Druckprozessor-Klassen sind vorbereitet.
|
||||
Diese Verantwortung liegt vollständig im PaperlessManager-Backend.
|
||||
|
||||
Reference in New Issue
Block a user