15
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Inkbird IBS-TH1 のログをbluetoothで取得してAmbientに送信し可視化する

Last updated at Posted at 2019-08-25

概要

  • Inkbird IBS-TH1からbluetoothでデータを取得する
  • 取得したデータをAmbientに送付する

背景

うさぎを飼っています。
うさぎは暑さに弱いので夏場は室温をキチンと制御することが必要です。そのためにInkbird IBS-TH1を購入して室温の状況を記録していました。

image.png 「エアコンの設定がxxx度だと、室温のログはこのぐらいだった。じゃぁ明日はこれぐらいにしよう」というふうにエアコンの適正温度の調整に役立ててます。

ただこれでは、エアコンが故障した場合に気づく事ができません。もし、夏場エアコンが故障して室温が上昇したら、うさぎは?と思うと仕事に手がつきません。
ということで、仕事先でも室温を確認できる仕組みを作ってみました。

仕組み

webで調べていると、NodejsでInkbird IBS-TH1 (BLE温湿度センサー) から温度湿度情報を得るを発見。手元のrasberry piがあるので、リアルタイムにデータの取得はできそうです。
あとは、これをクラウドに保存して表示するだけです。
最初、データの表示は、google spreadsheetを使おうと思っていたのですが、とAmbient が簡単そうだったので今回はこちらを使いました。

最終的に以下の仕組みになりました

  1. IBS-TH1 → rasberry pi で温度、湿度データ10分ごとに取得
  2. 取得した温度、湿度データをAmbientへ送信して保存
  3. 1と2を定期ジョブ(cron)にする

環境

  • Inkbird IBS-TH1 plus (miniでもOK)
  • rasberry pi 3b
    • BlueZがインストール済
    • python 2.7 (3でも多分大丈夫)

手順

IBS-THI → rasberry pi で温度、湿度データ取得

InkbirdのMACアドレス取得

bluetoothで情報を得るためには機器(今回はIBS-TH1)のMACアドレスが必要です。scanしてもいいのですが、デバイス名が表示されないこともあるので、一番簡単なのは、Inkbirdのアプリで接続する時に表紙される情報をメモすることです。
実際は下記の通りです。
機器登録するときに画面下部に出る(赤矢印)MACアドレスをメモしてください。
Image from Gyazo

Inkbird IBS-TH1 からデータを取得してみる

以下はすべて、raberry piでの操作です。
(BlueZをインストールしておいてください。インストールの仕方はwebに紹介記事がたくさんあるので割愛します。)

まず、gatttoolを使って、IBS-TH1からデータを取得してみましょう。

下記でhandleを指定して取得できる情報の一覧が表示されます。

gatttool -b XX:XX:XX:XX:XX:XX --characteristics

この中に目的とするデータがあるのですが・・・ただ、これだけだとさっぱりわからない。
ただ、こちらにhandle情報が書かれていました。これさえればOKです。

このhandleをもとに温度データを取得してみます。

gatttool -b XX:XX:XX:XX:XX:XX --char-read --handle=0x002d
Characteristic value/descriptor: cf 0a ee 17 00 1c 0d 

取得できました!

cf 0a ee 17 00 1c 0d というところが温度、湿度データです。

これを、実際に読めるデータに変換します。

前述のサイトによると

c8 0a uint16 Little Endian temperature value * 100
a8 16 uint16 Little Endian humidity value * 100

と、あります。
つまり、1バイト目と2バイト目が温度、3バイト目と4バイト目が湿度のデータです。さらに little endianで格納されているので下記の通り変換されます。

  • 温度は 0acf が 2767。なので、温度は 100で割った値、すなわち27.67度
  • 湿度が 17ee が 6126。なので、湿度は 100で割った値、すなわち 61.26%

pythonで取得してみる

pythonを使って、情報を取得してみます。 bluepy ライブラリを使います。 (事前にblueZのインストールが必要です!)
下記のコードを実行してください。ただいsm PERIPHERAL_MAC_ADDRESS はご自身のIBS-TH1のMACアドレスを入れてください。

main() を実行すると温度と湿度が表示されるはずです。

inkbird.py
from bluepy import btle
import binascii


PERIPHERAL_MAC_ADDRESS = 'XX:XX:XX:XX:XX:XX'
HANDLE = 0x002d


def main():
    peripheral = btle.Peripheral(PERIPHERAL_MAC_ADDRESS)
    characteristic = get_characteristic(peripheral, HANDLE)
    temperature = characteristic_to_temperature(characteristic)
    humidity = characteristic_to_humidity(characteristic)
    print(temperature)
    print(humidity)


def get_characteristic(peripheral, handle):
    return peripheral.readCharacteristic(handle)


def characteristic_to_temperature(characteristic):
    temp_hex = binascii.b2a_hex(characteristic[1]) + binascii.b2a_hex(characteristic[0])
    return float(int(temp_hex, 16)) / 100


def characteristic_to_humidity(characteristic):
    humid_hex = binascii.b2a_hex(characteristic[3]) + binascii.b2a_hex(characteristic[2])
    return float(int(humid_hex, 16)) / 100


ちょっと解説すると

