背景
ESCPOS規格のレシートプリンタ(USB接続)をReactNativeで動かそうとしたら対応するライブラリが見当たらなかったので、Android向けのESCPOSライブラリを利用してReactNativeのライブラリを作ってみました。OTGケーブルが必要だったり、無線デバッグが必要だったり、詰まりどころがあるので、使い方を共有します。
使ったもの
- OTGケーブル
とても重要な装置です。
Android端末を親機(ホストデバイス)として動かすために必要です。
Raspberry Pi Zeroに同梱されているAメス<->micorBケーブルは、OTGケーブルではないので、形状は一緒なのですが動きません。
OTGケーブルを準備してください。
amazon: USB TypeC OTGケーブル
amazon: USB microB OTGケーブル - ReactNativeのAndroidを開発出来るPC
環境構築手順に従い、React Native CLIを利用するためnpmとAndroid Studioをインストールし、Android Studioで必要なSDKをインストールし、ANDROID_HOMEという環境変数を設定したPCです。 - Android端末
下記の2種類の端末で動くことを確認しました。
Android6.1が入ったNexus5
Android8.0が入ったHuawei P20 Lite
Android11が入ったHuaweiのタブレット - ESCPOS対応のプリンタ
EPSONのTM-T88IVというレシートプリンタを利用しました。
USBポートをプリンタに繋ぐので、ReactNativeの無線デバッグモードを利用
Android端末にプリンタをUSB接続しても開発を進められるように、ReactNativeの無線デバッグモードを利用します。使い方を説明します。
Android端末とPCを同じWiFiに接続します。
ReactNativeのログ出力用ターミナルで「d」を入力するか、ReactNativeのアプリを動かしている端末を振って開発メニューを表示し、Settingsを選びます。
Debug server host & port for deviceを選びます。
PCのIPアドレス + 8081ポート を入力します。
例: 192.168.0.16:8081
これで、無線でデバッグできるようなります。
作ったライブラリ: react-native-escpos-android
Android向けに作られているESCPOS-ThermalPrinter-Androidというライブラリをreact-nativeのbridgeを利用してreact-nativeから機能の一部を呼べるようにしたライブラリです。https://github.com/asukiaaa/react-native-escpos-android
ライブラリの作成にはreact-native-builder-bobを利用しました。
npmやyarnでインストールできます。
npm install react-native-escpos-android --save
Androidのintentによる起動を設定しておくと、USBでプリンターが接続された際にアプリに対してUSBデバイスの利用を許可できるので、場合によっては便利です。
必須でないのでここでは説明しませんが、気になる方はライブラリのREADMEをご覧ください。
OTGケーブルを通してレシートプリンタとAndroid端末を接続した状態で下記の処理を実行すると、プリンタに情報を書き込めます。
import EscposAndroid from 'react-native-escpos-android';
let raw = [
0x1b, 0x40, // initialize
0x1c, 0x43, 0x01, // set shift-jis
0x82, 0xA0, 0x82, 0xA2, 0x82, 0xA4, // あいう in shift-jis
0x0a, // change line
0x8a, 0xbf, 0x8e, 0x9a, // 漢字 in shift-jis
0x1b, 0x64, 0x05, // feed
0x1D, 0x56, 0x01, // cut
]
await EscposAndroid.write({ raw })
escposのparserライブラリや文字コード変換ライブラリと合わせると便利
escposのコマンドを生成するライブラリや、shift-jisにエンコードするライブラリを併用すると、日本語のレシートを生成しやすくなって便利です。コマンド生成: EscPosEncoder
文字コード変換: iconv-lite
それらを利用すると、このように記述できます。
import EscposAndroid from 'react-native-escpos-android'
import EscPosEncoder from 'esc-pos-encoder'
import iconv from 'iconv-lite'
const commandBytes = encoder
.initialize()
.raw([
0x1c, 0x43, 0x01, // set shift-jis
0x82, 0xA0, 0x82, 0xA2, 0x82, 0xA4, // あいう in shift-jis
0x0a, // change line
0x8a, 0xbf, 0x8e, 0x9a, // 漢字 in shift-jis
0x0a, // change line
])
.raw(iconv.encode('試行錯誤な日々', 'SHIFT_JIS'))
.raw([
0x1b, 0x64, 0x05, // feed
0x1D, 0x56, 0x01, // cut
])
.encode()
const raw = [...commandBytes] // convert ArrayBuffer to array of number
await EscposAndroid.write({ raw })
出力したレシートがこちらです。
余談: シリアル通信ライブラリは、ポートを開く時の処理が異なるのか、escposは開けなかった
escpos用のライブラリを利用する前はreact-native-usbserial-cvkなどを利用して書き込みを試みていました。このライブラリを利用するとM5Stackに対しては書き込めたのですが、レシートプリンタに向けて書き込みを試みると下記のエラーが発生して使えませんでした。
[Fri Dec 25 2020 12:00:20.868] LOG {"devices": [{"deviceId": 1009, "deviceName": "/dev/bus/usb/001/009", "productId": 514, "productName": "EPSON UB-U02III", "serialNumber": "20101029084402093M03C", "vendorId": 1208}]}
[Fri Dec 25 2020 12:00:22.941] WARN Possible Unhandled Promise Rejection (id: 0):
Error: No control endpoint
promiseMethodWrapper@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:2242:45
openDeviceAsync@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:135886:47
writeSerial$@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:97338:68
tryCatch@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:24938:23
invoke@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:25111:32
tryCatch@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:24938:23
invoke@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:25011:30
http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:25021:21
tryCallOne@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:27020:16
http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:27121:27
_callTimer@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:30560:17
_callImmediatesPass@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:30599:17
callImmediates@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:30816:33
__callImmediates@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:2736:35
http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:2522:34
__guard@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:2719:15
flushedQueue@http://192.168.3.159:8081/index.bundle?platform=android&dev=true&minify=false:2521:21
flushedQueue@[native code]
invokeCallbackAndReturnFlushedQueue@[native code]
レシートプリンタも扱えるシリアル通信ライブラリをご存知でしたら、コメントなどで共有していただけると嬉しいです。
まとめ
Android向けに作られているescposのライブラリを利用してReactNative用のライブラリを作り、escposのコマンド生成ライブラリや文字コード変換ライブラリと組み合わせてレシートに日本語を出力できました。参考
nyampass/halake-raspi/src/receipt-printer.pylinux上でpythonでescposを操作するプログラムです。
Wireless Debugging — React Native
無線デバッグ機能の使い方を説明しているブログです。
0 件のコメント :
コメントを投稿