# BeanPrinter 2.2.7（Android・Python版）

[BeanCellar](https://bcellar.app)の印刷待ちを、AndroidタブレットからBrother VC-500Wへ送るプログラムです。実行するのは **`beanprinter.py`** です。**初回に導入コマンドを一度コピーして貼り付け、その後はホーム画面とブラウザーでタップして操作できます。**

プリンターは同じLANから自動検出します。DHCPでIPが変わった場合も、製造番号で同じプリンターを探し直します。1件につき1枚をフルカラーで印刷し、**毎回フルカットを指定します**。ハーフカットに変更する設定はありません。BeanPrinterのAPK作成、Android Studio、Java、Gradle、`pip`による追加作業は不要です。

## すでに導入済みの方：今回の更新はここだけ

**2.2.7では任意のSwitchBot Bot自動排出を追加しました。** Hub経由で、印刷成功を確認した後に1回押します。追加のPythonパッケージやBluetooth設定は不要です。設定は第9節を参照してください。未設定でも従来どおり使えます。管理ページのBeanPrinter見出し右側に実行中の版を表示します。配布・更新先は [https://print.bcellar.app](https://print.bcellar.app) に統一しました。

**2.2.2以降が稼働中なら、「アップデートを確認」をタップしてください。** 2.2.6ではバックグラウンドで動作し、起動後にTermuxの入力欄へ戻ります。旧版からの自動更新後も入力欄が戻るので、別のコマンドを入力できます。紙詰まりを含むすべてのプリンターエラーで監視を続け、解消後に自動で再開します。エラー時の再開ボタンはありません。更新前に監視中なら、更新後も「印刷を開始」の押し直しは不要です。自分で停止した状態は保持します。更新についての詳しい説明は第8節にあります。

**旧版の紙詰まり・結果不明で更新が待ち続ける場合は、下の1回コピーする手動更新を使ってください。** 旧版は未完了の印刷がある間、更新を延期します。2.2.5以降の起動時に旧版の紙詰まり停止を解除し、残っている送信記録からプリンターの監視を再開します。

自動更新できない旧版や手動で入れ替える場合は、下のコマンドを1回コピーして実行できます。ZIPのファイル名の入力・変更・手動解凍は不要です。

1. このREADMEと一緒に配布している**新しいZIP**をタブレットのDownloadへ保存します。[BeanPrinterの配布Site](https://print.bcellar.app)からダウンロードできます。名前に`(1)`が付いていても、`download.zip`などへ変わっていても構いません。
2. BeanPrinterで「印刷を停止」を押し、現在の印刷が終わったらラベルを取り除きます。Androidの設定からTermuxを強制停止し、Termuxを開き直します。
3. **次のコード枠全体をコピーし、Termuxで長押し→貼り付け→Enter**で実行します。コマンドの書き換えは不要です。

```sh
python -c 'from pathlib import Path; from zipfile import ZipFile,is_zipfile; root=Path.home(); names={"BeanPrinter/"+n for n in ("beanprinter.py","README.md","beanprinter-boot.sh","test_beanprinter.py","LICENSE","NOTICE")}; files=sorted((root/"storage/downloads").glob("*.zip"),key=lambda p:p.stat().st_mtime,reverse=True); found=next((p for p in files if p.is_file() and is_zipfile(p) and set(ZipFile(p).namelist())==names),None); assert found, "新しいBeanPrinterのZIPをDownloadへ保存してください"; ZipFile(found).extractall(root)' && python "$HOME/BeanPrinter/beanprinter.py" install
```

Download内のZIPを新しく保存した順に調べ、**中身がBeanPrinterの配布物と一致するもの**を選んで導入し、操作画面を開きます。無関係なZIPや、ダウンロードが完了していないファイルは対象にしません。新しいZIPを最後に保存してください。プリンター設定・認証・送信記録・ホーム画面の起動ボタンは引き継ぎます。

管理ページのBeanPrinter見出し右側が**v2.2.7**になったことを確認します。旧版の紙詰まり停止は自動で監視へ移行します。それ以外で手順2の停止状態が引き継がれた場合は「印刷を開始」を押してください。認証期限が切れていればアクセスコードを入力します。

初めて導入する場合は、この下の第1〜3節へ進んでください。初回もコマンドは1つのコード枠をコピーするだけです。

## 1. 最初に準備するもの

- VC-500Wに50mm幅のCZロールを装着します。原稿は50.8×50.8mmです。
- タブレットとプリンターを、インターネットを利用できる同じWi-Fi・LANへ接続します。プリンターのWi-Fi設定がまだならBrotherの案内・アプリで設定してください。**通常はIPの確認・入力・固定IP設定・DHCP予約は不要です。**
- 旧BeanPrinterアプリや、以前のPython版が稼働中なら停止します。

プリンターへの通信にはLAN内のTCP 9100を使います。ゲストWi-Fiや端末間通信が禁止されたネットワークでは利用できません。ルーターのインターネット側にポートを開放する必要はありません。

## 2. Androidに実行環境を入れる

タブレットで、同じF-Droidから次の2つをインストールします。各ページのアプリ本体のダウンロードを使えます。

| アプリ | 役割 |
| --- | --- |
| [Termux](https://f-droid.org/packages/com.termux/) | Pythonを動かす環境 |
| [Termux:Widget](https://f-droid.org/packages/com.termux.widget/) | ホーム画面からBeanPrinterをタップして起動 |

Androidから求められた場合は、ダウンロードに使ったブラウザーの「この提供元を許可」を有効にします。Termuxと追加アプリの導入元は揃えてください。インストール後、**Termuxを一度開き、準備が終わるまで待ちます**。

[Termuxの導入元についての公式説明](https://github.com/termux/termux-app#installation)、[Termux:Widgetの公式手順](https://github.com/termux/termux-widget#setup-instructions)

## 3. BeanPrinterをダウンロードして導入する

1. タブレットで[BeanPrinterの配布Site](https://print.bcellar.app)を開きます。
2. **「ZIPをダウンロード」** から、新しい`BeanPrinter-source.zip`をダウンロードします。この会話の添付ZIPを使っても構いません。通常のDownloadフォルダーに保存してください。
3. **以下の1行を全体コピーし、Termuxの画面を長押し→貼り付け→Enter**で実行します。手入力やIPの書き換えは不要です。

```sh
pkg update -y && pkg upgrade -y && pkg install -y python poppler && termux-setup-storage && read -r -p 'ファイルへのアクセスを許可し、Termuxに戻ったらEnter: ' beanprinter_ready && python -c 'from pathlib import Path; from zipfile import ZipFile,is_zipfile; root=Path.home(); names={"BeanPrinter/"+n for n in ("beanprinter.py","README.md","beanprinter-boot.sh","test_beanprinter.py","LICENSE","NOTICE")}; files=sorted((root/"storage/downloads").glob("*.zip"),key=lambda p:p.stat().st_mtime,reverse=True); found=next((p for p in files if p.is_file() and is_zipfile(p) and set(ZipFile(p).namelist())==names),None); assert found, "新しいBeanPrinterのZIPをDownloadへ保存してください"; ZipFile(found).extractall(root)' && python "$HOME/BeanPrinter/beanprinter.py" install
```

PythonとPDF変換環境の導入には時間がかかる場合があります。途中でAndroidのファイルアクセス許可が出たら許可し、Termuxに戻ってEnterを押します。既に共有ストレージを設定済みの場合などは、Termux側の確認にも従ってください。ZIPのファイル名は使わず、中身がBeanPrinterの配布物と一致するものを新しく保存した順に選びます。`(1)`が付いていても、別の名前でも構いません。

導入が完了するとブラウザーにBeanPrinterの操作画面が開き、Termuxには入力欄が戻ります。起動コマンドが終了してもBeanPrinterはバックグラウンドで動きます。PDF変換にはTermuxの[Popplerパッケージ](https://github.com/termux/termux-packages/blob/master/packages/poppler/build.sh)を使います。PillowやPyMuPDFのコンパイルは必要ありません。

## 4. タップして設定する

1. 操作画面の「アクセスコード」に、BeanCellarと同じコードを入力します。
2. **「認証してプリンターを探す」**をタップします。同じLANのVC-500Wを検索して登録します。
3. 複数台あれば製造番号が表示されるので、使うプリンターをタップします。
4. **「接続を確認」**で、認証・VC-500W・50mmロール・待機状態・PDF変換環境を確認できます。この操作では印刷しません。
5. BeanCellarのキューを確認し、必要なラベルだけが待機している状態で **「印刷を開始」** を押します。

**開始すると既存の印刷待ちも対象になります。** 最初は必要な1件で、台紙ごと切り離されること、日本語・QR・色・長さを確認してください。

アクセスコード自体は保存しません。セッション情報・端末ID・プリンターの製造番号・送信記録はTermux内の`~/.local/state/beanprinter/state.json`に保存します。フォルダーは0700、ファイルは0600です。暗号化ファイルではないため共有しないでください。旧APKの設定は移行されません。

## 5. 次回からホーム画面で開く

1. Androidのホーム画面の空いている場所を長押しし、「ウィジェット」を開きます。
2. **Termux:Widget**のウィジェットを配置します。
3. 表示された **BeanPrinter** をタップすると操作画面が開きます。表示されない場合はウィジェットの更新ボタンを押します。

起動用ファイルは導入時に自動作成します。起動後にTermuxの入力欄を占有しません。既に稼働中なら同じ操作画面を開き直すだけで、二重に印刷処理を起動しません。更新前からのホーム画面のボタンもそのまま使えます。

画面サービスを終了しても最後の開始・停止状態を保存します。ホーム画面から開き直すと、前回監視中だった場合は自動で再開します。「印刷を停止」を押した状態は保持します。プリンターエラーでは監視を停止しません。

日常の操作は次のとおりです。

| やりたいこと | タップするもの |
| --- | --- |
| 印刷待ちを自動で印刷する | 「印刷を開始」 |
| 最新版を確認して更新する | キューの下の「アップデートを確認」 |
| 自動印刷を止める | 「印刷を停止」。現在の処理が完了してから停止します |
| 待機件数・保留状態を確認する | 「状態を確認」。キューは接続設定より上に表示します |
| 認証し直す | アクセスコードを入力して「認証してプリンターを探す」 |
| プリンターを変更する | 印刷を停止し、未完了の印刷を解消してから「プリンターを探す」 |

**ブラウザーのタブを閉じても、開始済みの印刷監視は継続します。** 停止には画面の「印刷を停止」を使います。BeanPrinter全体を終了する場合は、現在の処理が終わってからAndroidの設定でTermuxを強制停止します。

ログは`~/.local/state/beanprinter/beanprinter.log`に保存します。起動時に1MiBを超えていれば、前回分を`beanprinter.previous.log`へ移し、直前の1世代を残します。ログも所有者だけが読み書きできる0600です。起動に失敗した場合は、Termuxにログの場所を表示して入力欄へ戻ります。

Androidの設定でTermuxの通知を許可し、バッテリーの最適化を除外するか「制限なし」にします。「バックグラウンドでの自動起動」がある機種ではTermuxを許可します。OSがアプリを終了した場合はホーム画面から開き直してください。常駐はAndroid・メーカーの制限を受けます。[TermuxのAndroid動作上の説明](https://github.com/termux/termux-app)

## 6. DHCPとプリンターの自動検出

初回はmDNS/DNS-SDとNetBIOSの機器検索を使い、候補へ機種と製造番号を問い合わせます。**検索中に印刷データは送りません。** IPは接続先のキャッシュとして保存し、印刷前と「接続を確認」で登録済みの製造番号を照合します。

保存したIPにつながらない、または別の機器が応答した場合は、同じ製造番号を自動で探してIPを更新します。複数台見つかっても別の製造番号へ勝手に切り替えません。以前のPython版でIPを手動登録済みでも、製造番号が保存されていれば更新後にこの処理を利用できます。

- 自動検出はプライベートIPv4 LANが対象です。mDNSは同じリンクを検索します。NetBIOSの補助検索は通常の家庭用LANを想定し、タブレットの属する範囲の最大254アドレスに限定します。ネットマスクを取得できないAndroidではローカルIPから`/24`を補助範囲にします。
- ゲストWi-Fi・AP隔離・VPN・mDNSやNetBIOSが遮断されるネットワークでは検出できない場合があります。`/24`より広いLANでは補助検索範囲外のプリンターを拾えない場合もあります。その場合は操作画面の「自動で見つからない場合」を開き、ルーターで確認した現在のIPを入力します。
- 印刷監視中、再検索が失敗した場合は少なくとも30秒空けて探し直します。印刷前の未送信状態なら接続復旧を待ちます。確保済みジョブにはサーバーの10分の期限があるため、期限が切れた未送信ジョブも、接続回復後に自動で印刷待ちへ戻して再開します。
- 印刷データ送信後の通信切断でも、同じ製造番号へ再接続して状態を確認します。成功を確認した印刷は再送しません。結果不明の再試行条件と重複の可能性は第7節を参照してください。

[公開Python実装のNetBIOS検出例](https://github.com/snoack/labelprinter-vc500w)、[VC-500WのmDNSとLANプロトコルの調査](https://m7i.org/projects/labelprinter-linux-python-for-vc-500w/)、[mDNSのユニキャスト応答仕様](https://www.rfc-editor.org/rfc/rfc6762#section-6.7)

## 7. ラベルの取り出し待ちと自動復帰

**紙詰まりを含め、プリンターのエラーはすべて回復待ちとして扱います。** ラベルが残っているためにJAMと返されても、監視を止めません。BUSY・排出中・待機要求・エラーの間は次の画像を送らず、時間制限なしで10秒ごとに確認します。エラーが消えて印刷可能になれば自動で続行します。印刷成功後は、次のジョブの確保前と画像送信前に状態を確認し、10秒離れた2回の確認で待機状態が続いてから先へ進みます。ラベルを取り除いた後、次の印刷まで10〜30秒程度かかることがあります。

これはプリンターの`print_state`・`print_job_stage`・`print_job_error`の応答に基づく判定です。独立した「ラベルを取った」センサーを読むものではありません。待機応答後でも印刷要求が拒否された場合はJPEGを送らず待ち、同じジョブで再確認します。今回追加した待機処理の、実機ファームウェアとの組み合わせは未検証です。

| 状態 | 動作 |
| --- | --- |
| フルカット後にラベルが排出口に残っている | 取り出し待ちを表示して確認を継続。次のラベルを送らない |
| Wi-Fi切断・IP変更・プリンターの電源断 | 同じ製造番号へ再接続し、状態確認から自動復帰 |
| 紙詰まり・用紙切れ・カバー開放など、すべてのプリンターエラー | 画像を送らず監視を継続。エラーが解消して印刷可能になれば自動復帰 |
| エラー解消後、受信済みラベルの成功を確認できた | 完了を通知して次へ進む。同じラベルは再印刷しない |
| エラー解消後も成功を確認できない失敗・送信結果不明 | 待機状態が30秒続いたら再試行し、キューを自動再開 |
| 完了通知だけが通信切断で失われた | 保存した同じ操作IDで通知を再送。ラベルは再印刷しない |
| 認証期限切れ | アクセスコードを再入力すると、保存した処理から監視を継続 |

**送信途中で通信が切れ、受信応答も印刷成功も確認できない場合**は、待機状態が30秒続いたことを確認して再試行します。この場合、実際には印刷済みだったラベルが重複する可能性があります。通信切断をまたぐ物理印刷の完全な重複防止はできません。通常の取り出し待ちや、成功を確認済みのジョブを再送することはありません。

**BeanPrinterのエラー時の再開・印刷結果確認ボタンは廃止しました。** ラベルを取り除くなどしてプリンターが回復すれば、画面操作は不要です。旧版が保存した紙詰まり停止も2.2.5以降の初回起動で自動監視へ移行します。その後、自分で「印刷を停止」を押した場合は停止を保持します。

別端末IDの未解決ジョブ、ジョブ削除や試行IDの競合は勝手に上書きしません。旧APKなど別端末の保留は、実物を確認してBeanCellar側のキューで解消してください。自端末の削除済み記録などの保守操作は、後述のコマンドを使えます。

| 症状 | 確認・対応 |
| --- | --- |
| ZIPが見つからない | 最新ZIPを通常のDownloadへ保存し、ファイルアクセスを許可します |
| 操作画面に接続できない | 更新時は自動再接続を待ちます。それ以外はホーム画面のBeanPrinterから開き直します |
| 起動できない・すぐ終了する | Termuxに表示されたログの場所を確認します。既定は`~/.local/state/beanprinter/beanprinter.log`です |
| ホーム画面にBeanPrinterがない | Termux:Widgetのウィジェットを追加して更新します |
| プリンターが見つからない | 電源・同じLAN・ゲストWi-Fi・VPN・端末間通信設定を確認します |
| 機種・ロール幅で待機 | VC-500Wと50mm CZロールを確認します |
| 認証エラー | アクセスコードを再入力して認証します |
| Python・PDF変換コマンドがない | 手動修復は`pkg install python poppler`です |

## 8. 今回の入れ替えと以後の自動更新

### 2.1以前から更新する場合

このREADMEの冒頭「すでに導入済みの方：今回の更新はここだけ」に、1回コピーする更新手順をまとめています。初回導入用のパッケージ更新を繰り返す必要はありません。古いZIP内・導入済みフォルダー内のREADMEでは新しい手順が表示されないため、この配布物のREADMEを使用してください。

### 自動更新は1日1回・手動更新はボタンから

- **2.2.2以降の自動確認は1日1回（前回の確認から24時間後）**です。初回は認証後に確認し、確認時刻を保存します。再起動しても24時間以内の自動確認を繰り返しません。失敗した確認もこの間隔に含めます。
- ブラウザーのBeanPrinter操作画面で、**印刷キューの下・接続設定の上**にある「ソフトウェア更新」→**「アップデートを確認」**をタップすると、24時間を待たずに最新版を確認します。更新があればダウンロード・検証・適用・再起動まで進みます。最新版なら、その旨を表示します。
- 印刷中は手動の確認要求を保持し、印刷の区切りで確認・適用します。印刷監視が停止中でも、認証済みで更新可能な状態ならボタンを使用できます。手動確認後の次回自動確認も24時間後です。
- 更新情報とZIPは、独立したBeanPrinter配布Siteの同じHTTPS配布先から取得します。BeanCellarのCookieやアクセスコードは配布Siteへ送りません。サイズ・SHA-256・ZIPの構成・Pythonの構文と起動検査を確認します。第三者サイトへのリダイレクトや古い版への更新は許可しません。
- **画像送信中・印刷結果の確認中・未完了通信がある間は適用を待ちます。** 新規ジョブを処理する前など、記録を引き継げる区切りで適用します。
- 検証済みのプログラムへ原子的に置き換え、自動再起動します。**更新前に印刷監視中なら「印刷を開始」を押し直さずに再開します。** 更新前・更新中に「印刷を停止」を押した状態は保持します。旧版の紙詰まり停止だけは、2.2.5以降の起動時に自動監視へ移行します。ブラウザーも自動で再接続・版変更時に再読み込みします。更新中に一時的に接続待ちと表示される場合があります。
- ダウンロード・検証に失敗した場合は現在の版で継続し、24時間後に自動で再確認します。すぐに再試行したいときは「アップデートを確認」を押します。直前のPythonファイルは`~/.local/state/beanprinter/beanprinter.previous.py`に保管します。更新後のすべての動作を監視して自動で旧版へ戻す機能ではありません。

2.2.0以降が稼働中なら、印刷の区切りで自動更新できます。2.2.2以降はキュー下の「アップデートを確認」でも更新できます。自動確認は2.2.2以降で1日1回です。旧版の紙詰まり・結果不明で更新が進まない場合は、冒頭の1回コピーする手動更新を使ってください。

2.2.3では接続確認・プリンター設定保存・PDF変換環境の確認を共通化しました。操作画面は古い通信応答で表示を戻さず、別の操作の応答を待っていても「印刷を停止」を送信します。ブラウザーの保存領域が使えない場合も、ホーム画面から開いたURLで操作を継続できます。

2.2.4では更新と終了処理が重なる場合の開始状態の消失を修正しました。サービスと最後の操作が終わってから状態を保存し、監視中なら自動再開します。再開時はその旨を画面に表示します。

2.2.5では紙詰まりを特別扱いする停止処理を廃止し、すべてのプリンターエラーを同じ監視・自動復帰処理へ統合しました。旧版の停止記録も移行します。10秒の監視、1日1回の更新確認、フルカットは継続します。プログラムの配布・自動更新先も専用Siteへ移しました。旧版向けにBeanCellar内の配布ZIPも2.2.5へ更新し、一度更新すれば、その後はBeanCellarの再ビルドなしで配布できます。

2.2.6では通常起動・ホーム画面・端末再起動時の起動を共通のバックグラウンド処理にしました。起動後はTermuxの入力欄が戻り、同時に開いても1つのサービスを共有します。更新時は監視状態とブラウザーの接続を引き継ぎます。この版はBeanPrinter専用Siteだけで配布します。2.2.5への移行が完了したため、BeanCellar内の旧ZIP配布は終了し、導入案内も専用Siteへ集約します。

初回の認証後、Termuxが稼働していれば専用Siteへ更新を確認します。BeanCellarのキュー取得先は従来どおりです。AndroidによってTermux自体が停止された場合は、ホーム画面から起動してください。TermuxやPoppler本体の更新はこの機能の対象外です。

## 9. SwitchBot Botでラベルを自動排出する（任意）

**この設定は省略できます。トークンなどを入力しなくてもBeanPrinterは動きます。** 使用する場合は、ラベル排出口でラベルを押し出せる位置へBotを取り付け、既存のHub経由で操作します。タブレットのBluetooth設定や追加アプリの導入、コマンド入力は不要です。ブラウザーを閉じていてもPythonが操作します。

1. SwitchBotアプリで対象のBotを**押すモード**にします。Botの設定で**クラウドサービスを有効**にし、Hubと接続します。Botの押す時間や取り付け位置は、ラベルを1回の操作で取り出せるように調整してください。
2. SwitchBotアプリの「プロフィール」→「設定」→「アプリについて」を開き、アプリバージョンを10回タップします。表示された「開発者向けオプション」→「トークンを取得」から、トークンとシークレットをコピーします。アプリの版・言語によって表記が異なる場合があります。[公式の取得手順](https://github.com/OpenWonderLabs/SwitchBotAPI#getting-started)
3. BeanPrinterの管理ページ下部で「ラベルの自動排出（任意）」→「SwitchBotを設定」を開き、トークンとシークレットを貼り付けて**「Botを探す」**を押します。印刷の処理中は設定を変えられないため、必要なら印刷を停止し、現在の処理が終わってから設定してください。
4. ラベル排出用のBotを名前と機器IDで選びます。IDの手入力は不要です。検索・選択だけではBotを動かしません。次の印刷完了から有効になります。印刷を停止していた場合は「印刷を開始」を押してください。

使わない場合は「自動排出を使わない・設定を削除」を押します。認証情報も削除します。保存する情報はTermux内のアクセス制限した`state.json`だけで、更新・再起動後も引き継ぎます。ブラウザーの保存領域・画面の状態API・ログ・BeanCellar・配布Siteにはトークンやシークレットを渡しません。入力欄は送信時に空になります。

印刷データを受信しただけではBotを押しません。第7節の印刷成功を確認してから[SwitchBot API v1.1](https://github.com/OpenWonderLabs/SwitchBotAPI)へ`press`を1回送ります。APIの受付はラベルが排出されたことの確認ではないため、その後も10秒ごとにプリンターを監視し、安定した待機状態に戻るまで次のラベルを送りません。

**Hub・Botの停止や通信失敗でも、印刷済みラベルを再印刷しません。** 操作結果は自動排出欄に表示します。応答が失われた場合に二重押ししないよう、送信前に記録を保存し、自動更新・再起動・BeanCellarへの完了通知の再送でも同じ指示を送り直しません。このため送信直前の端末停止などではBotが押せないことがあります。その場合はラベルを手で取り出してください。プリンターのエラー監視・自動復帰は継続します。過去の印刷や手動で印刷済みにした記録に対して、後からBotを押すことはありません。

この機能のテストでは外部通信を模擬しています。実機でのHub・Botの応答、取り付け位置、ラベルを押す力と時間は未確認です。

## 補足：端末再起動後の自動起動

ホーム画面からの操作で印刷が成功してから設定します。これは任意です。

1. 同じF-Droidから[Termux:Boot](https://f-droid.org/packages/com.termux.boot/)をインストールし、**アイコンを一度開きます**。
2. Termuxで次を一度コピーして実行します。

```sh
mkdir -p ~/.termux/boot && cp ~/BeanPrinter/beanprinter-boot.sh ~/.termux/boot/beanprinter && chmod 700 ~/.termux/boot/beanprinter
```

次回から、端末起動後に操作画面のサービスと印刷監視をバックグラウンドで開始します。ブラウザーは勝手に開かず、ホーム画面のBeanPrinterで表示できます。未完了処理は第7節の条件で自動復帰します。ログは通常起動と同じ`~/.local/state/beanprinter/beanprinter.log`です。旧版のBoot設定も動きますが、上のコピーで最新版の起動ファイルに揃えられます。解除する場合は`rm ~/.termux/boot/beanprinter`を実行します。[Termux:Boot公式手順](https://github.com/termux/termux-boot#how-to-use)

## 補足：コマンドで使う場合

通常は操作画面だけで使えます。コマンドでの操作を選ぶ場合は、画面で「印刷を停止」を押し、現在の処理が終わってからAndroidの設定でTermuxを強制停止して開き直します。同じ送信記録は二重起動できません。

```sh
cd ~/BeanPrinter
python beanprinter.py setup
python beanprinter.py discover
python beanprinter.py check
python beanprinter.py status
python -u beanprinter.py run
```

複数台を製造番号で選ぶ場合は`setup --serial 製造番号`、IPを手動指定する場合は`configure --printer 192.168.1.50`です。認証し直す場合は`login`、タップ操作へ戻す場合は`ui`を使います。`ui`はバックグラウンドで起動して入力欄を返します。診断のためTermux上にログを出し続ける場合だけ`ui --foreground`を使います。`run`と`ui --foreground`はCtrl+Cで停止できます。通常のバックグラウンド起動は、Termux側でCtrl+Cを押しても停止しません。`--state-dir`で保存先を変えた場合は、そのフォルダーにログを保存します。

通常のプリンターエラーにコマンド操作は不要です。記録の競合などを手動で保守する場合だけ、`recover --job ジョブID --action printed`、`retry`、`discard`を使えます。ジョブIDを実際のUUIDに置き換え、実物の確認後に実行します。`discard`はBeanCellarから削除済みの同じジョブだけが対象です。保留解消後は`resume`を実行してから`run`を再開します。

## フルカットの実装と確認範囲

VC-500W向け公開Python実装の[`--print-cut full`の仕様と通信記録](https://m7i.org/projects/labelprinter-linux-python-for-vc-500w/)を参照しています。BeanPrinterではPythonのソケットAPIでLANプロトコルを直接実装し、すべての印刷要求へ **`<cutmode>full</cutmode>`** を必ず含めます。ブラウザーの印刷ダイアログやAndroidの印刷サービスは使いません。[別のフルカット通信例](https://github.com/corentin-soriano/vc-500w_autocut)

既存PDFを317dpi・634×634pxのJPEGに変換するため、日本語・ロゴ・QR・背景色はBeanCellarのラベルを引き継ぎます。キュー・印刷状態・操作画面の定期確認は10秒間隔です。画像の受信応答だけで完了とせず、印刷中から成功への状態変化を確認します。10秒の間に終了する短い印刷は、受信応答に加えて受信から20秒以上経過し、待機・成功応答が10秒離れた2回の確認で続いた場合に完了とします。これは刃が台紙まで切れたことを独立したセンサーで確認するものではありません。失敗時にハーフカットへ切り替える処理はありません。

管理・操作画面はタブレット自身のローカルアドレス`127.0.0.1`だけで待ち受けます。画面HTMLとAPIの両方でソケットの接続元IP・Host・Originを検証し、公開IPや同じLANの別端末からの接続も許可しません。接続元を名乗る転送ヘッダーは信用しません。公開する専用Siteは配布・導入案内だけで、管理操作や印刷記録は公開しません。操作APIは起動時のトークン（自動更新による再起動では引き継ぐ）と送信元を確認し、認証コードやCookieを画面の状態APIに返しません。セッション情報を含む`ui-session.json`も共有しないでください。

オフラインの検証は次で実行できます。ローカル操作画面の試験に端末内の一時ポートを使いますが、プリンター・本番BeanCellarへの通信や実印刷は行いません。

```sh
cd ~/BeanPrinter
python -m unittest -v test_beanprinter
```

旧版のフルカット成功と、ラベルの取り出し待ちが紙詰まり扱いになる問題は利用者から報告されています。2.2.7はPythonテスト117件に加え、開発用リポジトリでローカル操作画面のJavaScriptテスト10件・配布Siteのテスト4件を実行します。各種エラー中の送信抑止、回復後の完了・再試行、旧停止記録の移行、ローカル接続制限、更新先への認証情報漏出防止、任意のBot連携・成功後の1回操作・送信記録の保持を検証します。画面のスクリプトは制御したDOM・通信・タイマーで実行します。

Linuxの実プロセスで、起動コマンドの終了後も管理画面が応答すること、同時起動・再表示で二重起動しないこと、起動失敗と私有ログの世代管理を確認します。別プロセスで実際に更新を適用し、execで再起動する試験は、監視中・停止中・更新中の停止・旧版の紙詰まり停止・移行後の更新中停止の5条件を扱います。外部HTTPの応答と試験用ポートは置き換えます。この作成環境からAndroidタブレットやVC-500Wを直接操作した実機検証、実ブラウザーによる描画・タップ検証は行っていません。全分岐・全端末での動作を保証するものではありません。開発用リポジトリの`docs/verification.md`に要件とテストの対応、計測範囲、残る未確認条件を記録しています。

ライセンスはAGPL-3.0-or-laterです。`LICENSE`と`NOTICE`を参照してください。
