Raspberry Pi Zero Wに洗濯機を監視させる
最近洗濯乾燥機を購入したのですが、乾燥の度合いによって残り時間が前後し表示されている数字があまり当てにならないため監視アプリケーションを作成しました。
設置
部材
すべてオンラインショップで調達
- Raspberry Pi Zero W
- コスパ最強、無線付き、最高では
- Logicool Webcam C270
- 電源タップ
- 3M コマンドタブ
- 壁に貼ってはがせるやつ
設置
3Mのコマンドタブが最高すぎるので、すごく適当にひとまず固定します。
RasPi 準備
OSを焼く
公式サイトからOSを落とします。GUIとかいらないのでRASPBIAN STRETCH LITEを選択。
ダウンロード後dd
でSDカードにそのまま書き込みます
sshを有効化
どうやら最新版はsshが無効化されているらしいのでルートにsshという名前でからファイルを作成。
無線LAN設定
初回起動後に無線設定をするのが面倒なので調べていたら(microHDMI+microUSBとか) 素晴らしいツールを作られている方がいたので使用します。
作成したwpa_supplicant.conf
をSDカード直下に配置
起動
無事立ち上がってssh経由でアクセスできることを確認します。また、すぐにパスワードを変えます。
実装
細かい話をするとgcfとかvision apiとかtesserct-ocrとか色々遠回りしたのですが、必要な箇所だけ書きます。
Pythonでやってもよかったのですが、気分でnode.jsを採用。
Webカメラの制御
opencvを使うか他の手法で悩みましたが、fswebcamを利用したnode-webcamを利用。
NodeWebcam.capture
だけで写真を取って保存できるので最高。
ただし、awaitして使うと写真が保存されていないタイミングがあるっぽい挙動が見えたため以下のように実装。
const onCapture = (opts) => { return new Promise((resolve, reject) => { const identify = "capture" const filename = `${identify}.jpg`; const filepath = path.resolve(__dirname, filename); try { if (fs.existsSync(filepath)) { fs.unlinkSync(filepath); } NodeWebcam.capture(identify, opts, (err, result) => { // ファイル存在確認 if (!fs.existsSync(filepath)) { reject("capture failure"); return; } console.log('captured!') resolve(filename); }); } catch (e) { console.error(e); reject(e); } }); };
opts
は解像度やフォーマット等の書式設定、configに逃がしてある。
Slackに画像アップロード
非常に残念なことにデータのアップはWebhookではできないため、File Upload APIを利用。*1
面倒なのでyarn add @slack/client
を利用する。
const web = new WebClient(slackToken); const result = await web.files.upload({ filename: filename, file: fs.createReadStream(filepath), title: filename, channels: slackChannel, initial_comment: comment }); if (result.ok) { console.log(`slack post! ${result.file.permalink}`); } else { console.error('slack post error', result.error); }
slackTokenにはSlack管理画面で取得したトークンを入れ、slackChannelには投稿したいチャンネルのIDを設定します。*2
定期実行
node-cronを使用。
let count = 0; new CronJob(cronTime, async () => { console.log(`Job Start #${count++}`) const filename = await onCapture(cameraOption); const result = await onPost(filename, slackWebhookUrl, slackToken, slackChannel, slackComment); console.log('Done'); }, null, true);
Dockerfile作成
fswebcamとかnode versionに依存すると最悪なので作成。
コンテナ内から実デバイス等いじるときは--privileged
するかデバイスを指定する必要があるらしい。
結果
うざいぐらい定期的にSlackに洗濯機写真が流せるようになりました。
まとめ
最初は7segフォントのOCRするつもりでしたが、作っていてこれで要件が完全に満たせているのでこれで運用してみます。