24
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Nature Remo APIとAlexaで部屋中の家電を操作する話

Posted at

はじめに

先日待ちに待ったNature Remoの公式APIが公開されました

で、Qiitaでこんなの素晴らしい記事も見つけました

これらを組み合わせてみます
Node-REDって今回はじめて使ったのですが、めちゃくちゃ便利ですね。これは楽しい

フロー的なもの

1.Echoに自然な感じで話しかける
 「アレクサ、テレビつけて」「エアコンつけて」「テレビの音量下げて」「電気消して」
2.Node-RED Alexa Home Skill Bridgeで受け取ってローカル(今回はラズパイ)のNode-REDに渡す
3.Node-REDからNature RemoのAPIを叩いて家電を操作

めっちゃ簡単そうに見える(簡単とは言っていない)

やったこと

Node-REDの登録とインストールと準備

この辺は前述の記事の「Amazon Echo + Macbook Pro + Nature Remoで家電を操作するための設定手順」がすごくわかりやすいのでそちらを参考に進めると良いです

まずはNode-RED Alexa Home Skill Bridgeにユーザ登録し、操作したいDeviceを登録
登録したDevicesはこんな感じ
nodered.png
Nameはアレクサに呼びかけるときの対象の名前で、これはあとでアプリから変更することもできるっぽいんですが、下手に変更すると管理しづらくなったり混乱するので最初から呼びかける名前で付けます
「アレクサ、照明つけて」より「電気つけて」のほうが呼びかけやすいし自然ですよね
Descriptionはまあ適当に。こっちはあとからEditできます
Actionは、デスクライトはオンオフのみ、テレビと電気は後述しますが音量や明るさを設定するために%も指定(+%、-%だとうまくいかず)、エアコンはわかりやすく温度とその+-ですね

次はスマホのalexaアプリかweb画面から操作です
まずはalexaに「Node-RED」のスキルを追加し、先程登録したDeviceを検出
web画面なら「検出」を、スマホアプリなら「+デバイスを追加」をタップで読み込んでくれます

Node-RED環境は、私はラズパイ上に構築したので元記事とちょっと違いました
困ったときの公式ドキュメント

私のラズパイにはNode-REDがプリインストールされていたっぽいので、お勧めに従いアップグレードしてみる

$ bash <(curl -sL https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/update-nodejs-and-nodered)
(なんか色々聞かれたけどとりあえずYって答えるとしばらく待たされる)
$ update-nodejs-and-nodered
(同じくYでまたしばらく待たされる)

これでインストールが完了したはず
node-redコマンドを実行してStart的なメッセージが出たらOK
http://<ラズパイのIP>:1880/にアクセスするとNode-REDの画面が出てきます

ついでに自動起動設定もするとなお良し

$ sudo systemctl enable nodered.service

Node-REDのフロー作成

ここからはhttp://<ラズパイのIP>:1880/のGUIから操作

やはり元記事が素晴らしいので、手順3の後半に従ってnode-red-contrib-alexa-home-skillというNode-RED用プラグイン(パレットと呼ぶらしい)をインストール
このとき検索結果にnode-red-contrib-alexa-homeという似た名前のものも出てくるので注意
こっちも使えるのかもだけど使ったことないのでわからんです

次はNode-REDのフローを作成。こんな感じです
nodered-flow.png

基本的には左側メニューからノードを持ってきていい感じにつなぐだけです。どれを選ぶかは図から判断してください
一応エアコンだけ中を載せます

nodered-aircon1.png
Accountのペンマークから手順1で登録した登録したユーザを入力し、Deviceの更新マークをクリックで登録したDeviceが出てくるので選択

nodered-aircon2.png
ここでは手順1で登録したDeviceに対応するActionのコマンドが選べます
コマンドはここの一覧から対応するものを選択

nodered-aircon3.png
changeノードでは次のノードであるexecノードに渡すパラメータを指定します
msg.payloadはデフォルトのままで良く、onとしているところは短くわかりやすいパラメータ名がおすすめ

