Pencetakan ESC/POS dari Peramban: Panduan Pengembang

Masalah Pencetakan Peramban

Jika Anda pernah mencoba mencetak struk dari aplikasi web, Anda tahu kesulitannya: window.print() membuka dialog cetak, merender halaman sebagai PDF, dan sama sekali tidak mendukung perintah ESC/POS seperti potong otomatis atau lebar kertas kustom.

Untuk printer struk termal, ini adalah masalah besar. Anda membutuhkan:

  • Pencetakan senyap — tanpa dialog, tanpa interaksi pengguna
  • Perintah ESC/POS — untuk potong otomatis, teks tebal, perataan, kode batang
  • Pengodean yang andal — UTF-8 ke halaman kode yang benar untuk printer Anda
  • Dukungan lintas platform — Mac, Windows, Linux

Solusinya adalah jembatan WebSocket lokal — aplikasi latar belakang kecil yang berjalan di komputer pengguna, menerima tugas cetak dari aplikasi web Anda, dan mengirim perintah ESC/POS mentah ke printer.


Cara Kerja Jembatan WebSocket

Aplikasi Web Anda  →  WebSocket (ws://localhost:8765)  →  Print Agent  →  Printer Termal

Alurnya sederhana:

  1. Aplikasi web Anda membuka koneksi WebSocket ke ws://localhost:8765
  2. Anda mengirim payload JSON yang menjelaskan struk
  3. Print Agent mengubahnya menjadi ESC/POS dan mengirimkannya ke printer
  4. Printer mencetak secara senyap — tanpa dialog, tanpa interaksi driver

MenuForma Print Agent mengimplementasikan jembatan ini. Ini gratis, sumber terbuka, dan berjalan di Mac, Windows, dan Linux.


Referensi API

Koneksi

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

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

ws.onerror = () => {
  console.log('Print Agent tidak berjalan');
};

Periksa Status Agen

Kirim ping untuk memverifikasi agen sedang berjalan:

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

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

Mencetak Struk

const receipt = {
  type: 'print',
  printer: 'auto',   // atau IP spesifik seperti '192.168.1.100'
  data: {
    storeName: 'Restoran Saya',
    storeAddress: 'Jl. Utama 123',
    orderNumber: '#1042',
    tableNumber: 'Meja 5',
    items: [
      { name: 'Pizza Margherita', qty: 1, price: 14.90 },
      { name: 'Air Mineral Berkarbonasi', qty: 2, price: 3.50 }
    ],
    subtotal: 21.90,
    tax: 1.97,
    total: 23.87,
    paymentMethod: 'Kartu',
    footer: 'Terima kasih telah bersantap bersama kami!'
  }
};

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

Contoh Integrasi React

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); // coba lagi
      };
      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 tidak terhubung');
    }
    wsRef.current.send(JSON.stringify({ type: 'print', data: receiptData }));
  }, []);

  return { connected, print };
}

Integrasi Shopify

Untuk toko Shopify, Anda dapat memicu pencetakan dari webhook Pesanan atau dari ekstensi peramban:

// Di etalase Shopify atau ekstensi admin Anda
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
      }
    }));
  };
}

Konfigurasi Printer

Bidang "printer" dalam payload cetak menerima:

Nilai Deskripsi
"auto" Gunakan printer yang dikonfigurasi dalam pengaturan Print Agent
"192.168.1.100" Sambungkan langsung ke printer jaringan berdasarkan IP
"USB" Gunakan printer USB pertama yang terdeteksi

Penanganan Kesalahan

ws.onmessage = (event) => {
  const response = JSON.parse(event.data);
  
  if (response.type === 'print_success') {
    console.log('Berhasil dicetak');
  } else if (response.type === 'print_error') {
    console.error('Pencetakan gagal:', response.error);
    // Tampilkan UI cadangan atau coba lagi
  }
};

Mendeteksi Apakah Print Agent Terinstal

Sebelum menampilkan fungsionalitas cetak di UI Anda, periksa apakah agen sedang berjalan:

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

// Penggunaan
const agentAvailable = await isPrintAgentAvailable();
if (!agentAvailable) {
  // Tampilkan permintaan unduh
  window.open('/print-agent', '_blank');
}

Unduh Print Agent

MenuForma Print Agent gratis dan tersedia untuk Mac, Windows, dan Linux. Ini mendukung printer termal USB, jaringan, dan Bluetooth, serta mengimplementasikan API WebSocket lengkap yang dijelaskan dalam panduan ini.

Untuk dokumentasi API lengkap dan kode sumber terbuka, kunjungi halaman Print Agent.

Related Articles

MenuForma Products