# 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 ```text 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](BACKEND_API.md). Der Agent fragt standardmäßig: ```http GET /api/label-print-agent/jobs/next?agentId={agentId} Authorization: Bearer {apiToken} ``` Wenn nichts zu drucken ist: ```http 204 No Content ``` 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 C:\ProgramData\LabelPrintAgent\settings.json ``` Beispiel: ```json { "backend": { "baseUrl": "https://paperlessmanager.local", "agentId": "PC-BUERO", "encryptedApiToken": "", "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 }, "worker": { "enabled": true, "pollIntervalSeconds": 30 } } ``` Der API-Token wird lokal mit Windows DPAPI verschlüsselt gespeichert. ## 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 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 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: ```text 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.