ダッシュボタンとラズパイとLINEでタイマーを作った話

# はじめに
半年前のプライムデーで調子に乗って買ったダッシュボタンが5つほどPC周りに転がってたんですよ
で、そいつを有効活用する方法ないかなーとずっと思ってて、つい先日echo dotが届いたタイミングで思いついたのがこれ

そうだ、タイマー作ろう

# フロー的なもの
1. ダッシュボタンを押す
1. ラズパイがそれを検知
1. xx分待ってからLINEに通知を送る
1. ハッピー

誰か簡単に図が描けるツール教えてください

# やったこと

## ダッシュボタンのセットアップ（途中まで）
そこらじゅうに記事が溢れるので適当に探してください
個人的にこれが丁寧でわかりやすかった
> Amazon Dash Button でおうちハックしようその1 セットアップ編 - Qiita
https://qiita.com/tokio-takeda/items/02bae474f8f20f35a02c

ついでに「ダッシュボタンを押すと毎回スマホに通知がきてうざい」問題を解決するために、
　amazonアプリ＞左上のハンバーガーメニュー（三みたいなやつ）＞設定＞プッシュ通知
から「Dash Buttonの通知」をオフにすればおｋ
＃iosの場合。androidは知らぬ

## ラズパイにdasherを入れてボタンの検知まで
Q. dasherって何？
A. ダッシュボタンが押されたことを検知してくれるやつ。これ↓
> maddox/dasher: A simple way to bridge your Amazon Dash buttons to HTTP services
https://github.com/maddox/dasher

readmeに従ってlibpcap-devとnpmとnodeを入れて、nodeを手動更新

```
$ sudo apt-get install libpcap-dev
$ sudo apt-get install npm
$ sudo apt-get install node
$ wget http://node-arm.herokuapp.com/node_latest_armhf.deb 
$ sudo dpkg -i node_latest_armhf.deb
```

`node -v`が効けばおｋ
効かなかったらとりあえず`sudo reboot now`しよう

gitを入れてgithubからdasherをcloneして`npm install`

```
$ sudo apt-get install git
$ git clone https://github.com/maddox/dasher.git
$ cd dasher
$ npm install
```

これでdasherの初期設定完了

ダッシュボタンを探すスクリプトを起動し、ダッシュボタンを押すと情報が出て来る
それっぽいのが出てきたら`ctrl + c`でキャンセル

```
$ script/find_button
Watching for arp & udp requests on your local network, please try to press your dash now
Dash buttons should appear as manufactured by 'Amazon Technologies Inc.'
Possible dash hardware address detected: xx:xx:xx:xx:xx:xx Manufacturer: unknown Protocol: udp
Possible dash hardware address detected: xx:xx:xx:xx:xx:xx Manufacturer: unknown Protocol: arp
^C
$
```

12桁のアドレスをメモっておく

## dasherの設定ファイルを編集

`config/config.example.json`にサンプルがあるのでコピー

```
$ cp -p config{.example,}.json
```

* `-p`でpermissionなどもコピる
* `config{.example,}.json`は`config.example.json config.json`に展開される
 * 同期に教えてもらったのをそのまま使ってるだけだからちゃんと理解してないのだけども

で、`config.json`を編集

```config.json
{"buttons":[
  {
    "name": "timer dash button",
    "address": "xx:xx:xx:xx:xx:xx",
    "cmd": "/path/to/shell/settimer.sh"
  }
]}
```

今回はボタンが押されたらシェルを実行したいのでcmdオプションを指定
サンプルの最後のブロックの`"Command Exec Button"`という名前の設定がコマンドを実行するものなので、それを参考に
他の設定もサンプルとgithubのreadmeとでにらめっこすればだいたい察せるはず

## タイマー代わりのcrontabを設定するシェルを作る
タイマー部分どうしようかなーと考えた結果、crontabに任せることに
というわけでダッシュボタンが押されたときに実行されてcrontabを設定するシェルがこれ

```settimer.sh
#!/bin/bash

TARGET_DIR='/path/to/shell'

# backup
crontab -u pi -l > $TARGET_DIR/crontab.bak

# create new crontab
crontab -u pi -l > $TARGET_DIR/crontab.new
min=`date --date "40 minutes" +%M`
echo "$min * * * * sh $TARGET_DIR/exectimer.sh" >> $TARGET_DIR/crontab.new

# set new crontab
crontab -u pi $TARGET_DIR/crontab.new

# clean new crontab
rm $TARGET_DIR/crontab.new
```

特に難しいことは書いてないと思うけどいくつか説明

* `crontab -l`で現在のcrontabの設定を表示、書き出し
* 変数`min`に現在時刻の40分後の時刻の「分」の値を設定
 * 例えば今が12時半なら「10」になる
 * `"40 minutes"`のところを変えればタイマーの時間を変更可能
