163 lines
4.7 KiB
PHP
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();
|
|
}
|
|
}
|