人間に水を飲ませる技術
妻が水を飲まない。健康のために水を飲むと自ら宣言したのに飲まない1。毎日「今日はこれを飲む」と言って 2L のペットボトルを仕事部屋に持っていくのに 500ml も飲んでいない。https://twitter.com/mtkasr/status/1384856756963135488 を見てぴよログで水を飲んだことを記録しはじめたがそれも 3 日で終わった。
常に「今日も水を飲めなかった…」とか言ってるのでとにかく記録させるために物理的なボタンを用意することにした。それで機械にリマインドさせたい。
できたもの。
これははてなブログに動画を貼りたいがためのツイートです pic.twitter.com/0QxAKJxWsQ
— やまま (@kirikiriyamama) May 31, 2021
用意したボタン。
仕組み。
- M5StickC のボタンを押すと GAS の Web Apps にリクエストが飛ぶ
- Web Apps で Spreadsheets に水を飲んだことを記録する
- 水を飲んでいなかったら GAS の cron で Slack にリマインドする
あと、一日のおわりにその日飲んだ量を Slack に流している。Spreadsheets で集計しているんだけど、普段あんまり Spreadsheets 使わないからこれが一番むずかしかった2。
M5StickC は Arduino (だいたい C 言語) で実装した。久しぶりの C 言語は文字列をフォーマットするだけでわあ大変ってなった。これが初期のコード。
#include <M5StickC.h> #include <HTTPClient.h> #include <WiFi.h> const char* ssid = "xxxxx"; const char* passphrase = "xxxxx"; const char* url = "https://example.com/"; void setup() { M5.begin(); Serial.begin(9600); delay(1000); // wait for serial initialization Serial.print("\n"); M5.Axp.ScreenBreath(10); M5.Lcd.setRotation(1); M5.Lcd.setTextSize(1); M5.Lcd.fillScreen(BLACK); M5.Lcd.print("connecting..."); WiFi.begin(ssid, passphrase); // TODO: timeout while (WiFi.status() != WL_CONNECTED) { delay(500); } M5.Lcd.println("ok"); Serial.println(WiFi.localIP()); } void loop() { M5.update(); if (M5.BtnA.wasReleased()) { M5.Lcd.print("sending..."); HTTPClient http; http.begin(url); http.addHeader("Content-Type", "application/json"); int code = http.POST("{}"); Serial.println(http.getString()); // TODO: follow redirects if (code == 302) { M5.Lcd.println("ok"); } else { M5.Lcd.println("failed"); if (code > 0) { M5.Lcd.println(code); } else { M5.Lcd.println(http.errorToString(code).c_str()); } } http.end(); } delay(1); }
周辺の技術がわかっていないのもあり、いまいち一次情報を見つけられなくて苦労した。以下のサイトは日本語で情報がまとまっていてとてもお世話になった。
あと M5StickC で調べるとそんなに情報が出てこないんだけど、中身としては ESP32 という SoC の上で FreeRTOS が動いているので、そのあたりの単語をつかって調べるとよかった。
このあと余計なことをしだして、バッテリー節約のために一定時間操作がなかったら Wi-Fi を切断するとか、送信に失敗したら LED を点滅させる (これを非同期でやりたい、愚直にやると操作をブロックしてしまう) とかやっていたら割り込みや排他処理と向き合わないといけなくなって大変だった。ボタンが手元にないときのために Slack の Slash Commands もつくって、最終的にこうなった3。
https://gist.github.com/kirikiriyamama/79c47a74e861e6a16d1b4106c70ec937
これでわりと水を飲むようにはなったんだけど、お昼ごはんのときにいっぱい飲んだり、一日の終わりに駆け込んでむりやり目標を達成したりしていて、そういうことじゃない気がしている。がんばってほしい。