flutter windows 桌面应用程序: 读取ble蓝牙扫码枪数据

您所在的位置:网站首页 flutter扫码枪 flutter windows 桌面应用程序: 读取ble蓝牙扫码枪数据

flutter windows 桌面应用程序: 读取ble蓝牙扫码枪数据

2024-01-12 13:50| 来源: 网络整理| 查看: 265

目标 能够监听电脑本身的蓝牙适配器状态 能够发现以及停止发现附近的ble蓝牙设备 连接指定的ble蓝牙设备 订阅指定ble蓝牙设备的特征数据 取消订阅指定ble蓝牙设备的特征数据 资源释放 环境说明

操作系统: Windows 11

flutter版本:

Flutter 3.13.9 • channel stable • https://github.com/flutter/flutter.git Framework • revision d211f42860 (2 weeks ago) • 2023-10-25 13:42:25 -0700 Engine • revision 0545f8705d Tools • Dart 3.1.5 • DevTools 2.25.0 依赖插件

flutter pub add win_ble

定义util类, 封装 win_ble 组件相关方法

win_ble_util.dart

import 'dart:async'; import 'dart:typed_data'; import 'package:win_ble/win_ble.dart'; import 'package:win_ble/win_file.dart'; typedef OnScanedBleDevice = Function(BleDevice); typedef OnBleStateChanged = Function(BleState); typedef OnCharacteristicValueStream = Function(SubscribeToCharacteristicData?); /// ble蓝牙设备连接回调方法 /// [connectResult] 连接结果. true表示连接成功, false表示连接失败 typedef OnConnectedCall = Function(bool connectResult); /// 特征返回的数据 class SubscribeToCharacteristicData { static const _mapKeydeviceAddr = 'address'; static const _mapKeyServiceId = 'serviceId'; static const _mapKeyCharacteristicId = 'characteristicId'; static const _mapKeyValue = 'value'; /// ble设备地址 String deviceAddr; /// ble设备服务id String serviceId; /// ble设备特征id String characteristicId; /// 返回的数据 List? data; SubscribeToCharacteristicData( {required this.deviceAddr, required this.serviceId, required this.characteristicId, this.data}); factory SubscribeToCharacteristicData.fromMap(Map map) { return SubscribeToCharacteristicData( deviceAddr: map[_mapKeydeviceAddr], serviceId: map[_mapKeyServiceId], characteristicId: map[_mapKeyCharacteristicId], data: map[_mapKeyValue]); } /// 将data转换为List数据类型 List? dataToListInt() { return data?.cast(); } /// 将data转换为String数据类型 /// [removeLineBreaks] 是否去除回车/换行符. 默认:false String? dataToString([bool removeLineBreaks = false]) { List? list = dataToListInt(); if (list != null) { String str = String.fromCharCodes(list); if (removeLineBreaks) { str = str.replaceAll("\r\n", ""); str = str.replaceAll("\n", ""); str = str.replaceAll("\r", ""); } return str; } else { return null; } } } /// WinBle组件工具 /// 大概使用流程 /// 1. listenBleState方法,监听蓝牙适配器的状态 /// 2. init方法,对WinBle组件进行初始化 /// 3. scan方法,发现附近的ble设备 /// 4. connect方法,连接指定的ble设备 /// 5. discoverServices方法,获取已连接ble设备提供的所有服务 /// 6. discoverCharacteristics方法,获取已连接ble设备的指定服务下的所有特征 /// 7. readData方法,从已连接ble设备的指定服务的指定特征下,读取一次数据 /// 8. writeDate方法,向已连接ble设备的指定服务的指定特征下,写入一次数据 /// 9. subscribeToCharacteristic方法,订阅已连接ble设备的指定服务的指定特征的数据流,可持续获取到该特征向当前ble适配器发送的数据 /// 10. unSubscribeFromCharacteristic方法,取消对已连接ble设备的指定服务的指定特征的数据流的订阅 /// 11. disconnect方法,断开与已连接ble设备的连接 /// 12. stopListenBleState方法,停止对ble适配器状态的监听 /// 13. stopScan方法,停止发现附近的ble设备 /// 14. dispose方法,释放所有资源 /// /// P.S. openBleAdaptor方法可以打开蓝牙适配器,closeBleAdaptor方法可以关闭蓝牙适配器,getMaxMtuSize方法可以获取已连接ble设备的MaxMtuSize /// /// 以实时获取蓝牙BLE扫描枪扫描的数据为例: (假设蓝牙扫描枪的名称为 Gun_BLE, 假设读取扫描枪数据的服务id和特征id为: xxx, yyy) /// /// 以下是伪代码 /// ```dart /// BleDevice? _connectedBleDevice; /// StreamSubscription? _characteristicStreamSubscription; /// /// // 初始化WinBle组件 /// WinBleUtil.instance.init(); /// // 发现附近的ble设备 /// WinBleUtil.instance.scan((BleDevice bleDevice){ /// if(bleDevice.name=='Gun_BLE'){ /// // 找到了特定设备 /// _connectedBleDevice = bleDevice; /// // 停止ble设备发现 /// WinBleUtil.instance.stopScan(); /// // 建立与ble设备的连接 /// WinBleUtil.instance.connect(_connectedBleDevice,(bool connectResult){ /// if(connectResult){ /// // 与ble设备连接成功,订阅指定特征的数据流,用于实时感知ble扫码枪发过来的数据 /// _characteristicStreamSubscription = WinBleUtil.instance.subscribeToCharacteristic('xxx','yyy',(dynamic data){ /// if(data!=null){ /// // 处理接收到的数据 /// debugPrint(data.runtimeType) /// } /// }); /// } /// }); /// } /// }); /// /// // 最后在合适的时机释放资源 /// if(null!=_characteristicStreamSubscription){ /// _characteristicStreamSubscription.cancel(); /// _characteristicStreamSubscription=null; /// } /// WinBleUtil.instance.dispose(); /// ``` class WinBleUtil { static WinBleUtil? _instance; WinBleUtil._(); static WinBleUtil get instance => _instance ??= WinBleUtil._(); StreamSubscription? _scanBleDeviceStreamSubscription; StreamSubscription? _bleStateStreamSubscription; StreamSubscription? _connectionStreamSubscription; /// 当前连接上的ble蓝牙设备 BleDevice? _connectedBleDevice; String get connectedBleDeviceName => null != _connectedBleDevice ? _connectedBleDevice!.name : ''; /// 当前是否完成了WinBle组件的初始化 bool _isInited = false; /// 当前是否正在发现附近的ble蓝牙设备 bool _isScaning = false; /// ble蓝牙组件初始化 Future init() async { if (_isInited == false) { _isInited = true; WinBle.initialize(serverPath: await WinServer.path, enableLog: false); } } /// 监听蓝牙适配器状态 void listenBleState(OnBleStateChanged onBleStateChanged) { _bleStateStreamSubscription = WinBle.bleState.listen(onBleStateChanged); } /// 打开蓝牙适配器 void openBleAdaptor(OnScanedBleDevice? onScanedBleDevice) { WinBle.updateBluetoothState(true); scan(onScanedBleDevice); } /// 关闭蓝牙适配器 void closeBleAdaptor() { disconnect(); stopScan(); WinBle.updateBluetoothState(false); } /// 发现附近的ble蓝牙设备 void scan(OnScanedBleDevice? onScanedBleDevice) { if (!_isScaning) { _isScaning = true; if (null != onScanedBleDevice) { _scanBleDeviceStreamSubscription = WinBle.scanStream.listen(onScanedBleDevice); } WinBle.startScanning(); } } bool hasConnectedBleDevice() { return _connectedBleDevice != null; } /// 连接指定的ble蓝牙设备 /// [bleDevice] ble蓝牙设备 /// [onConnectedCall] 连接回调方法, 该方法会返回连接结果 Future connect( BleDevice bleDevice, OnConnectedCall onConnectedCall) async { _connectedBleDevice = bleDevice; _connectionStreamSubscription = WinBle.connectionStreamOf(bleDevice.address).listen((onConnectedCall)); await WinBle.connect(bleDevice.address); } /// 获取已连接ble设备的maxMtuSize, 如果没有已连接设备,则返回 Future Future getMaxMtuSize() { if (_connectedBleDevice != null) { return WinBle.getMaxMtuSize(_connectedBleDevice!.address); } return Future.value(null); } /// 获取已连接ble设备的服务列表, 如果没有已连接设备,则返回 Future Future discoverServices() { if (_connectedBleDevice != null) { return WinBle.discoverServices(_connectedBleDevice!.address); } return Future.value(null); } /// 获取已连接ble设备的指定服务的BleCharacteristic列表, 如果没有已连接设备,则返回 Future /// [serviceId] 已连接ble设备的服务id Future discoverCharacteristics( String serviceId) async { if (_connectedBleDevice != null) { return WinBle.discoverCharacteristics( address: _connectedBleDevice!.address, serviceId: serviceId); } return Future.value(null); } /// 从已连接设备的,指定服务的,指定BleCharacteristic中,读取一次数据,如果没有已连接设备,则返回 Future /// [serviceId] 服务标识 /// [characteristicId] 特征标识 Future readData(String serviceId, String characteristicId) async { if (_connectedBleDevice != null) { List data = await WinBle.read( address: _connectedBleDevice!.address, serviceId: serviceId, characteristicId: characteristicId); return data; } else { return Future.value(null); } } /// 向已连接设备的,指定服务的,指定BleCharacteristic中,写入数据 /// [serviceId] 服务标识 /// [characteristicId] 特征标识 /// [data] 待写入的数据 Future writeData( String serviceId, String characteristicId, Uint8List data) async { if (_connectedBleDevice != null) { await WinBle.write( address: _connectedBleDevice!.address, service: serviceId, characteristic: characteristicId, data: data, writeWithResponse: false); } } /// 订阅已连接设备的,指定服务的,指定BleCharacteristic的connectionStream,当不存在已连接设备时,则返回null /// [serviceId] 服务标识 /// [characteristicId] 特征标识 /// [onCharacteristicValueStream] BleCharacteristic有响应数据时,执行的回调 StreamSubscription? subscribeToCharacteristic( String serviceId, String characteristicId, OnCharacteristicValueStream onCharacteristicValueStream) { if (_connectedBleDevice != null) { WinBle.subscribeToCharacteristic( address: _connectedBleDevice!.address, serviceId: serviceId, characteristicId: characteristicId); return WinBle.characteristicValueStream.listen((data) { SubscribeToCharacteristicData? val = data != null && data.runtimeType.toString() == '_Map' ? SubscribeToCharacteristicData.fromMap(data) : null; onCharacteristicValueStream(val); }); } return null; } /// 取消对已连接蓝牙设备的,指定服务的,指定BleCharacteristic的connectionStream订阅 /// [serviceId] 服务标识 /// [characteristicId] 特征标识 Future unSubscribeFromCharacteristic( String serviceId, String characteristicId) async { if (_connectedBleDevice != null) { await WinBle.unSubscribeFromCharacteristic( address: _connectedBleDevice!.address, serviceId: serviceId, characteristicId: characteristicId); } } /// 断开与已连接的ble设备的连接 void disconnect() { if (null != _connectedBleDevice) { WinBle.disconnect(_connectedBleDevice?.address); _connectionStreamSubscription?.cancel(); _connectedBleDevice = null; } } /// 取消对ble蓝牙适配器的状态改变监听 void stopListenBleState() { _bleStateStreamSubscription?.cancel(); } /// 停止发现附近的ble设备 void stopScan() { _scanBleDeviceStreamSubscription?.cancel(); WinBle.stopScanning(); _isScaning = false; } /// 释放所有资源(断开连接,停止对附近ble设备的发现,停止监听ble蓝牙适配器状态,关闭ble蓝牙适配器,执行WinBle.dispose) dispose() { stopListenBleState(); disconnect(); closeBleAdaptor(); WinBle.dispose(); } }

