LabelPrintAgent
Windows-Tray-Connector für den PaperlessManager.
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.
Ablauf
LabelPrintAgent
-> fragt alle X Sekunden PaperlessManager-Backend
-> erhält druckfertige Etikettenjobs, bis kein Job mehr vorhanden ist
-> lädt/liest das Etikettbild
-> druckt über Windows-Drucker
-> meldet Erfolg oder Fehler ans Backend zurück
Der Agent unterstützt Server-Sent Events für Push-Benachrichtigungen und nutzt Polling als Fallback. Jeder Poll-Lauf ruft so lange /jobs/next auf, bis das Backend 204 No Content zurückgibt.
Backend-Vertrag
Die ausführliche API-Beschreibung liegt in BACKEND_API.md.
Der Agent fragt standardmäßig:
GET /api/label-print-agent/jobs/next?agentId={agentId}
Authorization: Bearer {apiToken}
Wenn nichts zu drucken ist:
204 No Content
Wenn ein Etikett vorhanden ist:
{
"jobId": 12345,
"printerId": "PC-BUERO_DYMO_LABELWRITER_450",
"labelType": "artikel",
"windowsPrinterName": "DYMO LabelWriter 450",
"labelImageBase64": "...",
"labelImageContentType": "image/png",
"labelWidthMm": 57,
"labelHeightMm": 32
}
Alternativ darf das Backend statt labelImageBase64 eine URL liefern:
{
"jobId": 12345,
"printerId": "PC-BUERO_DYMO_LABELWRITER_450",
"labelType": "artikel",
"windowsPrinterName": "DYMO LabelWriter 450",
"labelImageUrl": "/api/label-print-agent/jobs/12345/image",
"labelImageContentType": "image/png",
"labelWidthMm": 57,
"labelHeightMm": 32
}
Der Agent meldet Erfolg:
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:
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:
C:\ProgramData\LabelPrintAgent\settings.json
Beispiel:
{
"backend": {
"baseUrl": "https://paperlessmanager.local",
"agentId": "PC-BUERO",
"encryptedApiToken": "",
"registerPrinterPath": "/api/label-print-agent/printers/register",
"deactivatePrinterPath": "/api/label-print-agent/printers/{printerId}/deactivate",
"nextJobPath": "/api/label-print-agent/jobs/next",
"imagePath": "/api/label-print-agent/jobs/{jobId}/image",
"reportSuccessPath": "/api/label-print-agent/jobs/{jobId}/printed",
"reportErrorPath": "/api/label-print-agent/jobs/{jobId}/error",
"useServerSentEvents": true,
"eventsPath": "/api/label-print-agent/events"
},
"printer": {
"printerName": "DYMO LabelWriter 450",
"labelWidthMm": 57,
"labelHeightMm": 32,
"dpi": 300
},
"printers": [
{
"printerId": "PC-BUERO_DYMO_LABELWRITER_450",
"name": "DYMO LabelWriter Regal",
"windowsPrinterName": "DYMO LabelWriter 450",
"dpi": 300,
"defaultWidthMm": 57,
"defaultHeightMm": 32,
"isActive": true
},
{
"printerId": "PC-BUERO_ZEBRA_GK420D",
"name": "Zebra GK420 Büro",
"windowsPrinterName": "Zebra GK420d",
"dpi": 203,
"defaultWidthMm": 101,
"defaultHeightMm": 76,
"isActive": false
}
],
"worker": {
"enabled": true,
"pollIntervalSeconds": 30
}
}
Der API-Token wird lokal mit Windows DPAPI verschlüsselt gespeichert.
Der Agent registriert Drucker nicht automatisch. Im Tab Drucker steht links die Druckerliste; rechts werden Aktiv-Status, Breite, Höhe und DPI pro Drucker gepflegt. Wird Aktiv gesetzt, registriert der Agent den Drucker im Backend. Wird der Haken entfernt, ruft der Agent den Deaktivierungs-Endpunkt auf. Das Feld printer bleibt als Kompatibilitätsfeld für ältere Einstellungen erhalten; neue Jobs werden anhand von windowsPrinterName aus der Backend-Antwort auf den passenden lokalen Windows-Drucker gedruckt.
Dymo-Druck
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.
Wichtig:
- 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.
Bedienung
- Anwendung starten.
- Tray-Symbol öffnen.
- Im Tab
BackendBaseUrl, AgentId und optional API-Token eintragen. - Im Tab
Druckerlinks einen Drucker auswählen und rechtsAktiv, Breite, Höhe und DPI setzen. - Im Tab
AllgemeinPolling aktivieren und Intervall setzen. - Mit
Jetzt prüfenkann sofort ein Poll-Lauf ausgelöst werden; dabei werden alle aktuell verfügbaren Jobs verarbeitet.
Updates
Im Tab Updates kann der Agent gegen die Gitea-Release-API nach neuen Versionen suchen. Standardmäßig wird das neueste Release dieses Repositorys abgefragt:
https://gitea.poettker-cloud.de/api/v1/repos/bjoernpoettker/LabelPrintAgent/releases/latest
Für private Repositories kann ein Gitea-Access-Token hinterlegt werden. Der Token wird lokal verschlüsselt gespeichert.
Wenn ein neueres Release gefunden wird, sucht der Agent nach einem ZIP-Asset, bevorzugt mit dem Suffix -win-x64.zip. Das ZIP enthält den framework-dependent win-x64-Publish inklusive .exe, App-Dateien und zugehöriger NuGet-.dll-Dateien, aber ohne die normale .NET-Laufzeit. Beim Installieren lädt der Agent das ZIP herunter, entpackt es in ein temporäres Verzeichnis, startet ein lokales Update-Skript, beendet sich selbst, ersetzt die Dateien im Installationsordner und startet anschließend neu.
Tray-Status
Das Tray-Icon zeigt den aktuellen Zustand:
- Grün: Worker ist aktiviert, Backend-Konfiguration ist vollständig, Drucker ist verfügbar und der letzte Backend-Kontakt war erfolgreich.
- Rot: Konfiguration fehlt, Drucker ist nicht verfügbar, Worker ist deaktiviert oder der Backend-Kontakt ist fehlgeschlagen.
Logs und 401-Fehler
Logs liegen standardmäßig unter:
C:\ProgramData\LabelPrintAgent\logs\label-print-agent-YYYYMMDD.log
Bei HTTP-Fehlern wie 401 Unauthorized protokolliert der Agent:
- HTTP-Methode und URL
- Statuscode und Reason Phrase
- ob ein Authorization-Header gesetzt wurde
- Authorization-Scheme, z. B.
Bearer - Token-Länge, aber niemals den Token selbst
- kurzer SHA-256-Fingerprint des Tokens zum Abgleich mit dem Backend
WWW-Authenticate-Header des Backends- gekürzten Response-Body des Backends
Beim Speichern wird der API-Token normalisiert. Falls versehentlich Bearer ... oder Authorization: Bearer ... eingefügt wurde, speichert der Agent nur den eigentlichen Tokenwert.
Nicht mehr im Agent
- keine Layout-JSON-Verwaltung
- keine lokalen LabelTemplates
- keine MySQL-Verbindung
- keine Nummernserver-URLs
- keine Nummernreservierung im Agent
Diese Verantwortung liegt vollständig im PaperlessManager-Backend.