No description
  • Python 55%
  • HTML 43.6%
  • Dockerfile 1.4%
Find a file
Markus Thiel 51cd37cb58 Kundenshop: Katalog, Etiketten-Editor mit Live-Vorschau, Bestellabschluss
- shop.html unter /: Sortiment aus Template-JSONs, dynamisches Formular,
  Live-Vorschau = serverseitiges Druckbild (WYSIWYG), Logo-Upload mit
  clientseitigem Downscale, Preisanzeige
- Templates: price_cents, description, Feld-Labels
- /api/templates liefert Preis + Beschreibung mit
2026-07-19 17:24:27 +00:00
agent Labelshop MVP: Render-Engine, EZPL-Druck, Druckzentrale, Docker-Stack 2026-07-19 16:33:26 +00:00
server Kundenshop: Katalog, Etiketten-Editor mit Live-Vorschau, Bestellabschluss 2026-07-19 17:24:27 +00:00
.env.example Compose deploy-fertig: Secrets via .env, Healthcheck, TZ, Port konfigurierbar 2026-07-19 16:37:37 +00:00
.gitignore Labelshop MVP: Render-Engine, EZPL-Druck, Druckzentrale, Docker-Stack 2026-07-19 16:33:26 +00:00
docker-compose.agent-mode.server.yml Labelshop MVP: Render-Engine, EZPL-Druck, Druckzentrale, Docker-Stack 2026-07-19 16:33:26 +00:00
docker-compose.agent.yml Labelshop MVP: Render-Engine, EZPL-Druck, Druckzentrale, Docker-Stack 2026-07-19 16:33:26 +00:00
docker-compose.yml Compose deploy-fertig: Secrets via .env, Healthcheck, TZ, Port konfigurierbar 2026-07-19 16:37:37 +00:00
README.md Kundenshop: Katalog, Etiketten-Editor mit Live-Vorschau, Bestellabschluss 2026-07-19 17:24:27 +00:00

Labelshop -- Godex-Etikettenshop (Docker)

Webserver und Godex stehen im selben LAN -> EIN Stack reicht. Der Labelshop-Container druckt direkt auf die LAN-IP des Godex (Port 9100), ein interner Worker arbeitet die Job-Warteschlange ab:

        Internet                         LAN zuhause
  Kunde --HTTPS--> Reverse Proxy --> +--------------------------+
                    (Plesk/nginx)    |  labelshop (Docker)      |
                                     |  Shop-API + Vorschau     |
                                     |  Bestellungen (SQLite)   |
                                     |  Druckzentrale /admin    |
                                     |  Druck-Worker -----------+--Raw 9100--> Godex
                                     +--------------------------+

Die Warteschlange bleibt trotzdem: Drucker aus = Jobs bleiben liegen und werden automatisch nachgeholt, sobald er wieder erreichbar ist. Der Worker prueft vor jedem Job die Erreichbarkeit.

Agent-Modus als Reserve: Laesst man PRINTER_HOST leer, druckt der Server nicht selbst, sondern stellt die Agent-API bereit (docker-compose.agent.yml + agent/ -- fuer den Fall, dass der Shop irgendwann auf einen externen Server umzieht). Fuer dein Setup: ignorieren.

Verzeichnis

labelshop/
├── docker-compose.server.yml   Stack fuer den Webserver
├── docker-compose.agent.yml    Stack fuer zuhause (neben Home Assistant o.ae.)
├── server/
│   ├── app.py                  FastAPI: Shop-, Admin- und Agent-API
│   ├── db.py                   SQLite (orders, jobs) auf Volume /data
│   ├── label_renderer.py       Template + Daten -> 1-Bit-Bitmap (WYSIWYG)
│   ├── ezpl.py                 Bitmap -> EZPL-Druckjob (GW-Grafik)
│   ├── admin.html              Druckzentrale (Web-UI unter /admin)
│   ├── label_templates/*.json  Etikettendefinitionen = Shop-Sortiment
│   └── Dockerfile              installiert auch fonts-dejavu-core!
└── agent/
    ├── agent.py                Poller: Job holen -> an 9100 senden -> done
    └── Dockerfile

Deployment

Stack aus docker-compose.yml (auch via Portainer):

  1. ADMIN_TOKEN durch langen Zufallswert ersetzen (openssl rand -hex 24).
  2. PRINTER_HOST = LAN-IP des Godex. Dem Drucker am besten eine feste IP bzw. DHCP-Reservierung geben, sonst wandert er irgendwann.
  3. Stack starten -> lauscht auf Port 8080. Reverse Proxy mit HTTPS davor (Plesk/nginx), z.B. labels.deine-domain.de -> 127.0.0.1:8080.
  4. Druckzentrale: https://labels.deine-domain.de/admin. Zeigt oben live, ob der Godex erreichbar ist (gruener/roter Punkt).

Docker-Hinweis: Der Container erreicht die Drucker-IP aus dem normalen Bridge-Netz heraus (ausgehendes NAT ueber den Host) -- kein network_mode: host und keine Sonderkonfiguration noetig.

Ablauf einer Bestellung

  1. Kunde (spaeter: Shop-Frontend) -> POST /api/orders mit Template-ID, Feldtexten, optional Logo (Base64-PNG), Stueckzahl. Der Server rendert einmal zur Probe -- kaputte Bestellungen werden sofort abgelehnt.
  2. Abends: Druckzentrale /admin zeigt alles gruppiert nach Etikettentyp. Vorschau pruefen, richtige Rolle einlegen, "Rolle liegt ein -> alle drucken". Es wird nie ueber Typgrenzen hinweg gemischt gedruckt.
  3. Der Druck-Worker im Container schickt die EZPL-Jobs nacheinander an den Godex -> Bestellung steht auf printed. Druckzentrale kurz aktualisieren und zuschauen, wie die Liste leer wird.

Neues Etikett ins Sortiment

Eine JSON-Datei in server/label_templates/ ablegen (Vorlage: die vorhandene), Container neu starten. Feldtypen: text (mit Auto-Verkleinern bei zu langem Text), image (Logo-Box mit Dithering), line. Wichtig: dpi muss zum Drucker passen (203 oder 300).

Kalibrierung beim ersten echten Druck

  • Invertierter Ausdruck -> LABEL_INVERT: "1" im Server-Stack.
  • Zu blass/zu fett -> LABEL_DARKNESS (0-19).
  • Laenge/Gap verrutscht -> gap_mm im Template + Gap-Kalibrierung am Drucker.

Shop-Frontend

Unter / liegt der Kundenshop (server/shop.html): Sortiment aus den Template-JSONs, Editor mit Live-Vorschau (debounced ueber POST /api/preview), Logo-Upload (wird clientseitig auf max. 1000px verkleinert), Stueckzahl mit Preisanzeige (price_cents im Template), Bestellabschluss. Die Vorschau ist das identische Bitmap, das spaeter gedruckt wird.

Was bewusst noch fehlt (naechste Ausbaustufen)

  • Stripe Checkout: Bestellung anlegen -> Checkout-Session -> Webhook setzt Status paid; Druckzentrale zeigt dann nur bezahlte Bestellungen.
  • Rate-Limiting auf den oeffentlichen Endpunkten, bevor der Shop live geht (Preview rendert Bilder, das soll niemand automatisiert hammern).
  • Job-Wiederholung/Storno in der Druckzentrale.