barcode_scanner_ble_util.dart

import 'dart:async'; import 'package:win_ble_demo/src/util/win_ble_util.dart'; class BarcodeScannerBleUtil { static BarcodeScannerBleUtil? _instance; // Avoid self instance BarcodeScannerBleUtil._(); static BarcodeScannerBleUtil get instance => _instance ??= BarcodeScannerBleUtil._(); static String _deviceName = 'BarCode Bluetooth BLE'; static const String _serviceId = '0000feea-0000-1000-8000-00805f9b34fb'; static const String _characteristicsId = '00002aa1-0000-1000-8000-00805f9b34fb'; /// 订阅该特征,就可以收到扫码枪返回的数据 StreamSubscription? subscribeToCharacteristic( OnCharacteristicValueStream onCharacteristicValueStream) { return WinBleUtil.instance.subscribeToCharacteristic( _serviceId, _characteristicsId, onCharacteristicValueStream); } /// 取消特征订阅 Future unSubscribeFromCharacteristic() { return WinBleUtil.instance .unSubscribeFromCharacteristic(_serviceId, _characteristicsId); } }

stateful_builder.dart

import 'package:flutter/material.dart'; class StatefulBuilder extends StatefulWidget { final StatefulWidgetBuilder builder; const StatefulBuilder({Key? key, required this.builder}) : super(key: key); @override _StatefulBuilderState createState() => _StatefulBuilderState(); } class _StatefulBuilderState extends State { @override Widget build(BuildContext context) => widget.builder(context, setState); } 定义ble蓝牙适配器状态组件

实现ble蓝牙适配器状态改变监听,以及连接指定的ble蓝牙设备

ble_status_widget.dart

import 'package:flutter/material.dart'; import 'package:win_ble/win_ble.dart'; import 'package:win_ble_demo/src/util/barcode_scanner_ble_util.dart'; import 'package:win_ble_demo/src/util/win_ble_util.dart'; class BleStatusWidget extends StatefulWidget { const BleStatusWidget({Key? key}) : super(key: key); @override _BleStatusWidgetState createState() => _BleStatusWidgetState(); } typedef stateStateMethod = void Function(void Function()); class _BleStatusWidgetState extends State { String _statusStr = '未知'; final List _bleDeviceList = []; stateStateMethod? _setStateMethod; @override void initState() { super.initState(); WinBleUtil.instance.init(); WinBleUtil.instance.listenBleState((p0) { switch (p0) { case BleState.Disabled: _statusStr = '禁用'; break; case BleState.On: _statusStr = '开启'; break; case BleState.Off: _statusStr = '关闭'; break; case BleState.Unsupported: _statusStr = '不支持'; break; default: _statusStr = '未知'; } debugPrint( '>>>>>>>>>>>>>>>>>>>>>>>>>>>状态变更


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3