Konnektoren

Fünf Datenbanken, sieben Nachrichtenbusse und zwei Objektspeicher - in beide Richtungen. Diese Seite nennt die Connection-String-Formate, die Umgebungsvariablen des Agenten, das Envelope-Format für ZPL aus dem Objektspeicher und die Ausgabeziele, die nach dem Druck ablegen und melden.

Überblick

Ein Etikett entsteht aus zwei Zutaten: Daten und einem Design. Die Daten kommen entweder auf Abruf aus einer Datenbank oder von selbst über einen Nachrichtenbus. Fertiges ZPL darf auch direkt in der Nachricht stecken oder in einem Objektspeicher liegen. Nach dem Druck kann zplCloud das Ergebnis wieder ablegen und Bescheid geben.

Konnektoren: Datenbanken, Nachrichtenbusse und Objektspeicher rein, Drucker und Archiv raus

Datenquellen (Datenhub)

Eine Datenquelle ist eine gespeicherte Abfrage auf eine Ihrer Datenbanken. Es gibt zwei Wege dorthin. Beim Agent-Weg führt der zplCloudCli-Agent die Abfrage in Ihrem Netz aus; der Connection-String liegt nur dort und verlässt Ihr Netz nie - über die Leitung gehen ausschließlich die Ergebniszeilen. Beim Cloud-Weg verbindet sich das Backend selbst, etwa mit einer Azure Database for PostgreSQL oder Amazon RDS; der Connection-String liegt dann AES-verschlüsselt in der Plattform-Datenbank und wird nur zur Ausführung entschlüsselt.

TypEngineWeg
agent-sqlMicrosoft SQL ServerAgent
agent-mongoMongoDBAgent
agent-postgresPostgreSQLAgent
agent-mysqlMySQLAgent
agent-mariadbMariaDBAgent
cloud-postgresPostgreSQLBackend direkt
cloud-mysqlMySQLBackend direkt
cloud-mariadbMariaDBBackend direkt

Der Datenhub ist ein Pro-Feature. Genutzt wird er von Print Views, DHL-Lookups und dem Batch-Druck.

Datenbanken am Agenten konfigurieren

Der Agent lernt seine Datenbanken auf drei Wegen: als Kommandozeilen-Option, als Umgebungsvariable oder aus einer Datei neben der Binary bzw. unter ~/.zplcloud/. Jede Engine hat ihren eigenen Namensraum, damit die Auswahl in der Oberfläche eindeutig bleibt.

EngineOptionUmgebungsvariableDatei
SQL Server--sql NAME=…ZPLCLOUD_SQL_<NAME>_CONNECTIONsqlservers.json
MongoDB--mongo NAME=…ZPLCLOUD_MONGO_<NAME>_CONNECTIONmongoservers.json
PostgreSQL--postgres NAME=…ZPLCLOUD_PG_<NAME>_CONNECTIONpgservers.json
MySQL--mysql NAME=…ZPLCLOUD_MYSQL_<NAME>_CONNECTIONmysqlservers.json
MariaDB--mariadb NAME=…ZPLCLOUD_MARIADB_<NAME>_CONNECTIONmariadbservers.json
# Alles in einem Aufruf (jede Option mehrfach möglich):
zplcloud proxy --agent "Lager" \
  --postgres WMS="Host=pg.internal.lan;Database=wms;Username=zplcloud;Password=...;SSL Mode=Require" \
  --mysql SHOP="Server=mysql.internal.lan;Database=shop;User ID=zplcloud;Password=..." \
  --mariadb ERP="Server=maria.internal.lan;Database=erp;User ID=zplcloud;Password=..."

# oder als Umgebungsvariablen (Windows PowerShell: $env:ZPLCLOUD_PG_WMS_CONNECTION = "...")
export ZPLCLOUD_PG_WMS_CONNECTION="Host=pg.internal.lan;Database=wms;Username=zplcloud;Password=..."
zplcloud proxy --agent "Lager"

# oder je Engine eine Datei neben der Binary bzw. unter ~/.zplcloud/
# pgservers.json      { "postgresServers": { "WMS":  "Host=...;Database=..." } }
# mysqlservers.json   { "mysqlServers":    { "SHOP": "Server=...;Database=..." } }
# mariadbservers.json { "mariadbServers":  { "ERP":  "Server=...;Database=..." } }

