├── .gitignore ├── src └── Epson │ ├── Devices │ ├── Device.php │ ├── Network.php │ ├── FileSystem.php │ └── Serial.php │ ├── EscPos.php │ └── Printer.php ├── composer.json ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Project directories and files 2 | vendor/* 3 | 4 | # IDE 5 | .idea 6 | .nbproject 7 | 8 | # OS 9 | .DS_Store 10 | Thumbs.db 11 | 12 | -------------------------------------------------------------------------------- /src/Epson/Devices/Device.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | */ 13 | 14 | namespace Epson\Devices; 15 | 16 | use Epson\EscPos; 17 | 18 | abstract class Device 19 | { 20 | abstract public function close(); 21 | abstract public function write($data); 22 | 23 | public function initialize() 24 | { 25 | $this->write(EscPos::CTL_ESC . "@"); 26 | } 27 | 28 | public function __destruct() 29 | { 30 | $this->close(); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Epson/Devices/Network.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | */ 13 | 14 | namespace Epson\Devices; 15 | 16 | class Network extends FileSystem 17 | { 18 | public function __construct($host, $port = 9100, $timeout = 30) 19 | { 20 | $this->resource = fsockopen($host, $port, $errorNo, $errString, $timeout); 21 | 22 | if (!$this->resource) { 23 | throw new \Exception($errString, $errorNo); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/Epson/Devices/FileSystem.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | */ 13 | 14 | namespace Epson\Devices; 15 | 16 | class FileSystem extends Device 17 | { 18 | protected $resource; 19 | 20 | public function __construct($path = "php://stdout") 21 | { 22 | if(empty($path) || !is_writable($path)) { 23 | throw new \Exception('Resource is not writable', 0); 24 | } 25 | 26 | $this->resource = fopen($path, "wb"); 27 | } 28 | 29 | function close() 30 | { 31 | fclose($this->resource); 32 | } 33 | 34 | function write($data) 35 | { 36 | fwrite($this->resource, $data); 37 | } 38 | } -------------------------------------------------------------------------------- /src/Epson/Devices/Serial.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | */ 13 | 14 | namespace Epson\Devices; 15 | 16 | class Serial extends Device 17 | { 18 | protected $resource; 19 | 20 | public function __construct($devfile = "/dev/ttyS0", $baudRate = 9600, $byteSize = 8, $parity = 'none') 21 | { 22 | $this->resource = new \PhpSerial(); 23 | 24 | $this->resource->confBaudRate($baudRate); 25 | $this->resource->confCharacterLength($byteSize); 26 | $this->resource->confParity($parity); 27 | $this->resource->deviceOpen(); 28 | } 29 | 30 | function close() 31 | { 32 | $this->resource->deviceClose(); 33 | } 34 | 35 | function write($data) 36 | { 37 | $this->resource->sendMessage($data); 38 | } 39 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xiidea/php-esc-pos", 3 | "type": "library", 4 | "homepage": "https://github.com/xiidea/php-esc-pos/", 5 | "description": "EPSON ESC/POS printer command generator library", 6 | "keywords": ["ESC-POS", "Thermal printer", "TM-T70", "Epson"], 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Roni Saha", 11 | "email": "roni.cse@gmail.com" 12 | } 13 | ], 14 | "minimum-stability": "dev", 15 | "require": { 16 | "php": ">=5.3.0" 17 | }, 18 | "suggest": { 19 | "hyperthese/php-serial": "Allows Communicate with devices connected over Serial port", 20 | "intervention/image": "Require when you want to print image", 21 | "endroid/qrcode": "Require when you want to print QRCode" 22 | }, 23 | "autoload": { 24 | "psr-0": { 25 | "Epson\\": ["src"] 26 | } 27 | }, 28 | "branch-alias": { 29 | "dev-master": "1.0.x-dev" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Michael Billington , 4 | with additions and modifications by Xiidea 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ESC/POS command SDK in PHP 2 | ========================== 3 | 4 | This library implements a subset of Epson's ESC/POS protocol for thermal receipt printers. It allows you to print receipts with basic formatting, cutting, and barcode printing on a compatible printer. 5 | 6 | It is intended for **Epson TM-T70** model, But other printers, produced by Epson or other vendors use the same standard, may also work. 7 | 8 | Basic usage 9 | ----------- 10 | 11 | ```php 12 | text("Hello World!\n"); 16 | $printer -> cut(); 17 | 18 | ``` 19 | 20 | Attribution 21 | ----------- 22 | This library is a modified version of escpos-php, a Library to work with ESC/POS thermal printers, implemented by Michael Billington. Further documentation is available at [https://github.com/mike42/escpos-php](https://github.com/mike42/escpos-php). 23 | 24 | Reference 25 | ========== 26 | 27 | * [FAQ about ESC/POS® from Epson](http://content.epson.de/fileadmin/content/files/RSD/downloads/escpos.pdf) 28 | * [TM-T70 supported commands](https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=80) 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/Epson/EscPos.php: -------------------------------------------------------------------------------- 1 | , 9 | * modifications by Roni Saha 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | namespace Epson; 30 | 31 | class EscPos 32 | { 33 | /* Feed Control */ 34 | const NUL = "\x00"; 35 | const CTL_ESC = "\x1b"; 36 | const CTL_LF = "\x0a"; # Print and line feed 37 | const CTL_GS = "\x1d"; 38 | const CTL_FF = "\x0c"; # Form feed 39 | const CTL_CR = "\x0d"; # Carriage return 40 | const CTL_HT = "\x09"; # Horizontal tab 41 | const CTL_VT = "\x0b"; # Vertical tab 42 | 43 | /* Print mode constants */ 44 | const MODE_FONT_A = 0; 45 | const MODE_FONT_B = 1; 46 | const MODE_EMPHASIZED = 8; 47 | const MODE_DOUBLE_HEIGHT = 16; 48 | const MODE_DOUBLE_WIDTH = 32; 49 | const MODE_UNDERLINE = 128; 50 | 51 | /* Fonts */ 52 | const FONT_A = 0; 53 | const FONT_B = 1; 54 | const FONT_C = 2; 55 | 56 | /* Justifications */ 57 | const JUSTIFY_LEFT = 0; 58 | const JUSTIFY_CENTER = 1; 59 | const JUSTIFY_RIGHT = 2; 60 | 61 | /* Paper Cut types */ 62 | const PAPER_CUT_FULL = 65; 63 | const PAPER_CUT_PARTIAL = 66; 64 | 65 | /* Barcode types */ 66 | const BARCODE_UPCA = 0; 67 | const BARCODE_UPCE = 1; 68 | const BARCODE_JAN13 = 2; 69 | const BARCODE_JAN8 = 3; 70 | const BARCODE_CODE39 = 4; 71 | const BARCODE_ITF = 5; 72 | const BARCODE_NW7 = 6; 73 | 74 | # Barcode format 75 | const BARCODE_TXT_OFF = 0; # HRI barcode chars OFF 76 | const BARCODE_TXT_ABOVE = 1; # HRI barcode chars above 77 | const BARCODE_TXT_BELOW = 2; # HRI barcode chars below 78 | const BARCODE_TXT_BOTH = 3; # HRI barcode chars both above and below 79 | const BARCODE_FONT_A = 0; # Font type A for HRI barcode chars 80 | const BARCODE_FONT_B = 1; # Font type B for HRI barcode chars 81 | const BARCODE_HEIGHT = 104; # Barcode Height [1-255] 82 | const BARCODE_WIDTH = 3; # Barcode Width [2-6] 83 | } 84 | -------------------------------------------------------------------------------- /src/Epson/Printer.php: -------------------------------------------------------------------------------- 1 | , 10 | * modifications by Roni Saha 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in all 20 | * copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ 30 | namespace Epson; 31 | 32 | use Epson\Devices\Device; 33 | use Epson\Devices\FileSystem; 34 | 35 | class Printer 36 | { 37 | /** 38 | * @var Device 39 | */ 40 | protected $device; 41 | 42 | public function __construct(Device $device = null) 43 | { 44 | $this->device = ($device == null) ? new FileSystem() : $device; 45 | 46 | $this->device->initialize(); 47 | } 48 | 49 | /** 50 | * Add text to the buffer 51 | * 52 | * @param string $str Text to print 53 | * 54 | * @return $this 55 | */ 56 | public function text($str = "") 57 | { 58 | return $this->send($str); 59 | } 60 | 61 | /** 62 | * Print and feed line / Print and feed n lines 63 | * 64 | * @param int $lines Number of lines to feed 65 | * 66 | * @return $this 67 | */ 68 | public function feed($lines = 1) 69 | { 70 | if ($lines <= 1) { 71 | $this->device->write(EscPos::CTL_LF); 72 | } else { 73 | $this->device->write(EscPos::CTL_ESC . "d" . chr($lines)); 74 | } 75 | 76 | return $this; 77 | } 78 | 79 | /** 80 | * Select print mode(s). 81 | * 82 | * Arguments should be OR'd together MODE_* constants: 83 | * MODE_FONT_A 84 | * MODE_FONT_B 85 | * MODE_EMPHASIZED 86 | * MODE_DOUBLE_HEIGHT 87 | * MODE_DOUBLE_WIDTH 88 | * MODE_UNDERLINE 89 | * 90 | * @param int|string $mode 91 | * 92 | * @return $this 93 | */ 94 | public function setPrintMode($mode = EscPos::NUL) 95 | { 96 | return $this->send(EscPos::CTL_ESC . "!" . chr($mode)); 97 | } 98 | 99 | /** 100 | * Turn underline mode on/off 101 | * 102 | * @param int $underline 0 for no underline, 1 for underline, 2 for heavy underline 103 | * 104 | * @return $this 105 | */ 106 | public function setUnderline($underline = 1) 107 | { 108 | return $this->send(EscPos::CTL_ESC . "-" . chr($underline)); 109 | } 110 | 111 | /** 112 | * Turn emphasized mode on/off 113 | * 114 | * @param boolean $on true for emphasis, false for no emphasis 115 | * 116 | * @return $this 117 | */ 118 | public function setEmphasis($on = true) 119 | { 120 | return $this->send(EscPos::CTL_ESC . "E" . ($on ? chr(1) : chr(0))); 121 | } 122 | 123 | /** 124 | * Turn double size 125 | * 126 | * @param boolean $on true for double size, false for normal 127 | * 128 | * @return $this 129 | */ 130 | public function setDoubleSize($on = true) 131 | { 132 | 133 | $size = $on ? chr(EscPos::MODE_DOUBLE_HEIGHT + EscPos::MODE_DOUBLE_WIDTH) : chr(0); 134 | 135 | return $this->send(EscPos::CTL_ESC . chr(33) . $size); 136 | } 137 | 138 | /** 139 | * Turn double-strike mode on/off 140 | * 141 | * @param boolean $on true for double strike, false for no double strike 142 | * 143 | * @return $this 144 | */ 145 | public function setDoubleStrike($on) 146 | { 147 | return $this->send(EscPos::CTL_ESC . "G" . ($on ? chr(1) : chr(0))); 148 | } 149 | 150 | /** 151 | * Select character font. 152 | * Font must be FONT_A, FONT_B, or FONT_C. 153 | * 154 | * @param int $font 155 | * 156 | * @return $this 157 | */ 158 | public function setFont($font) 159 | { 160 | return $this->send(EscPos::CTL_ESC . "M" . chr($font)); 161 | } 162 | 163 | /** 164 | * Select justification 165 | * Justification must be JUSTIFY_LEFT, JUSTIFY_CENTER, or JUSTIFY_RIGHT. 166 | */ 167 | public function setJustification($justification) 168 | { 169 | return $this->send(EscPos::CTL_ESC . "a" . chr($justification)); 170 | } 171 | 172 | /** 173 | * Print and reverse feed n lines 174 | * 175 | * @param int $lines number of lines to feed 176 | * 177 | * @return $this 178 | */ 179 | public function feedReverse($lines = 1) 180 | { 181 | return $this->send(EscPos::CTL_ESC . "e" . chr($lines)); 182 | } 183 | 184 | /** 185 | * Cut the paper 186 | * 187 | * @param int $mode Cut mode, either CUT_FULL or CUT_PARTIAL 188 | * @param int $lines Number of lines to feed 189 | * 190 | * @return $this 191 | */ 192 | public function cut($mode = EscPos::PAPER_CUT_FULL, $lines = 3) 193 | { 194 | return $this->send(EscPos::CTL_GS . "V" . chr($mode) . chr($lines)); 195 | } 196 | 197 | /** 198 | * Set barcode height 199 | * 200 | * @param int $height Height in dots [1-255] 201 | * 202 | * @return $this 203 | */ 204 | public function setBarcodeHeight($height = 162) 205 | { 206 | return $this->send(EscPos::CTL_GS . "h" . chr($height)); 207 | } 208 | 209 | 210 | /** 211 | * Set barcode width 212 | * 213 | * @param int $width Widht [1-4] 214 | * 215 | * @return $this 216 | */ 217 | public function setBarcodeWidth($width = 3) 218 | { 219 | return $this->send(EscPos::CTL_GS . 'w' . chr($width)); 220 | } 221 | 222 | /** 223 | * St barcode text position 224 | * 225 | * @param int $mode 226 | * 227 | * @return $this 228 | */ 229 | public function setBarcodeTextPosition($mode = EscPos::BARCODE_TXT_BELOW) 230 | { 231 | return $this->send(EscPos::CTL_GS . 'H' . chr($mode)); 232 | } 233 | 234 | /** 235 | * Set barcode font 236 | * 237 | * @param int $font 238 | * 239 | * @return $this 240 | */ 241 | public function setBarcodeFont($font = EscPos::BARCODE_FONT_A) 242 | { 243 | return $this->send(EscPos::CTL_GS . 'f' . chr($font)); 244 | } 245 | 246 | /** 247 | * Print a barcode 248 | * 249 | * @param string $content 250 | * @param int $type 251 | * 252 | * @return $this 253 | */ 254 | public function barcode($content, $type = EscPos::BARCODE_CODE39) 255 | { 256 | return $this->send(EscPos::CTL_GS . "k" . chr($type) . $content . EscPos::NUL); 257 | } 258 | 259 | public function image($resource, $width = null, $height = null) 260 | { 261 | throw new \Exception('Not implemented'); 262 | 263 | $img = \Intervention\Image\ImageManagerStatic::make($resource); 264 | 265 | if ($width != null && $height != null) { 266 | $img->fit($width, $height); 267 | } elseif ($width != null || $height != null) { 268 | $img->resize($width, $height, function ($constraint) { 269 | 270 | $constraint->aspectRatio(); 271 | $constraint->upsize(); 272 | }); 273 | } 274 | 275 | $w = $img->width(); 276 | $h = $img->height(); 277 | 278 | 279 | $this->send(EscPos::CTL_GS); 280 | $this->send('v'); 281 | $this->send(chr(48)); 282 | $this->send(chr(0)); 283 | $this->send(4); 284 | $this->send(chr(0)); 285 | $this->send(chr($height)); 286 | $im = $img->getCore(); 287 | $this->send($this->getImageRawData($im)); 288 | 289 | 290 | } 291 | 292 | protected function getImageRawData($im) 293 | { 294 | 295 | $data = ""; 296 | 297 | $w = imagesx($im); // image width 298 | $h = imagesy($im); // image height 299 | for($x = 0; $x < $h; $x++) { 300 | for($y = 0; $y < $w; $y++) { 301 | $rgb = imagecolorat($im, $y, $x); 302 | $r = ($rgb >> 16) & 0xFF; 303 | $g = ($rgb >> 8) & 0xFF; 304 | $b = $rgb & 0xFF; 305 | $gray = (int)(($r + $g + $b) / 3); 306 | 307 | $data .= chr($gray); 308 | } 309 | } 310 | 311 | 312 | return $data; 313 | } 314 | 315 | protected function send($data) 316 | { 317 | $this->device->write($data); 318 | 319 | return $this; 320 | } 321 | } 322 | --------------------------------------------------------------------------------