* それをcrontabの起動時刻の「分」に指定して一度`crontab.new`に追記書き込みし、そのファイルを`crontab`に食べさせて設定
* もちろん後処理も忘れずに（`.bak`の方は後で使うので残す）

ついでに試行錯誤したこともいくつか

* 当初は``TMP_DIR=`pwd```としてたけど、これだと**シェルのあるディレクトリではなくdasherのあるディレクトリ**が取れてしまうのでイマイチうまくいかなかった
* `.bak`や`.new`ファイルはディレクトリまで指定しないとやっぱりdasherのあるディレクトリに作られてこれまたうまくいかなかった
* `crontab -u pi`と明に実行ユーザを指定しないと、dasherの実行ユーザ（おそらく`sudo`するのでroot）のcrontabが対象になって混乱する（した）

そして賢明な読者諸氏は気づいたと思うが、このタイマーは60分以上には対応していない
つらい

さらに言えばタイマー完了前にもう一度シェルが実行されるとバグる
とてもつらい

## line notifyを設定する

通知部分にはline notifyを使う
line notifyを知らない？
ぐぐってください

> LINE Notify
https://notify-bot.line.me/ja/

ログインしてマイページに移動

![スクリーンショット (3).png](https://qiita-image-store.s3.amazonaws.com/0/127332/143cf147-5f12-b6b0-64c9-d1dd339db3bd.png)

トークンを発行する

![スクリーンショット (4).png](https://qiita-image-store.s3.amazonaws.com/0/127332/dfaeba0e-929a-3827-ba90-deca689f6216.png)

トークン名を適当に考えて、通知先は今回は自分宛てなので一番上（たぶん）の「1:1で～」を選択

![スクリーンショット (5).png](https://qiita-image-store.s3.amazonaws.com/0/127332/6c040136-6b17-8111-28bd-a2e23555df07.png)

これ、マジでここを逃すと二度と取得できないのでコピーしてどこかにメモっておきましょう

とりあえず一度curlで叩いてみる

```
$ curl -X POST https://notify-api.line.me/api/notify -H 'Authorization: Bearer [accesstoken]' -H 'Content-Type: application/x-www-form-urlencoded' -d 'message=aaa asdf gggfs'
```

結果

![スクリーンショット (6).png](https://qiita-image-store.s3.amazonaws.com/0/127332/44b797c8-9e70-c33d-d435-91c3f93524e6.png)

いい感じ

## タイマー時刻になったら起動するシェルを作る

というわけでさきほどのcurlを叩くシェルを作成

```exectimer.sh
#!/bin/bash

TARGET_DIR='/path/to/shell'

# call line notify
curl -X POST https://notify-api.line.me/api/notify -H 'Authorization: Bearer [accesstoken]' -H 'Content-Type: application/x-www-form-urlencoded' -d 'message=時間だよ！！！'

# set backup crontab
crontab -u pi $TARGET_DIR/crontab.bak

# clean backup crontab
rm $TARGET_DIR/crontab.bak
```

まあ説明はいらないですね

## dasherを起動

```
$ cd /path/to/dasher
$ sudo npm run start

> dasher@1.4.1 start /path/to/dasher
> node app.js

[2018-01-03T10:10:48.909Z] timer dash button added.
```

これでdasherがスタンバイ状態になっていつでもボタンを押しておｋ

```
[2018-01-03T10:11:14.751Z] timer dash button pressed. Count: 1
```

ボタンを押すとこんな感じに出てくる
そしてタイマーの方も起動してるはず

![スクリーンショット (7).png](https://qiita-image-store.s3.amazonaws.com/0/127332/1e54cfee-822c-6610-4a47-8b4be683f59c.png)

はい

# ラズパイ起動時にdasherを自動起動

いちいちdasherを起動してらんないので勝手に起動してもらう
`/etc/rc.local`に以下を追記

```rc.local
# dasher
sh /path/to/dasher/autorun.sh
```

まあシェルの場所はどこでもいいのだけども

```autorun.sh
#!/bin/bash

cd /path/to/dasher
sudo npm run start &
```

で、起動時に肝心のrc.local自体が実行されないのは困るので、設定を変更

> Raspbian Jessie /etc/rc.local で起動させる方法 | アラコキからの Raspberry Pi 電子工作
https://arakoki70.com/?p=852

これにてすべて世は事も無し

# まとめ

[はじめに](https://qiita.com/jutaroi01/items/88c118b4e238e4cb719d#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)を見返してみる

> つい先日echo dotが届いたタイミングで思いついたのがこれ

見返してみる

> echo dotが届いた

**echo dot使ってねえ！！！**