ちょっといまさら感がありますが、E-paperが大好きな自分としてはいつかやってみたいネタのKindleをJailbreakして好きな画像を表示させることをやってみました。
JailbreakしてSSH接続で温湿度などを表示させた画像を生成してKindleに表示させる方法を見つけたので試してみました。
- Kindle第7世代 KT2 5.7.4 Jailbreak メモ (現在このページにいます)
- Kindle第6世代 PW2 5.12.2.2 Jailbreak メモ
- Kindle第5世代 PW V5.6.1.1 Wifi+3G Jailbreak メモ
イチから自分で完成させることができないので、こちらのすっごく頭の良い方(電気スマートメーターの時もお世話になりました。スマートメーターをハックするUSBドングルのWi-SUNが壊れた?みたいなので今回は使いません。)のページを真似していきます。
以下、作業したメモになります。
Kindle Jailbreak 調査
まずはKindleでJailbreak できるのか調査。
ファームウェアバージョン Kindle 5.16.4は今のところJailbreak できない
以前、自分が買ったKindle Paperwhite第10世代はバージョンが5.16.4に自動的にアップデートされていたのでコレ↓だとJailbreak不可(Wifiを切断しておいてJailbreakできる機会まで待ちます。)
G000PP, G8S0PP | Kindle PaperWhite 4 (2018) WiFi, 8GB | PW4 |
かなり古いKindle 第七世代 4GB WP63GWはVer5.7.4でJailbreak可♪
Kindle 第七世代 4GB WP63GWを2.5千円ほどでオークションで買った。
こちらはファームウェアのバージョンがKindle5.7.4だったのでJailbreak可能でした!
Kindleのバージョン調べ
を見ると、Kindle7世代はシリアル番号が90C6から始まっているのでKT2のよう。
B0C6, 90C6 | Kindle Basic (2014) | KT2, BASIC | [Support added in KindleTool 1.6.3] |
Kindle Jailbreak 参考
ここにJailbreakの方法全て書いてある。
日本語ではここ↓を参考にJailbreakしていく。
Kindle端末のリセット
ホーム右上の点々 > 設定に行き、サイド右上の点々を再びタップすると「端末のリセット」「端末情報」を選べる。
端末情報はKindle5.7.4・シリアル番号の先頭は90C6でKT2と言われるもの。
端末のリセットを実行する。
バッテリーがヘタって動かないのでMicroUSBを取ると電源が落ちる。それとMicroUSBの接触が悪い。
Kindle 初期ファームウェア
ダウンロード
KT2を選ぶ。右クリックで新しいタブで、Downloadボタンを押す。
KT2 factory_KT2_5.6.0_initial MD5: d85a86f5c75b4b9d43648f3b6afd2e84
update_KT2_5.6.0_initial.binがDLされる。
Kindleにコピー
update_KT2_5.6.0_initial.binをKindleをPCで開いたフォルダにコピーする。
買ったKindleはバッテリーがヘタって動かないので、MicroUSBを抜かずに右クリックの取り出しで対応する。
Kindleをアップデート
設定 > 右上点々 > 設定 > 端末オプション > Kindleをアップデートでアップデートする。15分弱くらいかかった。
アップデート終わって自動再起動してPCから取り出し、端末情報を見ると5.6.0になってる!
Kindle Jailbreak
ファームウェアを5.6.0にしたのでJailbreak していきます。
main-htmlviewer.tar.gz Download
以下の部分でDL
main-htmlviewer.tar.gz をKindleをPCで開いたフォルダにコピーする。
Jailbreak 入力
;installHtml
リターンする。
自動再起動して以下のように表示される。
Hotfix Download
このページに必要な物が置いてあるみたい。
JailBreak-1.16.N-FW-5.x-hotfix.zipをDLした。
解凍してUpdate_jailbreak_hotfix_1.16.N_install.binをKindleをPCで開いたフォルダにコピーする。
Hotfix 適用
コピーし終わったらもう一度アップデートする。
設定 > 右上点々 > Kindleをアップデートでアップデートする。
Kindle アップデート
手動アップデート
好きなKindleバージョンをDLしてアップデートすれば良いらしい。
このページのKT2のファイルをDL、5.7.4だったのでコレにする。
あとは同様に設定 > 右上点々 > Kindleをアップデートでアップデートする。
自動アップデートを防ぐ
update.bin.tmp.partialフォルダを作ってKindleトップにコピーしておけばAmazonが勝手にアップデートしないみたい。
Kindle Jailbreak ツールインストール
ツールダウンロード
3つDLした。
3つのツールインストール
それぞれ解凍する。
KUAL-v2.7.31-g702078b-20231104.tar.xzのファイルは2つコピー
KUAL-v2.7.31-g702078b-20231104
KUAL-v2.7.31-g702078b-20231104.tar.xzを解凍して中のKUAL-KDK-2.0.azw2をKindleのdocumentsフォルダにコピー
↓Kindleのdocuments内。
KUAL-v2.7.xx Kindle第7世代 KT2 V5.12.2.2 の場合
7世代のKindle KT2 V5.12.2.2の場合はKUALのファイルが違ったのでご注意ください。3回Jailbreakしてやっと分かった。
Update_KUALBooklet_v2.7.32_install.binをKindleのmrpackagesフォルダにコピーする。
mrpackagesフォルダは下のkual-mrinstaller-1.7.N-r19303の操作でコピーされる。
多分ですがKindle7世代~新型でV5.12.2.2以上の場合は、上の「KUAL-KDK-2.0.azw2」をdocuments内にコピーしてもKUALが表示されない場合は試してみてください。
kual-helper-0.5.N-r18980
解凍した中のextensionsごとKindleのトップにコピーする。
kual-mrinstaller-1.7.N-r19303 MR Package Installer
2つのフォルダをKindleのトップにコピーする。
Kindleのフォルダは以下のようになった。
extensionsの中身↓
KUALを起動
マイライブラリにあるKindle LAUNCHERでKUALを起動してツールをインストールする。
Kindle Launcher(KUAL)を起動して各種ツールを起動する。
ツールインストール
ダウンロード
スクリーンセーバーは使わないけどインストールしてみる。↑USBNetwork HackがWifiでSSH接続を可能にするツール。
Kindle mrpackagesにコピー
(以下間違えてPackages targeting the Kindle 2/DX/DXG/3/4:用をダウンロードしてしまったが?なぜか動いた。
DLして解凍後にbinファイルをKindleのmrpackeagesフォルダにコピーする。
↑コレは、コピーしてもダメだった。
ツールは mrpackagesにコピーでOKみたい。だがUpdate_**ファイルが複数あるのでどれを入れたらいいのか迷う。
Kindle第7世代 KT2 V5.12.2.2はUpdate_usbnet_0.22.N_install_touch_pw.binはエラーでインストールできない。Update_usbnet_0.22.N_install_pw2_and_up.binを入れたらインストールできた。
usbnet
kindle-usbnet-0.22.N-r19297.tar.xzを解凍して中の「Update_usbnet_0.22.N_install_pw2_and_up.bin」をコピーした。
インストール
KUAL(kindle Launcher) > Helper+ ▽ > Install MR Packagesで mrpackeagesに入っているファイルのインストール作業開始。
以下を入れてインストールしたらUSBnetが使えるようになった。SSHできるかな?
USBnetでSSHができる。
Kterm
特に必要ないけどついでにインストールしてみる。
ktermフォルダをKUALのextensionsにコピーして、KindleでKUAL > Helper > Install MR Packagesでインストール
スクリーンセーバー
kindle-linkss-0.25.N-r18981のUpdate_linkss_0.25.N_install_touch_pw.binと、Update_linkss_0.25.N_install_pw2_and_up.binをインストールしたら動いた。
こちら↑の方が詳しく説明されている。
この画像が表示されたらスクリーンセーバーハックは完了。
設定を変更したら、Screen Savers > Restart the framework nowをすると再起動する。
うまく動くけど今回はスクリーンセーバーは使わないので停止しておく。
KindleをWifiでSSH接続できるようにする
ここからが、各部屋の温湿度を表示させる設定の前段階。
USBnet
USBnetでWifiからSSH接続するようにできる。
WifiでSSHを接続できるように「Allow SSH over WiFi」を設定しておく。
「SSH over Wifi」と「Enable verbose mode」もオンにしておく。SSH at boot, SSHD: Use OpenSSHもオンにする。
USBnetの初期化は、タップしても解除されないので右側の▶を押して次ページの「Restore default config」でUSBnet初期化する。
ここまできたらKindleのWifiを接続する。
SSH鍵の生成 ラズパイ4での操作
Raspi4Bにrootパスワード設定されていないので設定する。
rootパスワード設定
初期状態のラズパイでrootのパスワードが作成されていないので作っておく。
$ sudo passwd root
New password:
Retype new password:
passwd: password updated successfully
suでrootになれる。
su
Password:
root@Raspi4B:/home/go#
SSH鍵生成
Raspi4Bでrootで作業、全てリターンを押すと /root/.sshに id_rsaと id_rsa.pubが生成される。
root@Raspi4B:~# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:b8F0eQnuNplWyFmg73I87uITpm4kzO76ynfyV1XjWWU root@Raspi4B
The key's randomart image is:
+---[RSA 3072]----+
| o.. E|
| + * +o|
| o B =.+|
| o + =.o |
| o S o O. |
| + ..o*.. |
| . o o+o= |
| . + +.++ . |
| +*o*oo.+o |
+----[SHA256]-----+
パスワードはなにも入力しないでリターンを押す。(全てリターンだけ押す。)
SSH鍵生成されたか確認
以下が生成されている。
ls /root/.ssh
id_rsa id_rsa.pub
id_rsa.pubをKindleにauthorized_keysとしてコピーする。↓まずはローカルにコピーしておく。
cp /root/.ssh/id_rsa.pub /home/go/authorized_keys
authorized_keysをKindleのusbnet/etcにコピー
生成した鍵をKindleの/usbnet/etcにauthorized_keysをコピー↓
検索で~usbNetwork入力
;debugOn
~usbNetwork
;debugOff
コマンド ;un
最後に;unをホームの検索窓に入力してリターンを押した後にRaspi4Bでroot SSHアクセスするとうまく接続できた!
「SSH over Wifi」と「Enable verbose mode」もオンにしておかないとダメ。
~# ssh 192.168.31.40
ssh: connect to host 192.168.31.40 port 22: Connection refused
root@Raspi4B:~# ssh 192.168.31.40
The authenticity of host '192.168.31.40 (192.168.31.40)' can't be established.
ECDSA key fingerprint is SHA256:65X9gdR9f71y6Fs9qSNZFCez8mJ8RAQ4Lhq+1c46Ttw.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.31.40' (ECDSA) to the list of known hosts.
Welcome to Kindle!
#################################################
# N O T I C E * N O T I C E * N O T I C E #
#################################################
Rootfs is mounted read-only. Invoke mntroot rw to
switch back to a writable rootfs.
#################################################
[root@kindle root]# ls
[root@kindle root]# pwd
/var/tmp/root
[root@kindle root]#
WindowsPCのPowerShellだとパスワード聞かれるので接続できない?みたい。
PS C:\Users\GO> ssh 192.168.31.40
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
SHA256:1XJQmm3sGHrRI7j7RyM8lzmEbBvvg0O+ZpWWwDEfmO8.
Please contact your system administrator.
Add correct host key in C:\\Users\\GO/.ssh/known_hosts to get rid of this message.
Offending ED25519 key in C:\\Users\\GO/.ssh/known_hosts:11
Host key for 192.168.31.40 has changed and you have requested strict checking.
Host key verification failed.
PS C:\Users\GO> ssh 192.168.31.40
The authenticity of host '192.168.31.40 (192.168.31.40)' can't be established.
ED25519 key fingerprint is SHA256:1XJQmm3sGHrRI7j7RyM8lzmEbBvvg0O+ZpWWwDEfmO8.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.31.40' (ED25519) to the list of known hosts.
go@192.168.31.40's password:
Permission denied, please try again.
go@192.168.31.40's password:
Permission denied, please try again.
go@192.168.31.40's password:
go@192.168.31.40: Permission denied (publickey,password,keyboard-interactive).
ラズパイ4を新規インストールしたら繋がらなくなった
なぜかパスワードを聞くようになって接続できない。
root@Raspi4B:~# sudo rm /root/.ssh/known_hosts
root@Raspi4B:~# ssh 192.168.31.40
The authenticity of host '192.168.31.40 (192.168.31.40)' can't be established
ED25519 key fingerprint is SHA256:1XJQmm3sGHrRI7j7RyM8lzmEbBvvg0O+ZpWWwDEfmO8.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.31.40' (ED25519) to the list of known hosts.
Enter passphrase for key '/root/.ssh/id_rsa':
root@192.168.31.40's password:
Permission denied, please try again.
root@192.168.31.40's password:
Permission denied, please try again.
root@192.168.31.40's password:
root@192.168.31.40: Permission denied (publickey,password,keyboard-interactive).
間違ってインストールしたと思ったがしてない 未解決
間違えて、kindle-usbnetwork-0.57.N-r18979のUSBnetを入れてしまったからかもしれない。Update_usbnetwork_0.57.N_uninstall.binをHelper+ ▽ > Install MR Packagesに入れてアンインストール。
以下の2つをインストールした。Update_usbnet_0.22.N_install_touch_pw.bin単体でインストールしようとしたらインストールできなかったので、多分Update_usbnet_0.22.N_install_pw2_and_up.binがインストールされたと思う。
SSH鍵がECDSA→ED25519に変わってる
(2つ目のKindle第6世代 PW2も同様になったが、スクリプトはなぜか正常に動くので不思議に思っていたが、以下のようにPasswordを追加すれば正常に動いた。
mykey = paramiko.RSAKey(filename=private_key_path)
↓
mykey = paramiko.RSAKey(filename=private_key_path, password='pass')
前回SSH鍵作る時にパスワード入れてなかった(かもしれない)からうまくいったのかもしれない。
電源を切ったら鍵を削除
バッテリーがヘタっていてMicroUSB抜くと電源切れるので再起動する。とKeyが変わったと言われる。
root@Raspi4B:~# ssh 192.168.31.40
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:EnyqIeMglLeBP7sOKfWtHidGBlYL5I6wMy8/6++nbpk.
Please contact your system administrator.
Add correct host key in /root/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /root/.ssh/known_hosts:1
remove with:
ssh-keygen -f "/root/.ssh/known_hosts" -R "192.168.31.40"
ECDSA host key for 192.168.31.40 has changed and you have requested strict checking.
Host key verification failed.
ラズパイ4のknown_hostsファイルが邪魔をしているので、毎回MicroUSBプラグ抜いて再起動するたび(バッテリーが効かない場合のみ) known_hostsを削除↓して、新規でSSH接続したときに「yes」を入力して接続。
root@Raspi4B:~# rm .ssh/known_hosts
/mnt/us
SSHでログインできたら、/mnt/usがトップディレクトリ。PCにKindleをUSB接続した時も同じ/mnt/usがトップのフォルダ。
ここ/mnt/usに画像を置いて表示させる。
Kindleの検索まどからの操作 Helper
今回の作業には関係ないけど、Helperコマンドいくつか。
;711
Kindleのホームの検索に「;711」リターンで以下が表示される。
;411
バージョンなどが表示される。
Influxからデータを取得して表示
ここからはラズパイ4からJetson nano(温湿度などのセンシングデータをInfluxDBに保存してある)にアクセスして温湿度データを取得後にPNG画像に出力する作業をしていきます。
InfluxDBから4つの温湿度を取得するPythonスクリプト(テスト)
とりあえずInfluxDBのデータを取得してPuttyで表示するところまでやってみました。
以下をラズパイ4に保存する。(192.168.31.53はInfluxDBが稼働しているJetson nanoのIPアドレス)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#influxDB
from influxdb import InfluxDBClient
client = InfluxDBClient(host='192.168.31.53', port=8086, username='root', password='Pass', database='sensor')
measurement = 'air5'
hosts = ['WxBeacon2', 'Raspi3B', 'raspi3B+', 'M5Stack-Core2']
names = ['室外', '部屋', '寝室', '植物']
for host, name in zip(hosts, names):
# ホスト名にスペースが含まれている場合はダブルクォートで囲む
host_in_query = f'"{host}"' if ' ' in host else f"'{host}'"
query = f'SELECT "temp", "humi" FROM "air5" WHERE host = {host_in_query} ORDER BY time DESC LIMIT 1'
result = client.query(query)
points = list(result.get_points())
if points:
for point in points:
print(f"{name}: Time: {point['time']}, 温度: {point['temp']}, 湿度: {point['humi']}")
else:
print(f"No data for host: {host}")
実行すると以下のようにInfluxDBに保存されているデータが表示される。WxBeacon2はこの時ボタン電池切れで取得できず2日前のデータ・・・
室外: Time: 2023-12-28T13:23:04.126508Z, 温度: 10.55, 湿度: 75.74
部屋: Time: 2023-12-29T23:23:09.945244Z, 温度: 16.81, 湿度: 49.01
寝室: Time: 2023-12-30T01:36:02.667948Z, 温度: 16.32, 湿度: 53.44
植物: Time: 2023-12-30T01:35:54.656944Z, 温度: 16.52, 湿度: 51.4
PIL インストール
PINGイメージとして保存するのにPILが必要、最終的にラズパイのrootで使うのでrootになってからインストールしたほうが良さそう。
su
pip install matplotlib pillow
Raspberry Piに日本語フォントインストール
NotoとIPAexの日本語フォントインストール
sudo apt install fonts-noto-cjk
sudo apt install fonts-ipaexfont
フォントはBoldが好みで3つ試したが3つの中ではNotoSansCJK-Bold.ttcが見やすくて一番よさそう。
font_path = '/usr/share/fonts/opentype/ipaexfont-gothic/ipaexg.ttf'
font_path = '/usr/share/fonts/opentype/noto/NotoSerifCJK-Bold.ttc'
font_path = '/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc'
フォントキャッシュの更新
インストールしたフォントをシステムに認識させる。
sudo fc-cache -fv
インストールされているフォントの確認
日本語が使えそうなフォントは以下(他の日本語フォントではないフォントは省略しています。)
$ fc-list
/usr/share/fonts/opentype/noto/NotoSerifCJK-Bold.ttc: Noto Serif CJK JP:style=Bold
//usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc: Noto Sans CJK JP:style=Regular
/usr/share/fonts/opentype/ipaexfont-gothic/ipaexg.ttf: IPAexGothic,IPAexゴシック:style=Regular
/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc: Noto Serif CJK JP:style=Regular
/usr/share/fonts/opentype/ipaexfont-mincho/ipaexm.ttf: IPAexMincho,IPAex明朝:style=Regular
/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc: Noto Sans Mono CJK JP:style=Regular
/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc: Noto Sans CJK JP:style=Bold
matplotlibは面倒なのでやめた PNG画像保存テスト
取得した温湿度データをPNG画像に保存するときにmatplotlibを使うようになっていましたが、matplotlibはもともとグラフを書くライブラリです。スクリプト作りましたが↓この方法は向いてないのでやめました。
テスト的に書いてみるが、サイズを変更するとグチャグチャになって合わせるのが面倒です。
InfluxDBにアクセスしないでダミーデータでPNG画像生成してみる。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
from PIL import Image
# フォントパスを指定
font_path = '/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc'
font_prop = FontProperties(fname=font_path)
# クエリ結果のデータ(ダミーデータ)
data = {
'室外': {'temp': 25.7,'Time': '2023-12-28T13:23:04.126508Z', 'humi': 49.5},
'部屋': {'temp': 24.7,'Time': '2023-12-29T13:21:04.126508Z', 'humi': 55.5},
'寝室': {'temp': 24.5,'Time': '2023-12-29T13:08:04.126508Z', 'humi': 53.5},
'植物': {'temp': 25.6,'Time': '2023-12-30T13:16:04.126508Z', 'humi': 45.1}
}
fig, ax = plt.subplots(figsize=(10, len(data) * 4)) # matplotlib フィギュアと軸を作成
# データをプロット
for i, (place, values) in enumerate(data.items()):
ax.text(-0.1, i / 4 + 0.3, place, fontsize=50, fontproperties=font_prop)
ax.text(-0.1, i / 4 + 0.3 - 0.09, f'{values["temp"]}°C {values["humi"]}%', fontsize=90, fontproperties=font_prop)
time = datetime.datetime.strptime(values["Time"], '%Y-%m-%dT%H:%M:%S.%fZ')
ax.text(0.5, i / 4 + 0.3 - 0.13, f'{time.strftime("%Y-%m-%d %H:%M:%S")}', fontsize=30, fontproperties=font_prop)
# 日付と更新日時を表示
now = datetime.datetime.now()
ax.text(1.05, -0.1, now.strftime('%H:%M:%S'), fontsize=26, fontproperties=font_prop, ha='right', transform=ax.transAxes)
ax.text(1.05, -0.06, now.strftime('%Y-%m-%d'), fontsize=26, fontproperties=font_prop, ha='right', transform=ax.transAxes)
ax.axis('off') # 軸を非表示にする
plt.savefig('temp.png', dpi=300) # フィギュアを保存
img = Image.open('temp.png') # 画像を開く
img_resized = img.resize((1072, 1448)) # 画像のサイズを変更
img_resized.save('temp2.png') # 画像を保存
ax.axis(‘off’)にすると以下のようにグラフの線が表示される。
上画像は上下左右に余白ありすぎますが、plt.subplotsのオプションtight_layout=Trueを追加すると画面めいいっぱい使ってくれます。↓
InfluxDBからデータを取ってきてmatplotlibを使ったPNG画像生成
うまくいくかに見えたが、Kindleで表示させてみると画像の一部しか表示されない・・・サイズ変更するとガタガタになるのでmatplotlib使うのやめた。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
from PIL import Image
# フォントパスを指定
font_path = '/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc'
font_prop = FontProperties(fname=font_path)
#influxDB
from influxdb import InfluxDBClient
client = InfluxDBClient(host='192.168.31.53', port=8086, username='root', password='Pass', database='sensor')
import pytz
utc = pytz.utc
jst = pytz.timezone('Asia/Tokyo')
from dateutil.parser import parse
measurement = 'air5'
hosts = ['WxBeacon2', 'Raspi3B', 'raspi3B+', 'ESP32-plant']
names = ['室外', '部屋', '寝室', 'Hot']
fig, axs = plt.subplots(len(hosts), 1, figsize=(15, 15), tight_layout=True) # matplotlib フィギュアと軸を作成
for i, (host, name) in enumerate(zip(hosts, names)):
host_in_query = f'"{host}"' if ' ' in host else f"'{host}'"
query = f'SELECT "temp", "humi" FROM "air5" WHERE host = {host_in_query} ORDER BY time DESC LIMIT 1'
result = client.query(query)
points = list(result.get_points())
ax = axs[i]
if points:
for point in points:
time_str = point['time']
time = parse(time_str)
time = time.astimezone(jst)
print(f"{name}: Time: {time.strftime('%Y-%m-%d %H:%M:%S')}, 温度: {point['temp']}, 湿度: {point['humi']}")
#ax.axis('off') # 軸を非表示にする
ax.text(-0.25, 0.9, names[i], fontsize=60, fontproperties=font_prop)
ax.text(-0.1, 0.7, f'{point["temp"]}', fontsize=120, fontproperties=font_prop)
ax.text(1, 0.2, f'{point["humi"]}', fontsize=50, fontproperties=font_prop)
ax.text(0.75, 0.2, f'°C', fontsize=60, fontproperties=font_prop)
ax.text(1, -0.16, f'{time.strftime("%Y-%m-%d %H:%M:%S")}', fontsize=30, fontproperties=font_prop)
# 日付と更新日時を表示
now = datetime.datetime.now()
ax.text(0.8, 0, now.strftime('更新 %Y-%m-%d %H:%M:%S'), fontsize=30, fontproperties=font_prop, ha='right', transform=ax.transAxes)
plt.savefig('kindle.png', dpi=300) # フィギュアを保存
img = Image.open('kindle.png') # 画像を開く
#img = img.resize((768, 1024)) # 画像のサイズを変更
img_8bit = img.convert('L') # 画像を8ビットに変換
img_8bit.save('kindlesize.png') # 画像を保存
figsize=(15, 15)あたりを変更すると良いのですが・・・そもそもがmatplotlibはグラフを生成するライブラリなので、文字を並べるのには向いてない。
↑上のスクリプトで一応はPNG画像を生成できます。
それと、Kindle 第七世代は300PPI、横600X縦792ピクセルっぽいので生成する画像サイズを間違えていた。
PillowでPNG画像生成スクリプト
matplotlibよりもPillowを使ったほうが良いみたいなのでスクリプト変更。
Pillowインストール
su
pip install pillow
ModuleNotFoundError: No module named ‘dateutil’が表示されたら以下をインストール
pip install python-dateutil
PNG画像生成スクリプト
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime
from PIL import Image, ImageDraw, ImageFont
from influxdb import InfluxDBClient
import pytz
from dateutil.parser import parse
font_path = '/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc'
font100 = ImageFont.truetype(font_path, 100)
font80 = ImageFont.truetype(font_path, 80)
font60 = ImageFont.truetype(font_path, 60)
font20 = ImageFont.truetype(font_path, 20)
#influxDB
client = InfluxDBClient(host='192.168.31.53', port=8086, username='root', password='Pass', database='sensor')
#日本時間に時刻合わせ(InfluxDBClientがUTCに合わせちゃうので修正)
utc = pytz.utc
jst = pytz.timezone('Asia/Tokyo')
measurement = 'air5'
hosts = ['WxBeacon2', 'Raspi3B', 'raspi3B+', 'ESP32-plant']
names = ['室外', '部屋', '寝室', 'Hot']
img = Image.new('L', (600, 792), color = 255)
d = ImageDraw.Draw(img)
for i, (host, name) in enumerate(zip(hosts, names)):
host_in_query = f'"{host}"' if ' ' in host else f"'{host}'"
query = f'SELECT "temp", "humi" FROM "air5" WHERE host = {host_in_query} ORDER BY time DESC LIMIT 1'
result = client.query(query)
points = list(result.get_points())
if points:
for point in points:
time_str = point['time']
time = parse(time_str)
time = time.astimezone(jst)
print(f"{name}: Time: {time.strftime('%Y-%m-%d %H:%M:%S')}, 温度: {point['temp']}, 湿度: {point['humi']}")
d.text((3,180*i), f"{name}", fill=0, font=font60)
d.text((10,45+180*i), f"{point['temp']}", fill=0, font=font100)
d.text((275,140+180*i), f"°C", fill=0, font=font20)
d.text((350,70+180*i), f"{point['humi']}", fill=0, font=font80)
d.text((570,135+180*i), f"%", fill=0, font=font20)
d.text((380,160+180*i), f"{time.strftime('%Y-%m-%d %H:%M:%S')}", fill=0, font=font20)
now = datetime.datetime.now()
d.text((340,10), now.strftime('更新 %Y-%m-%d %H:%M:%S'), fill=0, font=font20)
img.save('/home/go/script/kindle.png')
PNG画像の保存は/home/go/script/kindle.pngに保存しました。
Hotは植物用のホットカーペットの温度です。
生成したPNG画像kindlesize.pngは↑こんな感じになってうまくいった。(湿度の下にある日付時刻はそれぞれのセンサーがInfluxDBにデータを送った時刻)
一番下の更新はPNG画像を生成した時刻。
KindleにPNG画像を定期的に送る
ラズパイ4でPNG画像を生成できたので、最後にPNG画像をKindleに送る設定をしていきます。
paramiko インストール
paramikoはPythonでSSH接続してコマンド操作できるライブラリ。
ラズパイ4のrootで操作するのでrootになってからインストールする。
su
pip install paramiko
フレームワークとスリープ停止
Kindleを操作する必要がなくなるので、両方停止する。
ラズパイ4から以下のように操作。
ssh root@192.168.31.40 'initctl stop powerd'
ssh root@192.168.31.40 'initctl stop framework'
Kindleを再起動するとGUI(フレームワーク)もスリープも復活して使えるようになる。
でも画像を送りつけると?スクリーンセーバーは復活しないかな?電源ボタンを押しても反応しなくなる。
KindleへPNG画像送信スクリプト 無限ループ版
上で紹介したスクリプトkindle_influx.pyでPNG画像を生成して以下↓のスクリプトでKindleに画像を定期的に送信しています。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#python kindle_send.py
#WifiSSHを有効にする。(電源を切るごとに1,2をrootで実行する)
#1,rm /root/.ssh/known_hosts
#2,Kindleの検索で「;un」を実行する。
#テスト表示: ssh root@192.168.31.40 '/usr/sbin/eips -g /mnt/us/kindlesize.png'
import paramiko
import subprocess
import time
import os
KINDLE_IP = '192.168.31.40'
UPDATE_SEC = 300
REFRESH = 180
private_key_path = "/root/.ssh/id_rsa"
mykey = paramiko.RSAKey(filename=private_key_path)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(KINDLE_IP, username='root', pkey=mykey)
ssh.exec_command('initctl stop powerd')
ssh.exec_command('initctl stop framework')
sftp = ssh.open_sftp()
i = 0
while True:
proc = subprocess.Popen(['python' , '/home/go/script/kindle_influx.py'])
out, err = proc.communicate()
if proc.returncode != 0:
print(f"kindle_influx.py failed with error: {err}")
break
if os.path.exists('/home/go/script/kindle.png'):
sftp.put('/home/go/script/kindle.png', '/mnt/us/kindle.png')
ssh.exec_command('eips %s -g /mnt/us/kindle.png' % ('-f' if (i % REFRESH) == 0 else ''))
else:
print("kindlesize.png does not exist or is not accessible")
time.sleep(UPDATE_SEC)
i += 1
sftp.close()
ssh.close()
上記スクリプトはkindle_send.pyとして保存してcronで起動時に1回だけ実行するようにしました。
InfluxDBが稼働しているJetson nanoが非力でInfluxDBに頻繁にアクセスするとJetson nanoのUSBについているWifiドングルが切断してしまうので、UPDATE_SECを長めの5分にしてあります。
(早くRaspberry Pi 5が普及し始めてほしいところ。)
最後にCronでPythonスクリプトkindle_send.pyをラズパイ4起動時に実行するように設定します。
su
crontab -e 以下入力
@reboot sleep 60; /usr/bin/python /home/go/script/kindle_send.py
reboot
KindleへPNG画像送信スクリプト cronで定期的に実行版
無限ループよりもCronで定期的に実行するほうがいいかな?
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import paramiko
import subprocess
import os
KINDLE_IP = '192.168.31.40'
private_key_path = "/root/.ssh/id_rsa"
mykey = paramiko.RSAKey(filename=private_key_path)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(KINDLE_IP, username='root', pkey=mykey)
ssh.exec_command('initctl stop powerd')
ssh.exec_command('initctl stop framework')
sftp = ssh.open_sftp()
proc = subprocess.run(['python' , '/home/go/script/kindle_influx.py'], capture_output=True, text=True)
if proc.returncode != 0:
print(f"kindle_influx.py failed with error: {proc.stderr}")
if os.path.exists('/home/go/script/kindle.png'):
sftp.put('/home/go/script/kindle.png', '/mnt/us/kindle.png')
ssh.exec_command('eips -f -g /mnt/us/kindle.png')
else:
print("kindle.png does not exist or is not accessible")
sftp.close()
ssh.close()
こちらは5分おきにcronで実行するPythonスクリプト
su
crontab -e
*/5 * * * * /usr/bin/python /home/go/script/kindle_send.py
完成です♪
植物を育ててると温湿度が気になる
ここ3・4年は趣味として植物を育てているので冬や真夏は温度と湿度が気になります。
なので、外の気温を含めた室内の気温を大きめのE-paperで表示するのにはピッタリ。
20代のころは必ず枯らしていたティランジアも育てられるようになって、アガベも水やりのコツをやっと分かってきた初心者。(パキポディウムの実生は未だに2,3株しかうまくいってない。難しい・・・)
古いKindleのプロジェクトなのでお役に立てるかどうか、分かりませんがE-paper好きな方はぜひチャレンジしてみてくださいね。
コメント
警告が出てしまうのでHTTPSに対応してほしいです。
コメントありがとうございます。
ありがとうございます!SSLが効いてませんでした。修正しておきました。