ヒント:このメッセージが表示されている場合、現在の記事は元のemlogブログシステムからここに移行されたものであり、記事の公開日時が非常に古いため、編成や内容が完全でない可能性があります。ご了承ください。
サーマル Bluetooth プリンター開発
日付:2019-11-5 阿珏 コードをいじる ビュー:2359 回 コメント:14 件
最近、レシート印刷に取り組んでおり、プロジェクトの要件はiOSとAndroidの両方を実現することでした。最初に取り組んだときは、何が何だかわからず、ネットで多くの資料を探し、たくさんの罠にハマり、たくさんの記事を読みましたが、結果的にはうまくいきました。Bluetoothプリンターは一般的に2つの印刷モードに分かれています:レシート印刷とラベル印刷です。
会社が購入した粗悪なプリンターには開発文書がなく、多くの罠にハマりました。開発を始めるときに相談してくれればよかったのに。
現在、WeChatミニプログラムでBluetoothプリンターに接続するwx.createBLEConnectionのテストはiOSデバイスでは問題ありませんが、一部のAndroidスマートフォンでは異常が発生します(接続時にシステムのペアリングボックスが表示され、キャンセルをクリックしてもペアリングコードを入力してもすぐに接続が切れます。入力せずにキャンセルしない場合は、30秒以内に自動的にBluetoothプリンターが切断されます)。
現在の方法は、AndroidとiOSそれぞれにBluetooth印刷のコマンドを1セットずつ書くことです。
iOS
Android
これは比較的簡単で便利で、Native.js を使用して Native Java インターフェースチャネルを直接呼び出し、plus.android を介して Android ネイティブシステム API を呼び出します。
ネイティブ Android ドキュメント
https://developer.android.google.cn/reference/android/bluetooth/BluetoothAdapter?hl=en
印刷コマンド
(詳細な印刷コマンドは https://www.jianshu.com/p/dd6ca0054298 を参照)
QR コードの印刷について
上記の文章からわかるように
生成された QR コードのピクセルの rgba を読み取り、画像データを 4 合 1 で判断し 0 または 1(0 は印刷、1 は印刷しない)し、次に 8 合 1 にします。1 バイトは 8 ビットです。最後にプリンターのビットマップコマンドを使用して行ごとにスキャンして印刷します。
4 合 1
QR コードは黒か白であると思っていましたが、実際には 255 または 0 ではなく、他の値も少し存在することに注意が必要です。各 4 ビットは 1 つのピクセルの rgba であり、黒と白の rgb は (0,0,0) と (255,255,255) です。したがって、各 4 ビットの最初のビットだけを黒白化し、各 4 ビットの最初のビットを新しい配列として取得します。rule>200 のとき、値は 0 を取得し、印刷しないことを示し、それ以外は 1 を取得し、印刷することを示します。
8 合 1
例えば、取り出した 8 ビットの数が [0,0,0,0,0,0,0,1] の場合、8 合 1 を行い、進数変換を行います。右から左に 2 の 0 乗、2 の 1 乗、などを加算していきます。実際には 0 * 27 + 0 * 26 + 0 * 25 + 0 * 24 + 0 * 23 + 0 * 22 + 0 * 21 + 1 * 20、この数が私たちが求める最終データの一部です。
データを ArrayBuffer に変換し、印刷には必ずコマンドが必要です!参照 URL および標準の ESC-POS コマンドセット、以下のコード内の数字はすべてコマンドです。また、私のプリンターは gb2312 形式をサポートしているため、ArrayBuffer に変換する際に、エンコーディング形式を正しい形式に変換する必要があります。
ただし、iOS と Android の違いに注意が必要です。Android は一度に 20 バイトを超えて書き込むことができず(iOS は具体的には不明ですが、目測で 120 バイト)、データを直接切り取ることをお勧めします data.slice (20, byteLength) で、印刷が成功したら再度コールバックし、ループ印刷します。
1、toArrayBuffer はコンポーネントで、インストールが必要です。https://www.npmjs.com/package/to-array-buffer または、このように書くこともできます const buffer = new Uint8Array (Buffer.from (cmds, 'gb2312')).buffer;
2、自分のデータが正しいかどうかを確認してください。描画データに問題があると、黒いブロックが印刷される可能性があります。
3、データを計算する必要があります!!!計算する必要があります!!!例えば、私が描画するのは 160*160 で、印刷データを結合するコマンド [29, 118, 48, 0, 20, 0, 160, 0] の中の 20 と 160 は計算されたものです。上記の文章を参照して理由を見てください。おおよそ 1:8 で、描画と読み取りのデータが一致します。
関連関数
(繰り返しテストした結果、印刷紙の 1 行あたりの最大バイト数は 32 バイトで、これは通常のレシートプリンターを指します)
3 列または 2 列の印刷には、スペースを計算して埋める必要があります。既製のコマンドはありません。
総幅 - 左側の文字の長さ - 右側の文字の長さがスペースの長さです。


コードの大部分はプロジェクトから直接コピーしたもので、整理されておらず、直接実行できません。参考のためにのみ提供します。
私の印刷失敗の印刷紙が失われたわけではありませんが、そうでなければ、初めてプリンター開発を行うプログラマーがどのようなものかを見せてあげたかったです。
読者のコメント:
深圳自考 7 ヶ月前 (2020-10-08)
すごい!まるで同じです。これからは「お腹が空いていない」会社を開けるかもしれません [#aru_1]
一朵时光红 1 年前 (2020-03-21)
テングの奇襲スキルを発動すると、神が筋斗雲に飛び乗り、完璧な分身を残します。
李鱼儿啊 1 年前 (2019-12-27)
楼主、プリンターに送信するバッファのコードをもう少し詳しく教えてもらえますか?今、私はこのステップでつまずいていて、とても混乱しています。私の QQ に追加できますか?2930962607
阿珏 1 年前 (2019-12-28)
@李鱼儿啊:あなたの問題を明確にする必要があります。
李鱼儿啊 1 年前 (2019-12-29)
@阿珏:私は uniApp のカスタムコンポーネントモードで開発しており、native.js を使用して Android スマートフォンの Bluetooth に接続しています。ページは web-view のサブウィンドウでローカル HTML ファイルを読み込んでいます。html2canvas.js プラグインを使用してページをキャプチャして画像を生成する必要があるため、プラグインのコールバックメソッドで canvas の DOM オブジェクトを取得できます。そのため、imageData のピクセル情報を取得できます。そして、あなたが書いた 4 合 1 と 8 合 1 を使用してデータを生成し、プリンターの write メソッドに送信する際に、try-catch を使用して送信時の例外をキャッチしました。問題は生成されたデータにあることがわかりました。時々、catch が null 配列の長さを取得しようとしたというエラーを報告し、時々空の {} JSON オブジェクトのエラーを直接報告します。重要な点は、あなたがバッファデータの変換で node.js の Buffer オブジェクトを使用していることですが、私の方ではそれを使用できません。どうか、解決策を教えていただければ幸いです。可能であれば、QQ を追加してください。2930962607
阿珏 1 年前 (2019-12-30)
@李鱼儿啊:申し訳ありませんが、Android の印刷画像データに関する問題は完全には解決できていないため、より良い解決策を提供できません。Android の印刷に関しては、Google Android の公式ドキュメントを参考にしてください。データ送信処理に問題があるはずです。
『乐 易』 2 年前 (2019-11-16)
これは、喵喵機に似ているのではないですか?ちょうど喵喵機 P1 を買ったところです [#aru_1]
阿珏 2 年前 (2019-11-17)
@『乐 易』:これは、あまり似ていないようですし、それは「グーグー機」と呼ばれていませんか [#aru_2]
『乐 易』 2 年前 (2019-11-17)
@阿珏:機能は同じですが、喵喵機は少し小さいだけです。そして、喵喵機ではなく、グーグー鶏です [#aru_38]
阿珏 2 年前 (2019-11-18)
@『乐 易』:なるほど、なるほど、実際に「喵喵機」というものがあるのですね [#aru_16]
mengkun 2 年前 (2019-11-05)
すごい!「お腹が空いていない」注文のレシートの味がします [#aru_53]
阿珏 2 年前 (2019-11-05)
@mengkun:私たちは「お腹が空いていない」ではありません [#aru_42]
repostone 2 年前 (2019-11-05)
技術的ではない通りすがり。
阿珏 2 年前 (2019-11-05)
@repostone:すごいことはそれだけです [#aru_43]