You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
7.4 KiB

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart' as fbp;
import 'package:permission_handler/permission_handler.dart';
import 'package:app_settings/app_settings.dart';
class BleController extends GetxController {
// 扫描状态
final RxBool isScanning = false.obs;
final RxBool isBluetoothOn = false.obs;
final RxBool hasPermissions = false.obs;
// 发现的设备列表
final RxList<fbp.ScanResult> scanResults = <fbp.ScanResult>[].obs;
// 连接的设备
final Rx<fbp.BluetoothDevice?> connectedDevice =
Rx<fbp.BluetoothDevice?>(null);
// 错误信息
final RxString errorMessage = ''.obs;
@override
void onInit() {
super.onInit();
_initBluetooth();
}
@override
void onClose() {
stopScan();
super.onClose();
}
// 初始化蓝牙
Future<void> _initBluetooth() async {
try {
// 先检查权限
await _checkPermissions();
// 检查蓝牙适配器状态
fbp.FlutterBluePlus.adapterState.listen((state) {
isBluetoothOn.value = state == fbp.BluetoothAdapterState.on;
if (state == fbp.BluetoothAdapterState.on) {
errorMessage.value = '';
} else {
errorMessage.value = 'pleaseEnableBluetooth'.tr;
stopScan();
}
});
// 监听扫描结果
fbp.FlutterBluePlus.scanResults.listen((results) {
scanResults.value = results;
});
// 监听扫描状态
fbp.FlutterBluePlus.isScanning.listen((scanning) {
isScanning.value = scanning;
});
} catch (e) {
errorMessage.value = 'bleInitFailedWithError'.trParams({'error': e.toString()});
}
}
// 检查权限(不请求)
Future<void> _checkPermissions() async {
try {
Map<Permission, PermissionStatus> statuses = await [
Permission.bluetoothScan,
Permission.bluetoothConnect,
Permission.location,
].request();
hasPermissions.value =
statuses.values.every((status) => status == PermissionStatus.granted);
if (!hasPermissions.value) {
errorMessage.value = 'needBluetoothAndLocationPermission'.tr;
}
} catch (e) {
print('检查权限失败: $e');
hasPermissions.value = false;
}
}
// 请求权限
Future<bool> _requestPermissions() async {
try {
Map<Permission, PermissionStatus> statuses = await [
Permission.bluetoothScan,
Permission.bluetoothConnect,
Permission.location,
].request();
bool allGranted =
statuses.values.every((status) => status == PermissionStatus.granted);
hasPermissions.value = allGranted;
if (!allGranted) {
// 检查是否有权限被永久拒绝
bool hasPermanentlyDenied = statuses.values
.any((status) => status == PermissionStatus.permanentlyDenied);
if (hasPermanentlyDenied) {
_showPermissionDialog();
} else {
errorMessage.value = 'needBluetoothAndLocationPermission'.tr;
}
}
return allGranted;
} catch (e) {
print('请求权限失败: $e');
errorMessage.value = 'permissionRequestFailedWithError'.trParams({'error': e.toString()});
return false;
}
}
// 显示权限对话框
void _showPermissionDialog() {
Get.dialog(
AlertDialog(
title: Text('needPermission'.tr),
content: Text('blePermissionDialogContent'.tr),
actions: [
TextButton(
onPressed: () => Get.back(),
child: Text('cancel'.tr),
),
TextButton(
onPressed: () {
Get.back();
AppSettings.openAppSettings();
},
child: Text('goToSettings'.tr),
),
],
),
);
}
// 显示蓝牙开启对话框
void _showBluetoothDialog() {
Get.dialog(
AlertDialog(
title: Text('needEnableBluetooth'.tr),
content: Text('enableBluetoothDialogContent'.tr),
actions: [
TextButton(
onPressed: () => Get.back(),
child: Text('cancel'.tr),
),
TextButton(
onPressed: () {
Get.back();
// 尝试开启蓝牙
fbp.FlutterBluePlus.turnOn();
},
child: Text('enableBluetooth'.tr),
),
],
),
);
}
// 开始扫描
Future<void> startScan() async {
try {
errorMessage.value = '';
// 检查权限
if (!hasPermissions.value) {
if (!await _requestPermissions()) {
return;
}
}
// 检查蓝牙状态
if (!isBluetoothOn.value) {
_showBluetoothDialog();
return;
}
// 清空之前的结果
scanResults.clear();
// 开始扫描
await fbp.FlutterBluePlus.startScan(
timeout: const Duration(seconds: 30),
androidUsesFineLocation: true,
);
} catch (e) {
errorMessage.value = 'bleScanFailedWithError'.trParams({'error': e.toString()});
}
}
// 停止扫描
Future<void> stopScan() async {
try {
await fbp.FlutterBluePlus.stopScan();
} catch (e) {
print('停止扫描失败: $e');
}
}
// 连接设备
Future<void> connectToDevice(fbp.BluetoothDevice device) async {
try {
errorMessage.value = '';
// 停止扫描
await stopScan();
// 连接设备
await device.connect(timeout: const Duration(seconds: 15));
connectedDevice.value = device;
Get.snackbar(
'bleConnectionSuccess'.tr,
'bleConnectedToDevice'.trParams({'device': device.platformName.isNotEmpty ? device.platformName : 'unknownEquipment'.tr}),
backgroundColor: Colors.green,
colorText: Colors.white,
);
} catch (e) {
errorMessage.value = 'bleConnectionFailedWithError'.trParams({'error': e.toString()});
Get.snackbar(
'connectionFailed'.tr,
e.toString(),
backgroundColor: Colors.red,
colorText: Colors.white,
);
}
}
// 断开连接
Future<void> disconnectDevice() async {
try {
if (connectedDevice.value != null) {
await connectedDevice.value!.disconnect();
connectedDevice.value = null;
Get.snackbar(
'bleDisconnected'.tr,
'bleDeviceDisconnected'.tr,
backgroundColor: Colors.orange,
colorText: Colors.white,
);
}
} catch (e) {
errorMessage.value = 'bleDisconnectFailedWithError'.trParams({'error': e.toString()});
}
}
// 获取设备名称
String getDeviceName(fbp.ScanResult result) {
if (result.device.platformName.isNotEmpty) {
return result.device.platformName;
}
if (result.advertisementData.localName.isNotEmpty) {
return result.advertisementData.localName;
}
return 'unknownEquipment'.tr;
}
// 获取信号强度描述
String getSignalStrengthText(int rssi) {
if (rssi >= -50) return 'signalStrong'.tr;
if (rssi >= -70) return 'signalMedium'.tr;
if (rssi >= -90) return 'signalWeak'.tr;
return 'signalVeryWeak'.tr;
}
// 获取信号强度图标
IconData getSignalStrengthIcon(int rssi) {
if (rssi >= -50) return Icons.signal_wifi_4_bar;
if (rssi >= -70) return Icons.signal_wifi_4_bar;
if (rssi >= -90) return Icons.signal_wifi_4_bar;
return Icons.signal_wifi_4_bar;
}
}