IOT家電をAPIハックして、Siriから簡単に操作する方法

#はじめに

スマホからWi-Fiを通してコントロールできるIOT家電って便利ですよね。
でも、
毎回毎回、家電ごとに専用アプリを開くのも面倒くさい。。
しかも家電が増えれば、アプリもドンドン増える。。。(´Д｀)

シンプルに、
**家にある家電全部が、Siriに呼びかけるだけで全部操作したい!**

少なくとも、appleWatchから2，3タップするだけで操作したい。
そんな、IOT家電をSiriにまとめる化計画です。


##ざっくりした流れ
この記事では大まかに以下の流れで説明していきます。

1. IOT家電と、アプリがどんなやり取りをしているか調べる
2. ブラウザや、フリーソフト、IDEのAPIツールからIOT家電を制御して挙動を確認してみる
3. 制御プログラムをコーディングする
4. Siriで使えるようにセッティングする(RaspberryPiを使う)

GitHubリポジトリはコチラになります↓
[Github:akiraset/daikinCleaner](https://github.com/akiraseto/daikinCleaner)


##環境
以下の環境を前提とします。

- RaspberryPi: homebridgeを常駐させてHomeKitのハブとするため
- iPhone: IOT家電のアプリを操作、mitmproxyで使用
- appleWatch: あると操作が楽しい♪ 夜寝る時に布団から操作しやすい。(iPhoneでも代用可)
- Mac: PC,Linuxでも可ですが適宜インストール方法を読み替えてください。
- python3.7


##おさらい: いわゆるIOT家電って?
"Internet Of Things モノがネットにつながること"
ちまたではそう説明されますが、今のIOT家電を一言でいうと、
**Wi-Fiを通してスマホアプリで制御できる家電!**
ひとまずこの一言だと思います。

特徴として、メーカーさん達が家電制御のためにアプリをそれぞれ提供しています。
空気清浄機→アプリA
TV→アプリB
エアコン→アプリC
︙
あぁ〜、、アプリがどんどん増えてきますね。
10個の家電を操作しようとしたら、10個のアプリをインストールして使い分けるという複雑怪奇な現状です。統一しようとする動きもあるようですが、しばらく時間がかかりそうです。

う〜ん、やっぱり面倒くさいです(´Д｀)
冒頭でも触れたとおり、単純にSiriや、appleWatchからON/OFFだけしたいです。


#IOT家電とアプリのやりとり: IOT家電はAPIで制御されてる?

ある日気付いたのですが、
Wi-Fiで同一ネットワークに繋がっている場合に家電が制御できるってことは、
単純に、APIでやり取りして制御しているだけなのでは?
**API仕様さえ分かってしまえば、アプリを使わなくてもプログラムから制御することができるのでは?!**

ただ、IOT家電にはアプリと認証が必須/不要の2種類があり注意が必要です。
結論からですが、
認証ありの場合は、プログラムから制御するのは難しそうです。
おそらくアプリと家電で認証keyを使ってやり取りしている。
使っている認証Keyを取得できないため、プログラムを用いて制御することは難しいかと考えます。
私の家の例ですが、NORITZ給湯機がIOT家電なのですが、認証必要となっています。
イロイロと探ってみましたが、私のスキルではプログラムからNORITZ給湯機を制御することはできませんでした。
![IMG_7425.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215645/c4c5a784-5479-1bd0-8c51-5d55b06ccefd.png)
よくよく考えてみると、ガス&火を扱う給湯器が簡単に制御を奪えるのは危険すぎますね。さすがNORITZさん!
そんなわけで、ハックするのは**認証が不要のIOT家電となります。**


##認証不要のIOT家電: ダイキン空気清浄機
我が家で条件にあったIOT家電を見つけました。
「ダイキン 加湿ストリーマ空気清浄機 MCK70W」
![IMG_7423.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215645/9a94aca0-4cca-c998-2195-642a69e81981.png)

今回はこの家電をベースに進めていきます。


##IOT家電とのAPI仕様を突き止める
まずは、どんなAPI仕様でやりとりしているか把握する必要があります。

最初にやることは、真っ先にメーカーのサイトでAPI仕様を探すことです。
メーカーがAPI仕様を公開していれば、そちらを参考にするのが一番確実で簡単です。

残念ながら、IOT家電のAPI仕様を公開してるメーカーは殆ど無いので、その場合は、自力で探る必要があります。
どうやって??:thinking:

制御アプリと、IOT家電の真ん中に入りこんで、APIの内容を覗き見れれば。。
そうすれば、自分が操作したいAPI内容を確認することができますね。
API仕様はすべて把握する必要は無く、自分が制御したい機能のみを把握できれば良いです。
また、アプリに実際に命令をさせて、その命令内容を確認できれば良い訳です。


#`mitmproxy`を使う
まさにピッタリのツールが`mitmproxy`です。
名前は"man in the middle proxy 中間者代理"の略です。

mitmproxyは、pythonで書かれたプログラムで、主にスマホアプリ開発において、アプリとサーバーの間に入り、request、responseをチェックするのによく使われるツールです。

詳しくは以下の記事を参照ください↓ ちょっと古いですが分かりやすくまとまっています。
[モバイルアプリ開発者のための mitmproxy 入門](https://qiita.com/hkurokawa/items/9034274cc1b9e1405c68)

mitmproxyでやることは、

1. Macにmitmproxyをインストール
2. iPhoneをproxyにするMacに通信するように設定
3. アプリで実際に命令を出し、中間に入ったMacでrequest,responseを確認する

それでは、導入方法を簡単に紹介します。


##mitmproxyの準備

まずはセットアップです。


###install
Macにインストールするには、pipで行います。
なお、インストールにはXcodeが必要となります。

```sh

#install
pip install mitmproxy
```


###iphoneの準備
次にiPhone側で、Macで動いているmitmproxyをプロキシサーバーとして受け付けるように設定します。
iPhoneの `設定 > Wi-Fi > 接続しているネットワーク > HTTPプロキシ`を選択。
以下の内容を設定します。

- サーバー: MacのIPアドレス
- ポート番号: 8080 (デフォルト)
- 認証: オフ

できたら、Mac側でmitmproxyを起動します。

```sh
mitmproxy
```

Macで起動したら、iPhone側でmitmproxyの証明書を取得する必要があるため、
再度iPhoneに戻ります。
iPhoneのブラウザを開き、`http://mitm.it`アドレスにアクセス。
![IMG_7431.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215645/36390e9a-b17e-aa9b-7b02-32322c3ebd8b.png)


Appleマークを選択して、証明書をインストール。
これで、mitmproxyを使う準備が整いました。


##実際に、アプリからのAPIをmitmproxyで確認する。
それでは、アプリから命令を出してみます。

・ダイキンのアプリ↓ 加湿モードを実行してみます。
![IMG_7430.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215645/aff332c2-b511-4045-35d4-80405c8e92cc.png)


・mitmproxyでrequestの受け取りを確認できました↓
![スクリーンショット 2020-03-08 22.00.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215645/e7f05cca-6d31-0af6-05c7-dc3a821c303c.png)


はい、取れました!
同様の方法で、自分が必要だと思う機能をドンドン確認していきます。


#開発
必要最低限のAPI仕様が掴めたら、APIを利用した制御プログラムを書いていきます。
mitmproxyで確認したAPIが、本当にIOT家電を制御できるか動きを確かめながらコーディングすると、分かりやすいのでおすすめです。


##APIを使って家電の挙動を確認してみる
ブラウザからAPIを叩いて確認することもできますが非常に効率が悪いです、API確認ツールの利用をオススメします。
私は、IntelliJのAPIツールを使用しています。
JetBrains社以外をご利用の方は、ご使用のIDEに似たような機能を使ってください、多分あるはずです。
ない場合は、`Postman`というフリーソフトが使いやすくて有名です。
[Postmanダウンロード](https://www.postman.com/)

以下からは、`IntelliJ: RESTful Web Service Test`ツールで説明します。
他のAPIツールも似たようなものだと思いますので、読み替えてください。

・空気清浄機に加湿モードで起動を命令
![スクリーンショット 2020-03-06 10.38.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215645/5d85fc74-c9cf-cf4a-09dc-79e987dd1b8d.png)

・空気清浄機からセンサー情報を取得
![スクリーンショット 2020-03-06 10.37.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215645/8ba320d4-ad3c-d7e8-56a6-5a3db0746601.png)

・履歴もさかのぼって確認、実行できます。
![スクリーンショット 2020-03-06 10.35.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215645/3f9f07bf-bb53-1b2e-c279-aded150f68c2.png)
「このRESTクライアントは〜」と表示がありますが、特に問題無いなく、普通に使用できます。
簡単に説明します。

- - メソッド: GET/POSTなど
- ホスト/ポート: 対象のIPアドレス(この場合IOT家電のIPアドレス)
- パス: APIなので処理内容により、このパス内容が異なります。ココが重要です。
- リクエスト・パラメーター: 必要なパラメーターを追加します。   
`+`で追加、`-`で削除。ダブルクリックで変更ができる。
- 左上の緑`▶`: 実行です。リクエストが送信されます。(IOT家電が挙動)
- リクエスト・ボディー: テキストや、ファイル内容などで、保存したjsonファイルをパラメーターとして使用できます。

他に、
- レスポンス: レスポンス内容を確認できます。(IOT家電からの返事が表示される)
- 左の矢印:履歴をさかのぼって見ることができます。
- インポート/エキスポートも可能

APIツールを使いながら、制御プログラムをコーディングしていくとかなり捗りますので試してみてください。


##制御プロブラム
簡単ですが、ざっとこんなコードを書きました。

```py:daikinCleaner.py

import sys
import requests

args = sys.argv
if len(args) == 1:
    print('An argument is necessary.')
    exit()
arg = args[1]

# 空気清浄機のIPアドレス
url = 'http://192.168.0.10'

# 基本情報
basic_info = '/common/basic_info'
# センサー取得
get_sensor = '/cleaner/get_sensor_info'

# コントロール取得
get_control = '/cleaner/get_control_info'
# コントロールSET
set_control = '/cleaner/set_control_info'

# 実行したいパラメータのセット
param_off = {'pow': 0}

param_max = {'pow': 1,
             'mode': 0,
             'humd': 3,
             'airvol': 5,
             }

param_hum = {'pow': 1,
             'mode': 4,
             'humd': 4,
             'airvol': 0,
             }


def control(params):
    return requests.get(url + set_control, params)


print('param: ', arg)

if arg == 'off':
    res = control(param_off)
    text = res.text
elif arg == 'max':
    res = control(param_max)
    text = res.text
elif arg == 'hum':
    res = control(param_hum)
    text = res.text
else:
    text = 'nothing'

print('res: ', text)
```

- プログラム自体に、引数を持たせました。
 - `off`: 空気清浄機をオフにする
 - `max`: 湿度最大、風力最大!
 - `hum`: 加湿モードで起動
- `/common/basic_info`: 空気清浄機の型番など基本情報を取得できます。
- `/cleaner/get_sensor_info`: 湿度や、温度、空気の汚れ具合などセンサー情報を取得できます。ダイキンさんのセンサーは優秀なので、このセンサー情報取得で何か別のものを作れそうです。(定期的に取得してグラフにして統計するとか、空気汚れたらライトが点灯するとかw)
- `/cleaner/set_control_info`: コチラのパスを使って空気清浄機を制御します。


#HomeKitに制御プログラムを設定する。
Siriで操作するためには、AppleのHomeKitでプログラムの命令を常時受け付けるようにする必要があるので、RaspberryPiをHomeKitのハブ端末化させて常時スタンバイさせます。

HomeKitにプログラムを登録するには、Node.jsライブラリのhomebridgeを利用することで簡単に設定することができます。HomeKitや、homebridgeの詳しい説明とセッティングに関しては以前の記事を御覧ください
[Philips_HueをAPI連動！〜ラズパイをHomeKit化する](https://qiita.com/akinko/items/58c650f99f25fc7e3cb5#%E3%83%A9%E3%82%BA%E3%83%91%E3%82%A4%E3%82%92homekit%E5%8C%96%E3%81%99%E3%82%8B)

今回はhomebridgeに以下を追加しました。

```json:config.json

  "accessories": [
    {
      "accessory": "CMD",
      "name": "エアクリーナー",
      "on_cmd": "python3 /home/pi/daikinCleaner/daikinCleaner.py hum",
      "off_cmd": "python3 /home/pi/daikinCleaner/daikinCleaner.py off"
    }
  ]
```

今回は、冬でお肌カサカサなので、引数に`hum`を指定して、加湿モードでON/OFFできるようにしました。梅雨が来たら、引数を変えて爽やか空気に変更する予定です:thumbsup_tone2:

ここまで設定したら、homebridgeをrestartしたら、準備完了!
さっそく使ってみます!!


#使用感
「エアクリーナー つけて(オン!)」 →空気清浄機が加湿モードで動きます
「エアクリーナー 消して(オフ)」 →空気清浄機がオフになります。

appleWatchでも操作可能です(iPhoneでも)
タップするだけで、on/off!
![IMG_7422.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215645/89ca9510-a809-c9ba-2ddf-a41961b3d518.png)
うれしくて空気清浄機の前で何度もやってしまいましたw

私は、さらにHomeのシーンに追加して、以下のように楽してます。
「おやすみ」 → 照明が消える & PS4が電源オフ & 空気清浄機がオフ
「おはよう」 → 照明がいくつかON & 空気清浄機が加湿モードで起動

目指すは寝たきりのぐうたら生活をしたいので、そのためにはどんな努力も全力を尽くしたいと思います!


#おわりに

今回は、ダイキンの空気清浄機で説明しましたが、Wi-fiを利用して認証が不要のものであれば、他のIOT化家電も制御できると思います。
目星をつけた家電を、ひとつづつ調べてSiriファミリーに組み込んでいく、、、
想像するだけで楽しくて興奮しますね。(そして、娘からの尊敬の眼差しが集められます。)

最後までお読み頂きありがとうございます。