RaspberryPiとAmazonDashButtonでサーボモーター(SG90R)を制御して家の鍵を開け閉めする

前に書いた記事でiPhoneからサーボを制御し、実際に家の鍵を開閉できるようにしたところめっちゃ使いにくい点がいくつか出てきてしまい、それの改善のためにAmazonDashButtonを導入しました。

前記事
[iPhoneアプリからRaspberryPi3につなげたサーボモーター(SG90R)を遠隔制御する](https://qiita.com/ryosuke_tamura/items/51684388b88952c0eca9)

家の鍵を回す部品とかはプログラム関係ないのではてなブログに残していますのでよかったら見てみてください
[家の鍵をキーレス化作戦・・・！！](http://crouton-camera.hatenablog.jp/entry/2017/11/15/192227)

#環境
Raspberrypi3
Node.js v9.2.0
Python 3.5.3

###問題点
- 鍵を閉め忘れた時に遠隔で鍵を閉める --> OK
- 外出して家に帰りドアを開けるときにスマホで開錠
する --> OK

前の記事ではこの２点だけに注目しすぎて家から出る時や、家に帰ってドアを閉めた後のことを何も考えていませんでした・・・
そのため次のような不便な点が・・・

- 家を出る時サーボモーターが邪魔で手で鍵を回せないためスマホをいちいち取り出す必要がある
- 外から帰ってきてドアを閉めた後鍵を掛けるのに手で鍵を回せないため、スマホから施錠命令を送らなければならない

つまり外からはいいけど家の中からの開け閉めがネックになっていました（アホ）
そこで室内にAmazonDashButtonを置き、これを押すと鍵が開いたり閉まったりするようにしました。

#参考にした記事
[RaspberrypiでAmazonDashButtonをハンドリングする](https://qiita.com/yusuke_tashiro/items/a27650a5c3cd529920d5)
[Amazon Dash Buttonを使ってスマートチャイムをつくる](https://watchcontents.com/amazon-dash-makechime/)

####この記事と上記記事が違う点
- AmazonDashButtonのMacアドレスを取得するのにdash-buttonのscanを利用しているが自分の環境では利用できなかったためwiresharkを利用した点
- Node.jsに初めて触ったためreadmeの場所すら分からなかった&書いてあるプログラムが動かなかったためそのあたりの追記
- ドア開閉に特化した内容の追記

#実装
###制御の流れ
1.AmazonDashButton(以下ADB)がarpを飛ばす
2.Raspberrypiでそれを検知(Node.js)
3.鍵が閉まっているのか開いているのか判定(Node.js)
4.サーボモーターを回す(Python)

ここでは1と2の部分について書きます。3の部分は最初に書いた前の記事をみてください。

####wiresharkでarpを検出
まずはwiresharkをインストール

```
$ sudo apt-get install wireshark
```
起動します

```
$ sudo wireshark 
```
起動するとこんな画面(Macのスクショですが基本同じなので気にしないでください）

ここで接続しているものを選びます(私のはWiFi(en0)で接続しています)

するとこんな画面に、上に表示フィルターというのがあります
![スクリーンショット 2017-12-16 14.55.48のコピー.png](https://qiita-image-store.s3.amazonaws.com/0/204184/7be147bd-7b51-f2ce-9309-8fdd657d1fe3.png)
そこに「arp」と入力してEnter
これであらゆる通信の中からarpだけ表示させることができます。

その状態でADBを押すと・・・
![スクリーンショット 2017-12-16 15.03.13のコピー.png](https://qiita-image-store.s3.amazonaws.com/0/204184/a8892083-7eae-ac8c-4bf2-9a46ac2aa71d.png)
下にMACアドレスが出ています、これでADBのMACアドレスを知ることができました

###鍵の開閉判定の仕組みを考える
iOSアプリやその他のアプリケーションからも鍵の開け閉めの情報を共有したかったのでプログラムの内部変数などではなく、ファイルとして開閉情報をかき出すようにしました。
具体的にはdoor.iniというファイルを作成し、その中に鍵が閉まっているならば"close"
鍵が開いているなら"open"というように記録するようにしました。
詳しくはプログラムを書く部分で書きます。
####開閉判定をする利点
- 鍵を開ける用のADBと鍵を閉める用のADBを用意しなくて済む
- 開閉を記録しておけば鍵の開閉をセンサーなどで得る必要がない
- 上にも書いたように他のアプリケーションから開閉状態を取得できる等・・・

###Node.jsでarpを取得してモーターを回す
参考にした記事ではここのプログラムがうまく動かず・・・
readmeがどこにあるのか初めてだったものでかなり時間かかってしまいました。
Node.jsのインストールが済んでいない方は[参考記事](https://qiita.com/yusuke_tashiro/items/a27650a5c3cd529920d5)をみてください。

####dash-buttonをインストールする
まずdash-buttonがarpをキャプチャーするのに必要なライブラリ(libpcap-dev)を入れてからdash-buttonをインストールします


```
$ cd ~/Desktop
$ mkdir button
$ cd button

$ sudo apt-get install libpcap-dev
$ npm install --save dash-button
```

これでbuttonフォルダの中には
node_modulesとpackage-lock.jsonがある状態になっていると思います
ここに新しくbutton.jsを作成してreadmeを参考にプログラムを書いて行きます。

####readmeの場所
```
...ユーザー名/Desktop/test/node_modules/dash-button/README.md
```
####プログラムを書いていく
```
$ cd ~/Desktop/button
$ touch door.ini
$ touch button.js
```

```button.js
const DashButton = require('dash-button');
const DASH_BUTTON_MAC_ADDRESS = '68:54:fd:3f:55:c8'; //あなたのボタンのMACアドレスに書き換えてください
let button = new DashButton(DASH_BUTTON_MAC_ADDRESS);

var fs = require('fs');

var exec = require('child_process').exec;

let subscription = button.addListener(async () => {//ボタンが押されるとこの中身が実行されます
  var data = fs.readFileSync('省略../Desktop/button/door.ini', 'utf-8');//door.iniの中身をdataに代入
    if(data == "open"){//もし鍵が開いていたら鍵を閉めてdoor.iniにcloseと書き込む
      exec('python3.5 省略..Desktop/Python/close.py', function(err, stdout, stderr){
        if (err) { console.log(err); }else{
          fs.writeFileSync('省略../Desktop/button/door.ini','close')//door.iniにcloseと書き込み
        }
      });
    }else{//もし鍵が閉まっていたら鍵を開けてdoor.iniにopenと書き込む
      exec('python3.5 省略../Desktop/Python/open.py', function(err, stdout, stderr){
        if (err) { console.log(err); }else{
          fs.writeFileSync('省略../Desktop/button/door.ini','open')//door.iniにopenと書き込み
        }
      });
    }
  });
```

#実行
```
$ sudo node button.js
```

この状態でボタンを押せばサーボが回るはず・・・！
押すたびにopenとcloseを切り替えられますし、iPhoneアプリやウェブから開け閉めするときにもbutton.jsから開け閉めすることで現実の鍵の状態とdoor.iniにズレが生まれなくなります。
また、今開いているのか、閉まっているのか知りたい時はdoor.iniの中身を見ればわかるのでアプリなどにも生かせそうです・・・

#最後に
ごちゃごちゃになってしまった気もしますがdash-buttonの動作についてはなんとか伝わったかなと・・・
今後はdoor.iniとNode.jsを活用してSuicaで鍵の開閉をしてみようかと思います。