部屋の不快指数を定期的に測定して、危険な値ならLINE通知を送るシステムをRaspberryPiで作ってみた

## きっかけ
- 今年も暑くなってきたけれど、クーラーってどれくらいの暑さで使うのがいいんだろう？
- 不快指数を測定して「危ないからクーラー使え！」って通知が来たらきっと楽だよな……
- 屋内でも熱中症の危険がある日本の夏、命を救うことが出来るシステム……かもしれない
- ラズパイにセンサ接続して疎通だけならやってたし、作ってみるか

## システム概要図
![Untitled Diagram (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224361/8b536953-27ba-a009-2fb3-3aa9d7c13036.png)


## 注意
- 試行錯誤しながらのメモを元に書いた記事なので、手順に抜け漏れがあるかもしれません……

## 使った物
- Raspberry Pi Zero WH
- AE-BME280
    - [ＢＭＥ２８０使用　温湿度・気圧センサモジュールキット](http://akizukidenshi.com/catalog/g/gK-09421/)
- [LINE Nortify](https://notify-bot.line.me/ja/)

## ラズパイ用OSの準備(Win10で作業)
### OSをSDカードに書き出し
- [Raspberry Pi Imager](https://www.raspberrypi.org/downloads/)をダウンロードしてインストール
- 起動してOSと書き出しするsdカードを指定して実行

### OSを書き出したSDカードのルートに2ファイル生成
#### ssh
空ファイルでOK
#### wpa_supplicant.conf
```Command:wpa_supplicant.conf
country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
  ssid="SSID"
  psk="暗号化キー"
}
```

## ラズパイ起動後設定(linux/raspberrypi作業)
teraterm等でWin10から接続しても良いですが、プログラミングは基本的にLinuxでやっていたので
Linux(Ubuntu)からsshでラズパイに接続して作業をする準備をしています。
 
### sshアクセス(Linux)
```bash:linux
ssh pi@raspberrypi.local
# pass:raspberry
```

### ラズパイ初期設定(raspberrypi)
```bash:raspberrypi
# sudoユーザ作成
sudo adduser kabu0404
sudo usermod -aG sudo kabu0404
su kabu0404

# 諸々更新
sudo apt update
sudo apt upgrade

# タイムゾーン/ロケール設定
sudo timedatectl set-timezone Asia/Tokyo
sudo localectl set-locale ja_JP.UTF-8
# 最終的にsudo raspi-configでいじったかも
```

### 公開鍵でのssh接続
```bash:linux
# 過去にssh-keygen -t rsaしてたので既存の公開鍵を送る
cd ~/.ssh
scp ./id_rsa.pub kabu0404@raspberrypi.local:~/.ssh/
```

```bash:raspberrypi
cd ~
chmod 700 .ssh
cd ~/.ssh
cat id_rsa.pub >> authorized_keys
chmod 600 authorized_keys
rm -fv ~/.ssh/id_rsa.pub
```

## BME280設定
### BME280の接続
- ブレッドボード経由で下表のように接続

|BME280側|ピン番号|
|---|---|
|VDD|1(3.3V)|
|GND|9(GND)|
|CSB|---|
|SDI|3(I2C1_SDA1)|
|SDO|9(GND)|
|SCK|5(I2C1_SCL1)|
※ スイッチサイエンス版の製品だとピンが一本多いので注意

### BME280の疎通
```bash:raspberrypi
# spi/i2cを有効化＆localeを直す
sudo raspi-config

sudo chmod 666 /dev/i2c-1

# 接続状態を確認
i2cdetect -y 1

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- 76 --  

# 76に接続されていることを確認

# レジスタ内容を確認
i2cdump -y 1 0x76

No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
80: 8a 70 89 8e 83 0f fc 06 34 6e 56 66 32 00 8a 8e    ?p??????4nVf2.??
90: 17 d6 d0 0b 5e 1d f0 ff f9 ff ac 26 0a d8 bd 10    ????^??.?.?&????
a0: 00 4b 40 00 00 00 00 00 00 00 00 00 33 00 00 c0    .K@.........3..?
b0: 00 54 00 00 00 00 60 02 00 01 ff ff 1f 60 03 00    .T....`?.?..?`?.
c0: 00 00 00 ff 00 00 00 00 00 00 00 00 00 00 00 00    ................
d0: 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    `...............
e0: 00 67 01 00 14 05 00 1e 57 41 ff ff ff ff ff ff    .g?.??.?WA......
f0: ff 00 00 00 00 00 00 80 00 00 80 00 00 80 00 80    .......?..?..?.?

# レジスタ設定
# 動作設定系レジスタの値確認
echo -n '0xF5:' ; i2cget -y 1 0x76 0xF5 ; \
echo -n '0xF4:' ; i2cget -y 1 0x76 0xF4 ; \
echo -n '0xF2:' ; i2cget -y 1 0x76 0xF2

# 動作設定系レジスタの値設定
# i2cset -y 1 0x76 [内部アドレス] [値]
i2cset -y 1 0x76 0xF5 0xA0 ; \
i2cset -y 1 0x76 0xF4 0x27 ; \
i2cset -y 1 0x76 0xF2 0x01
# 設定値は特殊なことをしたくなければ上記の設定でOKなはず

# 温度・湿度・気圧の値取得
i2cdump -r 0xF7-0xFE -y 1 0x76

No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
f0:                      54 0b 00 84 00 00 74 62              T?.?..tb 

# こんな感じで値が取得できていればOKのはず
# 他のレジスタの値を利用して上手いことやるときれいにデータが出力できるらしい
```

## Pythonでの測定値取得準備

キットは秋月電子の製品ですが、センサー自体は同じなので[SWITCHSCIENCEのサンプルコード](https://github.com/SWITCHSCIENCE/samplecodes/blob/master/BME280/Python27/bme280_sample.py)を活用しています

```bash:raspberrypi
mkdir i2ctest
cd i2ctest/
wget https://github.com/SWITCHSCIENCE/samplecodes/archive/master.zip
unzip master.zip
# 展開後必要となるのは
# i2ctest/BME280/Python27/bme280_sample.pyのみなので
# 任意のDir配下にtouchしたファイルにコード内容をコピペで十分

cd BME280/Python27/
sudo python bme280_sample.py
temp : 28.37  ℃
pressure : 1003.83 hPa
hum :  51.99 ％
```

## LINE通知用のトークン取得
- [PythonでLINEメッセージ送信](https://qiita.com/y-tksk/items/7707f5cbb429f1828bea) を参考にトークンを取得しました

## LINE通知用の追加コーディング
### 気温・湿度用関数をコンソール出力から値返却に変更
```bash:bme280_sample.py
# 気温用関数
def compensate_T(adc_T):
	# 中略
	# print "temp : %-6.2f ℃" % (temperature) 
	return temperature

# 湿度用関数
def compensate_H(adc_H):
	# 中略
	# print "hum : %6.2f ％" % (var_h)
	return var_h
```
### データ取得関数でLINE通知用関数を呼び出し
```bash:bme280_sample.py
def readData():
	# 中略
	temp = compensate_T(temp_raw)
	# 気圧は使用しない
	# compensate_P(pres_raw)
	hum  = compensate_H(hum_raw)

	# 不快指数を計算し80超なら通知を送る
	discomfortIndex = 0.81 * temp + 0.01 * hum * ( 0.99 * temp - 14.3 ) + 46.3
	if discomfortIndex > 80:
		sendNotice(temp, hum, discomfortIndex)
```

### LINE通知送信用関数を追加
- [PythonでLINEメッセージ送信](https://qiita.com/y-tksk/items/7707f5cbb429f1828bea) を参考にコーディングしました

```bash:bme280_sample.py
def sendNotice(temp, hum, discomfortIndex):
	url = 'https://notify-api.line.me/api/notify'
	token = #通知用のトークンを設定
	headers = {'Authorization' : 'Bearer ' + token}
	now = datetime.datetime.now()
	message = \
		'\r\n日付： ' + now.strftime('%Y/%m/%d') + \
		'\r\n時刻： ' + now.strftime('%H:%M:%S') + \
		'\r\n指数： %5.2f' % (discomfortIndex) + \
		'\r\n気温： %5.2f ℃' % (temp) + \
		'\r\n湿度： %5.2f ％' % (hum)
	payload = {'message' : message}
	r = requests.post(url, headers=headers, params=payload)
```

## 定期実行の設定
[RaspberryPi3で初めてcrontabを使う前に](https://qiita.com/Higemal/items/5a579b2701ef7c473062) を参考にcronで定期実行を設定

```vim:lineNoticeCron
# 5分間隔で実行する例
*/5 * * * * kabu0404 sudo python /home/kabu0404/i2ctest/BME280/Python27/bme280_sample.py

```


## 実行結果
![resised.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224361/01a377a0-8fa0-d2aa-84a8-c6be1800ed02.jpeg)

## 作ってみた感想
### LINE Nortify
- トークン取得したらリクエスト送るだけでOKだったので楽
- グループのトークルームにも通知を送信可能らしいので結構使えるかも。時間があるときに公式のドキュメント読んでみます

### シリアル通信
- I2C? SPI? 何だそれ? ってレベルだったので苦労しました。今もよくわからんです。
- ラズパイで何かしようとすると事実上必須みたいな部分でもあるので、もうちょっと勉強したほうが良さそう

### レジスタ仕様
- 読み飛ばせた部分だけれども、読み方で少し詰まった。
- 今の理解は下記、間違ってたらご指摘ください
    - `hoge<n:m>`や`fuga[n:m]`は、nbit目〜mbit目の値を使うって意味
    - `hoge<0>`や`fuga[0]`は、使用する値が1桁だけだと0:0って書くのは冗長なので省略

### Python
- 単純に勉強が足りない

### このシステムの使いみちって？
- クーラー嫌いの家族の家に置いて、グループラインに「暑いのにクーラーつけてないかも！」って通知する
- 窓の外に置いて「もうクーラー消しても良い程度に涼しくなったよ」って通知する

### その他
- IFTTTとかスマート家電（持ってないけど）を組み合わせると面白そう
- 接続まではしてあるGPSと組み合わせてなんか面白いこと出来ないもんかな

## 参考にさせていただいた記事・サイト
- [「Raspberry Pi Zero W」をWindows10PCだけでセットアップ](https://qiita.com/Mitsu-Murakita/items/c70c44a30ac72dbbb6c2)
- [SWITCHSCIENCEのサンプルコード](https://github.com/SWITCHSCIENCE/samplecodes/blob/master/BME280/Python27/bme280_sample.py)
- [BME280搭載　温湿度・気圧センサモジュールの使い方](http://trac.switch-science.com/wiki/BME280)
- [PythonでLINEメッセージ送信](https://qiita.com/y-tksk/items/7707f5cbb429f1828bea)
- [Raspberry Pi Zeroについて](http://hara.jpn.com/_default/ja/Topics/RaspPiZero.html)
- [RaspberryPi3で初めてcrontabを使う前に](https://qiita.com/Higemal/items/5a579b2701ef7c473062)
- 思い出せた限りは書きましたが、これ以外にも色々と検索した気がします