peripheral = btle.Peripheral(PERIPHERAL_MAC_ADDRESS)

ここで、デバイスに接続します。

次に、handleを指定してデータを読み出します。

peripheral.readCharacteristic(handle)

あとは、下記で読み出したデータから温度数値と湿度数値へ変換を行います。考え方は前記のデータ取得の箇所と同じです。

def characteristic_to_temperature(characteristic):
    temp_hex = binascii.b2a_hex(characteristic[1]) + binascii.b2a_hex(characteristic[0])
    return float(int(temp_hex, 16)) / 100


def characteristic_to_humidity(characteristic):
    humid_hex = binascii.b2a_hex(characteristic[3]) + binascii.b2a_hex(characteristic[2])
    return float(int(humid_hex, 16)) / 100

取得した温度、湿度データをAmbientへ送信して保存

ユーザー登録

まずAmbientでユーザー登録します。
image.png

普通にメールアドレスとパスワードなどを入力すると確認メールが送信されるので、確認作業をすれば登録完了です。

image.png

チャネル作成

データを送信するためにチャネルを作成します。
チャネルを作るボタンを押すと即時にチャネルが追加されます。

Image from Gyazo

設定を押します。

image.png

チャネル名とデータ1、データ2を下記のように入力します。

image.png

ambient送信

チャネル名とライトキーをメモしてください。(下記のキーは実際には存在しません。)

image.png

このデータを元にambieデータの送信を追加します。
該当箇所のみ抜粋すると以下の通りです。

inkbird.py
import ambient


CHANNEL_ID = 'あなたのチャネルiD'
WRITE_KEY = 'あなたのライトキー'

def main():
    # 省略
    data = send_data_params(temperature, humidity)
    peripheral.disconnect
    return send_ambient(data, CHANNEL_ID, WRITE_KEY)


def send_ambient(data, channel_id, write_key):
    am = ambient.Ambient(channel_id, write_key)
    am.send(data)


def send_data_params(temperature, humidity):
    return {
        'd1': temperature,
        'd2': humidity,
    }

ambientの設定画面の順番に従うので、d1 が temperature, d2 がhumidityです。

定期ジョブ(cron)にする

最終的なコード

最終的なコードは以下の通りです。

inkbird.py
from bluepy import btle
import binascii
import ambient


CHANNEL_ID = 'あなたのチャネルiD'
WRITE_KEY = 'あなたのライトキー'

PERIPHERAL_MAC_ADDRESS = 'あなたのデバイスのMACアドレス'
HANDLE = 0x002d


def main():
    peripheral = btle.Peripheral(PERIPHERAL_MAC_ADDRESS)
    characteristic = get_characteristic(peripheral, HANDLE)
    temperature = characteristic_to_temperature(characteristic)
    humidity = characteristic_to_humidity(characteristic)
    data = send_data_params(temperature, humidity)
    peripheral.disconnect
    return send_ambient(data, CHANNEL_ID, WRITE_KEY)


def send_ambient(data, channel_id, write_key):
    am = ambient.Ambient(channel_id, write_key)
    am.send(data)


def get_characteristic(peripheral, handle):
    return peripheral.readCharacteristic(handle)


def characteristic_to_temperature(characteristic):
    temp_hex = binascii.b2a_hex(characteristic[1]) + binascii.b2a_hex(characteristic[0])
    return float(int(temp_hex, 16)) / 100


def characteristic_to_humidity(characteristic):
    humid_hex = binascii.b2a_hex(characteristic[3]) + binascii.b2a_hex(characteristic[2])
    return float(int(humid_hex, 16)) / 100


def send_data_params(temperature, humidity):
    return {
        'd1': temperature,
        'd2': humidity,
    }


main()

上記を python ./inkbird.py で実行すると、ambientでデータが更新されるのが確かめられるはずです。

cronで定期実行する

上記のコードが実行されることが確認できたら、cronで定期実行にします。
cronでの実行は普通のやり方です。

たとえば、1分ごとに同期する場合の例です。

まずcrontab -e を実行します。すると、cronの設定が追加できる画面になります。そこで、末尾に下記を挿入します。

*/1 * * * * python /home/junara/inkbird.py

/home/junara/inkbird.py は今回実行したいpythonファイルの絶対パスです。

うまく行くとAmbientの Myチャネルから https://ambidata.io/ch/channel.html?id=XXXXX&private=true を開いておけば、下記のようなグラフが表示されます。1分ごとにデータが更新されます!

Image from Gyazo

(上記は1分ごと更新のときのぐらふですが、最終的には10分毎更新にしました。)

このグラフを、画面の片隅に開いておいて眺めておけば、安心して仕事できますね!

所感

  • handleがわかれば、bluetoothのデータ扱うの難しくないです。
  • Ambient使うと可視化楽ちんです。
    • 送信するだけで、作成日次を自動的に付与してくれるのは嬉しいです。
    • 心配な場合は、バックアップも兼ねて main() の処理の中に、ローカルのCSV書き出しもやっておくとよいかも。
  • コード https://gist.github.com/junara/229b2d324cb2928eb8966092db733078
15
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?