Edited at

enebular InfoMotion でオムロン環境センサー (2JCIE-BL01) を可視化してみた。


はじめに

enebular developer Meetuup Vol.3 で「enebular InfoMotion を使ってオムロン環境センサー (2JCIE-BL01) を可視化してみた。(仮)」というタイトルで LT する内容の記事です。

スクリーンショット 2018-09-23 20.26.56.png

Raspberry Piとオムロン環境センサーを使用して測定したデータを可視化する事例やハンズオンはいくつかあるが、データを Firebase へアップロードして、Firebase のデータを enebular InfoMotion で可視化してみた。


事前準備


  • Raspberry Pi


    • Raspberry Pi 3 Model B

    • Raspberry Pi 3 Model B+

    • Raspberry Pi Zero W

    • Raspberry Pi 2 Model B + Bluetooth 4.0 USBアダプタ(CSR V4.0、BT-Micro4 など)



 OS は "RASPBIAN STRETCH" Version:June 2018 (Release date:2018-06-27) を使用。


構成

スクリーンショット 2018-09-22 22.38.49.png


手順


Raspberry Pi


5分毎にデータをFirebaseへアップロードする場合 (Ambient のツールを流用しています)

# ライブラリをインストール

$ sudo apt-get install libglib2.0-dev
$ sudo pip3 install bluepy
$ sudo pip3 install pyrebase
# プログラムを実行
$ sudo nohup python3 omron_firebase.py < /dev/null &

omron_firebase.py プログラムは こちら

項目

設定値

config
apiKey
Firebase の apiKey を設定 (必須)

authDomain
Firebase の authDomain を設定 (必須)

databaseURL
Firebase の databaseURL を設定 (必須)

storageBucket
Firebase の storageBucket を設定 (必須)

email

Firebase の認証用 ID (必須)

password

Firebase の認証用 Password (必須)

address

オムロン環境センサーの BT アドレス (任意)


omron_firebase.py

# -*- coding: utf-8 -*-

#

from bluepy.btle import Peripheral, DefaultDelegate, Scanner, BTLEException, UUID
import bluepy.btle
import sys
import struct
from datetime import datetime
import argparse
import pyrebase

config = {
"apiKey": "",
"authDomain": "",
"databaseURL": "",
"storageBucket": ""
}
email = ''
password = ''
companyID = 'd502' # OMRON company ID (Bluetooth SIG.)
address = 'FFA511nnnnnn' # BT ADDRESS (replace nnnnnn to own device)

Debugging = False
def DBG(*args):
if Debugging:
msg = " ".join([str(a) for a in args])
print(msg)
sys.stdout.flush()

Verbose = True
def MSG(*args):
if Verbose:
msg = " ".join([str(a) for a in args])
print(msg)
sys.stdout.flush()

def send2firebase(dataRow):
(temp, humid, light, uv, press, noise, accelX, accelY, accelZ, batt) = struct.unpack('<hhhhhhhhhB', bytes.fromhex(dataRow))
MSG(temp/100, humid/100, light, uv/100, press/10, noise/100, (batt+100)/100)

firebase = pyrebase.initialize_app(config)
db = firebase.database()
auth = firebase.auth()
user = auth.sign_in_with_email_and_password(email, password)

now = datetime.now()
dt_s = now.strftime("%s") + str(int(now.microsecond/1000))
data = {
"timestamp": int(dt_s),
"value": {
"created": int(dt_s),
"address": address,
"battery": float((batt+100)/100),
"temperature": float(temp/100),
"humidity": float(humid/100),
"light": float(light),
"uv": float(uv/100),
"pressure": float(press/10),
"noise": float(noise/100)
}
}
MSG(data)
results = db.child("omron").child(address).push(data, user['idToken'])

class ScanDelegate(DefaultDelegate):
def __init__(self):
DefaultDelegate.__init__(self)
self.lastseq = None
self.lasttime = datetime.fromtimestamp(0)

def handleDiscovery(self, dev, isNewDev, isNewData):
if isNewDev or isNewData:
for (adtype, desc, value) in dev.getScanData():
if desc == 'Manufacturer' and value[0:4] == companyID:
delta = datetime.now() - self.lasttime
if value[4:6] != self.lastseq and delta.total_seconds() > 11:
self.lastseq = value[4:6]
self.lasttime = datetime.now()
send2firebase(value[6:])

def main():
parser = argparse.ArgumentParser()
parser.add_argument('-d',action='store_true', help='debug msg on')

args = parser.parse_args(sys.argv[1:])

global Debugging
Debugging = args.d
bluepy.btle.Debugging = args.d

