古い kindle をメッセージボードとして再利用

## １．はじめに
もう使わなくなった古い kindle 3G を、メッセージボードとして利用してみました。
LINE からメッセージを送ることで、表示内容を変更します。下記のようになります。
※更新されるまで 10 分ほどかかります。
![LINE.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246034/f9ac8d9d-ea96-3066-b1c6-131ad3e7fa59.png)　![kindle.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246034/287e8ba8-22d7-a6a5-60b3-cc565ef57c62.jpeg)



## ２．脱獄
ここでは詳しく説明していませんので、ネット上の情報などを参考にしてください。
USB 経由でファイルを kindle 上のフォルダに置き、アップデートするだけなので簡単です。

https://www.mobileread.com/forums/showthread.php?t=88004
上記から以下のファイルをダウンロードし、インストールしました。
kindle-jailbreak-0.13.n.zip 
kindle-ss-0.47.n-r17940.tar.xz
kindle-usbnetwork-0.57.n-r17940.tar.xz
kindle-python-0.14.n-k3g.zip

脱獄後は、"↑" "T" "T" で、Linux のプロンプトが現れます。
キー操作については、以下の URL に説明があります。
https://www.mobileread.com/forums/showthread.php?t=154500

必要に応じて root パスワードやネットワークなどを設定し、ネットワーク経由でログインできる環境を整備します。

## ３．バッテリー対策、必須じゃないけど・・・

古い kindle では、バッテリーが寿命に近づいている場合が多いと思います。わたしは念のために下記の対策を行いました。
kindle 3 は、デフォルトでは内部バッテリーが一定の電圧（3.0 ~ 4.2V) 以上を保っていないと起動しません。
じゃあ乾電池とか、適当な電池を接続すれば動作するのでは？ と考えるかもしれませんが、電圧情報はバッテリーから kindle へ I2C バスを経由して送られるため、電源供給しただけでは起動しません。

そこで、kindle 起動時のバッテリー電圧のチェック部分をスキップするように下記のように変更しておきます。

```
# mount -o remount,rw / 　  書き込みできるように再マウントし、
# vi /etc/init.d/battcheck
...中略...
# Don't check battery if we're on prototype/reference hardware
_SKIP_CHECK=1               ここを 0 から 1 へ変更します。
```

十分にはテストしていませんが、I2C の SCL, SDA ラインを接続しなくても起動できるところまでは確認しました。

下記の URL の方は、バッテリーを取り外し、レギュレータを介して＋と－端子のみに電圧供給していますね。
将来、完全にバッテリーがお亡くなりになったら真似するつもりです。
https://www.tablix.org/~avian/blog/archives/2013/03/on_kindle_power_supply/

## ４．LINE のイベントを Webhook で heroku へ送る設定

