スマートコンセント(HS105)を使って電気毛布を自動ON/OFF制御する #SleepTech

# はじめに

こんにちは。**電気毛布を自動制御**しようと頑張っているエンジニアです。

先日、「[最近寒いので電気毛布のリモート制御にチャレンジする #SleepTech](https://qiita.com/tmisuo0423/items/ab3c7efb96e21bef5a3d)」で、サーボモータを使って電気毛布のつまみを自動で上下させようとしたのですが、
電気毛布コントローラーの固定が甘かったせいでうまくいきませんでした。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">むむっ<br>接着かケースの強度が…(再掲) <a href="https://t.co/nXh82K75am">pic.twitter.com/nXh82K75am</a></p>&mdash; Takahiro Mitsuoka (@t_mitsuoka) <a href="https://twitter.com/t_mitsuoka/status/1211900173149859840?ref_src=twsrc%5Etfw">December 31, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

そこで、今回は「[tp-link製のスマートコンセントHS105](https://www.tp-link.com/jp/home-networking/smart-plug/hs105/)」を使って、電気毛布の ON/OFF 制御をしていこうと思います。

## 前提

本記事は、「[快適な睡眠を目指して寝床内気象を測定する(温度編) #sleeptech](https://qiita.com/tmisuo0423/items/8e3bba55c3242ba02cc7)」で作った仕組みの拡張です。
先にお読みいただくと、より理解しやすいかと思います。

## 用意したもの

- スマートコンセント 
  - TP-Link HS105 (https://www.tp-link.com/jp/home-networking/smart-plug/hs105/)
  - Amazon で 2200 円くらい

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90087/3408281b-19e2-044b-cb45-c31c40e21fea.png" width="300">

## 全体イメージとシステムイメージ

シンプルに、1 分毎に布団の温度を測り、電気毛布の ON/OFF を制御します。
ON/OFF する部分に HS105 を使用していきます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90087/6701bf59-2cb5-af71-375c-477ff74ba038.png" width="600">

システムイメージは以下のようになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90087/2ee06cee-7bcb-3cc0-dec0-390c5c3f8d49.png" width="600">


## HS105

### 初期設定をする

公式サイトの FAQ「[アプリ「Kasa」でミニ スマートWi-Fiプラグの初期設定をするには](https://www.tp-link.com/jp/support/faq/946/)」がめちゃくちゃわかりやすいので、そちらをご覧ください。
以降は、HS105 が Wifi につながっている前提の手順となります。

### Node.jsで操作する

HS105 を Node.js で操作できるライブラリ([tplink-smarthome-api](https://www.npmjs.com/package/tplink-smarthome-api))が公開されているので、ありがたくこちらを使用していきます。

#### IPアドレスを調べる

HS105 を操作するために、割り当てられているローカル IP アドレスが必要です。
`tplink-smarthome-apiのCLI`を使って簡単に調べられます。

まずは CLI をインストール。

```bash
$ npm install -g tplink-smarthome-api
```

`search`コマンドを実行する。

```bash
$ tplink-smarthome-api search
```

結果の中に HS105 に割り当てられている IP アドレスが表示されるので、コピーしておきます。
私の場合は、`192.168.10.3`でした。
以降のソースでは、この IP アドレスを使用して記述しますので、実行する場合は**自身のIPアドレス**に書き換えて実行してください。

```bash
$ tplink-smarthome-api search

Searching...
startDiscovery({
  discoveryInterval: 2000,
  discoveryTimeout: 10000,
  breakoutChildren: true
})
HS105(JP) plug IOT.SMARTPLUGSWITCH 192.168.10.3 9999 XXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
                                   ^^^^^^^^^^^^
```

#### 実際にON/OFFしてみる

[https://github.com/plasticrake/tplink-smarthome-api/blob/master/examples/plug-turn-on-off.js](https://github.com/plasticrake/tplink-smarthome-api/blob/master/examples/plug-turn-on-off.js)のコードを実行してみます。

```javascript
const { Client } = require('tplink-smarthome-api');

const client = new Client();

const plug = client.getPlug({ host: '192.168.10.3' }); // 各自のIPアドレスに書き換え
plug.setPowerState(true);
plug.setPowerState(false);
```

実行するとこんな感じで動く。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">電気毛布、サーボモータで強弱制御するのは難しそうなので、まずは スマートコンセント(HS105)でON/OFF制御していく<br><br>Node.jsでHS105のON/OFF制御はできたから、これから温度センサーと組み合わせていく <a href="https://t.co/hEjaotV5zq">pic.twitter.com/hEjaotV5zq</a></p>&mdash; Takahiro Mitsuoka (@t_mitsuoka) <a href="https://twitter.com/t_mitsuoka/status/1211891056964325377?ref_src=twsrc%5Etfw">December 31, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 布団の温度からON/OFFを制御する

obniz + 温度センサーから取得した温度を元に、HS105 を制御します。
obniz と HS105 の使い方さえわかれば、非常にシンプルなプログラムで動かすことができます。

```javascript
const Obniz = require('obniz');
const obniz = new Obniz(process.env.OBNIZ_ID);
const { Client } = require('tplink-smarthome-api');
const MAX = 100;

const callback = async () => {
  obniz.connect(); // obnizに接続
  await obniz.connectWait();
  const tempsens = obniz.wired('LM35DZ', { gnd: 0, output: 1, vcc: 2 });

  const client = new Client(); // HS105に接続
  const plug = client.getPlug({ host: '192.168.10.3' }); // 各自のIPアドレスに書き換え

  let temperature = 0; // obnizの温度センサーから温度を取得(バラつきがあるので100回平均している)
  for (let i = 0; i < MAX; i++) {
    temperature += await tempsens.getWait();
    await obniz.wait(10);
  }
  temperature /= MAX;

  if (temperature < 32) { // 温度に応じてHS105をON/OFF
    plug.setPowerState(true);
  } else {
    plug.setPowerState(false);
  }

  obniz.close(); // 繰り返し実行するので1回毎に切断する
  plug.closeConnection();
};

setInterval(callback, 60000); // 1分毎に実行する
```
## 実際に使ってみる

大晦日に作成してから使い続けていますが、今までと比べるとかなり快適になった気がします。

[Ambient](https://ambidata.io/)というサービスを使って、布団の温度や部屋の温湿度をグラフにしているのですが、昨日のグラフは以下のようになりました。
(左上：布団温度、右上：HS105 の ON/OFF、左下：寝室気温、右下；寝室湿度)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90087/6acaf0b2-06d9-d526-01d5-1892acb47362.png" width="900">

- 布団温度を見てみると、およそ 30℃～37℃の範囲で推移しているようです。平均は 33℃前後でしょうか。
    - プログラムを少し改良して、午後 10 時～翌朝 8 時までの間で電気毛布を制御するようにしました。
    - 電気毛布が OFF の時間になると 20℃前後で推移するようです。
    - それにしても測定誤差が大きいですね。10％程度はありそう。センサーや測定方法を検討する必要がありそうです。
- HS105 の ON/OFF は頻繁に切り替わっており、1 時間に数回～十数回は切り替わっています。
    - 切り替わるたびにカチッカチッとリレーが切り替わるような音がします。少し気になりますが、もう慣れました。
- 寝室気温は、18℃前後からほとんど変わらないようです。
- 寝室湿度は、加湿器を強めにつけているので、朝まではずっと湿度 95％でした（センサーの上限が 95%なので実際は 100%かもしれません）

## まとめ

簡単に作成した割には、満足のいく出来となりました。
早いところ誰かに使ってもらってフィードバックをもらいたいところです。

HS105 のライブラリを使うと、同一 LAN にいる端末からしか操作ができないようでした。
そのためノート PC から制御をかけているのですが、後々は AWS Lambda から操作できるようにしたいので調査が必要そうです。