しょんぼり技術メモ

まいにちがしょんぼり

ダイソーBluetoothリモートシャッターで、押された時刻をGoogle SpreadSheetに記録する

TL;DR: ダイソーBTボタン+bluebutton+GASで押された時刻を記録するやつ作った

我が家には気管切開を行って24時間人工呼吸器を着けている息子がおり、呼吸器から送られた空気は加温加湿器を通って息子の気管に流れ込むようになっている。本来ならば加温・加湿は鼻がもつ機能だが、気管に直接空気を送るため機械で補う必要があるのだ。

気管に直接送り込む関係で水道水を使うわけにはいかず、注射用水のような無菌のものを使う。これが案外ハイペースで消費してしまい、1日1リットル、一ヶ月で30リットルぐらい使ったりする。しかもこのペースは室温や湿度に影響され、補充は月に1度の通院の際だけだ。

前置きが長くなってしまった。そんな事情から、水の消費ペースをある程度把握しておきたくなったので、ダイソーBluetoothリモートシャッターとRaspberry Pi 3B、Google SpreadSheetを使って記録する仕組みを作ってみた。

簡単に書くと:

  • BTリモートシャッターを押す
  • RPi3で検知して、SpreadSheetに現在時刻を記録する
  • 記録された時刻をもとに、シート上で消費ペースと在庫数、枯渇までの猶予を計算する

というシステムにした。これまでの経験上、せいぜい2~3回/日の消費ペースなので、スケーラビリティはまったく気にしないしロックも不要だ。とりあえず動けば良い。枕元のホワイトボードに時刻を手書きしてペースを把握するアナログ手法より楽なら何でも良い。

下準備

基本的には下記のページに従う。 qiita.com

セットアップ~bluebuttonの設定までは書かれているとおり。

POSTされたらSpreadSheetに現在時刻を記録する

あらかじめGoogle SpreadSheetにドキュメントを作り、useシートにこんな感じの値を入れておく。

timestamp quantity
2018/10/21 01:23:45 1

スクリプトエディタを起動して、SpreadSheet処理を書く。スプレッドシートのIDはURLなどから広うのが手っ取り早い。 要するにdoPost()というメソッドが呼ばれたら、スプレッドシートの末尾に現在時刻を登録して、HTTPでHTMLの応答を返すようにすればよい。

function doPost(e){
  addConsume();
  return HtmlService.createHtmlOutputFromFile('register');
}

function addConsume() {
  const ssId = "your spread sheet id";
  var ss = SpreadsheetApp.openById(ssId);
  var sheet = ss.getSheetByName("use");
  
  const timestamp = Utilities.formatDate(new Date(), "Asia/Tokyo", "yyyy/MM/dd HH:mm:ss");
  const quantity = 1;
  sheet.appendRow([timestamp, quantity]);
}

register.htmlを作って応答を適当に書く。ぶっちゃけ何でも良い。 あとは「ファイル>版を管理」でバージョンを保存して、「公開>ウェブアプリケーションとして導入」で公開する。アプリケーションにアクセスできるユーザーとして、「全員(匿名ユーザーを含む)」を選択しておく。URLが十分にランダムなので、外部からはアクセス困難なはず。今回の用途であればこれで問題ない。ダイアログに表示されているURLをメモしておく。保存すると、アプリケーション連携の認可要求が出るのでよしなに。

curlコマンドでPOSTして、シートの最下行に時刻が記録されることを確認する。

curl -XPOST --data "" "https://script.google.com/macros/s/HOGEHOGE/exec"

bluebuttonでPOSTする

こんなスクリプト(on_button.sh)を作っておく。

#!/bin/bash
curl -XPOST --silent --data "" "https://script.google.com/macros/s/HOGEHOGE/exec" >/dev/null 2>/dev/null
if [ $? -eq 0 ]; then
    python /etc/bluebutton/success_led.py
fi

別件でRPiのGPIOにはフルカラーLEDが付いているので、フィードバック用のLED点滅処理を呼んでいる。 ダイソーBluetoothリモートシャッターは1分半でスリープするらしく、初回押下ではbluebuttonまで処理が来ないことがあるので、フィードバックがあった方が使い勝手が良い。

bluebuttonのコンフィグをこんな感じで書いておいて

keyup=true
keydown=/etc/bluebutton/on_button.sh
longup=true
longdown=true

systemdの設定を雑に書いて、systemctl daemon-reloadしてからenable、startする。

[Unit]
Description=BlueButton water management server
After=syslog.target network-online.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/bluebutton -d="AB Shutter3" -c /etc/bluebutton/bluebutton.conf
Restart=on-failure
RestartSec=10
KillMode=mixed
WorkingDirectory=/root

[Install]
WantedBy=multi-user.target

ダイソー Bluetoothリモートシャッター スリープ問題

どうやらこの製品は1分半でスリープするらしい。ペアリング後、最終利用から時間が経つとスリープに入り、ボタンを押すと起きて再接続が走る。このときLEDが3回点滅する。その後もう一度ボタンを押すと通信が飛んでいく模様。このときはLEDは1回点滅するが、必ずしもちゃんとbluebuttonまでリクエストが飛んでいるとは限らないようだ。

仕方ないので、bluebutton側のスクリプトでフィードバックを返すようにしている。使い途にもよるが、LED光らせる以外にも圧電ブザーを繋いで音を鳴らしたり、LINEなどに通知を飛ばすなりの方法を使うのが良さそう。

仕上げ:消費ペース等を表示する

useシートに消費した時刻が記録されるようにしているので、あとは表計算アプリケーションとして書いていけば良い。あとは在庫数をstockシートに記録したりして、まあ適当にでっち上げる。テストデータを消したいときには、useシートのテストデータの行をまるごと消してやれば良い。その後ボタンを押すと、ちゃんと最下行に追加される。

f:id:syonbori_tech:20181021172716p:plain

……ご覧のように、ちょっと多めに貰いすぎてしまっている。次回通院時には貰わなくても大丈夫か、1箱ぐらいでいいか、って感じですね……

オチ

ボタンは枕元の加湿器付近に固定している。RPiから1メートルぐらいの距離。つまり、RPiのGPIOにスイッチを繋いで線を延ばしてやれば、リモートシャッターのスリープ問題に悩まされることなく実現できる。これ、本当にリモートにする必要なかった……