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

Flutter血压原始数据读取异常修正:平均动脉压数值错误

修正BLE血压数据中平均动脉压的读取错误

问题说明

原始血压测量数据:[DE, E2, F4, 3E, F3, FF, 07, E8, 07, 03, 13, 02, 21, 00, 34, F3, 01, C0, 00],其中平均动脉压(meanAP)对应索引5和6的字节FF, 07,当前代码计算结果为-20.41 mmHg,而正确结果应为2047.0 mmHg。

错误原因

  1. 字节偏移量错误:代码中读取meanAP时使用了startByte + 5,导致读取了索引6和7的字节(07, E8),而非目标的索引5和6。
  2. 读取错误字节后,触发了不必要的负数转换逻辑,最终得到错误的负值结果。

修正后的完整代码

import 'package:flutter/material.dart';
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
import 'dart:typed_data';
import 'dart:math';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'BLE Scanner',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final FlutterReactiveBle flutterReactiveBle = FlutterReactiveBle();
  List<DiscoveredDevice> devices = [];
  double systolic = 0;
  double diastolic = 0;
  List<double> result = [
    0.0,
    0.0,
    0.0,
    0.0,
  ]; // 声明result变量
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('测量您的动脉血压'),
        backgroundColor: Colors.blue,
      ),
      body: Padding(
        padding: EdgeInsets.all(20.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: _scanForDevices,
              child: Text('搜索您的BM96设备'),
              style: ElevatedButton.styleFrom(
                foregroundColor: Colors.white,
                backgroundColor: Colors.blue,
              ),
            ),
            SizedBox(height: 20),
            Text(
              '已发现设备:',
              style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.bold,
                color: Colors.blue,
              ),
            ),
            SizedBox(height: 10),
            Expanded(
              child: ListView.builder(
                itemCount: devices.length,
                itemBuilder: (context, index) {
                  final device = devices[index];
                  return ListTile(
                    title: Text(
                      device.name ?? '未知设备',
                      style: TextStyle(
                        fontSize: 16,
                        color: Colors.black,
                      ),
                    ),
                    subtitle: Text(
                      device.id,
                      style: TextStyle(
                        fontSize: 14,
                        color: Colors.grey,
                      ),
                    ),
                    onTap: () {
                      _connectToDevice(device.id);
                      _subscribeToBloodPressureMeasurement(device.id);
                    },
                  );
                },
              ),
            ),
            SizedBox(height: 20),
            Text(
              '收缩压结果: ${result[0]}',
              style: TextStyle(fontSize: 20),
            ),
            SizedBox(height: 10),
            Text(
              '舒张压结果: ${result[1]}',
              style: TextStyle(fontSize: 20),
            ),
            SizedBox(height: 10),
            Text(
              '脉搏结果: ${result[2]}',
              style: TextStyle(fontSize: 20),
            ),
            SizedBox(height: 10),
            Text(
              '平均动脉压结果: ${result[3]}',
              style: TextStyle(fontSize: 20),
            ),
          ],
        ),
      ),
    );
  }

  void _scanForDevices() {
    flutterReactiveBle.scanForDevices(
      withServices: [Uuid.parse('00001810-0000-1000-8000-00805f9b34fb')],
      scanMode: ScanMode.lowLatency,
    ).listen(
      (device) {
        final existingDeviceIndex =
            devices.indexWhere((d) => d.id == device.id);
        if (existingDeviceIndex != -1) {
          setState(() {
            devices[existingDeviceIndex] = device;
          });
        } else {
          setState(() {
            devices.add(device);
          });
        }
      },
      onError: (error) {
        print('错误: $error');
      },
    );
  }

  void _connectToDevice(String deviceId) {
    flutterReactiveBle
        .connectToDevice(
      id: deviceId,
      servicesWithCharacteristicsToDiscover: {
        Uuid.parse('00001810-0000-1000-8000-00805f9b34fb'): [
          Uuid.parse('00002a35-0000-1000-8000-00805f9b34fb'),
          Uuid.parse('00002a49-0000-1000-8000-00805f9b34fb'),
        ],
      },
      connectionTimeout: const Duration(seconds: 2),
    )
        .listen(
      (connectionState) {
        if (connectionState == DeviceConnectionState.connected) {
          print("成功连接到设备: $deviceId");
          _subscribeToBloodPressureMeasurement(deviceId);
        }
      },
      onError: (error) {
        print('连接设备错误: $error');
      },
    );
  }

  void _subscribeToBloodPressureMeasurement(String deviceId) {
    try {
      final bloodPressureCharacteristic = QualifiedCharacteristic(
        characteristicId: Uuid.parse('00002a35-0000-1000-8000-00805f9b34fb'),
        deviceId: deviceId,
        serviceId: Uuid.parse('00001810-0000-1000-8000-00805f9b34fb'),
      );

      flutterReactiveBle
          .subscribeToCharacteristic(bloodPressureCharacteristic)
          .listen(
        (data) {
          print('接收到血压测量原始数据: $data');
          setState(() {
            result = parseBloodPressureData(data);
          });
        },
        onError: (error) {
          print('订阅血压测量错误: $error');
        },
      );
    } catch (e) {
      print('订阅血压测量时发生异常: $e');
    }
  }

  List<double> parseBloodPressureData(List<int> packet) {
    final data = ByteData.sublistView(Uint8List.fromList(packet));
    const startByte = 1;
    int value = 0;

// 收缩压
    value = data.getInt16(startByte, Endian.little);
    int mantissa = value & 0xfff;

    if (mantissa >= 0x0800) {
      mantissa = -((0x0FFF + 1) - mantissa);
    }

    int exponent = value >> 12;

    if (exponent >= 0x0008) {
      exponent = -((0x000F + 1) - exponent);
    }

    double magnitude = pow(10.0, exponent).toDouble();
    double systolic = mantissa * magnitude;

// 舒张压
    value = data.getInt16(startByte + 2, Endian.little);
    mantissa = value & 0xfff;

    if (mantissa >= 0x0800) {
      mantissa = -((0x0FFF + 1) - mantissa);
    }

    exponent = value >> 12;

    if (exponent >= 0x0008) {
      exponent = -((0x000F + 1) - exponent);
    }

    magnitude = pow(10.0, exponent).toDouble();
    double diastolic = mantissa * magnitude;

    // 脉搏
    value = data.getInt16(startByte + 13, Endian.little);
    mantissa = value & 0xfff;

    if (mantissa >= 0x0800) {
      mantissa = -((0x0FFF + 1) - mantissa);
    }

    exponent = value >> 12;

    if (exponent >= 0x0008) {
      exponent = -((0x000F + 1) - exponent);
    }

    magnitude = pow(10.0, exponent).toDouble();
    double pulse = mantissa * magnitude;

    // 平均动脉压(修正了字节偏移量)
    value = data.getInt16(startByte + 4, Endian.little);
  
    mantissa = value & 0xfff;

    if (mantissa >= 0x0800) {
     mantissa = -((0x0FFF + 1) - mantissa);
     }

     exponent = value >> 12;

      if (exponent >= 0x0008) {
      exponent = -((0x000F + 1) - exponent);
      }

    magnitude = pow(10.0, exponent).toDouble();
      double meanAP= mantissa * magnitude;

    return [systolic, diastolic, pulse,meanAP];
    
  }
}

关键修改点

仅修改了parseBloodPressureData函数中平均动脉压的读取偏移量:

// 原错误代码
value = data.getInt16(startByte + 5, Endian.little);
// 修正后代码
value = data.getInt16(startByte + 4, Endian.little);

修正后,代码会正确读取索引5和6的字节FF, 07,小端序组合为0x07FF(即十进制2047),结合exponent为0的情况,最终计算出正确的2047.0 mmHg。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 11:05:54