Raspberry PiとNatureRemoで「Nature(大自然)な目覚まし時計」を作ってみた話

#背景と概要
先日、「**たまにはモルディブの海辺で朝日を浴びながら目覚めてみたい**」
という~~無茶振りな~~お声をいただきました。

これを穏便に、自宅にいながら少ないお金で実現するべく
Raspberry Piで動画による目覚まし機能を実装し、
NatureRemoでIoT化したプロジェクターを媒体に「Natureな目覚まし時計」というのを作ってみました。


※目覚めるとこの視界が映るイメージ
![image](https://i-media.ittengo.com/staff-blog/wp-content/uploads/2018/10/seo428-main.jpg)



#用意したもの
* 赤外線リモコン付属のプロジェクター
* Nature Remo 3
* Raspberry Pi 4 モデルB
    * 事前にやっておいたこと
        * 日本語化：[Raspberry Pi 日本語化 + 日本語入力](https://qiita.com/HyunwookPark/items/e8a0c274b198235c8519)
        * HDMI出力時の音声設定：[【電子工作】Raspberry Pi 4BのHDMI出力で音声が出ない場合の対処](https://itneko.blogspot.com/2020/03/raspberry-pi-4bhdmi.html)
 

#NatureRemoの設定
「Nature Remo スマートリモコン」アプリでプロジェクターのリモコンを機器登録します。[Android版](https://play.google.com/store/apps/details?id=global.nature.remo&hl=ja&gl=US), [iOS版](https://apps.apple.com/jp/app/nature-remo/id1193531669)

#Raspberry Piの設定
今回は「就寝前にラズパイを起動しておき、指定時間にプロジェクターをNatureRemoのAPIで起動、接続しているラズパイから動画が流れる」という方針で実装します。
（ラズパイの自動起動は[他モジュール](https://www.indoorcorgielec.com/resources/raspberry-pi/rpz-powermgr-switch/)が必要など、ハードルが高く感じたため断念）


###1. NatureRemoのPythonライブラリを使えるまで
「nature-remo」というPython用のライブラリがあるので、こちらをインストールします。
日本語ドキュメントとしてもわかりやく[コチラ](https://pypi.org/project/nature-remo/)にまとまっています。

しかし、何も考えずに`pip install nature-remo`したところ下記のエラーが出ました。
![mashmallow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/738746/a929906f-f886-0675-fa87-f1a07a5cf118.png)
エラーの理由は、mashmallowというライブラがpython 3.5以上を要求していますが
RaspberryPiのデフォルト設定が2.Xとなっていたためでした。
参考：
[marshmallow 3.10.0](https://pypi.org/project/marshmallow/)
[marshmallow – 複雑なオブジェクトを単純なPythonデータ型との間で変換するための軽量ライブラリ](https://githubja.com/marshmallow-code/marshmallow)

回避するにはPythonのデフォルトバージョンを3.Xに切り替えるか、下記コマンドで乗り切れます。
参考：[Raspberry Pi の Python デフォルトバージョンを 2系 から 3系 に切り替える](https://qiita.com/nagase/items/029e8fab5d783bbf2743)

```
$ pip3 install nature-remo
```

###2. Pythonで家電に信号を送る
####2-1. NatureRemoのaccessToken取得
はじめに、自分のNatureRemoデバイスにアクセスするため、アクセストークンの取得を行います。
手順は[ログインサイト](https://api.nature.global/login)にNatureRemoアカウントでログインし、`Generate access token`ボタンを押すだけで発行できます。
下記の表示が出るのでメモしておきます。忘れて画面から移動した場合でも、再取得可能なので問題ありません。
![スクリーンショット 2021-03-22 19.22.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/738746/83e59a62-8be5-2147-24ba-ee4a4f3b3b0e.png)


####2-2. 登録家電情報を取得してみる
ここで少しNatureRemoのAPI仕様を深掘りしてみます。（詳細は[こちら](https://pypi.org/project/nature-remo/)）
NatureRemoで扱う情報は大きく分けて3つあります。

|名称|NatureRemoでの扱い|
|:---|:---|
|user|アカウント情報|
|device|NatureRemoデバイスの情報|
|appliance|NatureRemoに登録された家電情報|

基本的には**appliance**の情報がメインとなりそうなので
まずは下記スクリプトで家電情報を確認します。

```python
# conding: utf-8
from remo import NatureRemoAPI
api = NatureRemoAPI('accessToken')

appliance = api.get_appliances()
print(appliance)
```

上記で、自身で登録した全ての家電機器について
どの家電がどのIDを持ってどういった操作が登録されているか、
Listの中で何番目のデバイスなのか等を知ることができます。
例えば1つ目に登録されている家電が照明の場合、下記のように指定するとそのapplianceのみ照会できます。

```python
appliance = api.get_appliances()[0]
```

実際に取得してみた照明のapplianceデータも情報マスクして載せます。

<details><summary>applianceのデータ詳細</summary><div>


```
Appliance(
	id='appliance_id',
	device=Device(id='device_id',
		name='寝室のRemo',
		temprature_offset=0,
		humidity_offset=0,
		created_at=datetime.datetime(2021, 3, 23, 10, 0, 0, tzinfo=datetime.timezone.utc), 
		updated_at=datetime.datetime(2021, 3, 23, 10, 0, 0, tzinfo=datetime.timezone.utc),
		firmware_version='remo',
		mac_address='mac_address',
		serial_number='serial_no'
	),
	model=ApplianceModel(id='appaliance_id',
	manufacturer='Panasonic',
	remote_name='light',
	name='Panasonic LIGHT',
	image='ico_light'),
	nickname='寝室の照明',
	image='ico_light',
	type='LIGHT',
	settings=None,
	aircon=None,
	signals=[],
	tv=None,
	light=Light(
		state=LightState(brightness='100',
			power='on',
			last_button='on-100'
		),
		buttons=[
			Button(
				name='on',
				image='ico_on',
				label='Light_on'
			),
			Button(
				name='off',
				image='ico_off',
				label='Light_off'
			),
			Button(
				name='on-100',
				image='ico_light_all',
				label='Light_all'
			),
			Button(
				name='on-favorite',
				image='ico_light_favorite',
				label='Light_favorite'
			),
			Button(
				name='onoff',
				image='ico_io',
				label='Light_onoff'
			),
			Button(
				name='bright-up',
				image='ico_arrow_top',
				label='Light_bright'
			),
			Button(
				name='bright-down',
				image='ico_arrow_bottom',
				label='Light_dark'
			)
		]
	)
)
```
</div></details>

注目したのは、スマートリモコンの各ボタンの情報が`Light`オブジェクトで管理されているところです。
これは家電の種類によって異なり、こちらも3種類ありました。

|オブジェクト名称|デバイスの種類|
|:---|:---|
|TV|テレビ関連の機器|
|Light|照明関連の機器|
|Signals|それ以外？の機器|

今回は照明とプロジェクター、2種類の機器を扱うことにしましたが
照明は`Light`でプロジェクターは**`Signals`**オブジェクト内にボタンの情報があります。
ここの違いが、後述のAPIを呼び出す際に影響しますので確認が必要です。

そのため、この作業項目では`get_appliances()`の内容を確認して
API操作したい対象の下記ポイントを把握することがゴールとなります。

1. 登録家電リストの中で何番目の家電か
2. 対象家電のボタン情報はどのオブジェクトタイプか
3. 操作したいボタン情報がどれか（idやnameを確認する）

####2-3. Pythonで家電操作スクリプト作成
家電操作する場合に呼び出すAPIは、前述のオブジェクトタイプによって異なります。
今回は実装ポイントだけを簡単にまとめてみますが
APIで使用する引数の情報は、個人的にはGithubを直接参考されることをお勧めします。

Github：https://github.com/morinokami/nature-remo/blob/master/remo/api.py

|オブジェクトタイプ|信号送信のAPI|引数の値|
|:---|:---|:---|
|Light|send_light_infrared_signal(self, appliance: str, button: str)|appliance IDとbutton name|
|Signals|send_signal(self, signal: str)|signal ID|

上記の内容を踏まえて、下記2つのスクリプトを作成しました。
それぞれ部屋の照明On/Offとプロジェクターの電源の信号を飛ばすスクリプト
（添字等は適当に変更しています）

```python:light.py
# conding: utf-8
from remo import NatureRemoAPI
api = NatureRemoAPI('accessToken')

appliance = api.get_appliances()[0]

api.send_light_infrared_signal(appliance.id,appliance.light.buttons[0].name)
```

```python:projector.py
# conding: utf-8
from remo import NatureRemoAPI
api = NatureRemoAPI('accessToken')

projector = api.get_appliances()[1]
projectorPower = api.get_signals(projector.id)[0]

api.send_signal(projectorPower.id)
```

大きく違いはありませんが、`Signals`では`get_signals()`という
対象applianceのボタン情報をまとめて取得するAPIが利用できるので
applianceの情報から地道に辿らずに操作ボタンの情報が取得可能、という一例です。

###3. 動画再生のスクリプト作成
動画再生用のスクリプトは、下記サイト様の内容を全面的に使わせていただきました。
[Raspberry Pi 4を動画再生機（mp4プレーヤー）にした話](https://m0r1-39.hateblo.jp/entry/2020/06/27/010027)
今回はSDカードメディアではなく、無料素材を下記からローカルに保存しておきました。
[高品質なフリー動画素材](https://pixabay.com/ja/videos/)
###4. cron設定
最後に、作成したスクリプト群をcronで実行してもらうようスケジューリングします。

```
$ crontab -e
```

月曜から金曜まで設定する場合、下記のような形で設定しておきます。

```
7 30 * * 1-5 python3 projector.py
7 30 * * 1-5 python3 moviePlay.py
8 00 * * 1-5 python3 light.py
```

#まとめ
これで起床時間になるとプロジェクターが起動し
壁一面に海やリゾート地の風景動画を輝かせながら朝を迎えることができました！
NatureRemoのAPI仕様など、色々知見が広まったのもありますが
何よりこんなに簡単にできたということが感動的でした。
IoT DIYの入門として大変楽しめました、NatureRemo万歳！

ご自宅のIoT化をやってみたい、けど何からやったものかと悩んでいる方々や
QoL（Quality of Life）を上げてみたい！と思っている方々に響けば大変幸いです。

また長文となり大変申し訳ございません。ご一読いただいた皆様に感謝です。

##やってみた感想
* リゾート地の映像が美しくて最高！
* 音ではなく光によって自然に起こしてもらえる感
* 動画で起こしてくれるので、スヌーズ機能や二度寝防止の複数アラームが鳴ることによるイライラ解消
* 逆に寝る時の睡眠導入用にも応用できそう　など

副次的効果もあって結構評判良く安心しました。
動画は好みで変更可能なので、別の楽しみ方ができそうと、ワクワク感もありました。