nodered-aircon4.png
最後にここで実行するシェルスクリプトを指定します
まだ作ってなければ空でもOK

すべての編集操作が終わったら必ず右上の「デプロイ」ボタンを押しましょう
これ以降、何かしら変更を加えた際にも同じくです

Nature Remo APIを使おう

ここからは前項の最後で出てきたシェルスクリプトを作成します
今回はシェルスクリプトからNature Remo APIを叩くことで家電を操作するので、APIを色々といじくり回します
Nature Remo APIの公式ドキュメントはこちら

swagger、いいですよね(独り言)

まずはここからトークンを発行
一度表示されたトークンは二度と表示されないので何処かファイルにでもメモっておきましょう
こいつを使ってとりあえず自分のremoに登録されてる家電と操作を取得してみます

curl https://api.nature.global/1/appliances -H "Authorization: Bearer <accesstoken>" | jq .

<accesstoken>には取得したトークンを指定しましょう
ちなみにこのときトークンをファイルに1行ペロッと書き込んでると

curl https://api.nature.global/1/appliances -H "Authorization: Bearer $(cat /path/to/token.txt)" | jq .

みたいにそのまま読み込めるのでめっちゃ楽です
また、結果はJSONで返ってくるので整形するのにjqを使ってます
jqについてはこちらがわかりやすいです

さて結果です

