Nature Remo Cloud APIで家電を自動で制御する

この記事は[技術チャレンジ部アドベントカレンダー2024](https://qiita.com/advent-calendar/2024/challenge_club)4日目の記事です。

Nature Remoはお持ちでしょうか？

https://nature.global/

Nature Remoはスマートリモコンです。Wi-Fiで接続でき、赤外線の送受信や温度・湿度センサー等を備えているので、家電のリモコンの代わりにスマートフォンから家電の操作ができます。Nature公式ストアやAmazonから買えます。

Nature Remoはスマートフォンアプリの他にAPIによりインターネット経由で操作できます。iOS 17まではショートカットAppからも操作できたのですが、iOS 18の仕様変更によりショートカットからの操作ができなくなってしまいました。なので、代替案としてNature Remo Cloud APIを使うことにしました。

今回の記事では、Nature Remo Cloud APIとiOSのショートカットを組み合わせて、日没時に自宅の照明を自動で切り替えるセットアップを紹介します。

## 想定読者

- Nature Remoシリーズをお持ちの方
- 自宅の家電を自動で制御したい方
- IoTをやってみたい方
- 電気代を節約したい方

## 目的

日没時に部屋の照明を寒色から暖色に切り替える。

## 動機

- 部屋の中にいても日没したことが感覚的に分かるようにしたいから
- 以前はショートカットAppのみで実現できていたが、iOSの仕様変更で使えなくなったため

## 方法

ショートカットAppのオートメーションで日没時にNature Remo Cloud APIを実行するよう設定する。

## 手順

### 1. Nature Remoを準備する

Nature Remoは買いましたか？ではスマホアプリで設定しましょう。Nature Remoは基本的に電源ボタンの信号だけで機器を識別してくれますが、家電によっては独自コマンドがあるため、赤外線信号を個別のボタンに登録する機能があります。

例として、私が使っているパナソニックのシーリングライトの独自コマンドをお見せします。このシーリングライトは通常の白色光の他に、明るめの暖色と暗めの暖色（くつろぎ）のモードがあります。これは日没後に白色の明るい光を浴びたくない私にとってはとても重宝しています。惜しむらくは機器自体には日没時に切り替える機能がないことです。

![8DDF3804-30B8-4362-BB47-BEB291F2CC2E_1_201_a.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/443f4633-38e5-ca03-054c-29b2c70ed9f6.jpeg)
パナソニックのシーリングライトのコマンド

### 2. Nature Remo Cloud APIのアクセストークンを取得する

以下のページからアクセストークンを取得します。

https://home.nature.global/home

![スクリーンショット 2024-11-24 10.03.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/112831e8-b87d-4a0d-d24d-83fd146dfead.png)
アクセストークンを取得する。

:::note alert
アクセストークンがあれば家電を乗っ取れるので、厳重に保管してください。
:::

### 3. Postmanを準備する

APIリクエストをテストするためにPostmanを使います。

https://www.postman.com/downloads/

### 4. Postmanからリクエストを送信する

#### 4.1. 認証情報を設定する

「Nature Remo Cloud API」（名前は適当でいいです）というCollectionを作成します。

「Auth」タブの「Type」で「Bearer Token」を選択し、「Token」に `{{token}}` を指定します。

![スクリーンショット 2024-11-24 10.07.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/66a996fc-6d91-efac-3537-392ea721b4c3.png)

「Variables」タブで `token` という名前の変数を追加し、「Current value」に先ほど取得したアクセストークンを入力します。

:::note alert
「Initial value」には何も入力しないでください。クラウドに同期されるため、思わぬタイミングでアクセストークンが漏洩する可能性があります。
:::

![スクリーンショット 2024-11-24 10.07.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/bd36aa39-ed40-2b15-5a20-b6c912e92983.png)

これで認証の設定が完了しました。

#### 4.2. 家電IDと信号IDを取得する

CollectionのVariablesに `base_url` を追加し、Initial valueを https://api.nature.global に設定します。

左ペインのCollectionを右クリックし、「Add request」を押下します。「Fetch the list of appliances」とか適当な名前を付けてください。

メソッドをGETに設定し、URLを `{{base_url}}/1/appliances` に設定します。

![スクリーンショット 2024-12-05 20.08.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/953f3178-529a-6d3f-ed4f-a08d8f8eb1c3.png)

「Send」でリクエストを送信すると、下部パネルにレスポンスのJSONが表示されます。

![スクリーンショット 2024-12-05 21.09.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/72cd7fba-2194-f3f3-7a7c-76dfc7470971.png)

出力が長くて見づらいのでVSCodeにコピーしましょう。シーリングライトっぽい項目を見つけます。

![スクリーンショット 2024-12-05 21.38.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/cea57fe0-c6da-ec0f-0e71-d5746da85461.png)

1つ目の赤枠が家電IDになります。次に信号IDですが、今回は「暖かい光」に切り替えたいので2つ目の赤枠を使います。

CollectionのVariablesに戻って変数を設定します。 `appliance_id` と `signal_id` を設定してください。Current valueに赤枠の文字列をコピーします。

:::note alert
繰り返しになりますが、「Initial value」には何も入力しないでください。
:::

![スクリーンショット 2024-12-05 21.50.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/37d1303b-c193-7659-c4cf-2101a520a0fb.png)

次に信号を送信するためのリクエストを作成します。Collectionに「Send a signal」などの名前でリクエストを作成してください。今度はメソッドをPOSTに、URLを `{{base_url}}/1/signals/{{signal_id}}/send` に設定します。

Sendでリクエストを送信すると、シーリングライトの光が変わるはずです。これはスクリーンショットでは撮れないのでお家で確かめてください。

### 5. iOSのショートカットを設定する

iPhoneでショートカットAppを開き、「オートメーション」タブからオートメーションを追加します。「時刻」オートメーションを追加しましょう。

![IMG_3887.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/c7278184-5a14-5f66-6c1b-b8f8467aed6c.jpeg)
「時刻」を選択する。

![IMG_3888.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/452171bd-e15f-3681-066d-1fe0fa7f9c2b.jpeg)
「日の入」時に実行するよう設定する。


「新規の空のオートメーション」を押します。単純に照明を切り替えるリクエストを送信するだけのフローを書いても良いのですが、その場合だと在宅していない時でも照明がオンになってしまい、電気代を消費します。なので、iPhoneの現在地をもとに在宅かどうかを判定し、在宅時のみに照明を切り替えるフローを組みます。

以下のようなフローを作成します。

![IMG_3899.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/045e7857-2956-a3fe-cccd-d161f3401690.jpeg)
現在地の取得と条件分岐。

![IMG_3900.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/44db0f75-8965-42f5-2d99-4b88dee7b4bb.jpeg)
信号送出リクエストの送信。

フローチャートで書くとこうなります。

```plantuml
@startuml
start
:現在地を取得;
:現在地から自宅までの距離を取得;
if (距離が300 m以上) then (Yes)
    stop
else (No)
endif
:信号送出リクエストを送信;
@enduml
```

これで、在宅時は日没後に照明が暖かい光に切り替わり、外出時はリクエストを送信しないフローができました。

## 応用

Nature Remo Cloud APIとショートカットAppの組み合わせはアイデア次第で応用が利きます。

### 帰宅時に時間帯に合わせて照明を切り替える

オートメーションの「到着」を使って帰宅時に処理を実行します。

```plantuml
@startuml
start
:自宅の天気予報を取得;
:日の入時刻を取得;
if (現在時刻が日の入時刻より前) then (Yes)
    :「白い光」信号送出リクエストを送信;
else (No)
    :「暖かい光」信号送出リクエストを送信;
endif
@enduml
```

![IMG_3895.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/56e7a27a-badd-790e-b348-d0f3c441aee3.jpeg)
「到着」を選択。

![IMG_3893.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/9f90ee9a-54a3-8535-da63-52b47b2c0afe.jpeg)
日の入の前後の判定。

### 起床時の外気温によってエアコンのオンオフを切り替える

オートメーションの「睡眠」から「起床」を選択し、アラームを止めた時点で処理を実行します。または、「時刻」で決まった時間に実行しても良いです（目が覚めた時に部屋が暖まっているようにしたい）。

ほとんどのエアコンにはタイマー機能があると思いますが、今回はショートカットを使って、外気温によってオンオフを切り替えてみます。今回も在宅時のみ実行されるように現在地の取得と条件分岐を入れます。

```plantuml
@startuml
start
:現在地を取得;
:現在地から自宅までの距離を取得;
if (距離が300 m以上) then (Yes)
    stop
else (No)
endif
:自宅の現在の天気を取得;
:気温を取得;
if (気温が10 ℃以上) then (Yes)
    stop
else (No)
endif
:エアコンオンの信号送出リクエストを送信;
@enduml
```

![IMG_3901.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25047/31d700c0-8b01-f2b2-9953-d3ab9315f9d5.jpeg)
気温が10 ℃未満の場合、エアコンをオン。

## 最後に

ここまで読んでいただきありがとうございます。他におすすめの使い方があれば是非コメントして頂けると嬉しいです。

## 参考

- [Nature Developer Page | Nature Inc.](https://developer.nature.global/)
- [Nature Remo Cloud API | Swagger UI](https://swagger.nature.global/#/)