求助:使用Flutter Blue Plus获取BLE体重秤数据并转Double
Problem
I need to get the precise weight in grams from a BLE scale using the Flutter Blue Plus package when pressing a button that calls the getWeight function. This function should receive the data sent by the scale and return a double value representing the weight in grams. However, I'm unable to assign the data sent by the scale to a list and convert the corresponding bytes to the weight value. I've tried enabling characteristic subscription and assigning the sent values to an int list, but it didn't work.
Log Output
Weight 335.0 grams flutter: [FBP] [[ OnCharacteristicReceived ]] result: {remote_id: D5522E08-AAA5-292F-1ADF-6207EF692C2A, secondary_service_uuid: null, characteristic_uuid: fff1, success: 1, value: 1012004101020501f80d167e1f0258020181, error_code: 0, service_uuid: fff0, error_string: success} Weight 0.0 grams flutter: [FBP] [[ OnCharacteristicReceived ]] result: {remote_id: D5522E08-AAA5-292F-1ADF-6207EF692C2A, secondary_service_uuid: null, characteristic_uuid: fff1, success: 1, value: 1012004101020501f900007e1f025802015f, error_code: 0, service_uuid: fff0, error_string: success}
Current Code
// ignore_for_file: unused_import import 'dart:async'; import 'dart:ffi'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; class ReadData extends StatefulWidget { const ReadData({Key? key}) : super(key: key); @override State<ReadData> createState() => _ReadDataState(); } class _ReadDataState extends State<ReadData> { String weightRemoteID = 'D5522E08-AAA5-292F-1ADF-6207EF692C2A'; String weightServiceID = 'FFF0'; String weightCharacterisicsID = 'FFF1'; List<int> weightReceivedValue = []; double weightValue = 0; @override void initState() { _wait(); _startScanning(); _listenScanResult(); super.initState(); } void _wait() async { await FlutterBluePlus.adapterState .where((state) => state == BluetoothAdapterState.on) .first; } void _startScanning() { FlutterBluePlus.startScan(timeout: const Duration(seconds: 2)); } void _listenScanResult() { FlutterBluePlus.setLogLevel(LogLevel.verbose, color: false); FlutterBluePlus.scanResults.listen((scanList) async { for (ScanResult result in scanList) { if (result.device.remoteId.toString() == weightRemoteID) { result.device.connect(autoConnect: true); List<BluetoothService> services = await result.device.discoverServices(); services.forEach((service) async { var characteristics = service.characteristics; for (BluetoothCharacteristic c in characteristics) { await c.setNotifyValue(true); weightReceivedValue = await c.read(); setState(() { }); } }); } } }); } double getWeight(List<int> weightReceivedValue) { // to code return weightValue; } Widget buildButton(BuildContext context) { // to code return const FloatingActionButton(onPressed: null); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: SizedBox( width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ const Text("Weight"), const SizedBox(height: 16.0), Text("$getWeight g"), ], ), ), ); } }
Solution
1. Fix Characteristic Subscription & Data Listening
Your code uses c.read() which only fetches a single snapshot of the characteristic value. To receive continuous updates from the scale, listen to the characteristic's value stream instead. Also, filter for the specific service and characteristic UUIDs to avoid unnecessary iterations:
void _listenScanResult() { FlutterBluePlus.setLogLevel(LogLevel.verbose, color: false); FlutterBluePlus.scanResults.listen((scanList) async { for (ScanResult result in scanList) { if (result.device.remoteId.toString() == weightRemoteID) { // Avoid re-connecting if already connected if (result.device.connectionState != BluetoothConnectionState.connected) { await result.device.connect(autoConnect: true); } List<BluetoothService> services = await result.device.discoverServices(); for (var service in services) { if (service.uuid.toString().toLowerCase() == weightServiceID.toLowerCase()) { for (BluetoothCharacteristic c in service.characteristics) { if (c.uuid.toString().toLowerCase() == weightCharacterisicsID.toLowerCase()) { await c.setNotifyValue(true); // Listen to the value stream for real-time updates c.value.listen((value) { setState(() { weightReceivedValue = value; weightValue = getWeight(value); }); }); } } } } } } }); }
2. Parse BLE Data to Grams
Based on your log output, the weight data is stored in bytes 9 and 10 (0x0D and 0x16 for 335.0g, 0x00 and 0x00 for 0.0g). Combine these bytes into a raw integer and divide by 10 to get the final weight:
double getWeight(List<int> weightReceivedValue) { // Ensure there are enough data bytes to parse if (weightReceivedValue.length < 11) return 0.0; // Combine bytes 9 and 10 into a single integer (big-endian) int weightRaw = (weightReceivedValue[10] << 8) | weightReceivedValue[9]; // Convert to grams (raw value is multiplied by 10) return weightRaw / 10.0; }
3. Fix UI and Button Functionality
Update the button to trigger UI refreshes, and fix the weight display to show the parsed value:
Widget buildButton(BuildContext context) { return FloatingActionButton( onPressed: () { // Force UI refresh (subscription handles real-time updates, this is a fallback) setState(() {}); }, child: const Icon(Icons.refresh), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("BLE Weight Scale")), body: SizedBox( width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ const Text("Weight"), const SizedBox(height: 16.0), Text("${weightValue.toStringAsFixed(1)} g"), ], ), ), floatingActionButton: buildButton(context), ); }
4. Additional Improvements
- Add error handling with try/catch blocks around
connect()anddiscoverServices()to handle Bluetooth connection failures. - Listen to the device's
connectionStatestream to handle disconnections automatically. - Stop scanning once the target device is found to save battery.
内容的提问来源于stack exchange,提问作者mknnnnnnn

