ReButton を MicroPush Bot を押すリモートボタンにする

ReButton から Azure IoT Hub + Azure Functions を用いて IFTTT 経由で MicroPush Bot を操作することに成功しました。

赤枠が今回追加した構成です。
![](https://docs.google.com/drawings/d/e/2PACX-1vTXwaj8HhtzNQbFqk_qdtlk5OsOfppmi1jtjdA_rcBOGyEUpZTzeTKZ76vuvfKZwdoYbi-gvXNSz_Gn/pub?w=1106&h=815)

## TL;DR

元々 IFTTT 経由で MicroBot Push が動くように構成されているため、ReButton からの通知が IFTTT に届けば勝利です。

`request` モジュールのインストール方法は [Azure Functions (Node.js) で npm パッケージを追加して利用する方法 (コンソール利用)](https://qiita.com/ma2shita/items/e6d395a986bab4d81624) を見てください。

```js
const request = require('request');
const eventNameMap = {
    '2': 'GARAGEOPEN_DOUBLE'
};

module.exports = function (context, IoTHubMessages) {
    IoTHubMessages.forEach(message => {
        context.log(message);
        const eventName = eventNameMap[message.actionNum];
        if (eventName) {
            const key = process.env['IFTTT_WEBHOOK_KEY'];
            const url = `https://maker.ifttt.com/trigger/${eventName}/with/key/${key}`;
            request.post(url, (error, response, body) => {
                context.log(response);
            }).json(message);
        } else {
            context.log("Not found in eventNameMap");
        }
    });
    context.done();
};
```

## セットアップ

順番は以下のように進めると良いでしょう。

1. Azure IoT Hub
2. ReButton
3. Azure Functions

### Azure IoT Hub

とくに難しいことなく IoT Hub を作るだけです。
インスタンスサイズにはお気を付けください。

### ReButton

[ReButton のセットアップドキュメント](https://seeedjp.github.io/ReButton/) 通りに進めれば OK です。

### Azure Functions

Azure IoT Hub と Azure Functions の接続だけ解説します。

* ランタイムスタック(言語)は JavaScript(Node.js) を選択してください。(それ以外でもいいけど、私は知らん)
* クイックスタートから開始した際に [関数の作成] で *その他のテンプレート...* を選ぶと、トリガーの一覧の中で **IoT Hub (Event Hub)** があるので、これを選択します。
* 「機能拡張がインストールされていません」となったら "インストール" をしてください。(2分程度かかり、終了次第自動的に遷移します。)
* 「新しい関数」とダイアログが遷移したら [イベントハブ接続] で *新規* を選びます。
    * ダイアログで "IoT Hub" を選び、ReButton と接続されている IoT Hub 名を選択します。
    * [作成] をすれば IoT Hub と関数が接続されるので、あとは実装するだけです。

#### テストしてみる

標準の `index.js` はログ出力だけしてくれる最小限コードが実装済みですが、そのままだと `message` が `[object Object]` と中身を表示してくれないので

```js
context.log(message);
```

と修正しておきましょう。この状態で ReButton を押してみると [ログ] タブに表示されるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/faf9cfe9-3685-7d8e-9240-0c80c01a269b.png)

#### 残りの実装

以下は冒頭で掲載しているものと同じコードです。
ReButton のダブルクリック (`message.actionNum` == 2) に対して IFTTT のガレージを開けるイベント名 `GARAGEOPEN_DOUBLE` が割り当たるようにしました。

`process.env` で環境変数から IFTTT のキーなどを得ていますが、Azure Functions の環境変数設定は [プラットフォーム機能] > [構成] (もしくは [概要] での [アプリケーション設定]) における **Application settings** が環境変数です。 New Application Setting で作るようにしてください。

```js
const request = require('request');
const eventNameMap = {
    '2': 'GARAGEOPEN_DOUBLE'
};