以下を参考にさせていただきました。とてもわかりやすく解説されています。
[LINEのBot開発 超入門（前編） ゼロから応答ができるまで](https://qiita.com/nkjm/items/38808bbc97d6927837cd)

Line Developers のページでの Messaging API の設定は、こんな感じです。
![webhook.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246034/3bd499b6-5d15-691c-a57f-f6bcab922ad1.jpeg)

## ５．heroku 側のプログラム作成

"!" から始まるメッセージを受け取ると、! の次の文字からメッセージを保持し「kindle に伝えとくよ」メッセージを送ります。kindle 側から HTTP GET にて取りだされると 「kindle 受け取りました」 メッセージを送ります。

```
// -----------------------------------------------------------------------------
// モジュールのインポート
const server = require("express")();
const line = require("@line/bot-sdk"); // Messaging APIのSDKをインポート

// -----------------------------------------------------------------------------
// パラメータ設定
const line_config = {
    channelAccessToken: process.env.LINE_ACCESS_TOKEN, // 環境変数からアクセストークンをセットしています
    channelSecret: process.env.LINE_CHANNEL_SECRET // 環境変数からChannel Secretをセットしています
};

// -----------------------------------------------------------------------------
// Webサーバー設定
server.listen(process.env.PORT || 3000);

// APIコールのためのクライアントインスタンスを作成
const bot = new line.Client(line_config);

var kindle    = "";     // kindle message
var http = require('http');

// -----------------------------------------------------------------------------
// ルーター設定
server.post('/bot/webhook', line.middleware(line_config), (req, res, next) => {
    // 先行してLINE側にステータスコード200でレスポンスする。
    res.sendStatus(200);

    // すべてのイベント処理のプロミスを格納する配列。
    let events_processed = [];

    // イベントオブジェクトを順次処理。
    req.body.events.forEach((event) => {
        var userId = event.source.userId;
        // 招待イベントに答える
　　　　if (event.type == "join" ) {
            // replyText(event.replyToken, `Joined ${event.source.type}`);
            console.log("JOIN event!");
        }
        // この処理の対象をイベントタイプがメッセージで、かつ、テキストタイプだった場合に限定。
        if (event.type == "message" && event.message.type == "text"){
            // ! で始まるメッセージを kindle 宛てメッセージとしています。
            if ( event.message.text.startsWith("!") ) {
                events_processed.push(bot.replyMessage(event.replyToken, {
                    type: "text",
                    text: "kindle に伝えとくよ。"
                }));
                kindle = event.message.text.substr(1);
            }
        }
    });
});

server.get('/bot/kindle', (req, res) => {
    res.end (kindle);
    if( kindle != "" ) {
        kindle = "";
        bot.pushMessage('xxxx user id xxxxx ', {
            type: "text",
            text: "kindle 受けとりました"
        });
    }
});

```

## ６．kindle 側のプログラム作成
以下の設定などを行います。
1. フォントファイルのダウンロード - png ファイルを作成するための用意
2. シェルの作成　- curl で heroku に問い合わせ、png ファイルを作成
3. cron の登録　- 5分に一回 シェルを実行する

いい感じのフォント、瀬戸フォントを利用しました。
https://nonty.net/font/ から SetoFont v6.20 をダウンロードします。

次に、表示する png ファイルを作成するスクリプトを書きます。 kindle-ss-0.47 に ImageMagick の convert コマンドが含まれていますので、これを使います。
ただし、フォントサイズの認識に不具合がある様子で、正しいサイズにならないようです。
原因を突き詰めてはいませんが、改行の数を増やすことで対処しています。
出来上がったシェルは以下となります。

```
#!/bin/bash
MSG_FILE="/mnt/us/abc/message"
SLEEP_FILE="/mnt/us/abc/need_sleep"

# 文字位置の調整として、1改行を3改行に増加
/usr/bin/curl --silent https://私のheroku ID.herokuapp.com/bot/kindle | \
awk '{ print $0"\n\n" }' > $MSG_FILE

# 再起動後、スクリーンセーバの画像表示させるためスリープモードにする。
# LINE からのメッセージがなければ終了
if [ ! -s $MSG_FILE ] ; then
    if [ -s $SLEEP_FILE ] ; then
        GotoSleep=`cat $SLEEP_FILE`
        if [ $GotoSleep -eq 1 ] ; then
            /usr/bin/powerd_test -p
            echo 0 > $SLEEP_FILE
        fi
    else
        echo 0 > $SLEEP_FILE
    fi
    exit
fi
echo 1 > $SLEEP_FILE

# line メッセージより png ファイルを作成
/mnt/us/linkss/bin/convert -size 800x600 -font /mnt/us/abc/setofont.ttf \
-pointsize 38 -gravity Center -draw "text 0,20 '$(cat $MSG_FILE)' " \
-pointsize 22 -gravity South label:"私の名前：　会社携帯 080-1234-1234" \
/mnt/us/abc/00out.png 2>/mnt/us/abc/convert.error

# 90°　回転させ、スクリーンセーバのディレクトリへ配置
/mnt/us/linkss/bin/convert /mnt/us/abc/00out.png -rotate +90 \
/mnt/us/linkss/screensavers/00out.png

# 再起動
reboot
```

上記のシェルを 5 分に一回実行させるために cron に登録します。

```
# mount -o remount,rw / 
# vi /etc/crontab/root
... 中略 ... 以下の設定を追加します。
*/5 * * * * /mnt/us/abc/kindle.sh 
```

以上です。実際に作成してみると、いろいろとハマるところがあるかもしれませんが、何かの参考となれば幸いです。