🌡️

温湿度センサからBluetoothでデータを取得する

2025/02/21に公開

Bluetooth通信が可能な温湿度センサからPythonで温湿度データを取得するプログラムです。

使用したセンサ

取得方法、参考にしたサイト

どちらのセンサもBLE(Bluetooth Low Energy)通信のAdvertisementフレームに温湿度、バッテリ残量の情報がのっているので、この情報を取得します。メーカーや製品によってのっている場所が違うので、下記サイトを参考にしつつ、最後は実測値とプログラム上で取得したバイト列を眺めて試行錯誤で正解にたどり着きました。

コード

早速コードです。Bluetoothの通信ライブラリとしてbleakを使ってます。

import asyncio
from bleak import BleakScanner
import time

async def main():
    stop_event = asyncio.Event()

    # TODO: add something that calls stop_event.set()

    def callback(device, advertising_data):
        # TODO: do something with incoming data
        temp = 0
        humid = 0
        battery = 0
        if(device.address == "SwitchBotのMACアドレス"):
            data_manu = advertising_data.manufacturer_data.get(1)
            if(data_manu[2]&0b10000000 == 0b10000000):
                temp_t = (data_manu[2]&0b01111111) * 256*256 + data_manu[3] * 256 + data_manu[4]
                temp = 0 - ((temp_t - (temp_t % 1000)) / 10000)
            else:
                temp_t = data_manu[2] * 256*256 + data_manu[3] * 256 + data_manu[4]
                temp = (temp_t - (temp_t % 1000)) / 10000
            humid = (temp_t % 1000) /10
            battery = data_manu[5]
            print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " , temp=" + str(temp) + ", humid=" + str(humid) + ", battery=" + str(battery) )
        elif(device.address == "GoVeeのMACアドレス"):
            data_manu = advertising_data.manufacturer_data.get(2409)
            data_srv = advertising_data.service_data.get('0000fd3d-0000-1000-8000-00805f9b34fb')
            temp = (data_manu[9] & 0b01111111) + (data_manu[8] & 0b00001111) / 10
            humid = data_manu[10]
            isOverZero=(data_manu[9] & 0b10000000)
            if not isOverZero:
              temp = 0 - temp
            if(data_srv != None):
              battery = data_srv[2] & 0b01111111
            print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " , temp=" + str(temp) + ", humid=" + str(humid) + ", battery=" + str(battery) )
        pass

    async with BleakScanner(callback) as scanner:
        # Important! Wait for an event to trigger stop, otherwise scanner
        # will stop immediately.
        await stop_event.wait()

    # scanner stops when block exits
    print("stop")

asyncio.run(main())

Discussion