pythonでレシートプリンターを操作する

## 関連記事

* [レシートプリンタでメモ書きを印刷する](https://qiita.com/kurikurisan/items/f769c822274dea21e804)

## 困っていること
まずは何あれ、問題定義！
私は、タスク管理ツールを何度も使ってみては、失敗してを繰り返しているのですが、それは、スマホでいちいちタスクを開くのが面倒くさいから、物理的に見えないからなのではないかと思い、プリンターで印刷してしまえばいいのではと思いこれらを作成しました。

## 機能

* プリンターで文字と画像を印刷する
* PILにフォントを設定する

## 使用するもの

* python3.6
* [python-escposライブラリ](https://github.com/python-escpos/python-escpos)
* Python Imaging Library
* OS(ubuntu18.04LTS)
* [レシートプリンター](https://www.amazon.co.jp/Symcode-58MM-USB-サーマルレシートプリンター-プリント指令セットと両立/dp/B071X6RHM1/ref=sr_1_6?adgrpid=54026665180&dchild=1&gclid=CjwKCAjwxLH3BRApEiwAqX9arSxbljEevQZn5vUPqoNranPZsNpVG2WyzRo8Ex8Z0WoQ70gO7BsMqxoCYZ0QAvD_BwE&hvadid=338579793965&hvdev=c&hvlocphy=1009318&hvnetw=g&hvqmt=b&hvrand=7868074443600921801&hvtargid=kwd-312095979101&hydadcr=19158_11045751&jp-ad-ap=0&keywords=レシート+プリンター&qid=1592615126&sr=8-6&tag=googhydr-22)
* ![IMG_20200620_101456.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192308/2256a53d-95ad-dfd3-53f3-3d209bc8052c.jpeg)



## 設計

### 1. 設定とコーディング1
まずはプリンターの設定と何がレシートプリンターでどんな文字が印刷できるかの調査
### pythonで使用するライブラリをインストール

```
pip install python-escpos
pip install Pillow
```

### フォントはフリーのフォントを使用させていただきました。
[フリーフォントサイト](https://jp.stanby.com/media/free-font/)


### プリンターでの印刷

```
from escpos.printer import Usb
from escpos import *

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

# レシートプリンターを使った印刷

width = 500
height = 250

image = Image.new('1', (width, height), 255)
draw = ImageDraw.Draw(image)
font = ImageFont.truetype('FLOPDesignFont.ttf', 50, encoding='unic')
draw.text((0, 0), "日本語" + " ", font=font, fill=0)
font = ImageFont.truetype('FLOPDesignFont.ttf', 28, encoding='unic')
draw.text((0, 82), "abcdefghijklmnopqrstuvwxyz", font=font, fill=0)
draw.text((0, 112), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", font=font, fill=0)
draw.text((0, 142), "1234567890" + " ", font=font, fill=0)
draw.text((0, 172), "!\"#$%&'()=~|+*<>?_{}" + " ", font=font, fill=0)

p = Usb(0x0416, 0x5011, 0, 0x81, 0x03)
p.text("Hello World\n")
p.image(image)
p.cut()
```


こちらを印刷したものが下記のようになります。
※ `p.text("Hello World\n")`でテキストを実行する場合、最初の位置文字が消えるので、気をつけてください。

![IMG_20200620_103642.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192308/0b844be3-e144-34fe-36a9-ff5ed4155114.jpeg)

### USBの設定
レシートプリンターで印刷する場合は、こちらを設定する必要があります。
それについて、確認していきます。

`p = Usb(0x0416, 0x5011, 0, 0x81, 0x03)`

まずは、lsusbを実行しましょう

```
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 006: ID 8087:07dc Intel Corp. 
Bus 001 Device 005: ID 0bda:579a Realtek Semiconductor Corp. 
Bus 001 Device 004: ID 0bda:0129 Realtek Semiconductor Corp. RTS5129 Card Reader Controller
Bus 001 Device 003: ID 0bda:b812 Realtek Semiconductor Corp. 
Bus 001 Device 008: ID 0416:5011 Winbond Electronics Corp. Virtual Com Port
Bus 001 Device 002: ID 062a:4102 Creative Labs 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```

下記のものがレシートプリンターに接続されているものです。
`Bus 001 Device 008: ID 0416:5011 Winbond Electronicのs Corp. Virtual Com Port`
この`0416:5011`の部分がUsb引数の１つめと、2つめとなります。

これだけでもsudoをつけて、root権限でpythonを実行すれば、印刷ができます。
このときに、一般ユーザーからもこのデバイスにアクセスできるように udev にルールを追加して、udev のルールを読み込ませてやります。

※[udev](https://linuc.org/study/knowledge/416/)
簡単に説明するとUSBデバイスを抜き差ししても、このUSBが何かを管理してくれるものです。(正確にはリンクで確認してください。)

udevの設定
/etc/udev/rules.d/10-printer.rulesファイルを作成し、下記を記載します。
先のlsusbで　`デバイスID: 0416: 5011` が異なる場合には、こちらも合わせてください。

```
SUBSYSTEM=="usb", ATTR{idVendor}=="0416", ATTR{idProduct}=="5011", MODE="0666", GROUP="plugdev"
```

### 2. 設定とコーディング2
指定の画像をロゴごとして追加して印刷する
下記の画像を先程作成したデータに追加して印刷する。

![qiita-logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192308/a053f30f-d581-63fd-a5dd-df20299b6687.png)

```
from escpos.printer import Usb
from escpos import *

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

# レシートプリンターを使った印刷

width = 500
height = 400

image = Image.new('1', (width, height), 255)
draw = ImageDraw.Draw(image)
font = ImageFont.truetype('FLOPDesignFont.ttf', 50, encoding='unic')
draw.text((0, 100), "日本語" + " ", font=font, fill=0)
font = ImageFont.truetype('storage/font/FLOPDesignFont.ttf', 28, encoding='unic')
draw.text((0, 182), "abcdefghijklmnopqrstuvwxyz", font=font, fill=0)
draw.text((0, 212), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", font=font, fill=0)
draw.text((0, 242), "1234567890" + " ", font=font, fill=0)
draw.text((0, 272), "!\"#$%&'()=~|+*<>?_{}" + " ", font=font, fill=0)

logo = Image.open('qiita-logo.png')

image.paste(logo, (150, 10))

# image.show()
p = Usb(0x0416, 0x5011, 0, 0x81, 0x03)
p.text(" \n")
p.image(image)
p.cut()
```


![IMG_20200620_114940.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192308/b9c58e1c-ba02-4fbf-7e87-da38fe89d4fb.jpeg)




## まとめ

これで、テキストや簡単な画像をレシートプリンターで印刷できるようになりました。
ちなみに今回レシートプリンターを選択したのは、単純に金額が安価なためです。レシートプリンターが4500円/ レジペーパーも5個で900円程度ですしね！