import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
logDog(String log) {
debugPrint('BluetoothClient->$log');
}
///低功耗蓝牙插件 BLE
///不需要处理api返回的流中的onError和onDone方法,除了FlutterBluePlus.scanResults的onError
///对于ios,每一个相关api的调用都会显示系统的蓝牙弹窗
///可以通过remoteId直接连接,而不需要扫描
///自动重连和mtu不可同时设置
class BluetoothClient {
///监听log流
void setupLog() {
// if your terminal doesn't support color you'll see annoying logs like `\x1B[1;35m`
FlutterBluePlus.setLogLevel(LogLevel.verbose, color: true);
FlutterBluePlus.logs.listen((String s) {
logDog(s);
});
}
///*****************************************************************************************蓝牙支持***/
///是否支持蓝牙
Future<bool> isSupported() async {
bool bl = await FlutterBluePlus.isSupported;
logDog('是否支持蓝牙:$bl');
return bl;
}
///*****************************************************************************************蓝牙适配器开关***/
///打开蓝牙
///只有android支持,ios由用户自己控制
Future<bool> turnOn() async {
if (Platform.isAndroid) {
await FlutterBluePlus.turnOn();
}
return true;
}
///监听蓝牙打开状态
///对于ios初始化状态是 BluetoothAdapterState.unknown
///如果没有权限状态是 BluetoothAdapterState.unauthorized
StreamSubscription<BluetoothAdapterState> adapterStateListener() {
logDog('设置蓝牙打开状态监听');
return FlutterBluePlus.adapterState.listen((BluetoothAdapterState state) {
logDog('蓝牙打开状态变化:$state');
});
}
///取消监听蓝牙打开状态
void cancelAdapterState(
StreamSubscription<BluetoothAdapterState> subscription) async {
logDog('取消蓝牙打开状态监听');
await subscription.cancel();
}
///当前的蓝牙是否是打开的
Future<bool> isBluetoothOn() async {
bool bl = FlutterBluePlus.adapterStateNow == BluetoothAdapterState.on;
logDog('当前蓝牙是否打开状态:$bl');
return bl;
}
///阻塞线程等待蓝牙打开
Future<bool> waitForBluetoothOn() async {
logDog('阻塞线程等待蓝牙打开');
await FlutterBluePlus.adapterState.where((val) => val == BluetoothAdapterState.on).first;
return true;
}
///*****************************************************************************************蓝牙设备搜索***/
///如果蓝牙没找到--------------
///如果添加扫描过滤器可以减少主线程的使用
///第一种:清除两次扫描中间的结果
StreamSubscription<List<ScanResult>> onScanResultsListener(Function(List<ScanResult>) resultBack) {
logDog('设置扫描结果监听 onScanResults');
return FlutterBluePlus.onScanResults.listen((List<ScanResult> event) {
logDog('收到扫描结果 onScanResults');
resultBack(event);
for (var element in event) {
logDog('扫描到:${element.device.platformName} ${element.device.remoteId}');
}
if (event.isNotEmpty) {
ScanResult r = event.last; //最近找到的设备
}
}, onError: (e) => logDog('蓝牙扫描结果异常:$e'));
}
///第二种:获取当前扫描结果或上一次扫描结果
StreamSubscription<List<ScanResult>> scanResultsListener() {
logDog('设置扫描结果监听 scanResults');
return FlutterBluePlus.scanResults.listen((List<ScanResult> event) {
logDog('收到扫描结果 scanResults');
for (var element in event) {
logDog('扫描到:${element.device.platformName} ${element.device.remoteId}');
}
}, onError: (e) => logDog('蓝牙扫描结果异常:$e'));
}
///自动取消监听蓝牙设备扫描结果
void autoCancelScanResults(
StreamSubscription<List<ScanResult>> subscription) {
logDog('自动取消监听蓝牙设备扫描结果');
FlutterBluePlus.cancelWhenScanComplete(subscription);
}
///开始扫描
///需要蓝牙已打开,给予了权限,开启了定位服务
Future startScan() async {
logDog('打开蓝牙扫描');
await FlutterBluePlus.startScan(
androidUsesFineLocation: true,
// withNames: ['MG','IPC'],
withKeywords: ['MG','IPC','MC'],
timeout: const Duration(seconds: 30) //60s后停止扫描
);
}
///关闭扫描
Future stopScan() async {
logDog('关闭蓝牙扫描');
await FlutterBluePlus.stopScan();
}
///设置扫描状态监听
StreamSubscription<bool> scanningListener(Function(bool doesScanning) doesScanning){
logDog('设置扫描状态监听');
return FlutterBluePlus.isScanning.listen((event) {
logDog('扫描状态:$event');
doesScanning(event);
});
}
///是否正在扫描
bool isScanning() {
bool bl = FlutterBluePlus.isScanningNow;
logDog('是否正在扫描设备:$bl');
return bl;
}
///*****************************************************************************************蓝牙设备连接***/
///监听设备连接状态
StreamSubscription<BluetoothConnectionState> connectionStateListener(
BluetoothDevice device,Function() isConnected) {
logDog('开始监听设备连接状态');
return device.connectionState.listen((BluetoothConnectionState state) {
logDog('设备连接状态:${device.platformName} : $state');
isConnected.call();
if (state == BluetoothConnectionState.disconnected) {
//1.这里面一般做重连 2.必须重新探索服务
logDog(
'设备断开原因:${device.disconnectReason?.code} ${device.disconnectReason?.description}');
}
});
}
///自动取消监听设备连接状态
void autoCancelConnectionState(BluetoothDevice device,
StreamSubscription<BluetoothConnectionState> subscription) async {
logDog('自动取消监听设备连接状态');
device.cancelWhenDisconnected(subscription, delayed: true, next: true);
}
///主动取消监听设备连接状态
void cancelConnectionState(
StreamSubscription<BluetoothConnectionState> subscription) async {
logDog('主动取消监听设备连接状态');
await subscription.cancel();
}
///连接设备
void connect(BluetoothDevice device) async {
logDog('开始设备连接');
await device.connect();
}
///断开连接设备
void disconnect(BluetoothDevice device) async {
logDog('断开设备连接');
await device.disconnect();
}
///获取已经连接成功的设备
List<BluetoothDevice> connectedDevices() {
logDog('获取已经连接成功的设备');
List<BluetoothDevice> devs = FlutterBluePlus.connectedDevices;
for (var d in devs) {
logDog('获取已经连接成功的设备条目:${d.remoteId}');
}
return devs;
}
///*****************************************************************************************mtu***/
///设置mtu,android一般是512,但是ios是自动协商的
void setMtu(BluetoothDevice device) async {
logDog('设置mtu');
final subscription = device.mtu.listen((int mtu) {
//ios初始值是23,但是会立即提高这个值
logDog('mtu值:$mtu');
});
device.cancelWhenDisconnected(subscription);
if (Platform.isAndroid) {
await device.requestMtu(512);
}
}
///*****************************************************************************************探索服务***/
///每一次重连都需要探索服务
void discoverServices(BluetoothDevice device) async {
logDog('探索服务');
List<BluetoothService> services = await device.discoverServices();
services.forEach((service) {
logDog('探索服务条目:${service.remoteId}');
});
}
///读取 Characteristics
void readCharacteristics(BluetoothService service) async {
logDog('读取Characteristics');
var characteristics = service.characteristics;
for (BluetoothCharacteristic c in characteristics) {
if (c.properties.read) {
List<int> value = await c.read();
logDog('读取Characteristics 条目 $value');
}
}
}
///写入 Characteristics
///allowLongWrite 忽略mtu进行长数据写入,设备必须支持 long writ ble协议
void writeCharacteristics(BluetoothCharacteristic c, List<int> value,
{bool allowLongWrite = false}) async {
logDog('写入Characteristics');
await c.write(value, allowLongWrite: allowLongWrite);
}
///监听 Characteristics 通过 onValueReceived
void onValueReceivedListener(
BluetoothDevice device, BluetoothCharacteristic c) {
logDog('监听 Characteristics 通过 onValueReceived');
final subscription = c.onValueReceived.listen((value) {
//此回调收到数据的前提 1.c.read() 调用 2.c.setNotifyValue(true) 调用
logDog('onValueReceived收到:$value');
});
device.cancelWhenDisconnected(subscription);
}
///监听 Characteristics 通过 lastValueStream ,onValueReceived 的替代方案
void lastValueStreamListener(
BluetoothDevice device, BluetoothCharacteristic c) {
logDog('监听 Characteristics 通过 lastValueStream');
final subscription = c.lastValueStream.listen((value) {
//此回调收到数据的前提 1.c.read() 调用 2.c.setNotifyValue(true) 调用 3.c.write() 调用
logDog('lastValueStream 收到:$value');
});
device.cancelWhenDisconnected(subscription);
}
///允许蓝牙设备主动发起通知
void setNotifyValue(BluetoothCharacteristic c, bool notify) async {
logDog('是否允许蓝牙设备主动发起通知:$notify');
await c.setNotifyValue(notify);
}
///Characteristics 服务变化监听
void onServicesReset(BluetoothDevice device) {
logDog('Characteristics 服务变化监听');
device.onServicesReset.listen((event) async {
logDog('服务变化 onServicesReset');
//必须重新调用探索服务
await device.discoverServices();
});
}
}