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


関連記事

困っていること

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

機能

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

使用するもの

設計

1. 設定とコーディング1

まずはプリンターの設定と何がレシートプリンターでどんな文字が印刷できるかの調査

pythonで使用するライブラリをインストール

pip install python-escpos
pip install Pillow

フォントはフリーのフォントを使用させていただきました。

フリーフォントサイト

プリンターでの印刷

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")でテキストを実行する場合、最初の位置文字が消えるので、気をつけてください。

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引数の1つめと、2つめとなります。

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

udev
簡単に説明すると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

指定の画像をロゴごとして追加して印刷する
下記の画像を先程作成したデータに追加して印刷する。

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()

まとめ

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