#!/usr/bin/env python3 """Фоновый логгер ЧСС с BLE HR-датчика (стандарт 0x180D / 0x2A37, напр. Coospo H808S). Пишет строки 'epoch,bpm' в указанный файл, пока процесс не убьют. Авто-переподключение при обрыве. Спаривание не требуется. Использование: python3 tools/hr_log.py """ 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())