心拍は血流速度です。従って、その時間変化は本質的に血圧の情報を含んでいます。そこで、2点間の心拍から血圧を予測することに挑戦してみます。
前回までには、心拍計の選定と心拍数を取得するために必要なラズベリーパイの準備の手順を紹介しました。
本記事では、ラズベリーパイからPolar OH1の心拍数を取得するプログラムを作成する前段階として、MacOSからPolar OH1の心拍数を取得するプログラムを作成してみます。
1. Python用のBLEライブラリの選定
こちらで紹介されているように、PythonからBluetoothのシグナルを取り扱うためのライブラリにはpybleuzやpyGATTなど複数あります。
2025/01/25段階ではMacOSから扱う場合、bleakというライブラリが良さそうです。
2. Polar OH1の検出
近くにあるBluetoothのデバイスからシグナルを受信し、デバイスの情報を以下のようにして表示させることができます。
import asyncio from bleak import BleakScanner async def run(): devices = await BleakScanner.discover(return_adv=True) for device, adv_data in devices.values(): print(f"address: {device.address}, name: {device.name}, uuid: {adv_data.service_uuids}") loop = asyncio.get_event_loop() loop.run_until_complete(run())
上記の出力結果は、例えば以下のようになります。
address: 23A0251C-8590-B388-0D30-96CA94743EBE, name: None, uuid: []
address: 1C4BD0DD-96AC-9125-A347-EC6A5278F0E8, name: None, uuid: []
address: A1EC6040-E143-9DC2-0F69-61BA09B78380, name: LE-Bose QuietComfort 35 Serie, uuid: ['0000febe-0000-1000-8000-00805f9b34fb', '0000fe26-0000-1000-8000-00805f9b34fb', '0000fe03-0000-1000-8000-00805f9b34fb']
address: 80A32DBE-B8F5-34E5-B941-B56281A68524, name: Polar OH1 XXXXXXXX, uuid: ['xxxxxxxx-0000-1000-8000-00805f9b34fb', 'xxxxxxxx-0000-1000-8000-00805f9b34fb']
address: B4BF7906-1270-323E-0CC0-9D96C5DE9938, name: None, uuid: ['0000fe9f-0000-1000-8000-00805f9b34fb']
address: 849BE66D-7DDD-CCBB-4BEE-D5205E463919, name: None, uuid: []
address: C7317B31-46B6-0C97-3764-48C2CA2347FA, name: None, uuid: []
address: E4702025-2C65-4317-8F67-9BB31171E59C, name: None, uuid: []
address: E125DF3B-223D-DEE3-17E5-D5FB32CC3605, name: XXXXさんのApple Watch, uuid: []
address: BE041992-7286-25C4-4ECE-F274983ABD10, name: None, uuid: []
XXXXXXXXやXXXXの部分は個人情報なので伏せてあります。
※ こちらを参考にしました。
3. デバイスに接続する際のアドレスを調べる
前節のaddressで接続できる場合もあります。その場合は、前節のaddressをメモしてこの節は飛ばして次節に進んでください。
本節では上記のaddressで次節に従っても接続できなかった場合のaddressの取得方法について説明します。
async def run(): devices = await BleakScanner.discover(return_adv=True) for device, adv_data in devices.values(): if device.name is not None: if 'Polar OH1' in device.name: print(f'cnt:{adv_data.count}, idx:{adv_data.index}, local_name:{adv_data.local_name}, mdata:{adv_data.manufacturer_data}, pdata:{adv_data.platform_data}, rssi:{adv_data.rssi}, service_data:{adv_data.service_data}, service_uuids:{adv_data.service_uuids}, tx_power:{adv_data.tx_power}') loop = asyncio.get_event_loop() loop.run_until_complete(run())
上記を実施した結果が以下となります。
cnt:<built-in method count of AdvertisementData object at 0x10cdcd270>, idx:<built-in method index of AdvertisementData object at 0x10cdcd270>, local_name:Polar OH1 XXXXXXXX, mdata:{107: b"r\x08\xfdV\x14\x03\x00\x00\x00\x00z\x01\x01'\x00Q"}, pdata:(<CBPeripheral: 0x600000ca05b0, identifier = XXXXXXXX-B8F5-34E5-B941-B56281A68524, name = Polar OH1 5F9C7424, mtu = 0, state = disconnected>, {
kCBAdvDataIsConnectable = 1;
kCBAdvDataLocalName = "Polar OH1 XXXXXXXX";
kCBAdvDataManufacturerData = {length = 18, bytes = 0x6b007208fd561403000000007a0101270051};
kCBAdvDataRxPrimaryPHY = 1;
kCBAdvDataRxSecondaryPHY = 0;
kCBAdvDataServiceUUIDs = (
"Heart Rate",
FEEE
);
kCBAdvDataTimestamp = "759475474.275034";
}, -54), rssi:-54, service_data:{}, service_uuids:['xxxxxxxx-0000-1000-8000-00805f9b34fb', 'xxxxxxxx-0000-1000-8000-00805f9b34fb'], tx_power:None
上記の identifier である’XXXXXXXX-B8F5-34E5-B941-B56281A68524′ をaddressとして次節に進んでください。
4. 心拍数をリアルタイムに取得して表示
以下で心拍数をリアルタイムでMacOSのPythonのコンソールに表示できます。
model_uid
とbattery_uid
とheartbeat_uid
はこちらで定義されている値であり、Polar OH1の各商品ごとに変わるものではないので、そのまま以下のコードの値を使用して下さい。
なお、こちらのbleakライブラリのページを探しても心拍数受信用のUUIDは見つかりませんので注意して下さい。
import asyncio from bleak import BleakClient model_uid = "00002a24-0000-1000-8000-00805f9b34fb" battery_uid = "00002a19-0000-1000-8000-00805f9b34fb" heartbeat_uid = "00002a37-0000-1000-8000-00805f9b34fb" running = True async def run(address): async with BleakClient(address) as client: model = await client.read_gatt_char(model_uid) model = model.decode("utf-8") battery = await client.read_gatt_char(battery_uid) battery = battery[0] print("device: {:s}, battery: {:d}%, press enter to stop".format(model, battery)) await client.start_notify(heartbeat_uid, lambda sender, data: print("\r{:d} bpm ".format(data[1]), end="")) while await client.is_connected() and running: await asyncio.sleep(1) threading.Thread(target=asyncio.run, args=(run(address),)).start() # mix of paradigms: event loop in background input()
上記を実施すると以下のようになります。
device: OH1, battery: 80%, press enter to stop
81 bpm
2行目の bpm の数値の部分が毎秒変化して表示されます。
※ こちらを参考にしました。
5. まとめ
本記事ではMacOSからPolar OH1の心拍数を取得する手順について説明しました。
次回ではラズベリーパイからの取得や、機械学習や深層学習を用いた血圧予測について記します。
以上になります。
コメント