module.exports = function (context, IoTHubMessages) {
    IoTHubMessages.forEach(message => {
        context.log(message);
        const eventName = eventNameMap[message.actionNum];
        if (eventName) {
            const key = process.env['IFTTT_WEBHOOK_KEY'];
            const url = `https://maker.ifttt.com/trigger/${eventName}/with/key/${key}`;
            request.post(url, (error, response, body) => {
                context.log(response);
            }).json(message);
        } else {
            context.log("Not found in eventNameMap");
        }
    });
    context.done();
};
```

以上でおしまいです。

## あとがき

### そもそも MicroPush Bot を用いた仕組みについて

先日、[SORACOM LTE-M Button powered by AWS を使うことで「どこでも MicroBot Push が押せるボタン」](https://qiita.com/ma2shita/items/e35b991e292056e69956) を作りました。

このボタンを作った理由ですが、我が家の電動ガレージは電波によるリモート開閉が可能です。しかし、この電波が10m程度しか飛ばないため、ガレージ前で操作する必要があります。
一方、ガレージ前の道路が狭いうえに路線バスが通るくらいの交通量があるため、ガレージ前まで行ってから開くのを待っていると、邪魔になってしまいます。
私のような小市民には、この待っている時間が心を削るのです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/8a25f943-0b57-9ab1-2f3e-de8f74c16f6a.png)

そのため [MicroBot Push]() をリモートから操作することでガレージを開けた状態にしてしまおうというのが、先ほどの SORACOM LTE-M Button powered by AWS との組み合わせです。

#### なんでボタンを追加したのか？

SORACOM LTE-M Button powered by AWS によって帰宅時の遠隔操作の問題は、完全に解消しました。
しかし、少々不便なことがあるのです。それは ボタンを家の中に持ち込まないと家の中からの操作、たとえば外出前のガレージオープンには対応できない ということです。

正直、SORACOM LTE-M Button powered by AWS は車の中に安置しておき、家の中には別のボタンがあったらなーと思ってたのです。

#### 得た学び

IoT においては、このようにハブサービスを経由するようにしておくことで、ハードウェアの追加・変更に対して強くなることができます。この辺はマイクロサービスの考え方をハードウェアや比較的遅延が大きいネットワークに対しても適用できるようになると、サービスインまでの時間短縮（モックだけでも動かせる）、製品寿命を延ばす(Blue/Green deploy)ができるんじゃないかなー

### Seeed Studio 社の ReButton

もう一個 SORACOM LTE-M Button powered by AWS を買えば解決する話なのですが、**なぜか** ReButton が入手できたので、これを使ってみます。

ReButton は単4電池2本で動くボタンデバイスです。通信には Wi-Fi を使い、連携先クラウドサービスは Azure IoT Hub もしくは Azure IoT Central になります。
詳しい話は [ReButton の商品紹介](https://www.seeedstudio.com/ReButton-p-2930.html) を見てください。

#### どこで買えるの？

[Mouser さんのこのページ](https://www.mouser.jp/ProductDetail/Seeed-Studio/114991735?qs=sGAEpiMZZMve4%2FbfQkoj%252BP9KiVky7ZkuOiqydGvvcK0%3D) が良いのかな？ちょっと自信がありません。[Seeed さんの日本法人](https://www.seeed.co.jp/)があるので聞いてみてください。

#### 私はどうやって手に入れたの？

IoT が学べるガジェット系コミュニティ "ALGYAN" の [4/6 に開催された４周年記念イベント](https://algyan.connpass.com/event/122064/)で登壇したのですが、その時のじゃんけん大会で当たりました。なんでやねん。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">当たってしまった某ボタンの人w <a href="https://twitter.com/hashtag/ALGYAN?src=hash&amp;ref_src=twsrc%5Etfw">#ALGYAN</a> <a href="https://twitter.com/hashtag/soracom?src=hash&amp;ref_src=twsrc%5Etfw">#soracom</a> <a href="https://t.co/vBgPQZMpfr">pic.twitter.com/vBgPQZMpfr</a></p>&mdash; にしだ ゆうき (@EDOkko360) <a href="https://twitter.com/EDOkko360/status/1114469800665731072?ref_src=twsrc%5Etfw">2019年4月6日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#### 技適は？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/8d293374-2f3a-ab35-068c-941418653e9b.png)

問題ない。

#### Azure IoT Central を使わなかった理由

Azure IoT Central の "ルール" を用いて Functions を起動できそうだったのですが、ウィンドウサイズ(集計期間)があり、そのあとに発火する仕様のようでした。
そうなると、ボタン押してからすぐ動いてもらいたい身としては、ちょっとユースケースに合わない感じというのが理由です。

ReButton と Azure IoT Central を連携させる方法は [Seeed ReButtonを動かしてみる](http://matsujirushi.hatenablog.jp/entry/2019/01/23/171257) に記載されています。試してみてくださいね。

## ほんとうのあとがき

平成の宿題を終えられて、ほっとしています。

## NOTE: az iot hub monitor-events の結果 JSON

https://seeedjp.github.io/ReButton/IoT_Hub.html に書いてある `az iot hub monitor-events` を実行した際に IoT Hub から得られる JSON を記録しておきます。

```json
{
    "event": {
        "origin": "ReButton1",
        "payload": "{\"actionNum\":\"2\",\"message\":\"Double click\",\"batteryVoltage\":3.02}",
        "annotations": {
            "iothub-connection-device-id": "ReButton1",
            "iothub-connection-auth-method": "{\"scope\":\"device\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}",
            "iothub-connection-auth-generation-id": "636XXXXXXXXXXXX790",
            "iothub-enqueuedtime": 1555231257080,
            "iothub-message-source": "Telemetry",
            "x-opt-sequence-number": 1,
            "x-opt-offset": "416",
            "x-opt-enqueued-time": 1555231257095
        },
        "properties": {
            "system": {}
        }
    }
}
```

EoT