Wi-Fiスマート電球の中の禁書図書館
(richardosgood.com)- Banned Book Library は、Wi-Fiスマート電球を公開アクセスポイント兼Webサーバーに変え、電球が点灯している間、周囲の機器から電子書籍にアクセスできるようにするデジタル・デッドドロップ・プロジェクトである
- ハードウェアは ESP32C3 4MB ベースでTasmotaがプリインストールされた電球から始まり、小さなフラッシュ容量のため、ファームウェア・Webサイト・書籍ファイルをすべて収めるストレージ調整が最大の制約となった
- microSDの追加は、実際の電球内部ではんだ付けや基板の取り外しが難しく、安全に再組み立てするのも困難なため断念され、代わりに パーティションテーブル を修正してファイル保存領域を320KBから2MBに拡張した
- Arduinoだけでは保護されたフラッシュ領域にアクセスできなかったため、ESP-IDF と Arduino as a Component を使用し、別個のsafebootファームウェアとElegantOTAで更新経路を構成した
- 最終的なWebアプリは、書籍一覧、管理パネル、復元機能、キャプティブポータル を備え、4MBという制限のため、1つの電球は多数の本を収めるというより、選ばれた数冊を入れた個人的なライブラリに近いものになった
概要
- Wi-Fiスマート電球 を改造して、オープンなWi-Fiアクセスポイントと禁書Webサーバーを提供するというアイデアからプロジェクトは始まった
- 電球が点灯していれば、周囲の利用者はWi-Fi対応の電子機器から電球に保存された資料へアクセスできる
- 電球の形なので目立ちにくく、価格も比較的低いため、街のあちこちに置いておくデジタル・デッドドロップとして構想された
- アイデアは Ben Brown の短編 Library に影響を受けており、その物語の「図書館」は、創作物、取扱説明書、3Dモデルなど、インターネットから消えてはならない資料を保管するデジタルアーカイブとして機能する
- 数か月前に実際の作業が始まり、成果物は Banned Book Library として公開された
ハードウェア
- 地元のDEFCONミートアップでアイデアを共有した後、Tasmota を検討することになった
- Tasmotaは、さまざまなスマート機器に導入して、HomeAssistantのようなホームオートメーションシステムと統合できるオープンソースのファームウェアである
- 主な目的は、クラウドサービスに依存せず機器をローカルで制御できるようにすることにある
- 多くのスマート機器は、時間とともに変化したり消滅したりしうるクラウドサービスに依存しており、Tasmotaはそれを内部ホスティングに置き換えられる
- Tasmota自体を直接改変したわけではないが、TasmotaがプリインストールされたWi-Fi電球の販売元を見つけた
- 製品ページには、その電球が
ESP32C3 4MBを使用していると記載されていた - LED制御用のGPIOピンも公開されており、後の作業に役立った
- ピンマッピングは
R=GPIO6,G=GPIO7,B=GPIO5,CW=GPIO3,WW=GPIO4だった
- 製品ページには、その電球が
- TasmotaにはOTAファームウェア更新機能があり、電球を分解せずにカスタムファームウェアを書き込める可能性があった
- 最大の問題は 4MBフラッシュ であり、この中にファームウェア、Webサイト、書籍ファイルをすべて入れなければならなかった
- 実験中に1つ壊してしまう可能性を考え、電球を2個購入した
分解
- 電球上部の白いプラスチック製ディフューザーは、刃物で周囲に2回切れ込みを入れた後、ひねって取り外した
- 内部にはLEDが載った円形の子基板があり、下側の基板と6本のピンで接続されていた
- 中央の穴からメイン基板の一部が上に出ており、この部分はESP32のアンテナだった
- 電球の筐体と子基板はアルミニウム製で、Wi-Fi信号の確保を考慮した設計に見えた
- 子基板を取り外すと、内部の ESP32C3 と、電源変換およびLED駆動用と思われる部品が見えた
- ESP32には露出したピンが複数あり、microSDカードリーダーを取り付けられる可能性があるように見えた
- 電球の内側にはんだごてを入れられないため、メイン基板を取り出す必要があり、ゴムのようなポッティング材をナイフとドライバーで掘り出さなければならなかった
- メイン基板の取り外しは非常に面倒で、再設置後の安全性も信頼しがたく、実際のデッドドロップ設置における必須工程とするには不向きだった
- 分解した電球は開発プラットフォームとして使われ、シリアル書き込みのために VCC、GND、TX、RX、IO9 に配線をはんだ付けした
- AliExpressにある同一モジュールの写真でピンラベルを確認し、VCC、GND、TX、RXの位置を把握した
- GNDは、はんだ付けしやすい金属シールドに接続した
- ダウンロードモードへ入るには、IO9をGNDに落とした状態で起動する方法が使われた
esptoolでファームウェア全体をダンプし、数分後にtasmota_original_firmware.binを確保した
初期実験
-
Hello World
- 当初はTasmotaのソースコードを改変してBanned Book Libraryを作ろうとしたが、ファームウェアは予想以上に複雑で、複数のアーキテクチャや機器をサポートしており、範囲が大きすぎた
- プロジェクトの目的上不要な機能を減らし、保存領域を確保したかったため、Tasmotaの改変は断念した
- ESP32をArduinoでプログラムできることを確認し、Arduino IDEを設定した
- 基本的なHello Worldプログラムを書き込み、シリアルポートにメッセージを送らせることで、電球に直接カスタムファームウェアを書けることを確認した
-
Webサーバー
- 次の段階は、オープンなWi-FiアクセスポイントとWebサーバーを構成することだった
- ESP32 Webサーバーのチュートリアルを参考にしたが、当時の目的はLED制御ではなかったため修正した
- その後 Async Web Server に移行し、関連チュートリアルをベースに実装を進めた
-
microSDカード
- 保存容量を拡張するため、SparkfunのmicroSDブレークアウトボードを購入した
- ESP32C3のデータシートを参照してSDカードリーダーの配線を確認した
- 実際の電球の代わりに、Adafruit ItsyBitsy ESP32 をプロトタイプに使用した。ピンヘッダーのはんだ付けとmicroSD接続がはるかに容易だったためである
- microSDとLittleFSを使ってWebサーバーファイルをホストすることには成功したが、実際の電球へ適用するのが難しく、microSD方式は断念された
- 実際の電球のESP32C3にはんだ付けするには、基板を筐体から取り出す必要があり、事実上デバイスを壊す作業に近かった
- LED制御ピンの再利用も試みたが、その構造ではGPIOはトランジスタをオンにして回路をGNDへ成立させる出力用途にしか使えなかった
- ESP32の上から被せてピンと接触させる3Dプリント製クランプも設計したが、不安定で信頼性が低すぎたため廃案となった
回避策の検討
- よりはんだ付けしやすい電球がないか確認するため、別のスマート電球も調査した
- いくつもの分解記事を探したが、ほとんどは既存の電球と似た内部構造だった
- 一部の電球はESP32ではないチップを使っていたが、すでにESP32のプログラミングを習得していたため、ESP32ベースの電球に絞った
- 地元のハードウェア店で買った電球の1つは似た構造だったが、メイン基板を安全に取り外しにくいアルミ保護部があった
- Philips WiZ はプラスチック製ディフューザーを外すだけで ESP32C3-mini-1 が露出し有望に見えたが、必要なESP32ピンにはアクセスできなかった
- 一般的なLED電球に独自回路を入れる方法も検討したが、Tasmota電球を書き換えるよりさらに複雑で特殊な作業になった
- 最終的にはTasmota電球を維持し、4MB制限 の中で解決することにした
保存容量の問題
- ESP32のパーティションテーブルは通常フラッシュオフセット
0x8000に保存されており、この領域をダンプしてCSVに変換し、構造を確認した - 既存のパーティションは
nvs,otadata,safeboot,app0,spiffsの5つだったnvsは、Wi-Fiネットワーク、パスワード、LED色などの設定を保存する不揮発性ストレージとして使われるotadataはOTA更新に関連する領域と見られたsafebootは、Tasmotaがメインファームウェアを書き込むために使う別個のブート用ファームウェアだったapp0にはメインファームウェアが保存されるspiffsはファイル保存用の小さなファイルシステムパーティションで、この場合はLittleFSも表しうる
- 既存構成ではメインファームウェアがほぼ3MB、safebootがほぼ1MBを占め、ファイル保存領域はわずか320KBしかなかった
- カスタムファームウェアはTasmotaより単純なので、
app0のサイズを縮小しspiffsを拡張できると判断した - 新しいパーティション構成では
spiffsを0x200000サイズに設定し、Webファイルと書籍のための 2MBストレージ を確保した - パーティションテーブルの修正は危険で、破損するとデバイスは起動できず、シリアル書き込みでしか復旧できない
- テーブル末尾にはMD5チェックサムがあるため、オフセットとサイズを変えるだけでは起動できない
- 実行中の
app0パーティション自体を移動すると、そのファームウェアへ再起動できなくなるため、app0の開始位置は維持する必要があった - 新しいパーティションCSVを作成し、
gen_esp32part.pyでバイナリテーブルを生成し、その後xxdでC配列形式にしてpartition.hに組み込んだ - パーティションテーブルのMD5がすでに新しいテーブルと一致していればスキップし、異なればテーブルを消去して新しいテーブルを書き込む関数を作成した
- Arduino環境では保護されたフラッシュ領域へのアクセスがブロックされており、APIが成功を返しても実際にはパーティションテーブルを読み書きできなかった
ESP-IDF
- 公式のESP32フレームワークである ESP-IDF は設定と使用がより複雑だが、デバイスとフレームワークに対する制御範囲が広い
idf.py menuconfigでフレームワーク設定を変更でき、このメニューはLinuxカーネルのmenuconfigに似た方式である- パーティションテーブルを読み書きするには
SPI_FLASH_DANGEROUS_WRITE_ALLOWEDをAllowedに設定する必要があった SPI_FLASH_DANGEROUS_WRITE_ABORTSも無効化して初めて、パーティションテーブルへアクセスできるようになった- ESP-IDFを直接使うとArduinoの便利機能はそのまま使えなかったが、Arduino as a Component を追加することで、Arduinoの機能とESP-IDFの制御を併用できた
- ElegantOTA、Async_TCP、AsyncWebServer といったライブラリは、プロジェクトの
componentsディレクトリまたはArduinoコンポーネントのlibrariesディレクトリに複製する必要があった - 一部の
CMakeLists.txtも調整が必要で、この反復作業を処理するbuild.shスクリプトをリポジトリに追加した - ビルドは
idf.py buildで行い、シリアル書き込みはesptool -p /dev/ttyUSB0 write-flash 0xe0000 build/library.binで実施した
設定ページ
- メインファームウェアイメージには重要なWebサーバーエンドポイントが含まれるが、実際のライブラリコードはLittleFSパーティションに別途保存される
- ファイルシステムイメージは別に書き込む必要があり、そのためにElegantOTAが含まれている
- まだファイルシステムを書き込んでいない状態で起動すると、設定ページが表示される
- 設定ページでは、ElegantOTAでファイルシステムイメージとsafebootファームウェアを書き込む手順が案内される
Safeboot
- メインファームウェアのOTA更新を維持するため、当初はTasmota safebootをそのまま使おうとした
- Tasmota safebootは
nvsパーティションのWi-Fi設定を使って更新を行う - この過程で、Wi-FiのSSIDとパスワードが
nvsパーティションに平文で保存されることが問題になった - 電球を屋外に置いておく場合、Wi-Fi認証情報がそのまま残るのは好ましい運用セキュリティ状態ではない
- カスタムファームウェアはまず
nvsパーティションを消去し、さらにSPIFFSパーティションも消去する nvsのWi-Fi設定が消えると、Tasmota safebootはネットワークに接続できず、標準のファームウェア更新経路が途切れてしまう- これを解決するため、別個の カスタムsafebootファームウェア が必要になった
- 最小構成のWebサーバーとアクセスポイントでOTA更新を行うGitHubサンプルをベースに、safebootファームウェアを作成した
- 一部の
menuconfig項目を無効化して、safebootパーティションに収まるまでイメージを縮小し、最終的に動作した - safebootパーティション自体にはパスワードがないが、safebootへ再起動する管理機能はパスワードで保護されている
Webアプリケーション
-
ライブラリ
- 最初の画面には、扉の付いた黄色い輸送コンテナの画像が表示される
- この画像は、先に触れた Ben Brown の短編 Library を参照した要素である
- 画像は保存容量を消費するが維持され、トップ画面には「ハッカーっぽい」雰囲気を出すためのグリッチ効果も入っている
- メインのライブラリページは、HTMLとCSSを手書きして実装された
- 当初の計画は、ファイル一覧だけの基本的なHTMLインデックスだったが、より見栄えがよく楽しい形に変わった
- サイト構造は比較的シンプルである
- 現在見ているものが何なのかを説明するセクションがある
- 書籍セクションには、タイトル、著者、異議申し立てや禁止の理由が表示される
- 参考リンクのセクションもあるが、Banned Book Library のアクセスポイントにはインターネット接続がないため、接続中は外部リンクは機能しない
-
管理者
/adminパスには、パスワード保護された 管理パネル がある- 管理パネルではLEDの色温度を制御できる
- 公共の場に設置する際、既存の電球の色に合わせて変更を目立ちにくくすることが目的である
- 電球販売元が各LED色制御用GPIOピンを公開していたため、
AnalogWrite()で色ごとの強度を設定できた - 色設定は
NVSに保存され、次回起動時も同じ色に戻る - 管理機能には復元ページへ移動するボタンもある
-
復元
- 復元機能は、パーティションテーブルをある程度元に戻し、safebootで起動するようにする
- 実際にはカスタムsafebootパーティションへ再起動し、Banned Book Library ファームウェアの上に別のファームウェアを書き込めるようにする
- 書き込む対象は、新バージョン、Tasmota、ESPHome などでありうる
- safebootパーティション自体を復元するよい方法はまだ見つかっていない
- Tasmotaを再度書き込んだあと、Tasmotaインターフェースで「Firmware Upgrade」を押すと、再びカスタムsafebootへ再起動する
- このsafebootはTasmota更新に使えるものの、Tasmota本来の通常アップグレード体験とは滑らかには噛み合わない
- この問題のため、パーティション復元ではsafebootのサブタイプを
Factoryに完全には戻さず、OTA_1のままにしている
-
キャプティブポータル
- 利用者はオープンアクセスポイントに接続した後、インターネットがないと分かっただけで諦めてしまう可能性があるため、キャプティブポータル が必要になった
- 以前の方式はHTTPリクエストを横取りしてポータルへリダイレクトするものだったが、現在はほとんどのWebサイトがHTTPSを使うため、この方法はあまり適していない
- 現代的な方式では、キャプティブポータルの使用を通知するDHCPオプションと、デバイスごとのポータル検出リクエストへの対応が用いられる
- ESP32向けのキャプティブポータルサンプルコードを見つけ、プロジェクトに一部取り入れた
- そのコードは2つの処理を行う
- DNSサーバーがすべての要求に対し、ESP32自身のIPアドレスで応答する
- Microsoft、Android、iOS、Firefox などで使われる特定のHTTPリクエストを捕捉し、リダイレクトまたは応答を返す
- 不明なリクエストは
server.onNotFoundでローカルURLへリダイレクトされ、シリアルモニターにはリクエストホストとURLが出力される
最終的な考え
-
サイズ制限
- デバイスの総保存容量は 4MB に制限されている
- 確認したepub書籍のいくつかは1冊あたり約350KBで、電球1つにはこうした本を数冊しか収められない
- 当初は多数の禁書を提供するWebサーバーを想像していたため、この制限は失望だった
- その後、限られた容量ゆえに各デッドドロップが作り手の選択を反映する点が長所として受け止められるようになった
- 作り手は、自分にとって重要な本や、他の人がアクセスすべきだと感じる本を選ばなければならない
- ある地域に複数設置され、それぞれの電球に異なる資料が入っていれば、探し回って内容を発見する体験はさらに面白くなるかもしれない
-
今後のアイデア
-
色制御
- RGBカラーと白色の色温度をより細かく制御するスライダーを追加したいとしている
- これにより、設置場所の既存照明の色により近づけられる
-
メッシュネットワーキング
- 保存容量の制限に関連して、複数の電球が メッシュネットワーク を形成するアイデアが出ている
- 分散ハッシュテーブルのような方式を使えば、互いに通信圏内にあるデバイスの書籍を、どれか1台に接続した利用者へ提供できる
- このアイデアは、探究する価値のある面白い方向性として残っている
-
その他
- スマート機器を別用途に再利用するアイデアは、ほかにもいくつもある
- ESP32チップは非常に安価でありながら性能は十分だと評価されている
- ESP32の使い方を学んだことで、今後さらに多くのESP32プロジェクトを作る可能性が高くなった
-
1件のコメント
Hacker Newsの意見
Alpha CentauriのPravin Lalの台詞のように、情報の流れを統制しようとする者は結局支配者になろうとしている、という警告は今でもなお的確に感じられる
「民主主義は雷鳴のような拍手の中で死ぬ」のほうが現実に近い気がする
歴代最高の4Xゲームであり、そのゲームが想像した2060年が日に日に近づいているように思える
ゲームにおける複雑さと成熟さが頂点に達していた作品のように見える
このゲームとその思想は本当に時代を超えている
嘘も情報であり、同じ流れに乗ればむしろもっとよく広がることを私たちは見てしまったからだ
予想どおり、記事に出てきた本の例は実際には「禁書」ではなかった
たいていは保護者の要請に応じて、露骨な内容を含む本が学校図書館の蔵書から外されるケースだ
記事の核心ではないので、本の例は2つほどしか見かけなかった気がする
Nineteen Eighty-four にも性的な内容は含まれているのだから、全体主義文学へのアクセスを減らしたい権威主義者は、保護者が性の問題に怒るよう仕向けるだけでいい
ある本が世界中で禁止されていなければ「禁止」と呼べないわけではない
実際にはそういう本は多くないだろうが、最近では悪名を得る近道のようにも見える
以前にはPirateBoxというものがあった
小型のWi-FiアクセスポイントにWebサーバーやフォーラム/ファイルホストを載せたカスタムファームウェアを書き込む方式で、元のサイトは消えてしまったが派生プロジェクトがここにある: https://www.jasongriffey.net/librarybox/
ただしユーザーアップロードを許可すると、どんなファイルが上がってくるか考えるだけでも不安になる
人々はオープンなWi-Fiに接続するのを怖がり、「無料インターネット」が得られるわけでもないので、たいていすぐ切断してしまった
残念ながら、LibraryBoxという派生プロジェクトももう活発ではない
禁書リストが気になる
最大級のソーシャルプラットフォームの1つが欠けている状態でざっと見ると、面白い本はなさそうで、主流の書店の「禁書」コーナーで見かけるような本ばかりに思える
意味のある多様性が欠けた平凡な思考のように見える
「禁書」リストは短く、Call of the Wild、The Adventures of Huckleberry Finn、The Adventures of Tom Sawyer、Women in Love といった程度だ
なんとも驚くべき勇敢さだ
したがって単一のリストはなく、入れたいものを入れればよい
2012年ごろにも、こういうものがPirate Boxと呼ばれているのを見た
基本的なアイデアは、より広いインターネットから切り離された状態でWi-FiネットワークとWebサーバーを立ち上げ、人々がファイルをアップロード・ダウンロードできる箱にすることだ
地理的に制限されたデジタル共有図書館というわけだ
効率的なソフトウェアやエネルギー使用を気にする人にしては、記事内の画像が5MBのPNGである点が目につく
Androidは、インターネットを提供しないWi-Fiネットワークから自動で切断するのを好む
この機能をオフにするには、かなりわかりにくい設定を何段階もたどる必要がある
最後に確認したときは、スマホのポータル検出は有効なHTTPS証明書までは要求していなかった
ユーザーに「Sign In」を押すよう案内し、すぐにデッドドロップを見せるという方式だ
ただし自分では試しておらず、これが実際に動くのか、あるいはDNSが適切に必要なのかはわからない
初期知識がそれほど多くなくても、明確な目標と情熱、好奇心があれば、どこまで行けるかを示す良い例だ
クールではあるが、「電球なので検知しにくく目立たないだろう」という話には疑問がある
公開アクセス可能な他のWi-Fi機器より止めにくいわけではないし、電源や機器を少しずつ切っていけば見つけられそうだ
現代的な企業向けアクセスポイントには、機器を物理的に見つける機能や、無許可アクセスポイントの自動警告も備わっている
ただし後者は、誰かがWi-Fi Directで印刷したり画面をキャストしたりするたびに鳴るので、無視されるか無効化されていることが多い
とくに所定の場所に取り付けられた普通の電球に見えるなら、誰がそれをWi-Fiアクセスポイントだと思うだろうか
茶色のポッティング材は、他の役割に加えて、部品から熱を逃がすために使われていた可能性がありそうだ