Node-RED dashboard+Sesameでスマートロックの開閉を行う

本記事は[Node-REDアドベントカレンダー2019](https://qiita.com/advent-calendar/2019/node-red/) の16日目の記事です。


スマートロック Sesame便利ですね。
WiFiアクセスポイント（セサミのWiFi中継アダプタ）経由で利用していて、
アプリの起動後から解錠できるようになるまで30秒以上かかる、１つのドアに複数の鍵がついていて同時制御を行いたいなど、セサミ純正のアプリで動かしにくい痒いところをAPIで解決したいと思います。

書いているタイミングですでに記事になっていることを見つけてしまったのですが、
せっかくなのでDashboardを利用したサンプルということで公開します。

[Node-REDでSesame API v3を使う](https://qiita.com/kamijyo/items/a0517a23d997902db749)

# SESAMEって何？
[CANDY HOUSE](https://jp.candyhouse.co/)さんが販売している鍵を開けるためのデバイスで
アプリからBluetooth or WiFiで解錠ができます。
アプリ自体がものすごく優秀でスマホを叩くと解錠したり、ゲストへ一時的な解錠権限を与えたりと。
便利な機能が目白押しです。
既存のどの様な鍵でも、ツマミを回して解錠するタイプの鍵であれば解錠することができます。

## APIキーを取得する
[APIリファレンスサイト](https://docs.candyhouse.co/)のトップページにある、
SESAMEのダッシュボードかrAPIキーを取得します。
デバイスIDとAPIキーは外に漏れないように取り扱いには気をつけてください。

## 完成図
<img width="828" alt="スクリーンショット 2019-12-23 3.13.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126158/99cb5384-d4bd-3b35-a511-39f37d286fac.png">

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3132363135382f31633463383738392d663132662d613463302d373835372d3232313930616339343061352e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126158/65d829c9-8494-cc34-3c78-099aba1c66de.png)


## 今回のポイント
- dashboard UIを使って少しリモコン風に
- dashboard UIは5秒おきに自動リロード
- 同一WiFi or VPN経由以外からは解錠命令が行えない
- 物理ボタンで複数鍵を連動させたい（リクエスト部分を並列にすることで対応可能）
- ドア情報は10秒毎日取得

## 今後
- APIキーとデバイスIDの管理、ノード化にチャレンジしたい
- 人物認証させて鍵をあけたい

## flow
`[DEVICE-ID HERE]`と`[API-KEY HERE]`の部分はご自身の環境に合わせて変更してください。


```node.js
[
    {
        "id": "d4474836.f27568",
        "type": "tab",
        "label": "ひらけゴマ！",
        "disabled": false,
        "info": ""
    },
    {
        "id": "360bdbc6.d2f234",
        "type": "http request",
        "z": "d4474836.f27568",
        "name": "",
        "method": "POST",
        "ret": "obj",
        "paytoqs": false,
        "url": "https://api.candyhouse.co/public/sesame/[DEVICE-ID HERE]",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "",
        "x": 550,
        "y": 260,
        "wires": [
            [
                "a72c458d.ab8038"
            ]
        ]
    },
    {
        "id": "a72c458d.ab8038",
        "type": "debug",
        "z": "d4474836.f27568",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 730,
        "y": 260,
        "wires": []
    },
    {
        "id": "f65de333.472a8",
        "type": "ui_button",
        "z": "d4474836.f27568",
        "name": "",
        "group": "52d3067e.551b18",
        "order": 1,
        "width": 0,
        "height": 0,
        "passthru": false,
        "label": "open",
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "icon": "",
        "payload": "unlock",
        "payloadType": "str",
        "topic": "",
        "x": 110,
        "y": 260,
        "wires": [
            [
                "3de6481a.912ff8"
            ]
        ]
    },
    {
        "id": "76ecd368.ec713c",
        "type": "ui_button",
        "z": "d4474836.f27568",
        "name": "",
        "group": "52d3067e.551b18",
        "order": 2,
        "width": 0,
        "height": 0,
        "passthru": false,
        "label": "close",
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "icon": "",
        "payload": "lock",
        "payloadType": "str",
        "topic": "",
        "x": 110,
        "y": 320,
        "wires": [
            [
                "3de6481a.912ff8"
            ]
        ]
    },
    {
        "id": "3de6481a.912ff8",
        "type": "function",
        "z": "d4474836.f27568",
        "name": "OPEN THE SESAMI",
        "func": "msg.headers = {'Authorization' : \"[API-KEY HERE]\"};\nmsg.payload = {'command' : msg.payload};\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 340,
        "y": 260,
        "wires": [
            [
                "360bdbc6.d2f234"
            ]
        ]
    },
    {
        "id": "bb7fa876.a6b4d8",
        "type": "http request",
        "z": "d4474836.f27568",
        "name": "",
        "method": "GET",
        "ret": "obj",
        "paytoqs": false,
        "url": "https://api.candyhouse.co/public/sesame/[DEVICE-ID HERE]",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "",
        "x": 530,
        "y": 420,
        "wires": [
            [
                "4e9e2b1.7b0c5d4",
                "c35d53ae.fda13",
                "925a5ef9.86267"
            ]
        ]
    },
    {
        "id": "b2c3fbbb.6e0de8",
        "type": "function",
        "z": "d4474836.f27568",
        "name": "SESAMI STATUS",
        "func": "msg.headers = {'Authorization' : \"[API-KEY HERE]\"};\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 330,
        "y": 420,
        "wires": [
            [
                "bb7fa876.a6b4d8"
            ]
        ]
    },
    {
        "id": "9bcf4c4e.24892",
        "type": "inject",
        "z": "d4474836.f27568",
        "name": "CHECK/10sec",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "10",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "x": 140,
        "y": 420,
        "wires": [
            [
                "b2c3fbbb.6e0de8"
            ]
        ]
    },
    {
        "id": "4e9e2b1.7b0c5d4",
        "type": "debug",
        "z": "d4474836.f27568",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 730,
        "y": 420,
        "wires": []
    },
    {
        "id": "c35d53ae.fda13",
        "type": "ui_text",
        "z": "d4474836.f27568",
        "group": "52d3067e.551b18",
        "order": 2,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "battery remain",
        "format": "{{msg.payload.battery}} %",
        "layout": "row-spread",
        "x": 740,
        "y": 480,
        "wires": []
    },
    {
        "id": "817a5286.a654d",
        "type": "ui_text",
        "z": "d4474836.f27568",
        "group": "52d3067e.551b18",
        "order": 3,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "DOOR STATUS",
        "format": "{{msg.payload}}",
        "layout": "row-spread",
        "x": 740,
        "y": 560,
        "wires": []
    },
    {
        "id": "cc15f307.f48c8",
        "type": "function",
        "z": "d4474836.f27568",
        "name": "CLOSE",
        "func": "msg.payload=\"CLOSE\"\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 540,
        "y": 520,
        "wires": [
            [
                "817a5286.a654d"
            ]
        ]
    },
    {
        "id": "558c83c2.0c0b4c",
        "type": "function",
        "z": "d4474836.f27568",
        "name": "OPEN",
        "func": "msg.payload=\"OPEN\"\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 530,
        "y": 600,
        "wires": [
            [
                "817a5286.a654d"
            ]
        ]
    },
    {
        "id": "925a5ef9.86267",
        "type": "switch",
        "z": "d4474836.f27568",
        "name": "",
        "property": "payload.locked",
        "propertyType": "msg",
        "rules": [
            {
                "t": "true"
            },
            {
                "t": "false"
            }
        ],
        "checkall": "false",
        "repair": false,
        "outputs": 2,
        "x": 370,
        "y": 560,
        "wires": [
            [
                "cc15f307.f48c8"
            ],
            [
                "558c83c2.0c0b4c"
            ]
        ]
    },
    {
        "id": "d739c35a.6d765",
        "type": "ui_template",
        "z": "d4474836.f27568",
        "group": "52d3067e.551b18",
        "name": "UI AUTO RELOAD",
        "order": 4,
        "width": 0,
        "height": 0,
        "format": "<meta http-equiv=\"refresh\" content=\"2; URL=./\">",
        "storeOutMessages": true,
        "fwdInMessages": true,
        "templateScope": "global",
        "x": 150,
        "y": 600,
        "wires": [
            []
        ]
    },
    {
        "id": "5cb1bf8d.b36e1",
        "type": "comment",
        "z": "d4474836.f27568",
        "name": "DOOR open and close",
        "info": "",
        "x": 160,
        "y": 220,
        "wires": []
    },
    {
        "id": "cbc90cb4.4b49",
        "type": "comment",
        "z": "d4474836.f27568",
        "name": "DOOR status info",
        "info": "",
        "x": 140,
        "y": 380,
        "wires": []
    },
    {
        "id": "52d3067e.551b18",
        "type": "ui_group",
        "z": "",
        "name": "sesami",
        "tab": "2611d96b.5b0f96",
        "disp": true,
        "width": "6",
        "collapse": false
    },
    {
        "id": "2611d96b.5b0f96",
        "type": "ui_tab",
        "z": "",
        "name": "Home",
        "icon": "dashboard",
        "disabled": false,
        "hidden": false
    }
]
```