PepperからAirPrintで印刷してみた。

きっかけはとある相談から始まった。
「Pepperで撮影した写真をプリントアウトするような機能ってありませんか。Pepperと連携可能な写真プリンタの機能要件などご存知でしょうか。」

最初、「Pepperからlprコマンドを叩けばOKでしょ。」と安易に思いついたが、長い道のりの始まりだった。

「あれ？！lprコマンドが無い。」
PepperへSSHでログインしてlprコマンドを探してみたが存在しなかった。
$ which lpr
which: no lpr in (/home/nao/.local/bin:/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/local/sbin:/usr/sbin:/sbin)

さて、どうしたものかと検索したら、Pepperとプリンターの間にPCを挟んで実現している例は見つかった。
参考：
http://www.nct-inc.jp/engineer_blog/721/
ただ、この方法だとPCからPepperのALMemoryを監視しているので、Pepperからプリンターへ直接印刷している感じがしないし、印刷するデータをPCへ渡す手段を別に考えないといけないので、別の手段(Pepperからプリンターへ直接印刷する手段)を模索する旅が始まった。

最初に考えたのが、lprのソースコードを持ってきてPepper用にビルドする方法である。
id:takuji_kawataさんの「OpenNAO OS VirtualBox を使って NAO (Pepper) を機能拡張してみる」という記事を思い出した。
参考：
http://tkawata.hatenablog.com/entry/2016/08/13/230752

AldebaranのコミュニティホームページからOpenNAO OS VirtualBox 2.1.2のイメージファイルをダウンロードしてきて、母艦(Mac)上のvirtualboxで起動する。
virtualboxでopennao-vm-2.1.2.17を起動後、母艦(Mac)からSSHで接続する。
virtualboxのネットワークの初期設定はNATで、port forwardingの設定(ホスト Port:2222 → ゲスト Port:22)がされている。
$ ssh -p 2222 nao@localhost

パッケージ管理ツールemergeでlprコマンドのインストールを試して見る。
参考：
http://www.atzm.org/gentoo/original1.html