[
  {
    "id": "6c10f1a1-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "device": {
      "name": "Remo",
      "id": "837b1dc8-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "created_at": "2017-11-12T09:05:04Z",
      "updated_at": "2018-02-12T07:47:31Z",
      "firmware_version": "Remo/1.0.62-gabbf5bd",
      "temperature_offset": 0,
      "humidity_offset": 0
    },
    "model": {
      "id": "DCF7AEC4-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "manufacturer": "daikin",
      "remote_name": "xxxxxxxx",
      "series": "Daikin AC",
      "name": "Daikin AC 002",
      "image": "ico_ac_1"
    },
    "nickname": "Daikin AC 002",
    "image": "ico_ac_1",
    "type": "AC",
    "settings": {
      "temp": "26",
      "mode": "warm",
      "vol": "auto",
      "dir": "",
以下略

なげえよ。。。
まあでも取得できるのがわかったので良し

次に家電を操作するための信号を送信してみます
先程の結果から一部を抜粋

  {
    "nickname": "デスクライト",
    "signals": [
      {
        "id": "5320d922-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "name": "オン",
        "image": "ico_record"
      }
    ]
  }

このidの値を使って、こんな感じ

curl -X POST https://api.nature.global/1/signals/5320d922-xxxx-xxxx-xxxx-xxxxxxxxxxxx/send -H "Authorization: Bearer $(cat /path/to/token.txt)

はいデスクライトついたー(はず)
他も基本的には同じです
が、エアコンだけはAPIが違います
先程の結果の一部を再度抜粋

  {
    "id": "6c10f1a1-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "device": {
      "name": "Remo",
      "id": "837b1dc8-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "created_at": "2017-11-12T09:05:04Z",
      "updated_at": "2018-02-12T07:47:31Z",
      "firmware_version": "Remo/1.0.62-gabbf5bd",
      "temperature_offset": 0,
      "humidity_offset": 0
    },
    "model": {
      "id": "DCF7AEC4-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "manufacturer": "daikin",
      "remote_name": "xxxxxxxx",
      "series": "Daikin AC",
      "name": "Daikin AC 002",
      "image": "ico_ac_1"
    },
    "nickname": "Daikin AC 002",
    "image": "ico_ac_1",
    "type": "AC",
    "settings": {
      "temp": "26",
      "mode": "warm",
      "vol": "auto",
      "dir": "",
以下略

使うのはやはりidです
このときdevice.idmodel.idと間違えやすいのでご注意を
とりあえず電源オンしてみますが、aircon_settingsAPIでは操作はすべてform dataで送信します
で、電源オン・オフはbuttonの項目で指定しますが、その説明がこちら

Specify “power-off” always if you want the air conditioner powered off. Empty means powered on.

意訳:"power-off"指定でオフ、空文字指定でオンだよ

は? クソ設計 あまり見かけない斬新な設計ですね!
やってみた

curl -X POST https://api.nature.global/1/appliances/6c10f1a1-xxxx-xxxx-xxxx-xxxxxxxxxxxx/aircon_settings -H "Authorization: Bearer $(cat /path/to/token.txt)" -d "button="

たぶんこれでエアコンがついたはずです
温度操作も同じくform dataでの指定ですが、現在の設定に対する+-には対応しておらず、値を直接指定するしかないです

curl -X POST https://api.nature.global/1/appliances/6c10f1a1-xxxx-xxxx-xxxx-xxxxxxxxxxxx/aircon_settings -H "Authorization: Bearer $(cat /path/to/token.txt)" -d "temperature=27"

これってエアコン側の縛りなんですかね? クソ素敵すぎる
幸いにして現在の設定は最初に叩いたappliancesAPIでGETできるJSONに含まれているので、こんな感じで抽出します

curl https://api.nature.global/1/appliances -H "Authorization: Bearer $(cat /path/to/token.txt)" | jq -r '.[] | select(.id == "6c10f1a1-xxxx-xxxx-xxxx-xxxxxxxxxxxx") | .settings.temp' | cat
# =>27

jqのselect文めっちゃ便利

今回使うのはこの辺ですかね
シェルスクリプト化していきましょう

シェルスクリプトを作成

githubに上げたのでそれを見ていただければほぼOKです!!!(ぶん投げ)

一応いくつか解説します

テレビ用スクリプト

tv.sh
#!/bin/bash

echo `date` "exec command $1" >> /path/to/log/tv.log

TOKEN=$(cat /path/to/token.txt)

case $1 in
  on|off)
    curl -X POST https://api.nature.global/1/signals/2c9aa4b9-xxxx-xxxx-xxxx-xxxxxxxxxxxx/send -H "Authorization: Bearer $TOKEN";;
  11)
    # 1ch
    curl -X POST https://api.nature.global/1/signals/0ddd912a-xxxx-xxxx-xxxx-xxxxxxxxxxxx/send -H "Authorization: Bearer $TOKEN";;
  4)
    # 4ch
    curl -X POST https://api.nature.global/1/signals/8ab05d9a-xxxx-xxxx-xxxx-xxxxxxxxxxxx/send -H "Authorization: Bearer $TOKEN";;
  10)
    # volume down
    curl -X POST https://api.nature.global/1/signals/da9efa43-xxxx-xxxx-xxxx-xxxxxxxxxxxx/send -H "Authorization: Bearer $TOKEN"
    curl -X POST https://api.nature.global/1/signals/da9efa43-xxxx-xxxx-xxxx-xxxxxxxxxxxx/send -H "Authorization: Bearer $TOKEN"
    curl -X POST https://api.nature.global/1/signals/da9efa43-xxxx-xxxx-xxxx-xxxxxxxxxxxx/send -H "Authorization: Bearer $TOKEN";;
  100)
    # volume up
    curl -X POST https://api.nature.global/1/signals/85a0f17d-xxxx-xxxx-xxxx-xxxxxxxxxxxx/send -H "Authorization: Bearer $TOKEN"
    curl -X POST https://api.nature.global/1/signals/85a0f17d-xxxx-xxxx-xxxx-xxxxxxxxxxxx/send -H "Authorization: Bearer $TOKEN"
    curl -X POST https://api.nature.global/1/signals/85a0f17d-xxxx-xxxx-xxxx-xxxxxxxxxxxx/send -H "Authorization: Bearer $TOKEN";;
  *)
    echo `date` "unknown command $1" >> /path/to/log/tv.log
