どうも、可視化愛好家の前加賀美 Necozay Gurlukovich(まえかがみ・ねこぜい・ごるるこびっち)です。
テレワークも常駐化してきて自室の環境がとても大事になってきましたので、部屋の環境を少しでも改善するため、部屋の不快な度合いを可視化します。
今回は、Amazon prime 感謝祭で割引で購入したswitchbotを使用します。
割引で1500円くらいで買いました。
今回すること
switchbotで取得されている気温のデータをpythonで取得して、それをGrafanaで表示させます。
気温に関してはswitchbotに連携したアプリで見れるんですけどね!
これは今後色々カスタマイズしていくとするということで、その前段として今回の可視化を試します。
環境はラズベリーパイで行います。
InfluxDB
まずはinfuxdbの設定です。(influxdbがまだ入っていない想定で書いてます。)
infuxdbの役割は時系列でデータを格納していきます。
今回の場合ですと、気温が時系列データとして格納されていきます。
ラズベリーパイの中に入って、下記のコマンドを実行していきます。
$ sudo apt update
$ sudo apt install influxdb
$ sudo pip3 install influxdb
$ sudo apt install influxdb-client
$ sudo systemctl unmask influxdb.service
$ sudo systemctl start influxdb
infuxdb内にDBを作成します。
$ influx
Connected to http://localhost:8086 version 1.6.4
InfluxDB shell version: 1.6.4
> CREATE DATABASE tempDB
> exit
これでinfuxdb側の設定は完了です。
python実装
次にpythonです。(pythonはもう入っている想定で書いてます。)
pythonの役割はswitchbotから値を取得することです。
bluepyをインストールします。
$ sudo pip3 install bluepy
switchbotから値を取得するコードを書いていきます。
取得した値をinfluxdbに接続し、格納する部分も書いています。
switchbotから値を取得するコードは以下
from influxdb import InfluxDBClient
import struct
import sys
from bluepy.btle import Scanner, DefaultDelegate
import time
from datetime import datetime
# データベースに接続
dbclient = InfluxDBClient(host='localhost', port=8086, database='tempDB')
#Broadcastデータ取得用デリゲート
#class SwitchbotScanDelegate(btle.DefaultDelegate):
class SwitchbotScanDelegate(DefaultDelegate):
#コンストラクタ
def __init__(self, macaddr):
#btle.DefaultDelegate.__init__(self)
DefaultDelegate.__init__(self)
#センサデータ保持用変数
self.sensorValue = None
self.macaddr = macaddr
# スキャンハンドラー
def handleDiscovery(self, dev, isNewDev, isNewData):
# 対象Macアドレスのデバイスが見つかったら
if dev.addr == self.macaddr:
# アドバタイズデータを取り出し
for (adtype, desc, value) in dev.getScanData():
#環境センサのとき、データ取り出しを実行
if desc == '16b Service Data':
#センサデータ取り出し
self._decodeSensorData(value)
# センサデータを取り出してdict形式に変換
def _decodeSensorData(self, valueStr):
#文字列からセンサデータ(4文字目以降)のみ取り出し、バイナリに変換
valueBinary = bytes.fromhex(valueStr[4:])
#バイナリ形式のセンサデータを数値に変換
batt = valueBinary[2] & 0b01111111
isTemperatureAboveFreezing = valueBinary[4] & 0b10000000
temp = ( valueBinary[3] & 0b00001111 ) / 10 + ( valueBinary[4] & 0b01111111 )
if not isTemperatureAboveFreezing:
temp = -temp
humid = valueBinary[5] & 0b01111111
#dict型に格納
self.sensorValue = {
'SensorType': 'SwitchBot',
'MacAddr': self.macaddr,
'Temperature': temp,
'Humidity': humid,
'Battery': batt
}
def send_temp_data(macaddr):
# macaddr指定した温湿度センサの値を取得
macaddr = str.lower(macaddr)
scanner = Scanner().withDelegate( SwitchbotScanDelegate(macaddr) )
#スキャン(timeout9s)
scanner.scan( 9.0 )
temp=0
#出力
try:
temp = str(scanner.delegate.sensorValue['Temperature'])
except TypeError as e:
print("Temporarily lost communication with Bluetooth temperature device.",e)
except:
import traceback
traceback.print_exc()
return temp
if __name__ == '__main__':
while True:
print("temp is : ", send_temp_data('FE:EA:12:3D:E8:00'))
json_body = [
{
"measurement": "temp_measurement",
"time": datetime.utcnow(),
"fields": {
## ★XX:XX:XX:XX:XX:XXにはswitchbotのmacアドレスを入れてください
"temp": float(send_temp_data('XX:XX:XX:XX:XX:XX')),
}
}
]
dbclient.write_points(json_body)
time.sleep(10)
実際に実行してみると以下のように部屋の気温が取得できると思います。
$ sudo python3 switchbot.py
## 実行結果
temp is : 22.9
上記のコードの
# データベースに接続
dbclient = InfluxDBClient(host='localhost', port=8086, database='tempDB')
の部分で、infruxdbと接続しています。
これでpythonコードを実行している間、infruxdbにデータが蓄積します。
このデータをGrafanaで可視化しようという流れです。
ですので、常にデータを表示するときはpythonを実行し続ける必要があります。
Grafana
次にGrafanaです。(Grafanaがまだ入っていない想定で書いてます。)
Grafanaはデータを可視化するダッシュボードを提供します。
以下のコマンドを実行していきます。
$ sudo apt install -y apt-transport-https
$ sudo apt install -y software-properties-common wget
$ wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
$ echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
$ sudo apt update
$ sudo apt install grafana
$ sudo systemctl daemon-reload
$ sudo systemctl start grafana-server
http://<ラズベリーパイのIP>:3000にアクセスする。
すると、以下のようなログイン画面が出ていればOK
😫ラズパイのgrafanaにブラウザから接続できない問題が出た場合
ブラウザでGrafanaにアクセスしようとすると以下のようにGrafanaの画面が表示されないことがあります。
これに関しては、画像にも書いてある通りファイアウォール周りに問題がある可能性があります。
ラズベリーパイで以下のコマンドを実行して、
$ sudo ufw status | grep 3000
以下の出力がされない場合は、ファイアウォールに設定が必要です。
3000/tcp ALLOW Anywhere
3000/tcp (v6) ALLOW Anywhere (v6)
Grafanaのポートをファイアウォールに設定するには以下を実行します。
$ sudo ufw allow 3000/tcp
これで以下のように表示できると思います。
ここからGrafanaのinfluxdbの説明は画像が多くなるので割愛しますが、
ググると結構でてきますので、それらを参考にすると良いです。
そこまでハマらないかと思います。
ハマるとしたら、pythonでswitchbotのデータをinfluxdbに格納するときにstr型で格納してしまい、プロットが上手くいかないといったところがあるのでそこは注意します。
ということで、以下のようにプロットができました。