scanner = Scanner().withDelegate(ScanDelegate())
while True:
try:
scanner.scan(5.0)
except BTLEException:
MSG('BTLE Exception while scannning.')

if __name__ == "__main__":
main()



一括でCSVファイルのデータをFirebaseへアップロードする場合 (オムロンのサンプルプログラムが出力するCSVファイルを使用)

# ライブラリをインストール

$ sudo apt-get install python-bluez
$ sudo pip3 install pyrebase
# プログラムを実行
$ python3 omron_csv_firebase.py ./log/env_sensor_log.csv

omron_csv_firebase.py プログラムは こちら

項目

設定値

config
apiKey
Firebase の apiKey を設定 (必須)

authDomain
Firebase の authDomain を設定 (必須)

databaseURL
Firebase の databaseURL を設定 (必須)

storageBucket
Firebase の storageBucket を設定 (必須)

email

Firebase の認証用 ID (必須)

password

Firebase の認証用 Password (必須)


omron_csv_firebase.py

import sys

import csv
from datetime import datetime
import pyrebase

config = {
"apiKey": "",
"authDomain": "",
"databaseURL": "",
"storageBucket": ""
}
email = ''
password = ''

arguments = sys.argv

if len(arguments) == 1:
print ("Usage: python omron_csv_firebase.py CSV_FILE")
sys.exit()

csvfile = arguments[1]

def main():
firebase = pyrebase.initialize_app(config)
db = firebase.database()
auth = firebase.auth()
user = auth.sign_in_with_email_and_password(email, password)

## CSV_FILE format
## Time,Gateway,Address,Type,RSSI (dBm),Distance (m),Sequence No.,Battery (mV),Temperature (degC),Humidity (%%RH),Light (lx),UV Index,Pressure (hPa),Noise (dB),Discomfort Index,Heat Stroke Risk,Accel.X (mg),Accel.Y (mg),Accel.Z (mg)
## 2018-09-17 00:04:53.831591,raspberrypi,FFA511nnnnnn,EP,-66,1.77188476275,69,2830.0,22.68,82.6,0,0.01,996.3,34.64,71.4,23.37,0.0,0.0,0.0

f = open(csvfile, 'r')
reader = csv.reader(f)

for row in reader:
if row[0] == 'Time':
continue
dt = datetime.strptime(row[0][0:19], '%Y-%m-%d %H:%M:%S')
dt_s = dt.strftime('%s') + row[0][20:23]

data = {
"timestamp": int(dt_s),
"value": {
"created": int(dt_s),
"address": row[2],
"rssi": float(row[4]),
"distance": float(row[5]),
"battery": float(row[7]),
"temperature": float(row[8]),
"humidity": float(row[9]),
"light": float(row[10]),
"uv": float(row[11]),
"pressure": float(row[12]),
"noise": float(row[13]),
"di": float(row[14]),
"heat": float(row[15])
}
}
## print (data)
results = db.child("omron").child(row[2]).push(data, user['idToken'])

f.close()
return

if __name__ == "__main__":
main()


※ pyrebase をインストールした後、プログラムを実行すると「ImportError: cannot import name 'opentype' 」エラーが出力されるので、google-auth-oauthlib をアップグレードする。

$ sudo pip3 install --upgrade google-auth-oauthlib


Firebase

omron → BT アドレス (FFA511nnnnnn) 配下にデータが格納される。データ構造は以下。

第一階層
第二階層

timestamp

タイムスタンプ Unixtime (ミリ秒)

value
address
オムロン環境センサーの BT アドレス

battery
バッテリー電圧 (mV)

created
タイムスタンプ Unixtime (ミリ秒)

di
不快指数

distance
距離 (m)

heat
熱中症警戒度

humidity
湿度 (%)

light
照度 (Lm)

noise
騒音 (dBm)

pressure
気圧 (hPa)

rssi
電波強度 (dBm)

temperature
気温 (℃)

uv
UV Index

Firebase_2.png


InfoType

InfoMotion 作成の前に InfoType 作成を実施する必要があるが、InfoType 作成には InfoMotion Tool を導入する必要があるため、今回はサンプルで用意されている linechart をダウンロードして使用することにした。

(参考) https://docs.enebular.com/ja/infomotion/infomotiontool

(参考) https://docs.enebular.com/ja/infomotion/SampleInfoTypes.html

enebular_linechart.png


InfoMotion

InfoType と DataSource を指定して InfoMotion ダッシュボードを作成する。(参考)

TYPE に linechart を指定する。

DATASOURCE に Firebase DataSource を指定する。

Label に address データキーを指定する。

Value に 上記の第二階層のデータキーを指定する。(気温であれば temperature を指定する。)

enebular_add_graph_3.png

enebular_add_graph_2.png


結果

enebular.png