Files
2026-09-16 23:20:08 +07:00

163 lines
4.7 KiB
PHP

<?php
namespace App\Helpers;
/**
* Class EscPosPrinter
* Enterprise Thermal Printer ESC/POS Command Builder (Queue Tickets & Tax Invoices)
*
* @package App\Helpers
*/
class EscPosPrinter
{
private string $buffer = "";
private string $ip;
private int $port;
// ESC/POS Command Constants
const ESC = "\x1B";
const GS = "\x1D";
const LF = "\x0A";
public function __construct(string $ip = '192.168.1.200', int $port = 9100)
{
$this->ip = $ip;
$this->port = $port;
$this->init();
}
/**
* Initialize Printer
*/
public function init(): self
{
$this->buffer .= self::ESC . "@"; // Reset
return $this;
}
/**
* Set text alignment
* @param string $align 'left' | 'center' | 'right'
*/
public function setAlign(string $align): self
{
$val = 0;
if ($align === 'center') $val = 1;
if ($align === 'right') $val = 2;
$this->buffer .= self::ESC . "a" . chr($val);
return $this;
}
/**
* Set text size
* @param int $width 1-8
* @param int $height 1-8
*/
public function setSize(int $width = 1, int $height = 1): self
{
$w = ($width - 1) << 4;
$h = ($height - 1);
$this->buffer .= self::GS . "!" . chr($w | $h);
return $this;
}
/**
* Set font emphasis (Bold)
*/
public function setBold(bool $enabled = true): self
{
$this->buffer .= self::ESC . "E" . chr($enabled ? 1 : 0);
return $this;
}
/**
* Print text line with Line Feed
*/
public function text(string $text): self
{
// ในระบบ Thermal Printer ไทยมักใช้ TIS-620 หรือ CP874
// แปลง UTF-8 เป็น CP874
$converted = @iconv('UTF-8', 'CP874//IGNORE', $text);
$this->buffer .= ($converted !== false ? $converted : $text) . self::LF;
return $this;
}
/**
* Print Horizontal Line separator (80mm = 48 chars)
*/
public function line(): self
{
$this->text(str_repeat('-', 48));
return $this;
}
/**
* Feed paper and cut
*/
public function cut(): self
{
$this->buffer .= self::LF . self::LF . self::LF;
$this->buffer .= self::GS . "V" . chr(66) . chr(0); // Partial cut
return $this;
}
/**
* Get RAW buffer for WebUSB / Browser Print
*/
public function getBuffer(): string
{
return $this->buffer;
}
/**
* Get Base64 encoded buffer for JSON API transfer to POS Frontend
*/
public function getBase64Buffer(): string
{
return base64_encode($this->buffer);
}
/**
* Send command directly to Network LAN Printer via Socket
* @return bool
*/
public function sendToPrinter(): bool
{
$fp = @fsockopen($this->ip, $this->port, $errno, $errstr, 2.0);
if (!$fp) {
error_log("ESC/POS Printer Connect Failed ({$this->ip}:{$this->port}) - {$errstr} ({$errno})");
return false;
}
fwrite($fp, $this->buffer);
fclose($fp);
return true;
}
/**
* Build Queue Ticket Buffer (ใบคิวสำหรับผู้ป่วย)
*/
public static function buildQueueTicket(array $queueData): string
{
$printer = new self();
$printer->setAlign('center')
->setSize(2, 2)->setBold(true)->text("ใบคิวนวดแผนไทย")
->setSize(1, 1)->setBold(false)->text($queueData['branch_name'] ?? "TTMQMS Center")
->line()
->setSize(3, 3)->setBold(true)->text($queueData['queue_no'])
->setSize(1, 1)->setBold(false)->text("ประเภทคิว: " . ($queueData['priority'] ?? 'Normal'))
->line()
->setAlign('left')
->text("ผู้รับบริการ: " . ($queueData['patient_name'] ?? '-'))
->text("บริการ: " . ($queueData['service_name'] ?? '-'))
->text("หมอนวด: " . ($queueData['therapist_name'] ?? 'รอจัดสรร (AI Queue)'))
->text("ห้องนวด: " . ($queueData['room_no'] ?? '-'))
->line()
->setAlign('center')
->text("เวลาออกคิว: " . ($queueData['checkin_time'] ?? date('Y-m-d H:i:s')))
->text("โปรดรอเรียกคิวที่หน้าจอ TV Display")
->text("*** ขอบพระคุณที่ใช้บริการ ***")
->cut();
return $printer->getBase64Buffer();
}
}