51 lines
1.8 KiB
Python
51 lines
1.8 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
"""Фоновый логгер ЧСС с BLE HR-датчика (стандарт 0x180D / 0x2A37, напр. Coospo H808S).
|
|||
|
|
Пишет строки 'epoch,bpm' в указанный файл, пока процесс не убьют. Авто-переподключение
|
|||
|
|
при обрыве. Спаривание не требуется.
|
|||
|
|
|
|||
|
|
Использование: python3 tools/hr_log.py <BLE-addr> <logfile>
|
|||
|
|
"""
|
|||
|
|
import asyncio, sys, time
|
|||
|
|
from bleak import BleakClient, BleakScanner
|
|||
|
|
|
|||
|
|
ADDR = sys.argv[1]
|
|||
|
|
LOG = sys.argv[2]
|
|||
|
|
HR_CHR = "00002a37-0000-1000-8000-00805f9b34fb"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def make_cb(logf):
|
|||
|
|
def cb(_, data: bytearray):
|
|||
|
|
flags = data[0]
|
|||
|
|
bpm = int.from_bytes(data[1:3], "little") if flags & 1 else data[1]
|
|||
|
|
logf.write(f"{time.time():.1f},{bpm}\n")
|
|||
|
|
logf.flush()
|
|||
|
|
return cb
|
|||
|
|
|
|||
|
|
|
|||
|
|
async def main():
|
|||
|
|
logf = open(LOG, "a")
|
|||
|
|
logf.write(f"# {time.time():.1f} start addr={ADDR}\n")
|
|||
|
|
logf.flush()
|
|||
|
|
while True:
|
|||
|
|
try:
|
|||
|
|
dev = await BleakScanner.find_device_by_address(ADDR, timeout=15.0)
|
|||
|
|
if dev is None:
|
|||
|
|
logf.write(f"# {time.time():.1f} not_found, retry\n")
|
|||
|
|
logf.flush()
|
|||
|
|
await asyncio.sleep(3)
|
|||
|
|
continue
|
|||
|
|
async with BleakClient(dev) as cli:
|
|||
|
|
logf.write(f"# {time.time():.1f} connected\n")
|
|||
|
|
logf.flush()
|
|||
|
|
await cli.start_notify(HR_CHR, make_cb(logf))
|
|||
|
|
while cli.is_connected:
|
|||
|
|
await asyncio.sleep(1)
|
|||
|
|
logf.write(f"# {time.time():.1f} disconnected, reconnect\n")
|
|||
|
|
logf.flush()
|
|||
|
|
except Exception as e:
|
|||
|
|
logf.write(f"# {time.time():.1f} err {e}\n")
|
|||
|
|
logf.flush()
|
|||
|
|
await asyncio.sleep(3)
|
|||
|
|
|
|||
|
|
|
|||
|
|
asyncio.run(main())
|