esac

Node-REDフローの最後のexecノードに渡されるパラメータ(msg.payload)に応じてcase文で分岐させます
あとはまあログを出したりIDとTOKENを変数化したりしてますがその辺は読んで察してください
で、工夫点として後述する「定型アクション」のためにチャンネル選択と音量の上下を数値で指定しています。これは照明用のlight.shも同様
あと音量は一度のコールで3つずつ上下するようにしています
我が家の場合、音量が1だけ上がっても大して変わらないからですね
この辺は実際に運用して調整すると良いです

こいつをNode-REDで指定してデプロイすればもうアレクサに話しかければオンオフくらいの操作はできるはずです
「アレクサ、テレビつけて」「電気つけて」「エアコンの温度上げて」「エアコンの温度を26度にして」など
ちなみにエアコン関連の操作は「すみません、よくわかりませんでした」と答えながらもしっかり操作してくれてることが多いです
アレクサさんマジポンコツお茶目

定型アクションを設定

今のままだとテレビの音量を上げるのに「テレビを100にして」という必要があります
なので、これを自然な呼びかけでいけるようにします

定型アクションは、alexaのスマホアプリの左側メニューにある「定型アクション」から追加します

  1. 右上の+ボタンをタップ
  2. 「実行条件」から呼びかけるための「開始フレーズ」を入力。短くわかりやすいフレーズが良い
  3. 「アクションを追加」から、スマートホーム>操作したいデバイスを選択して【オン・オフ】と【パーセント】を指定
  4. 下にある「作成」ボタンを押すことで保存(地味に忘れがち)

ポイントは2.で【パーセント】を指定するところです
例えば先程のテレビ用スクリプトの例では、100を指定することで音量を上げるようにしていたので以下のように指定します
iOS からアップロードされた画像 (1).png
これにより、このアクションが呼ばれるとNode-REDに『100%が指定された』というコマンドが送られ、結果シェルスクリプトの100の分岐に入って音量を上げる処理が実行されます
しかしそもそもここで%指定じゃなくて単純な+-が指定できれば、「100を指定する=音量上げる」みたいなわけのわからない設計にしなくて済んだんですけどね。。。
これはNode-REDスキルの問題なのかな

さて、そしてこっちは完全にバグっぽい挙動なのですが、パーセント指定の最小値である1を指定してアクションを作成すると、実際の実行時には何故か『100%が指定された』ことになります
謎い
そのため、私はNHKをつけるためのアクションでは1のかわりに11を指定するようにしています
1chだから1のほうがわかりやすいんですけど、まあそこはどうせ隠蔽されるので気にしない方向で

というわけで1~4を繰り返すことで一通り指定した結果がこちら
iOS からアップロードされた画像.jpg

まあ無難ですね
ちなみにNHKと日テレしかないのは私が主にそれしか観ないからですw
そしてよく見ると**「NHK」と「つけて」の間に半角スペース**が入ってます
これは、半角スペースなしだとalexaがフレーズをうまく認識してくれなかったからです
アルファベットと日本語の組み合わせは苦手みたいですね

まとめ

  • Node-REDめっちゃ便利。しかも直感的にフローが組める。神か
  • alexaスキルの方はもうちょい改善されると嬉しいです。+-をなにとぞ!
  • Nature Remo APIも素晴らしい。いちいち赤外線情報とか送信しないで済むのが良いですね
  • 定型アクションのおかげでalexaさんが自然な日本語を理解してくれる。これはもっと使いみちがありそう
  • そもそも本来はワンフレーズで複数アクションを実行させる、みたいな用途みたいですね

一度一通り組んでしまえば、機器や操作の追加はちょろで済むので色々遊びたいですね
出かけるときや寝るときなどに一声で色々消えるとか?
、、、と思ったけどこれは定型アクションでいけるか
何しようかなあ。。。

参考

素晴らしい記事をありがとうございました!

24
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?