Amazon Dash Buttonを(正しくない方向で)使ってみた



**2019/11/6追記**
既にAmazonのApp上から設定項目が削除されてしまった関係上、DashButtonのセットアップ手段がないのでこちらの手法を使うのはかなり厳しいかと思います。
代替のセットアップ手法があれば良いんですが、Amazon側がリセットコマンド返せたりするので多分面倒しかないです。

いずれにしても安くでボタンを買える以外にはメリットがないので、省電力なワイヤレスボタンがほしいってニーズを満たすなら、割高ではありますが[AWS IoTエンタープライズボタン](https://amzn.to/34Hjuiv)あたりを検討したほうが良いかと思います。
少なくとも低消費電力という点はDashButton同様ですし、ローカルで監視掛けなくても良いのでスマートです。

----

話題のAmazon Dash Buttonを買ってみました。昼過ぎに買えば19時には届いたのでAmazonすげぇなと。
それはさておき、4個も買った理由は500円という値段もさることながら、一応魔改造(簡易的なハックから、ファームウェア書き換えまで)も出来るという事をなんとなく伝え聞いていたからでもあります。

既に海外の先人がちゃんとしたライブラリ作ってくれてるので、仕事の合間にちょろっと調べて値が取得できるところを確認してみました。
備忘録的にどうやったのかだけ残しときます。

-----

## 動作確認した環境
- MacBook Pro + macOS Sierra
- 普通の無線LAN環境
- node.js v6.2.0

-----
## 実作業

### 準備

#### パッケージのインストール
[Dash button for Node](https://www.npmjs.com/package/dash-button)なるものを使ってみました。似たライブラリとしては「node-dash-button」というのもあったんですが、当方のローカル環境ではうまく動かず。とりあえず前者がサクッと動いたのであまり悩まずにこちらで進めます。適当にディレクトリを切った後に以下を実行してパッケージを突っ込みましょう。

```bash
$ npm init
$ npm install --save dash-button

```

#### Dashボタンのセットアップとフィジカルアドレスの取得をする。
dash-buttonのドキュメント通りにpackage.jsonの"script"キーを編集します。

```json
{
  "scripts": {
    "scan": "dash-button scan"
  }
}

```

同じくドキュメントで指示があるように以下を叩きます。するとDashボタンの捜索を開始し、見つけたDashボタンのフィジカルアドレスが吐き出されるようになります。この間でフィジカルアドレスを確認できるので、通常通りにDashボタンのセットアップも平行して行いましょう。この時、商品の選択の途中で抜けることもお忘れなく。

```bash
$ sudo npm run scan

//　この間で普通にDashボタンのセットアップをiPhone/AndroidのAmazonAppを用いて行います。
// 商品選択を×ボタンで抜ければ注文はせずネットワークにシグナルだけを流してくれる状態になります。


Scanning for DHCP requests and ARP probes on en0...
Detected a DHCP request or ARP probe from xx:xx:xx:xx:xx:xx // ←こいつがDashボタンをフィジカルアドレス。
// 出てこなければセットアップ後に1回ボタンをポチっとしてみてください。
```

これが出来ればとりあえず事前準備はOKです。フィジカルアドレスはちゃんと控えておいてください。

-----

## 試してみよう。

とりあえずこんな簡単なテスト用のスクリプトを作ってみました。

```js
const DashButton = require("dash-button"); // モジュール読み込み

const PHY_ADDR = "xx:xx:xx:xx:xx:xx"; // ここでフィジカルアドレスを指定

let button = new DashButton(PHY_ADDR); // ボタンのアドレスを引数に渡してDashButtonクラスを呼び出し

console.log("I'm listening'") // 「がんばってます」を主張
let i = 0; // カウントしたかったのでとりあえずカウント用の変数を置いときます。

/*
  以下が発火するイベントの指定部。
*/
button.addListener(() => {
  console.log("["+(i++)+"] It works."); // 今回はシンプルに呼び出し回数を併記してコンソール出力
});

```

で結果はこんな感じ。無事取れてますね。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Dash buttonのボタン押下取得できた。<br>家のいろんなスイッチを作ろう。夜の営みクイック設定ボタンとか。 <a href="https://t.co/o0gvivjLzT">pic.twitter.com/o0gvivjLzT</a></p>&mdash; Yabu Kiyohide [ow;d] (@takustaqu) <a href="https://twitter.com/takustaqu/status/805734766712524800">2016年12月5日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

レイテンシーは大体10秒程度ありますので、少々使い方は考えなくてはいけないものの、実売500円でネットワーク越しに取得出来るボタンとして使うことが出来るのはなかなか魅力ではないでしょうか。AWS IoTボタンが出てくるのが一番幸せな感じですが、いうてあれも出たところで2000円ぐらいになるでしょうからね。

(追記：まあ冷静に考えると、ボタンを複数個並べるようなところは素直にラズパイにスイッチぶら下げたほうが良いでしょうね。逆に電源が取れないところだったり、ボタン1つで済むようなところ、ワイヤレスリモコン的な使い方したいところには良いのかも。)

まあ何も難がないとはいいません、どうも一瞬で2回イベントが発火することがあったりもするので、このあたりある程度考慮して作ってあげたほうが良いでしょう。
自宅内で待受するサーバーを立てる必要こそありますが、使いみちは色々あると思います。インターホン周りを改造してSlackへの同報とか、Hueの制御とかさせてみようかなーとか色々考え中でございます。

冬休みの工作の素材に、如何でしょうか？


-----

## その後

その後ちょっと気が向いたのでDash buttonを自宅用にさらに買い足し、色々作ってみました。

サーバーマシンは暫定的にMac　-> BeagleBone Black -> 余っていたAtomのラップトップと試してこれに落ち着いています。
BBBはコンパクトで良いのですが、ちょっと事故で破損し現状文鎮化。まあそのうち直しますかね...用途的に近いのでHomebridgeも並走させています。普通にいくならRaspberry Piでしょうか。

### 実際にボタンを作ったもの

- 外出・帰宅ボタン
    - Slackに日時送信、サーバーマシンから音声フィードバックが流れる(いってきます、いってらっしゃい)
- 照明ON/OFF
    - 風呂場のHueを物理スイッチではなくソフトウェア制御に統一したかったので。

...などなど。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">うちのIoT事情。家の入退室管理にDashボタン。押したらサーバーマシンから音声メッセージが流れる。帰宅時は照明が付く。<br>サーバーはBBBでやってたけど、余ったラップトップにリプレース。<br>homebridgeでIRKit叩いてシーリングライトとかも付く。 <a href="https://t.co/9AomK8s5tF">pic.twitter.com/9AomK8s5tF</a></p>&mdash; Yayane Kiyohide (@takustaqu) <a href="https://twitter.com/takustaqu/status/818021911900717057">2017年1月8日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

面倒なので基本的にはIFTTTを叩いているだけですが、音声フィードバックは[VoiceText WebAPI](https://cloud.voicetext.jp/webapi)をサーバー側で叩いてそのまま再生させています。

Slack、HueもIFTTT越しではなく直接叩いたほうがまあ理想としては良いでしょう。特にHueはIFTTT越しに叩くと凄まじくレイテンシが大きいので実用を考えると照明ON/OFFのようにスピードが早いほうが望ましいものはIFTTTに頼るのは避けたほうが良いでしょう。

前述の通りボタン自体のレイテンシも大きいですが、自宅内でのテストではボタンのイベント検出自体は5~10秒程度です。大きいか小さいかは用途次第ですが、今のところそんなに不都合は感じてないです。手軽さが遥かにそれを上回る感じ。

まあこのあたりはとりあえず普通にボタンをそのまま使っています。

そうそう、[本体ラベルのテンプレート](https://cl.ly/3Q2V1K2P1O1h)作ったので、ご興味が有ればどうぞ。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">誰も作ってなかったのでDash buttonのテンプレート作っておきました。PDFです。こんな具合で使えます。<a href="https://t.co/CyIBYtteZO">https://t.co/CyIBYtteZO</a> <a href="https://t.co/gaXbxAwkhE">pic.twitter.com/gaXbxAwkhE</a></p>&mdash; Yayane Kiyohide (@takustaqu) <a href="https://twitter.com/takustaqu/status/818023448949600256">2017年1月8日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

### Dashボタンそのものの加工

DashButton自体は皆さん御存知の通り既に第2世代目となっており、海外の分解レポートにあるタブ付け電池ではなく
普通に単4が外せます。ただ、超音波溶着されているので削りながらこじ開ける形ですね。

既に1個分解していますが、ボタン自体は電池の-側からGNDを取り、ボタン横の小さなランドとショートさせればボタンを発火出来ます。
インターホンのSlackへの通知は前々からやりたかったので、インターホンと連動して動作するリレーを用意して、そいつと繋いで動作させます。
まだ部品もないので、とりあえず準備はここまで。既にIFTTTのタスクは準備済。

![image](https://qiita-image-store.s3.amazonaws.com/0/61912/60941175-81d0-6c74-2b34-ff724e920669.png)

こんな感じでピンを外に出したDashボタンを用意しておくと何かと便利でしょう。
接着はみんな大好きblu-tackなりでやっておくと簡単に開けれる。素敵。

### いろいろ作った感想。

実際問題スタンバイ中に電気を食わず、ステータス取得も特殊なレシーバーなしに使えるボタンってそうそうないと思うのです。
近いものだとSonyのMESHだけど、あれ高いしMESHのアプリに依存しちゃいますしね...まあなんにしてもDashボタンは非常に良く出来てる。

懸念があるとしたらAmazon側の対策が入らないかどうかという事。どうもDashボタンを押した時に、Amazon側でボタンの廃止指示が返ってくるとWiFiへのコネクションを行わなくなるようである。現状明示的にユーザー側でボタンの停止処理をしない限りこれは来ないが、いつまでも商品注文の紐付いていないボタンにAmazon側が対策をしないとも限らない。
願わくばHackableなモデルが出てくれると嬉しい。1個2000円までなら考える。1000円なら最高。少なくとも今コレと同じことの出来るデバイスを僕は知らないしね。