You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Movesense ECG测量间隔特征值?写入无效问题求助

问题:无法通过Bleak修改Movesense自定义固件的ECG采样间隔

我使用搭载Jonas Primbs基于v2.2.1分支开发的自定义movesense-ble-ecg-firmware的Movesense设备,通过Python脚本结合Bleak库可成功连接设备并读取0x2bdd特征的ECG电压,但无法通过写入ECG测量间隔特征(0x2be3)修改采样间隔。

尝试过写入允许的数值:2(500Hz)、4(250Hz)、8(125Hz)、10(100Hz),以及b'\x10\x00'、b'\x10'、b'\x00\x10'等多种格式,但读取结果始终为b'\x04\x00'(对应250Hz)。测试脚本如下:

import asyncio
from bleak import BleakClient, BleakScanner

# BLE device name
DEVICE_NAME = 'Movesense 202930001412'

# ECG sampling rates
SAMPLE_500_HZ = b'\x02\x00' #  2
SAMPLE_250_HZ = b'\x04\x00' #  4
SAMPLE_125_HZ = b'\x08\x00' #  8
SAMPLE_100_HZ = b'\x10\x00' # 10

# ECG service and characteristics UUIDs
ECG_SERIVCE         = 0x1859
ECG_FREQ_READ_WRITE = 0x2be3
CORE_UUID = '0000{0:x}-0000-1000-8000-00805f9b34fb'
ECG_SERIVCE_UUID            = CORE_UUID.format(ECG_SERIVCE)
ECG_FREQ_READ_WRITE_UUID    = CORE_UUID.format(ECG_FREQ_READ_WRITE)

async def find_device(name):
    # Scan to get device with desired name.
    devices = await BleakScanner.discover()
    for device in devices:
        if device.name == name:
            return device
    return None

async def run(name):
    # Find device with desired name
    device = await find_device(name)
    if not device:
        print(f'Device with name {name} not found...')
        return

    # Connect to device as client
    async with BleakClient(device) as client:
        if not client.is_connected:
            print('Failed to connect to the BLE device...')
            return

        print('Connected to the BLE device.')
        
        # Write ECG sampling time
        await client.write_gatt_char(ECG_FREQ_READ_WRITE_UUID, b'\x10\x00', response=False)

        # Read ECG sampling time
        sample_freq = await client.read_gatt_char(ECG_FREQ_READ_WRITE_UUID)
        print('sample frequency', sample_freq)

        await asyncio.sleep(5)

        # Disconnect from device
        await client.disconnect()

asyncio.run(run(DEVICE_NAME))

排查与解决建议

1. 修正字节序与数值错误

你当前定义的SAMPLE_100_HZ = b'\x10\x00'对应十进制16,而不是需要的10(100Hz对应间隔10ms)。Movesense使用小端字节序,十进制10的十六进制是0x0A,正确的字节数组应为b'\x0A\x00'。

修正后的采样间隔常量:

# 正确的小端字节序(对应十进制间隔值,频率=1000/间隔值 Hz)
SAMPLE_500_HZ = b'\x02\x00'  # 间隔2ms → 500Hz
SAMPLE_250_HZ = b'\x04\x00'  # 间隔4ms → 250Hz
SAMPLE_125_HZ = b'\x08\x00'  # 间隔8ms → 125Hz
SAMPLE_100_HZ = b'\x0A\x00'  # 间隔10ms → 100Hz

2. 使用带响应的写入

当前代码中response=False会触发无响应写入,设备可能不会处理请求或返回错误。改为response=True,强制等待设备确认,能直接获知写入是否成功:

await client.write_gatt_char(ECG_FREQ_READ_WRITE_UUID, SAMPLE_100_HZ, response=True)

3. 先停止ECG测量再修改参数

多数Movesense固件要求修改采样间隔前,必须停止当前的ECG数据输出。如果0x2bdd特征处于通知状态,写入操作会被忽略。需先关闭通知,修改间隔后再重新开启:

# 假设ECG数据特征UUID是0x2bdd
ECG_DATA_UUID = CORE_UUID.format(0x2bdd)
# 关闭ECG数据通知
await client.stop_notify(ECG_DATA_UUID)
# 修改采样间隔
await client.write_gatt_char(ECG_FREQ_READ_WRITE_UUID, SAMPLE_100_HZ, response=True)
# 重新开启ECG数据通知
await client.start_notify(ECG_DATA_UUID, ecg_callback)

4. 验证特征写入权限

通过代码确认0x2be3特征是否支持写入:

char = client.get_gatt_char(ECG_FREQ_READ_WRITE_UUID)
print(f'特征属性:{char.properties}')

输出应包含write或write-without-response,否则固件可能限制了该特征的写入权限。


修改后的完整测试脚本
import asyncio
from bleak import BleakClient, BleakScanner

# BLE设备名称
DEVICE_NAME = 'Movesense 202930001412'

# ECG采样间隔(小端字节序,间隔值对应ms,频率=1000/间隔值 Hz)
SAMPLE_500_HZ = b'\x02\x00'  # 500Hz
SAMPLE_250_HZ = b'\x04\x00'  # 250Hz
SAMPLE_125_HZ = b'\x08\x00'  # 125Hz
SAMPLE_100_HZ = b'\x0A\x00'  # 100Hz

# ECG服务与特征UUID
ECG_SERVICE         = 0x1859
ECG_FREQ_READ_WRITE = 0x2be3
ECG_DATA_CHAR       = 0x2bdd
CORE_UUID = '0000{0:x}-0000-1000-8000-00805f9b34fb'
ECG_SERVICE_UUID            = CORE_UUID.format(ECG_SERVICE)
ECG_FREQ_READ_WRITE_UUID    = CORE_UUID.format(ECG_FREQ_READ_WRITE)
ECG_DATA_UUID               = CORE_UUID.format(ECG_DATA_CHAR)

async def find_device(name):
    devices = await BleakScanner.discover()
    for device in devices:
        if device.name == name:
            return device
    return None

async def run(name):
    device = await find_device(name)
    if not device:
        print(f'未找到设备:{name}')
        return

    async with BleakClient(device) as client:
        if not client.is_connected:
            print('连接BLE设备失败')
            return

        print('已连接BLE设备')
        
        # 检查特征写入权限
        char = client.get_gatt_char(ECG_FREQ_READ_WRITE_UUID)
        print(f'ECG间隔特征属性:{char.properties}')

        try:
            # 先关闭ECG数据通知(如果之前开启过)
            await client.stop_notify(ECG_DATA_UUID)
            # 带响应写入采样间隔
            await client.write_gatt_char(ECG_FREQ_READ_WRITE_UUID, SAMPLE_100_HZ, response=True)
            print('采样间隔写入请求已发送')
        except Exception as e:
            print(f'写入失败:{str(e)}')

        # 读取并解析当前采样间隔
        sample_bytes = await client.read_gatt_char(ECG_FREQ_READ_WRITE_UUID)
        interval = int.from_bytes(sample_bytes, byteorder='little')
        print(f'当前采样间隔:{interval}ms,对应频率:{1000/interval}Hz')

        await asyncio.sleep(2)

asyncio.run(run(DEVICE_NAME))

内容的提问来源于stack exchange,提问作者JRBoston

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 20:56:00