TI社のSensorTagで測った温度、湿度、気圧、照度、バッテリーレベルをBluetooth Low Energy(BLE)でRaspberry Pi3(RPi3)に送り、RPi3からIoTデーター可視化サービス「Ambient」に送ってデーターをグラフ化しました。
2017/6/1追記。「SensorTagはアドバタイズ状態で2分間放っておくとスリープモードに入って通信できなくなるので、長期間測定する端末としては使いにくい」と書きましたが、接続したままにすればスリープモードには入らないので、長期間測定する端末としても問題なく使えることが分かりました。詳しくは「SensorTagで温度、湿度などを測りRaspberry Pi3経由でAmbientに送ってグラフ化する」をご覧ください。
SensorTag
SensorTagは通信モジュールの異なる3種類のデバイスがあります。今回使ったのは「マルチスタンダード SensorTag」というもので、BLEで通信します。センサーとしては周囲および表面の温度センサー、湿度センサー、気圧センサー、周辺光センサー、加速度センサー、ジャイロスコープ、コンパス、磁気センサーが搭載されています。
SensorTagは3分間放っておくとスリープモードに入ります。省電力設計なのですが、再度電源ボタンを押さないと通信できなくなるので、どこかに設置して長期間気温などを測定する端末としては使いにくい仕様です。
今回はこの使いにくい仕様には目をつぶり、SensorTagからRPi3を経由してAmbientにデーターを送るテストをおこないました。
Raspberry Pi3(RPi3)のPythonでAmbientに中継する
「マルチスタンダード SensorTag」はBLEで通信します。そこでゲートウェイとしてRaspberry Pi3(RPi3)を使い、RPi3からBLEでSensorTagのデーターを取得し、Ambientに送りました。
プログラムはPythonで書きました。ライブラリーとしてbluepyを使いました。まずbluepyをRPiにインストールします。
pi$ sudo apt-get install python-pip libglib2.0-dev
pi$ git clone https://github.com/IanHarvey/bluepy.git
pi$ cd bluepy
pi$ python3 setup.py build
pi$ sudo python3 setup.py install
次にAmbientのPythonライブラリーもインストールします。
pi$ sudo pip install git+https://github.com/TakehikoShimojima/ambient-python-lib.git
SensorTagからデーターを取得するPythonプログラムは大まかには次のような流れになっています。
- BLEデバイスをスキャンする
- スキャンできたデバイスから、SensorTagを探す
(SensorTagはローカルネームが’CC2650 SensorTag’になっている) - SensorTagに接続する
(SensorTagクラスのインスタンスを作ると接続してくれる) - 温度、湿度、気圧、照度、バッテリーセンサーを有効化する
- 温度、湿度、気圧、照度、バッテリーの値を読む
- センサーを無効化する
- 読んだ値をAmbientに送信する
- 5秒ごとに上記の動作を繰り返す
このプログラムを動かすと、SensorTagのデーターがAmbientに送信され、グラフ化されるのが確認できました。
pi$ sudo python3 st2ambient.py
scanning tag
found SensorTag, addr = 24:71:89:bc:63:84
{'d4': 81, 'd5': 336.32, 'd2': 45.806884765625, 'd1': 25.1875, 'd3': 1016.45}
200
プログラムを最後に掲載します。今回はSensorTagからRPi3を経由してAmbientにデーターを送るテストということで、SensorTagがスリープモードに入った場合は手動で電源ボタンを押して再起動する必要がありますし、Pythonプログラムは複数のSensorTagがある場合を考慮していません。これらは次の課題です。
# -*- coding: utf-8 -*-
# while True:
# SensorTagをスキャンし、見つけたデバイスに接続し、
# 温度、湿度、気圧、照度、バッテリーレベルを取得し、Ambientに送信
#
import bluepy
import time
import sys
import argparse
import ambient
def main():
channelId = チャネルID
writeKey = 'ライトキー'
parser = argparse.ArgumentParser()
parser.add_argument('-i',action='store',type=float, default=120.0, help='scan interval')
parser.add_argument('-t',action='store',type=float, default=5.0, help='scan time out')
arg = parser.parse_args(sys.argv[1:])
scanner = bluepy.btle.Scanner(0)
am = ambient.Ambient(channelId, writeKey)
while True:
dev = None
print('scanning tag...')
devices = scanner.scan(arg.t) # BLEをスキャンする
for d in devices:
for (sdid, desc, val) in d.getScanData():
if sdid == 9 and val == 'CC2650 SensorTag': # ローカルネームが'CC2650 SensorTag'のものを探す
dev = d
print('found SensorTag, addr = %s' % dev.addr)
sys.stdout.flush()
if dev is not None:
tag = bluepy.sensortag.SensorTag(dev.addr) # 見つけたデバイスに接続する
tag.IRtemperature.enable()
tag.humidity.enable()
tag.barometer.enable()
tag.battery.enable()
tag.lightmeter.enable()
# Some sensors (e.g., temperature, accelerometer) need some time for initialization.
# Not waiting here after enabling a sensor, the first read value might be empty or incorrect.
time.sleep(1.0)
data = {}
data['d1'] = tag.IRtemperature.read()[0] # set ambient temperature to d1
data['d2'] = tag.humidity.read()[1] # set humidity to d2
data['d3'] = tag.barometer.read()[1] # set barometer to d3
data['d5'] = tag.lightmeter.read() # set light to d5
data['d4'] = tag.battery.read() # set battery level to d4
tag.IRtemperature.disable()
tag.humidity.disable()
tag.barometer.disable()
tag.battery.disable()
tag.lightmeter.disable()
print(data)
r = am.send(data)
print(r.status_code)
sys.stdout.flush()
time.sleep(arg.i)
# tag.waitForNotifications(arg.t)
tag.disconnect()
del tag
if __name__ == "__main__":
main()