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",
    "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
    },
    {
      "printerId": "PC-BUERO_ZEBRA_GK420D",
      "name": "Zebra GK420 Büro",
      "windowsPrinterName": "Zebra GK420d",
      "dpi": 203,
      "defaultWidthMm": 101,
      "defaultHeightMm": 76
    }
  ],
  "worker": {
    "enabled": true,
    "pollIntervalSeconds": 30
  }
}

Der API-Token wird lokal mit Windows DPAPI verschlüsselt gespeichert.

Beim Start registriert der Agent jeden Eintrag aus printers beim Backend. 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

  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:

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.

S
Description
No description provided
Readme 273 KiB
2026-05-31 20:21:53 +00:00
Languages
C# 100%