※注意 … パッケージ情報を更新するとemergeコマンドが実行できなくなるのでやっちゃダメ。
$ emerge --sync
$ emerge
!!! /etc/make.profile is not a symlink and will probably prevent most merges.
!!! It should point into a profile within /usr/portage/profiles/
!!! (You can safely ignore this message when syncing. It's harmless.)
!!! Your current profile is invalid. If you have just changed your profile
!!! configuration, you should revert back to the previous configuration.
!!! Allowed actions are limited to --help, --info, --search, --sync, and
!!! --version.

lprコマンドをインストールする。
$ sudo emerge net-print/lprng

lprコマンドを実行する。
$ lpr
Get_local_host: hostname 'virtual-nao' bad
エラーが出て'virtual-nao'というホスト名を/etc/hostsへ登録する必要がある。

と、ここでPepper上でコマンドを実行することを想定した場合、Pepper内の環境設定ファイルを変更するのは現実的な手段ではないことに気がつく。
さて、困ったものだなぁと思いながらリモートで接続されたプリンターへ印刷する手段を調べていたところ、最近はLPR/LPD(Line Printer Daemon protocol)プロトコルを使用せず、IPP(Internet Printing Protocol)プロトコルを使用しているとのことで、CUPS(Common Unix Printing System)と呼ばれるツールがサポートしていることが判明。
他にCIFS(Samba)プロトコルを使用する手段が存在するが、Kernelがサポートする必要があるということで、これもPepper上で実行するには現実的な手段ではないと判断。
参考：
https://wiki.gentoo.org/wiki/Printing/ja

cupsをインストールする。
$ sudo emerge net-print/cups
しかし、エラーが出る。

仕方がないので、ソースコードからビルドすることにする。
$ git clone https://github.com/apple/cups
$ cd cups/
$ ./configure 
$ make
正常に完了。

ipptoolコマンドで印刷してみる。
参考：
http://stackoverflow.com/questions/19232082/printing-using-ipp-without-drivers-ipp-client

ipptoolコマンドがあるディレクトリへ移動する。
$ cd test

printfile.ippファイルを作成する。
内容：
{
OPERATION Print-Job
GROUP operation-attributes-tag
ATTR charset attributes-charset utf-8
ATTR language attributes-natural-language en
ATTR uri printer-uri $uri
FILE $filename
}

※2017/3/4追記
AirPrintに対応したプリンター(例.EP-879A)を用意する。
まず、ブラウザからプリンターへアクセスする。
※プリンターに割り当てられたIPアドレスが「192.168.3.51」の場合、「192.168.3.51:631」へアクセスする。
![スクリーンショット 2017-03-04 23.13.15.png](https://qiita-image-store.s3.amazonaws.com/0/72479/57394bd0-cc20-9c7f-f823-95595ce9c823.png)

次に「AirPrint設定」をクリックして、IPP接続情報を確認する。
この場合、Bonjour名は「EPSOND7E1AA.local」で、プリンター名は「ipp/print」であることが分かる。
![スクリーンショット 2017-03-04 23.28.48.png](https://qiita-image-store.s3.amazonaws.com/0/72479/b7c68ef9-3493-2002-8613-f9d212ba2d25.png)
![スクリーンショット 2017-03-04 23.15.46.png](https://qiita-image-store.s3.amazonaws.com/0/72479/ba376bda-414c-718a-8f4b-ddc0c28ff3d0.png)

それでは、サンプル画像ファイルを共有プリンタへ印刷する。
$ ./ipptool-static -tv -f sample.jpg ipp://192.168.3.51:631/ipp/print printfile.ipp
※sample.jpgはサンプル画像ファイル名。192.168.3.51はプリンターのIPアドレス。ipp/printはプリンター名。

(出力)
"printfile.ipp":
    Print-Job:
        attributes-charset (charset) = utf-8
        attributes-natural-language (naturalLanguage) = en
        printer-uri (uri) = ipp://192.168.3.51:631/ipp/print
    printfile                                                            [PASS]
        RECEIVED: 239 bytes in response
        status-code = successful-ok (successful-ok)
        attributes-charset (charset) = utf-8
        attributes-natural-language (naturalLanguage) = en
        job-uri (uri) = ipp://192.168.3.51:631/jobs/2
        job-id (integer) = 2
        job-uuid (uri) = urn:uuid:a420585e-86c6-4072-a35e-e8e3fd1d6abb
        job-state (enum) = processing
        job-state-reasons (keyword) = job-printing

正常に印刷できた。めでたし。めでたし。
![プリント結果.jpg](https://qiita-image-store.s3.amazonaws.com/0/72479/cda7c82c-2d53-d3f8-b9b9-5620c1e14735.jpeg)

AirPrintに対応したプリンターを用意できない場合は母艦(Mac)のプリンターを共有する。
![スクリーンショット 2017-01-20 18.27.12.png](https://qiita-image-store.s3.amazonaws.com/0/72479/06247afa-edbb-7660-aafc-a5e444610399.png)

紙へ印刷したくない場合は印刷をPDF化する仮想プリンターを追加して共有する。
参考：CUPS-PDFの代わりにVipRiserをインストール
http://5zalt.hatenablog.com/entry/2014/11/14/150208

または、ラズパイをAirPrintサーバ化する方法もあるようだ。
参考：Raspberry PiをAirPrintサーバ化して、iPadでAirPrint非対応プリンタで印刷するまで
http://qiita.com/keita1987/items/35172a731f932444e1fa

それでは、サンプル画像ファイルを共有プリンタへ印刷する。
$ ./ipptool-static -tv -f color.jpg ipp://192.168.3.6/printers/Print_to_VipRiser printfile.ipp
※color.jpgはサンプル画像ファイル名。192.168.3.6は母艦(Mac)のIPアドレス。printers/Print_to_VipRiserは共有した仮想プリンター名。

正常に印刷できた。まずは、めでたし、めでたし。
![スクリーンショット 2017-01-07 20.51.58.png](https://qiita-image-store.s3.amazonaws.com/0/72479/9dfb6d49-fa8a-017f-fe0f-b9689028acf6.png)

ビルドしたipptool-staticとprintfile.ippファイルはこちらに置いておきます。
https://github.com/kitazaki/ipptool/raw/master/ipptool.zip

さて、これからが実機(Pepper)での動作確認手順となるが、Choregrapheで新規にプロジェクトを作成して、以下のように各種ファイルを配置する。
![スクリーンショット 2017-01-20 18.44.50.png](https://qiita-image-store.s3.amazonaws.com/0/72479/45fc6aa1-7c58-65cc-80f3-c65571f09876.png)
※プロジェクト名は20170118_ipptoolにしました。
※htmlフォルダを作成し、htmlフォルダの中にipptool-static、printfile.ipp、test.jpg(サンプル画像)を配置する。

ボックスライブラリは Programming -> System Actions -> Reboot を拝借しました。
![スクリーンショット 2017-01-20 18.49.30.png](https://qiita-image-store.s3.amazonaws.com/0/72479/081b6819-b527-3429-1145-586b80577dd0.png)

Rebootボックスをダブルクリックしてコードの編集画面を開く。
![スクリーンショット 2017-01-20 18.41.22.png](https://qiita-image-store.s3.amazonaws.com/0/72479/c1311b10-8aad-f332-3e07-9dc595837836.png)
※1行目でosモジュールを読み込む。
※16行目でipptoolコマンドを実行する。(bmnm2543000031.localは母艦(Mac)のBonjourのホスト名です。RICOH_imagio_MP_C2800は母艦(Mac)で共有したプリンター名です。

Choregrapheの全体像はこんな感じ。(Show Imageボックスはサンプル画像(test.jpg)をタブレットへ表示するだけです。)
![スクリーンショット 2017-01-20 18.40.17.png](https://qiita-image-store.s3.amazonaws.com/0/72479/fb17448d-b148-4010-15d1-6948b9be9997.png)

正常に印刷できた。めでたし、めでたし。
![スクリーンショット 2017-01-20 19.04.11.png](https://qiita-image-store.s3.amazonaws.com/0/72479/5bc75c7e-cec4-4cd9-df4e-f59391328302.png)

応用事例としてはPepperにチェキを撮ってもらって、その場で直ぐにプリンターへ印刷して、プレゼントするようなアプリが考えられる。(このアプリの制作過程については次回の記事に。）

Pepperから汎用的な出力手段(ネットワークプリンターへ印刷する手段)が確立できたので、今後、応用事例がたくさん出てくることを期待しながら、みなさまの一助になればと思います。

※2017/5/20追記
Pepperを2.4.3から2.5.5へバージョンアップしたら動作しなくなったと問い合わせを受けたので調べてみたところipptoolで必要となるライブラリのバージョンが上がっていることが判明。
OpenNAO 2.1.2　→/usr/lib/libgnutls.so.26
Pepper 2.4.3　→/usr/lib/libgnutls.so.26
Pepper 2.5.5　→/usr/lib/libgnutls.so.<FONT COLOR=#FF0000>28</FONT>

[解決方法1]
Pepperへssh(naoアカウント)でログインし、libgnutls.so.26からlibgnutls.so.28へシンボリックリンクを作成し、環境変数LD_LIBRARY_PATHを設定してipptoolコマンドを実行する。
$ ln -s /usr/lib/libgnutls.so.28 /home/nao/libgnutls.so.26
$ LD_LIBRARY_PATH=/home/nao ipptool-static

[解決方法2]
cupsをビルドする際にSSL/TLSサポートを無効化する。
$ ./configure --disable-ssl
プリンター側で非セキュア通信を許可する設定へ変更する。
![スクリーンショット 2017-05-20 15.52.28.png](https://qiita-image-store.s3.amazonaws.com/0/72479/0052e5d6-d795-9838-9a07-2a6076ce87e1.png)