diff --git a/lib/modules/meeting/controllers/meeting_connect_controller.dart b/lib/modules/meeting/controllers/meeting_connect_controller.dart index 8a3bbff56..34fedb289 100644 --- a/lib/modules/meeting/controllers/meeting_connect_controller.dart +++ b/lib/modules/meeting/controllers/meeting_connect_controller.dart @@ -7,11 +7,17 @@ class MeetingConnectController extends GetxController { RxString stateStr = '搜索中...'.obs; RxBool isRescan = false.obs; RxBool isImportedFiles = false.obs; + RxString importedFilesStr = ''.obs; late StreamSubscription> _scanResultsSubscription; late StreamSubscription _isScanningSubscription; BluetoothDevice? _device; + bool isScanFailed = false; + + late BluetoothCharacteristic? _writeCharacteristic; + late StreamSubscription>? _valueReceivedSubscription; + @override void onInit() { super.onInit(); @@ -21,6 +27,11 @@ class MeetingConnectController extends GetxController { } }); _isScanningSubscription = FlutterBluePlus.isScanning.listen((state) { + if (isScanFailed) { + stateStr.value = '搜索失败,请检查蓝牙是否开启'; + isRescan.value = true; + return; + } if (!state && _device == null) { stateStr.value = '未搜索到 AI PEN 设备'; isRescan.value = true; @@ -36,19 +47,25 @@ class MeetingConnectController extends GetxController { void onClose() { _scanResultsSubscription.cancel(); _isScanningSubscription.cancel(); + _valueReceivedSubscription?.cancel(); _stopScan(); _disconnect(); super.onClose(); } Future startScan() async { - await FlutterBluePlus.startScan( - timeout: const Duration(seconds: 15), - withServices: [ - Guid('FFF0'), - ], - withNames: ['AI PEN'], - ); + try { + isScanFailed = false; + await FlutterBluePlus.startScan( + timeout: const Duration(seconds: 15), + withServices: [ + Guid('FFF0'), + ], + withNames: ['AI PEN'], + ); + } catch (e) { + isScanFailed = true; + } } Future _stopScan() async { @@ -57,6 +74,7 @@ class MeetingConnectController extends GetxController { Future _connect() async { await _device?.connect(); + await _discoverServices(); } Future _disconnect() async { @@ -71,4 +89,55 @@ class MeetingConnectController extends GetxController { stateStr.value = '已连接到 AI PEN 设备'; } } + + Future _discoverServices() async { + List services = await _device?.discoverServices() ?? []; + if (services.isNotEmpty) { + for (var element in services) { + if (element.serviceUuid == Guid('FFF0')) { + _readCharacteristics(element.characteristics); + } + } + } + } + + Future _readCharacteristics( + List characteristics) async { + for (var element in characteristics) { + if (element.characteristicUuid == Guid('FFF1')) { + _writeCharacteristic = element; + stateStr.value = '检查是否有新文件需要导入'; + sendData([0x5a, 0x01, 0x0d]); + } else if (element.characteristicUuid == Guid('FFF2')) { + await element.setNotifyValue(true); + _valueReceivedSubscription = element.onValueReceived.listen((value) { + _listenData(value); + }); + } + } + } + + Future sendData(List value) async { + await _writeCharacteristic?.write(value, withoutResponse: true); + } + + void _listenData(List value) { + print('----$value--------'); + int command = value[2]; + switch (command) { + case 0x0d: // 是否有导入文件 + if (value[3] == 0x01) { + isImportedFiles.value = true; + importedFilesStr.value = '检查到有新文件,是否导入'; + } else { + isImportedFiles.value = false; + importedFilesStr.value = '没有新文件需要导入'; + } + break; + case 0x87: // Wi-Fi 开启/关闭 + if (value[2] == 0x01) {} + break; + default: + } + } } diff --git a/lib/modules/meeting/views/meeting_connect_view.dart b/lib/modules/meeting/views/meeting_connect_view.dart index fbe9ac918..66dd589c6 100644 --- a/lib/modules/meeting/views/meeting_connect_view.dart +++ b/lib/modules/meeting/views/meeting_connect_view.dart @@ -48,42 +48,42 @@ class MeetingConnectView extends GetView { mainAxisAlignment: MainAxisAlignment.center, children: [ Obx( - () => Text( - controller.stateStr.value, - style: TextStyle( - fontSize: 20.sp, - color: isDarkMode ? Colors.white : Colors.black, - fontWeight: FontWeight.bold, + () => Padding( + padding: EdgeInsets.only(bottom: 30.w), + child: Text( + controller.stateStr.value, + style: TextStyle( + fontSize: 20.sp, + color: isDarkMode ? Colors.white : Colors.black, + fontWeight: FontWeight.bold, + ), ), ), ), Obx( () => controller.isRescan.value - ? Padding( - padding: EdgeInsets.only(top: 20.w), - child: _button('重新连接', Icons.refresh, onTap: () { - controller.startScan(); - }), - ) + ? _button('重新连接', Icons.refresh, onTap: () { + controller.startScan(); + }) : const SizedBox(), ), Obx( - () => controller.isImportedFiles.value - ? Padding( - padding: EdgeInsets.only(top: 30.w), - child: Text( - '检测到有新文件,是否导入', - style: TextStyle( - fontSize: 16.sp, - color: isDarkMode ? Colors.white70 : Colors.black54, - ), - ), - ) - : const SizedBox(), + () => Text( + controller.importedFilesStr.value, + style: TextStyle( + fontSize: 16.sp, + color: isDarkMode ? Colors.white70 : Colors.black54, + ), + ), ), Obx( () => controller.isImportedFiles.value - ? _button('导入文件', Icons.file_download, onTap: () {}) + ? Padding( + padding: EdgeInsets.symmetric(vertical: 10.w), + child: _button('导入文件', Icons.file_download, onTap: () { + controller.sendData([0x5a, 0x01, 0x0d]); + }), + ) : const SizedBox(), ), ], @@ -97,7 +97,6 @@ class MeetingConnectView extends GetView { child: Container( width: 150.w, height: 42.w, - margin: EdgeInsets.symmetric(vertical: 10.w), decoration: BoxDecoration( color: Colors.black, borderRadius: BorderRadius.circular(42.w),