Was in einer Abfrage erlaubt ist

Für alle relationalen Quellen gelten dieselben Regeln, egal ob Agent oder Cloud. Sie sind bewusst eng: eine Datenquelle soll lesen, nicht schreiben.

  • Nur ein einzelnes SELECT (oder WITH) - kein ;, keine Kommentare, keine Multi-Statements.
  • Filterwerte gehen immer als Parameter (@p0) an die Datenbank, nie per String-Verkettung.
  • Filter, Sortierung und LIMIT/OFFSET werden in der Quelle angewandt (Pushdown), nicht im Speicher der Plattform.
  • Höchstens 1000 Zeilen je Abruf, Zeitlimit 15 Sekunden. Größere Mengen holt die Plattform serverseitig in Blöcken.

Nachrichtenbusse

Ein Abo verbindet einen Bus mit einem Drucker. Jede eingehende Nachricht wird zu einem Datensatz, füllt die Bindings eines Designs und druckt - oder trägt fertiges ZPL als Envelope. Kafka läuft wahlweise direkt aus der Cloud oder on-prem über den Agenten, alle übrigen Busse laufen direkt aus der Cloud.

TypConnection-StringTopic-Feld
cloud (Kafka)BootstrapServers=broker:9092;GroupId=zplCloudConsumerTopic
agent (Kafka on-prem)liegt im Agenten (--kafka NAME=…)Topic
servicebusEndpoint=sb://…;SharedAccessKeyName=…;SharedAccessKey=…Queue oder topic/Subscriptions/name; entfällt bei EntityPath im String
mqttServer=broker;Port=8883;Tls=true;Username=…;Password=…;Qos=1Topic-Filter (+ und # erlaubt)
amqp10amqps://user:passwort@broker:5671Adresse (Queue oder Node)
rabbitmqamqp://user:passwort@rabbit:5672/vhostQueue-Name (wird nicht automatisch angelegt)
sqsQueueUrl=…;Region=eu-central-1;AccessKey=…;SecretKey=…Queue-URL; entfällt, wenn QueueUrl im String steht
pubsubProjectId=…;SubscriptionId=…;CredentialsBase64=…Subscription-ID; entfällt, wenn SubscriptionId im String steht

Bei Amazon SQS greift ohne AccessKey/SecretKey die normale AWS-Credential-Kette (IAM-Rolle, Umgebung, Profil). Bei Google Pub/Sub wird das Service-Account-JSON Base64-kodiert übergeben, weil es selbst Semikolons und Zeilenumbrüche enthält, die sonst die Schlüssel=Wert-Paare zerlegen würden.

Quittierung: nichts geht still verloren

Alle Busse folgen derselben Regel: quittiert wird erst nach dem Druck. Solange das ZPL nicht am Drucker angekommen ist, gilt die Nachricht als offen und wird erneut zugestellt.

BusBei ErfolgBei Druckfehler
KafkaOffset committenOffset bleibt stehen, Nachricht kommt wieder
Azure Service BusComplete (PeekLock)Abandon mit Backoff, nach 3 Zustellungen Dead-Letter
MQTTAckkein Ack - der Broker stellt bei QoS 1/2 erneut zu
AMQP 1.0AcceptRelease, der Broker stellt erneut zu
RabbitMQBasicAckBasicNack mit requeue
Amazon SQSDeleteMessagenicht löschen, nach dem Visibility-Timeout erneut (dann Redrive/DLQ)
Google Pub/SubAckNack, Pub/Sub stellt laut Retry-Policy erneut zu

ZPL-Envelope und ZPL aus dem Objektspeicher

Ein Abo ohne Design erwartet fertiges ZPL in der Nachricht. Das Feld printer nennt die Ziel-Seriennummer, rp:{id} für einen Remote-Drucker oder "*" für alle Drucker des Kontos.

{
  "schemaVersion": 1,
  "printer": "*",
  "zpl": "^XA^FO50,50^A0N,40,40^FDHello^FS^XZ"
}

Große Druckdateien gehören nicht in eine Bus-Nachricht. Statt das ZPL einzubetten, verweist die Nachricht darauf: storage ist der Name einer Storage-Verbindung, key der Objekt-Schlüssel darin. Geholt wird die Datei erst beim Druck. Aufgelöst wird der Name nur im eigenen bzw. Firmen-Scope - eine fremde Verbindung ist so nicht erreichbar.

{
  "schemaVersion": 1,
  "printer": "rp:7",
  "zplRef": { "storage": "archiv", "key": "auftraege/4711.zpl" }
}

Storage-Verbindungen (S3 und Azure Blob)

Eine Storage-Verbindung wird einmal angelegt und in beide Richtungen genutzt: zum Lesen über zplRef und zum Schreiben über ein Ausgabeziel. Die Zugangsdaten liegen AES-verschlüsselt in der Plattform-Datenbank; die Oberfläche zeigt nur, ob welche hinterlegt sind, nie ihren Wert.

ProviderBucket / ContainerZugangsdatenBesonderheit
s3BucketAccessKey=…;SecretKey=… (optional SessionToken)Ohne Zugangsdaten greift die AWS-Credential-Kette. Eigener Endpoint + Path-Style für MinIO, R2, Wasabi, Backblaze und Ceph.
azureblobContainerConnection-String oder Container-SAS-URLBei einer SAS-URL zeigt der Link bereits auf den Container.

Ausgabeziele: ablegen und Bescheid geben

Ein Ausgabeziel bündelt bis zu drei Schritte, die nach einem erfolgreichen Druck laufen. Jeder ist einzeln zuschaltbar, und alle laufen nach dem Druck: ein Fehler dort stoppt niemals den Druck, er landet nur im Protokoll der Subscription.

  1. Ablegen - das gedruckte ZPL wandert als Datei in eine Storage-Verbindung.
  2. Melden - eine Nachricht geht an einen Broker; unterstützt werden dieselben Protokolle wie beim Empfang.
  3. Anstoßen - ein HTTP-POST an eine eigene URL, HMAC-SHA256-signiert wie die übrigen Webhooks.

Dateiname der Ablage

Der Schlüssel entsteht aus einer Vorlage. Alle Zeitangaben sind UTC, Platzhalter ohne Wert entfallen.

PlatzhalterBedeutung
{yyyy} {MM} {dd}Jahr, Monat, Tag
{HH} {mm} {ss}Stunde, Minute, Sekunde
{subscription}Name des Abos
{printer}Ziel-Drucker
{key}Schlüssel der Bus-Nachricht
{id}eindeutige ID je Etikett
Vorlage:  {yyyy}/{MM}/{dd}/{subscription}/{id}.zpl
Ergebnis: 2026/09/09/Warenausgang/8f3c1e2a9b7d4c0e.zpl

Was in der Meldung steht

Message und Webhook bekommen dieselbe Nutzlast. Das ZPL selbst ist nur enthalten, wenn das ausdrücklich gewünscht ist - sonst sprengt eine grafiklastige Datei jedes Message-Limit.

{
  "schemaVersion": 1,
  "event": "label.printed",
  "utc": "2026-09-09T12:34:56.7890000Z",
  "subscriptionId": 12,
  "subscription": "Warenausgang",
  "topic": "orders.shipped",
  "printer": "rp:7",
  "messageKey": null,
  "designId": 42,
  "storageKey": "zpl/2026/09/09/Warenausgang/8f3c1e2a.zpl",
  "storageUrl": "https://archiv.s3.eu-central-1.amazonaws.com/zpl/2026/09/09/...",
  "zplBytes": 812,
  "zpl": null
}

Der Webhook trägt dieselben Kopfzeilen wie die regulären Webhook-Endpunkte: X-ZplCloud-Event, X-ZplCloud-Delivery, X-ZplCloud-Timestamp und, sobald ein Secret hinterlegt ist, X-ZplCloud-Signature mit dem HMAC-SHA256 über den rohen Rumpf.

Ohne Hardware ausprobieren

Zum Testen braucht es keinen echten Drucker: ein virtueller Testdrucker nimmt ZPL an wie ein Gerät und legt das gerenderte Etikett in einen eigenen Verlauf - ohne Render-Verbrauch, mit Wasserzeichen. Er steht im Reiter „Sandbox-Drucker“ unter Drucker und in jedem „ZPL senden“-Dialog zur Auswahl. So lässt sich ein ganzes Abo inklusive Ausgabeziel durchspielen, bevor Papier läuft.