暗くなったら窓シャッターを自動的に閉める(Raspberry Pi Zero W + Switch Bot)

マンションの一階に住んでいるんですが、
日が落ちても窓のシャッターを閉め忘れることがよくある。

通りに面しているので、外から部屋が丸見え。恥ずかしい。

ということで、暗くなったら自動的にシャッターが閉まるスマートホームを目指します。

![device](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208648/ead37924-f343-39cc-1ed4-29a2e96bc659.jpeg)


## 使うもの
- Raspberry pi Zero W
- [照度センサ(BH1750FVI)](https://www.mouser.com/ds/2/348/bh1750fvi-e-186247.pdf)
- [Switch Bot](https://www.switchbot.jp/bot)

うちの窓シャッターはPush式で自動開閉できるので、Switch Botをくっつけて遠隔操作できるようにしています。

![switchbot](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208648/47d38c0a-cec6-5bac-d1ea-cb340425d5d0.jpeg)


上下のボタンを押すとシャッターが自動で開閉してくれます。

Switch Botは専用アプリで定時実行ができるので、
開けるときはタイマーで朝７時になると自動的にPushするようになっています。
閉めるときもタイマーでもいいのですが、季節によって６時で暗かったり８時でも明るかったりして難しい・・・。
そこを照度センサを使ってうまくやれないかと。

ちなみにSwitch Bot Hubを導入すれば、IFTTTや各種スマートスピーカとも連携可能ですが、
[PythonでON/OFFできるスクリプト](https://github.com/OpenWonderLabs/python-host)が公開されているので、今回はRaspberryPiで実装します。


## やったこと
- RaspberryPi初期設定（省略）
- 照度センサの接続・計測値グラフ化
- Switch Bot動作確認
- センサの値をトリガーにボタンON/OFF

### 全体像
もはや描く意味あるかもわからない構成図
![全体像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208648/cef6743b-1582-fff9-5c38-dbc08f3e825e.png)


#### RaspberryPi初期設定（省略）
こちらの方法はネットにたくさんあるので割愛させていただきます。
主にやったこととしては、OSの書込/Wifi設定/ssh接続ぐらいです。
ちなみにOSはRaspbian GNU/Linux 9.9 (stretch)でした。

#### 照度センサの接続
まずは窓際にセンサを置いて明るさを測ってみます。
照度センサはBH1750FVIです。amazonで３個600円くらいで売ってます。

照度センサとRaspberry piを繋いできます。
[こちらのページ](https://www.raspberrypi-spy.co.uk/2015/03/bh1750fvi-i2c-digital-light-intensity-sensor/)を参考にしました。

BH1750FVIはI2C通信をするので、RaspberryPiのI2C通信設定をONにしておきます。

```
$  sudo raspi-config
```

[5.Interfacing Options] -> [P5 I2C] -> [enable]でOK

次にi2c-toolsというI2C接続を確認するツールを導入します。

```
$ sudo apt-get install i2c-tools
$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- 23 -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --     
```

`0x23`アドレスに接続が確認できました。
先ほどのページに`bh1750.py`というサンプルコードがあるので使ってみます。

```
$ wget https://bitbucket.org/MattHawkinsUK/rpispy-misc/raw/master/python/bh1750.py
$ sudo apt-get install python-smbus
$ python bh1750.py
Light Level : 66.67 lx
Light Level : 29.17 lx
Light Level : 22.50 lx
Light Level : 30.00 lx
Light Level : 33.33 lx
Light Level : 21.67 lx
Light Level : 30.00 lx
Light Level : 32.50 lx
...
```
ちゃんと取得できていますね

#### 計測値グラフ化

次に、１日の明るさの推移をみるために、グラフ化します。
[Focuslight](http://focuslight.github.io/index.ja.html)というグラフ化ツールが便利そうだったのでこちらを使います。

##### インストール方法
Focuslightの[Github](https://github.com/focuslight/focuslight)を参考にインストールします。

まずは必要なパッケージを入手

```
$ sudo apt-get install rrdtool librrd-dev libsqlite3-dev default-libmysqlclient-dev
```
Gem packageでインストール

```
$ gem install focuslight
$ focuslight new
$ cd focuslight
$ focuslight init # creates database scheme on SQLite
$ focuslight start
```

照度データを送るスクリプトを書く

```sendLightData.py
#!/usr/bin/python
import commands
import smbus
 
bus = smbus.SMBus(1)
addr = 0x23
lux = bus.read_i2c_block_data(addr,0x11)
 
lux_output = commands.getoutput("curl -F number=" + str((lux[0]*256+lux[1])/1.2) + " http://localhost:5125/api/home/sensor/lux")
print lux_output
```
forcuslightの`.env`ファイルでfloatを有効にしておく

```:.env
...
FLOAT_SUPPORT=y
...
```

forcuslightを起動した状態で、動作確認

```
$ python sendLightData.py 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   547  100   402  100   145    355    128  0:00:01  0:00:01 --:--:--   355
{"error":0,"data":{"id":1,"service_name":"home","section_name":"sensor","graph_name":"lux","number":55,"description":"","sort":0,"created_at":"2019/07/13 22:08:48","updated_at":"2019/07/13 22:28:47","mode":"gauge","color":"#9933cc","ulimit":1000000000000000,"llimit":-1000000000,"type":"AREA","adjust":"*","adjustval":"1","unit":"","complex":false,"md5":"c4ca4238a0b923820dcc509a6f75849b","meta":null}}

```

毎分動作するようにcronを設定

```:/etc/crontab
...
* * * * * root /usr/bin/python /[user_loacal]/sendLightData.py
```
cronの再読み込み

```
$ sudo service cron rload
```
http://localhost:5125
にアクセスすると以下のようにグラフが生成されています。

![照度グラフ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208648/624ba402-6a2e-2e8a-6eae-bb776de59e8e.png)



#### Switch Bot動作確認

Switch Botは専用アプリから操作するのが基本ですが、
公式からpythonで動作する[python-host](https://github.com/OpenWonderLabs/python-host)が公開されています。

まずは動作確認。
必要なパッケージをインストールします。

```
$ sudo apt-get update
$ sudo apt-get install python-pexpect
$ sudo apt-get install libusb-dev libdbus-1-dev libglib2.0-dev 
$ sudo apt-get install libudev-dev libical-dev libreadline-dev
$ sudo pip install bluepy
$ git clone https://github.com/OpenWonderLabs/python-host.git
```

アプリからSwirchBotのMACアドレスがわかるので、それをメモしておきます。
`python-host`内の`switchbot.py`を叩く。

```
$ sudo python switchbot.py [MACアドレス] Press
Preparing to connect.
Trigger complete
```

Trigger completeと出てSwitchBotが動いたので動作OKです。


#### センサの値をトリガーにボタンON/OFF

`bh1750.py`を参考に実装していきます。

```autoSwitch.py
#!usr/bin/python

import smbus
import subprocess
import json

DEVICE     = 0x23 # I2C address

bus = smbus.SMBus(1)  # Rev 2 Pi uses 1

def convertToNumber(data):
  result = (data[1] + (256 * data[0])) / 1.2
  return (result)

def readLight(addr):
  data = bus.read_i2c_block_data(addr,0x11)
  return convertToNumber(data)

def main():

    lightLevel = readLight(DEVICE)
    prevLightLevelStr = subprocess.check_output("curl -s http://localhost:5125/xport/home/sensor/lux?t=sh",shell=True) 
    prevLightLevel = json.loads(prevLightLevelStr)

    pLL1 = float(prevLightLevel['rows'][-4][0]) # ３分前
    pLL2 = float(prevLightLevel['rows'][-3][0]) # 2分前
    pLL3 = float(prevLightLevel['rows'][-2][0]) # 1分前

    # 条件を満たしたらSwitch botを動作させる
    if (pLL1 >= 100) & (pLL2 < 100) & (pLL3 < 100):
        press = subprocess.call("sudo python [fullpass]/switchbot.py [MACアドレス] Press",shell=True)

    # 値をfocuslightに送る
    lux_output = subprocess.check_output("curl -s -F number=" + str(lightLevel) + " http://localhost:5125/api/home/sensor/lux",shell=True) 


if __name__=="__main__":
   main()

```

照度の値が100以上のあとに２回連続で100未満だったらSwitchBotを動かすようにしています。
もっと良い条件設定があったら、ぜひ教えてください。。。

またSwitchBotの動作もスクリプトを組み込まずにsubprocessで強引に動かしています。

諸々、雑なところが残りますが、とりあえずこちらを定時実行します。

```:/etc/crontab
...
* * * * * root /usr/bin/python /[user_loacal]/autoSwitch.py
```

２〜３日窓際においといたら、おうちに帰るころにはちゃんとシャッターがしまってました。
やったね！

## おわりに

Raspberry Pi Zeroでもおうちハックできました！
私の家は自動シャッターだったのでSwitchBotを利用しましたが、
[自動でカーテンを操作するデバイス](https://mornin.jp/)もあるようなので応用できそうですね。

SwitchBotはひとつ4000円くらいしますが、押すだけでなく「引く」こともできるので、
よくあるパチパチ切り替えるスイッチにも使えます。デザインもかわいいのでオススメ。

それでは、よいおうちハックを！


## 参考
- [Raspberry Piと温度・湿度・光センサーでオフィスの状況を可視化する](http://tech.toreta.in/entry/2016/02/15/153203)
- [Using the BH1750FVI I2C Digital Light Sensor](https://www.raspberrypi-spy.co.uk/2015/03/bh1750fvi-i2c-digital-light-intensity-sensor/)
- [focuslight](https://github.com/focuslight/focuslight)
- [Raspberry Pi で温湿度・光量を取得してグラフ化する](http://jimaoka.hatenablog.jp/entry/raspi-sensor)