PageRenderTime 70ms CodeModel.GetById 38ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/includes/mike42/escpos-php/README.md

http://github.com/Dolibarr/dolibarr
Markdown | 589 lines | 432 code | 157 blank | 0 comment | 0 complexity | 094a1dc5f964016c5391c0765ece2e76 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-3.0, LGPL-2.0, CC-BY-SA-4.0, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, LGPL-2.1, MIT
  1. # ESC/POS Print Driver for PHP
  2. [![Build Status](https://travis-ci.org/mike42/escpos-php.svg?branch=master)](https://travis-ci.org/mike42/escpos-php) [![Latest Stable Version](https://poser.pugx.org/mike42/escpos-php/v/stable)](https://packagist.org/packages/mike42/escpos-php)
  3. [![Total Downloads](https://poser.pugx.org/mike42/escpos-php/downloads)](https://packagist.org/packages/mike42/escpos-php)
  4. [![License](https://poser.pugx.org/mike42/escpos-php/license)](https://packagist.org/packages/mike42/escpos-php)
  5. [![Coverage Status](https://coveralls.io/repos/github/mike42/escpos-php/badge.svg?branch=development)](https://coveralls.io/github/mike42/escpos-php?branch=development)
  6. This project implements a subset of Epson's ESC/POS protocol for thermal receipt printers. It allows you to generate and print receipts with basic formatting, cutting, and barcodes on a compatible printer.
  7. The library was developed to add drop-in support for receipt printing to any PHP app, including web-based point-of-sale (POS) applications.
  8. ## Compatibility
  9. ### Interfaces and operating systems
  10. This driver is known to work with the following OS/interface combinations:
  11. <table>
  12. <tr>
  13. <th>&nbsp;</th>
  14. <th>Linux</th>
  15. <th>Mac</th>
  16. <th>Windows</th>
  17. </tr>
  18. <tr>
  19. <th>Ethernet</th>
  20. <td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/ethernet.php">Yes</a></td>
  21. <td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/ethernet.php">Yes</a></td>
  22. <td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/ethernet.php">Yes</a></td>
  23. </tr>
  24. <tr>
  25. <th>USB</th>
  26. <td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/linux-usb.php">Yes</a></td>
  27. <td>Not tested</td>
  28. <td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/windows-usb.php">Yes</a></td>
  29. </tr>
  30. <tr>
  31. <th>USB-serial</th>
  32. <td>Yes</td>
  33. <td>Yes</td>
  34. <td>Yes</td>
  35. </tr>
  36. <tr>
  37. <th>Serial</th>
  38. <td>Yes</td>
  39. <td>Yes</td>
  40. <td>Yes</td>
  41. </tr>
  42. <tr>
  43. <th>Parallel</th>
  44. <td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/windows-lpt.php">Yes</a></td>
  45. <td>Not tested</td>
  46. <td>Yes</td>
  47. </tr>
  48. <tr>
  49. <th>SMB shared</th>
  50. <td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/smb.php">Yes</a></td>
  51. <td>No</td>
  52. <td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/smb.php">Yes</a></td>
  53. </tr>
  54. <tr>
  55. <th>CUPS hosted</th>
  56. <td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/cups.php">Yes</a></td>
  57. <td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/cups.php">Yes</a></td>
  58. <td>No</td>
  59. </tr>
  60. </table>
  61. ### Printers
  62. Many thermal receipt printers support ESC/POS to some degree. This driver has been known to work with:
  63. - 3nStar RPT-008
  64. - Approx APPPOS80AM
  65. - AURES ODP-333
  66. - AURES ODP-500
  67. - Bematech-4200-TH
  68. - Bematech LR2000E
  69. - Birch PRP-085III
  70. - Bixolon SRP-350III
  71. - Bixolon SRP-350Plus
  72. - Black Copper BC-85AC
  73. - CHD TH-305N
  74. - Citizen CBM1000-II
  75. - Citizen CT-S310II
  76. - Dapper-Geyi Q583P
  77. - Daruma DR800
  78. - DR-MP200 (manufacturer unknown)
  79. - EPOS TEP 220M
  80. - Elgin i9
  81. - Epson EU-T332C
  82. - Epson FX-890 (requires `feedForm()` to release paper).
  83. - Epson TM-T20
  84. - Epson TM-T20II
  85. - Epson TM-T70
  86. - Epson TM-T70II
  87. - Epson TM-T81
  88. - Epson TM-T82II
  89. - Epson TM-T88II
  90. - Epson TM-T88III
  91. - Epson TM-T88IV
  92. - Epson TM-T88V
  93. - Epson TM-U220
  94. - Epson TM-U295 (requires `release()` to release slip).
  95. - Epson TM-U590 and TM-U590P
  96. - Equal (EQ-IT-001) POS-58
  97. - Everycom EC-58
  98. - Excelvan HOP-E200
  99. - Excelvan HOP-E58
  100. - Excelvan HOP-E801
  101. - Gainscha GP-2120TF
  102. - Gainscha GP-5890x (Also marketed as EC Line 5890x)
  103. - Gainscha GP-U80300I (Also marketed as gprinter GP-U80300I)
  104. - gprinter GP-U80160I
  105. - HOIN HOP-H58
  106. - Ithaca iTherm 28
  107. - Hasar HTP 250
  108. - Metapace T-1
  109. - Metapace T-25
  110. - Nexa PX700
  111. - Nyear NP100
  112. - OKI RT322
  113. - OKI 80 Plus III
  114. - Orient BTP-R580
  115. - P-822D
  116. - P85A-401 (make unknown)
  117. - Partner Tech RP320
  118. - POSLIGNE ODP200H-III-G
  119. - QPOS Q58M
  120. - Rongta RP326US
  121. - Rongta RP58-U
  122. - Rongta RP80USE
  123. - SAM4S GIANT-100DB
  124. - Senor TP-100
  125. - Sewoo SLK-TS400
  126. - SEYPOS PRP-96
  127. - SEYPOS PRP-300 (Also marketed as TYSSO PRP-300)
  128. - SNBC BTP-R880NPIII
  129. - Solux SX-TP-88300
  130. - Sicar POS-80
  131. - Silicon SP-201 / RP80USE
  132. - SPRT SP-POS88V
  133. - Star BSC10
  134. - Star TSP100 ECO
  135. - Star TSP100III FuturePRNT
  136. - Star TSP-650
  137. - Star TUP-592
  138. - TVS RP45 Shoppe
  139. - Venus V248T
  140. - Xeumior SM-8330
  141. - Xprinter F-900
  142. - Xprinter XP-365B
  143. - Xprinter XP-58 Series
  144. - Xprinter XP-80C
  145. - Xprinter XP-90
  146. - XPrinter XP-Q20011
  147. - Xprinter XP-Q800
  148. - Zjiang NT-58H
  149. - Zjiang ZJ-5870
  150. - Zjiang ZJ-5890 (Also sold as POS-5890 by many vendors; ZJ-5890K, ZJ-5890T also work).
  151. - Zjiang ZJ-8220 (Also marketed as Excelvan ZJ-8220)
  152. - Zjiang ZJ-8250
  153. If you use any other printer with this code, please [let us know](https://github.com/mike42/escpos-php/issues/new) so that it can be added to the list.
  154. ## Basic usage
  155. ### Include the library
  156. #### Composer
  157. If you are using composer, then add `mike42/escpos-php` as a dependency:
  158. ```bash
  159. composer require mike42/escpos-php
  160. ```
  161. In this case, you would include composer's auto-loader at the top of your source files:
  162. ```php
  163. <?php
  164. require __DIR__ . '/vendor/autoload.php';
  165. ```
  166. #### Manually
  167. If you don't have composer available, then simply download the code and include `autoload.php`:
  168. ```bash
  169. git clone https://github.com/mike42/escpos-php vendor/mike42/escpos-php
  170. ```
  171. ```php
  172. <?php
  173. require __DIR__ . '/vendor/mike42/escpos-php/autoload.php';
  174. ```
  175. #### Requirements
  176. To maintain compatibility with as many systems as possible, this driver has few
  177. hard dependencies:
  178. - PHP 5.4 or above.
  179. - `mbstring` extension, since the driver accepts UTF-8 encoding.
  180. It is also suggested that you install either `imagick` or `gd`, so that you can
  181. print images.
  182. A number of optional packages can be added to enable more specific features. These
  183. are described in the "suggest" section of [composer.json](https://github.com/mike42/escpos-php/tree/master/composer.json).
  184. ### The 'Hello World' receipt
  185. To make use of this driver, your server (where PHP is installed) must be able to communicate with your printer. Start by generating a simple receipt and sending it to your printer using the command-line.
  186. ```php
  187. <?php
  188. /* Call this file 'hello-world.php' */
  189. require __DIR__ . '/vendor/autoload.php';
  190. use Mike42\Escpos\PrintConnectors\FilePrintConnector;
  191. use Mike42\Escpos\Printer;
  192. $connector = new FilePrintConnector("php://stdout");
  193. $printer = new Printer($connector);
  194. $printer -> text("Hello World!\n");
  195. $printer -> cut();
  196. $printer -> close();
  197. ```
  198. Some examples are below for common interfaces.
  199. Communicate with a printer with an Ethernet interface using `netcat`:
  200. ```bash
  201. php hello-world.php | nc 10.x.x.x. 9100
  202. ```
  203. A USB local printer connected with `usblp` on Linux has a device file (Includes USB-parallel interfaces):
  204. ```bash
  205. php hello-world.php > /dev/usb/lp0
  206. ```
  207. A computer installed into the local `cups` server is accessed through `lp` or `lpr`:
  208. ```bash
  209. php hello-world.php > foo.txt
  210. lpr -o raw -H localhost -P printer foo.txt
  211. ```
  212. A local or networked printer on a Windows computer is mapped in to a file, and generally requires you to share the printer first:
  213. ```
  214. php hello-world.php > foo.txt
  215. net use LPT1 \\server\printer
  216. copy foo.txt LPT1
  217. del foo.txt
  218. ```
  219. If you have troubles at this point, then you should consult your OS and printer system documentation to try to find a working print command.
  220. ### Using a PrintConnector
  221. To print receipts from PHP, use the most applicable [PrintConnector](https://github.com/mike42/escpos-php/tree/master/src/Mike42/Escpos/PrintConnectors) for your setup. The connector simply provides the plumbing to get data to the printer.
  222. For example, a `NetworkPrintConnector` accepts an IP address and port:
  223. ```php
  224. use Mike42\Escpos\PrintConnectors\NetworkPrintConnector;
  225. use Mike42\Escpos\Printer;
  226. $connector = new NetworkPrintConnector("10.x.x.x", 9100);
  227. $printer = new Printer($connector);
  228. try {
  229. // ... Print stuff
  230. } finally {
  231. $printer -> close();
  232. }
  233. ```
  234. While a serial printer might use:
  235. ```php
  236. use Mike42\Escpos\PrintConnectors\FilePrintConnector;
  237. use Mike42\Escpos\Printer;
  238. $connector = new FilePrintConnector("/dev/ttyS0");
  239. $printer = new Printer($connector);
  240. ```
  241. For each OS/interface combination that's supported, there are examples in the compatibility section of how a `PrintConnector` would be constructed. If you can't get a `PrintConnector` to work, then be sure to include the working print command in bug.
  242. ### Using a CapabilityProfile
  243. Support for commands and code pages varies between printer vendors and models. By default, the driver will accept UTF-8, and output commands that are suitable for Epson TM-series printers.
  244. When trying out a new brand of printer, it's a good idea to use the "simple" `CapabilityProfile`, which instructs the driver to avoid the use of advanced features (generally simpler image handling, ASCII-only text).
  245. ```php
  246. use Mike42\Escpos\PrintConnectors\WindowsPrintConnector;
  247. use Mike42\Escpos\CapabilityProfile;
  248. $profile = CapabilityProfile::load("simple");
  249. $connector = new WindowsPrintConnector("smb://computer/printer");
  250. $printer = new Printer($connector, $profile);
  251. ```
  252. As another example, Star-branded printers use different commands:
  253. ```php
  254. use Mike42\Escpos\PrintConnectors\WindowsPrintConnector;
  255. use Mike42\Escpos\CapabilityProfile;
  256. $profile = CapabilityProfile::load("SP2000")
  257. $connector = new WindowsPrintConnector("smb://computer/printer");
  258. $printer = new Printer($connector, $profile);
  259. ```
  260. For a list of available profiles, or to have support for your printer improved, please see the upstream [receipt-print-hq/escpos-printer-db](https://github.com/receipt-print-hq/escpos-printer-db) project.
  261. ### Tips & examples
  262. On Linux, your printer device file will be somewhere like `/dev/lp0` (parallel), `/dev/usb/lp1` (USB), `/dev/ttyUSB0` (USB-Serial), `/dev/ttyS0` (serial).
  263. On Windows, the device files will be along the lines of `LPT1` (parallel) or `COM1` (serial). Use the `WindowsPrintConnector` to tap into system printing on Windows (eg. [Windows USB](https://github.com/mike42/escpos-php/tree/master/example/interface/windows-usb.php), [SMB](https://github.com/mike42/escpos-php/tree/master/example/interface/smb.php) or [Windows LPT](https://github.com/mike42/escpos-php/tree/master/example/interface/windows-lpt.php)) - this submits print jobs via a queue rather than communicating directly with the printer.
  264. A complete real-world receipt can be found in the code of [Auth](https://github.com/mike42/Auth) in [ReceiptPrinter.php](https://github.com/mike42/Auth/blob/master/lib/misc/ReceiptPrinter.php). It includes justification, boldness, and a barcode.
  265. Other examples are located in the [example/](https://github.com/mike42/escpos-php/blob/master/example/) directory.
  266. ## Available methods
  267. ### __construct(PrintConnector $connector, CapabilityProfile $profile)
  268. Construct new print object.
  269. Parameters:
  270. - `PrintConnector $connector`: The PrintConnector to send data to.
  271. - `CapabilityProfile $profile` Supported features of this printer. If not set, the "default" CapabilityProfile will be used, which is suitable for Epson printers.
  272. See [example/interface/](https://github.com/mike42/escpos-php/tree/master/example/interface/) for ways to open connections for different platforms and interfaces.
  273. ### barcode($content, $type)
  274. Print a barcode.
  275. Parameters:
  276. - `string $content`: The information to encode.
  277. - `int $type`: The barcode standard to output. If not specified, `Printer::BARCODE_CODE39` will be used.
  278. Currently supported barcode standards are (depending on your printer):
  279. - `BARCODE_UPCA`
  280. - `BARCODE_UPCE`
  281. - `BARCODE_JAN13`
  282. - `BARCODE_JAN8`
  283. - `BARCODE_CODE39`
  284. - `BARCODE_ITF`
  285. - `BARCODE_CODABAR`
  286. Note that some barcode standards can only encode numbers, so attempting to print non-numeric codes with them may result in strange behaviour.
  287. ### bitImage(EscposImage $image, $size)
  288. See [graphics()](#graphicsescposimage-image-size) below.
  289. ### cut($mode, $lines)
  290. Cut the paper.
  291. Parameters:
  292. - `int $mode`: Cut mode, either `Printer::CUT_FULL` or `Printer::CUT_PARTIAL`. If not specified, `Printer::CUT_FULL` will be used.
  293. - `int $lines`: Number of lines to feed before cutting. If not specified, 3 will be used.
  294. ### feed($lines)
  295. Print and feed line / Print and feed n lines.
  296. Parameters:
  297. - `int $lines`: Number of lines to feed
  298. ### feedForm()
  299. Some printers require a form feed to release the paper. On most printers, this command is only useful in page mode, which is not implemented in this driver.
  300. ### feedReverse($lines)
  301. Print and reverse feed n lines.
  302. Parameters:
  303. - `int $lines`: number of lines to feed. If not specified, 1 line will be fed.
  304. ### graphics(EscposImage $image, $size)
  305. Print an image to the printer.
  306. Parameters:
  307. - `EscposImage $img`: The image to print.
  308. - `int $size`: Output size modifier for the image.
  309. Size modifiers are:
  310. - `IMG_DEFAULT` (leave image at original size)
  311. - `IMG_DOUBLE_WIDTH`
  312. - `IMG_DOUBLE_HEIGHT`
  313. A minimal example:
  314. ```php
  315. <?php
  316. $img = EscposImage::load("logo.png");
  317. $printer -> graphics($img);
  318. ```
  319. See the [example/](https://github.com/mike42/escpos-php/blob/master/example/) folder for detailed examples.
  320. The function [bitImage()](#bitimageescposimage-image-size) takes the same parameters, and can be used if your printer doesn't support the newer graphics commands. As an additional fallback, the `bitImageColumnFormat()` function is also provided.
  321. ### initialize()
  322. Initialize printer. This resets formatting back to the defaults.
  323. ### pdf417Code($content, $width, $heightMultiplier, $dataColumnCount, $ec, $options)
  324. Print a two-dimensional data code using the PDF417 standard.
  325. Parameters:
  326. - `string $content`: Text or numbers to store in the code
  327. - `number $width`: Width of a module (pixel) in the printed code. Default is 3 dots.
  328. - `number $heightMultiplier`: Multiplier for height of a module. Default is 3 times the width.
  329. - `number $dataColumnCount`: Number of data columns to use. 0 (default) is to auto-calculate. Smaller numbers will result in a narrower code, making larger pixel sizes possible. Larger numbers require smaller pixel sizes.
  330. - `real $ec`: Error correction ratio, from 0.01 to 4.00. Default is 0.10 (10%).
  331. - `number $options`: Standard code `Printer::PDF417_STANDARD` with start/end bars, or truncated code `Printer::PDF417_TRUNCATED` with start bars only.
  332. ### pulse($pin, $on_ms, $off_ms)
  333. Generate a pulse, for opening a cash drawer if one is connected. The default settings (0, 120, 240) should open an Epson drawer.
  334. Parameters:
  335. - `int $pin`: 0 or 1, for pin 2 or pin 5 kick-out connector respectively.
  336. - `int $on_ms`: pulse ON time, in milliseconds.
  337. - `int $off_ms`: pulse OFF time, in milliseconds.
  338. ### qrCode($content, $ec, $size, $model)
  339. Print the given data as a QR code on the printer.
  340. - `string $content`: The content of the code. Numeric data will be more efficiently compacted.
  341. - `int $ec` Error-correction level to use. One of `Printer::QR_ECLEVEL_L` (default), `Printer::QR_ECLEVEL_M`, `Printer::QR_ECLEVEL_Q` or `Printer::QR_ECLEVEL_H`. Higher error correction results in a less compact code.
  342. - `int $size`: Pixel size to use. Must be 1-16 (default 3)
  343. - `int $model`: QR code model to use. Must be one of `Printer::QR_MODEL_1`, `Printer::QR_MODEL_2` (default) or `Printer::QR_MICRO` (not supported by all printers).
  344. ### selectPrintMode($mode)
  345. Select print mode(s).
  346. Parameters:
  347. - `int $mode`: The mode to use. Default is `Printer::MODE_FONT_A`, with no special formatting. This has a similar effect to running `initialize()`.
  348. Several MODE_* constants can be OR'd together passed to this function's `$mode` argument. The valid modes are:
  349. - `MODE_FONT_A`
  350. - `MODE_FONT_B`
  351. - `MODE_EMPHASIZED`
  352. - `MODE_DOUBLE_HEIGHT`
  353. - `MODE_DOUBLE_WIDTH`
  354. - `MODE_UNDERLINE`
  355. ### setBarcodeHeight($height)
  356. Set barcode height.
  357. Parameters:
  358. - `int $height`: Height in dots. If not specified, 8 will be used.
  359. ### setBarcodeWidth($width)
  360. Set barcode bar width.
  361. Parameters:
  362. - `int $width`: Bar width in dots. If not specified, 3 will be used. Values above 6 appear to have no effect.
  363. ### setColor($color)
  364. Select print color - on printers that support multiple colors.
  365. Parameters:
  366. - `int $color`: Color to use. Must be either `Printer::COLOR_1` (default), or `Printer::COLOR_2`
  367. ### setDoubleStrike($on)
  368. Turn double-strike mode on/off.
  369. Parameters:
  370. - `boolean $on`: true for double strike, false for no double strike.
  371. ### setEmphasis($on)
  372. Turn emphasized mode on/off.
  373. Parameters:
  374. - `boolean $on`: true for emphasis, false for no emphasis.
  375. ### setFont($font)
  376. Select font. Most printers have two fonts (Fonts A and B), and some have a third (Font C).
  377. Parameters:
  378. - `int $font`: The font to use. Must be either `Printer::FONT_A`, `Printer::FONT_B`, or `Printer::FONT_C`.
  379. ### setJustification($justification)
  380. Select justification.
  381. Parameters:
  382. - `int $justification`: One of `Printer::JUSTIFY_LEFT`, `Printer::JUSTIFY_CENTER`, or `Printer::JUSTIFY_RIGHT`.
  383. ### setLineSpacing($height)
  384. Set the height of the line.
  385. Some printers will allow you to overlap lines with a smaller line feed.
  386. Parameters:
  387. - `int $height`: The height of each line, in dots. If not set, the printer will reset to its default line spacing.
  388. ### setPrintLeftMargin($margin)
  389. Set print area left margin. Reset to default with `Printer::initialize()`.
  390. Parameters:
  391. - `int $margin`: The left margin to set on to the print area, in dots.
  392. ### setPrintWidth($width)
  393. Set print area width. This can be used to add a right margin to the print area. Reset to default with `Printer::initialize()`.
  394. Parameters:
  395. - `int $width`: The width of the page print area, in dots.
  396. ### setReverseColors($on)
  397. Set black/white reverse mode on or off. In this mode, text is printed white on a black background.
  398. Parameters:
  399. - `boolean $on`: True to enable, false to disable.
  400. ### setTextSize($widthMultiplier, $heightMultiplier)
  401. Set the size of text, as a multiple of the normal size.
  402. Parameters:
  403. - `int $widthMultiplier`: Multiple of the regular height to use (range 1 - 8).
  404. - `int $heightMultiplier`: Multiple of the regular height to use (range 1 - 8).
  405. ### setUnderline($underline)
  406. Set underline for printed text.
  407. Parameters:
  408. - `int $underline`: Either `true`/`false`, or one of `Printer::UNDERLINE_NONE`, `Printer::UNDERLINE_SINGLE` or `Printer::UNDERLINE_DOUBLE`. Defaults to `Printer::UNDERLINE_SINGLE`.
  409. ### text($str)
  410. Add text to the buffer. Text should either be followed by a line-break, or `feed()` should be called after this.
  411. Parameters:
  412. - `string $str`: The string to print.
  413. # Further notes
  414. Posts I've written up for people who are learning how to use receipt printers:
  415. * [What is ESC/POS, and how do I use it?](https://mike42.me/blog/what-is-escpos-and-how-do-i-use-it), which documents the output of `example/demo.php`.
  416. * [Setting up an Epson receipt printer](https://mike42.me/blog/2014-20-26-setting-up-an-epson-receipt-printer)
  417. * [Getting a USB receipt printer working on Linux](https://mike42.me/blog/2015-03-getting-a-usb-receipt-printer-working-on-linux)
  418. # Development
  419. This code is MIT licensed, and you are encouraged to contribute any modifications back to the project.
  420. For development, it's suggested that you load `imagick`, `gd` and `Xdebug` PHP exensions, and install `composer`.
  421. The tests are executed on [Travis CI](https://travis-ci.org/mike42/escpos-php) over PHP 5.4, 5.5, 5.6, 7.0, 7.1 and 7.2, plus the latest LTS version of HHVM, 3.21. Older versions of PHP are not supported in current releases.
  422. Fetch a copy of this code and load dependencies with composer:
  423. git clone https://github.com/mike42/escpos-php
  424. cd escpos-php/
  425. composer install
  426. Execute unit tests via `phpunit`:
  427. php vendor/bin/phpunit --coverage-text
  428. This project uses the PSR-2 standard, which can be checked via [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer):
  429. php vendor/bin/phpcs --standard=psr2 src/ -n
  430. The developer docs are build with [doxygen](https://github.com/doxygen/doxygen). Re-build them to check for documentation warnings:
  431. make -C doc clean && make -C doc
  432. Pull requests and bug reports welcome.