Das Browser-Druckproblem
Wenn Sie jemals versucht haben, einen Beleg aus einer Web-App zu drucken, kennen Sie den Schmerz: window.print() öffnet einen Druckdialog, rendert die Seite als PDF und bietet keinerlei Unterstützung für ESC/POS-Befehle wie automatischen Schnitt oder benutzerdefinierte Papierbreite.
Für Thermo-Belegdrucker ist dies ein entscheidender Nachteil. Sie benötigen:
- Lautloses Drucken – kein Dialog, keine Benutzerinteraktion
- ESC/POS-Befehle – für automatischen Schnitt, Fettdruck, Ausrichtung, Barcodes
- Zuverlässige Kodierung – UTF-8 zur richtigen Codepage für Ihren Drucker
- Plattformübergreifende Unterstützung – Mac, Windows, Linux
Die Lösung ist eine lokale WebSocket-Brücke – eine kleine Hintergrund-App, die auf dem Computer des Benutzers läuft, Druckaufträge von Ihrer Web-App entgegennimmt und rohe ESC/POS-Befehle an den Drucker sendet.
Wie die WebSocket-Brücke funktioniert
Ihre Web-App → WebSocket (ws://localhost:8765) → Print Agent → Thermodrucker
Der Ablauf ist einfach:
- Ihre Web-App öffnet eine WebSocket-Verbindung zu ws://localhost:8765
- Sie senden eine JSON-Nutzlast, die den Beleg beschreibt
- Der Print Agent konvertiert sie in ESC/POS und sendet sie an den Drucker
- Der Drucker druckt lautlos – kein Dialog, keine Treiberinteraktion
MenuForma Print Agent implementiert diese Brücke. Er ist kostenlos, Open Source und läuft auf Mac, Windows und Linux.
API-Referenz
Verbindung
const ws = new WebSocket('ws://localhost:8765');
ws.onopen = () => {
console.log('Print Agent verbunden');
};
ws.onerror = () => {
console.log('Print Agent läuft nicht');
};
Agent-Status prüfen
Senden Sie einen Ping, um zu überprüfen, ob der Agent läuft:
ws.send(JSON.stringify({ type: 'ping' }));
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'pong') {
console.log('Agent-Version:', data.version);
}
};
Beleg drucken
const receipt = {
type: 'print',
printer: 'auto', // oder spezifische IP wie '192.168.1.100'
data: {
storeName: 'Mein Restaurant',
storeAddress: 'Hauptstraße 123',
orderNumber: '#1042',
tableNumber: 'Tisch 5',
items: [
{ name: 'Margherita Pizza', qty: 1, price: 14.90 },
{ name: 'Sprudelwasser', qty: 2, price: 3.50 },
],
subtotal: 21.90,
tax: 1.97,
total: 23.87,
paymentMethod: 'Karte',
footer: 'Vielen Dank für Ihren Besuch!',
}
};
ws.send(JSON.stringify(receipt));
React-Integrationsbeispiel
import { useEffect, useRef, useCallback, useState } from 'react';
function usePrintAgent() {
const wsRef = useRef(null);
const [connected, setConnected] = useState(false);
useEffect(() => {
const connect = () => {
const ws = new WebSocket('ws://localhost:8765');
ws.onopen = () => setConnected(true);
ws.onclose = () => {
setConnected(false);
setTimeout(connect, 3000); // erneut versuchen
};
wsRef.current = ws;
};
connect();
return () => wsRef.current?.close();
}, []);
const print = useCallback((receiptData) => { if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) { throw new Error('Print Agent not connected'); } wsRef.current.send(JSON.stringify({ type: 'print', data: receiptData })); }, []);
return { connected, print }; }
---
## Shopify-Integration
Für Shopify-Shops können Sie den Druck über einen Bestell-Webhook oder über eine Browser-Erweiterung auslösen:
```javascript
// In Ihrer Shopify-Storefront oder Admin-Erweiterung
async function printShopifyOrder(order) {
const ws = new WebSocket('ws://localhost:8765');
ws.onopen = () => {
ws.send(JSON.stringify({
type: 'print',
data: {
storeName: order.shop_name,
orderNumber: order.name,
items: order.line_items.map(item => ({
name: item.title,
qty: item.quantity,
price: parseFloat(item.price),
})),
total: parseFloat(order.total_price),
paymentMethod: order.payment_gateway,
}
}));
};
}
Drucker-Konfiguration
Das Feld "printer" in der Druck-Payload akzeptiert:
| Wert | Beschreibung |
|---|---|
| "auto" | Verwenden Sie den in den Print Agent-Einstellungen konfigurierten Drucker |
| "192.168.1.100" | Direktverbindung zu einem Netzwerkdrucker über IP |
| "USB" | Verwenden Sie den ersten erkannten USB-Drucker |
Fehlerbehandlung
ws.onmessage = (event) => {
const response = JSON.parse(event.data);
if (response.type === 'print_success') {
console.log('Erfolgreich gedruckt');
} else if (response.type === 'print_error') {
console.error('Druck fehlgeschlagen:', response.error);
// Fallback-UI anzeigen oder erneut versuchen
}
};
Erkennen, ob Print Agent installiert ist
Bevor Sie die Druckfunktion in Ihrer Benutzeroberfläche anzeigen, prüfen Sie, ob der Agent ausgeführt wird:
async function isPrintAgentAvailable() {
return new Promise((resolve) => {
const ws = new WebSocket('ws://localhost:8765');
const timeout = setTimeout(() => {
ws.close();
resolve(false);
}, 1000);
ws.onopen = () => {
clearTimeout(timeout);
ws.close();
resolve(true);
};
ws.onerror = () => {
clearTimeout(timeout);
resolve(false);
};
});
}
// Verwendung
const agentAvailable = await isPrintAgentAvailable();
if (!agentAvailable) {
// Download-Aufforderung anzeigen
window.open('/print-agent', '_blank');
}
Print Agent herunterladen
MenuForma Print Agent ist kostenlos und für Mac, Windows und Linux verfügbar. Es unterstützt USB-, Netzwerk- und Bluetooth-Thermodrucker und implementiert die vollständige WebSocket-API, die in diesem Leitfaden beschrieben wird.
Für die vollständige API-Dokumentation und den Open-Source-Code besuchen Sie die Print Agent Seite.
Related Articles
- Personalnot in der Gastronomie: Wenn der Wirt Doppelschichten schiebt
- Ladekreis des Todes: Warum Gäste von schlechten QR-Speisekarten genervt sind
- KI und Automatisierung: Die Rettung für Deutschlands Gastronomie?