ESC/POS printen vanuit de browser: een handleiding voor ontwikkelaars

Het Browser Afdrukprobleem

Als je ooit hebt geprobeerd een bon af te drukken vanuit een web-app, ken je de pijn: window.print() opent een afdrukvenster, rendert de pagina als een PDF en heeft geen ondersteuning voor ESC/POS-commando's zoals automatisch snijden of een aangepaste papierbreedte.

Voor thermische bonprinters is dit een dealbreaker. Je hebt nodig:

  • Stil afdrukken — geen dialoogvenster, geen gebruikersinteractie
  • ESC/POS-commando's — voor automatisch snijden, vetgedrukte tekst, uitlijning, barcodes
  • Betrouwbare codering — UTF-8 naar de juiste codepagina voor je printer
  • Cross-platform ondersteuning — Mac, Windows, Linux

De oplossing is een lokale WebSocket-brug — een kleine achtergrond-app die op de computer van de gebruiker draait, afdruktaken van je web-app accepteert en ruwe ESC/POS-commando's naar de printer stuurt.


Hoe de WebSocket-brug werkt

Your Web App  →  WebSocket (ws://localhost:8765)  →  Print Agent  →  Thermal Printer

De stroom is eenvoudig:

  1. Je web-app opent een WebSocket-verbinding met ws://localhost:8765
  2. Je stuurt een JSON-payload met de beschrijving van de bon
  3. Print Agent converteert deze naar ESC/POS en stuurt deze naar de printer
  4. De printer drukt stil af — geen dialoogvenster, geen driverinteractie

MenuForma Print Agent implementeert deze brug. Het is gratis, open-source en draait op Mac, Windows en Linux.


API Referentie

Verbinding

const ws = new WebSocket('ws://localhost:8765');

ws.onopen = () => {
  console.log('Print Agent verbonden');
};

ws.onerror = () => {
  console.log('Print Agent draait niet');
};

Agentstatus controleren

Stuur een ping om te controleren of de agent draait:

ws.send(JSON.stringify({ type: 'ping' }));

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  if (data.type === 'pong') {
    console.log('Agentversie:', data.version);
  }
};

Een bon afdrukken

const receipt = {
  type: 'print',
  printer: 'auto',   // of specifiek IP zoals '192.168.1.100'
  data: {
    storeName: 'My Restaurant',
    storeAddress: '123 Main St',
    orderNumber: '#1042',
    tableNumber: 'Table 5',
    items: [
      { name: 'Margherita Pizza', qty: 1, price: 14.90 },
      { name: 'Sparkling Water', qty: 2, price: 3.50 },
    ],
    subtotal: 21.90,
    tax: 1.97,
    total: 23.87,
    paymentMethod: 'Card',
    footer: 'Bedankt voor het dineren bij ons!',
  }
};

ws.send(JSON.stringify(receipt));

React Integratie Voorbeeld

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); // opnieuw proberen
      };
      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-integratie

Voor Shopify-winkels kunt u het afdrukken activeren via een Order-webhook of via een browserextensie:

```javascript
// In uw Shopify storefront of admin-extensie
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,
      }
    }));
  };
}

Printerconfiguratie

Het veld "printer" in de print-payload accepteert:

Waarde Beschrijving
"auto" Gebruik de printer geconfigureerd in de Print Agent-instellingen
"192.168.1.100" Maak rechtstreeks verbinding met een netwerkprinter via IP
"USB" Gebruik de eerst gedetecteerde USB-printer

Foutafhandeling

ws.onmessage = (event) => {
  const response = JSON.parse(event.data);
  
  if (response.type === 'print_success') {
    console.log('Succesvol afgedrukt');
  } else if (response.type === 'print_error') {
    console.error('Afdrukken mislukt:', response.error);
    // Toon fallback UI of probeer opnieuw
  }
};

Detecteren of Print Agent is geïnstalleerd

Voordat u de printfunctie in uw gebruikersinterface toont, controleert u of de agent actief is:

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);
    };
  });
}

// Gebruik
const agentAvailable = await isPrintAgentAvailable();
if (!agentAvailable) {
  // Toon downloadprompt
  window.open('/print-agent', '_blank');
}

Print Agent downloaden

MenuForma Print Agent is gratis en beschikbaar voor Mac, Windows en Linux. Het ondersteunt USB-, netwerk- en Bluetooth-thermische printers en implementeert de volledige WebSocket API die in deze handleiding wordt beschreven.

Voor volledige API-documentatie en de open-source code, bezoek de Print Agent-pagina.

Related Articles

MenuForma Products