|
|
|
@ -1,13 +1,19 @@ |
|
|
|
import 'dart:async'; |
|
|
|
import 'dart:io'; |
|
|
|
|
|
|
|
import 'package:flutter_blue_plus/flutter_blue_plus.dart'; |
|
|
|
import 'package:get/get.dart'; |
|
|
|
import 'package:path_provider/path_provider.dart'; |
|
|
|
import 'package:wifi_iot/wifi_iot.dart'; |
|
|
|
|
|
|
|
import '../../../core/utils/ftpconnect/ftpconnect.dart'; |
|
|
|
import 'meeting_controller.dart'; |
|
|
|
|
|
|
|
class MeetingConnectController extends GetxController { |
|
|
|
final _meetingController = Get.find<MeetingController>(); |
|
|
|
|
|
|
|
RxString stateStr = '搜索中...'.obs; |
|
|
|
RxBool isRescan = false.obs; |
|
|
|
RxBool isImportedFiles = false.obs; |
|
|
|
RxString importedFilesStr = ''.obs; |
|
|
|
|
|
|
|
late StreamSubscription<List<ScanResult>> _scanResultsSubscription; |
|
|
|
@ -16,8 +22,8 @@ class MeetingConnectController extends GetxController { |
|
|
|
|
|
|
|
bool isScanFailed = false; |
|
|
|
|
|
|
|
late BluetoothCharacteristic? _writeCharacteristic; |
|
|
|
late StreamSubscription<List<int>>? _valueReceivedSubscription; |
|
|
|
BluetoothCharacteristic? _writeCharacteristic; |
|
|
|
StreamSubscription<List<int>>? _valueReceivedSubscription; |
|
|
|
|
|
|
|
String _wifiSSID = ''; |
|
|
|
String _wifiPassword = ''; |
|
|
|
@ -26,6 +32,13 @@ class MeetingConnectController extends GetxController { |
|
|
|
String _ftpAccount = ''; |
|
|
|
String _ftpPassword = ''; |
|
|
|
|
|
|
|
FTPConnect? _ftpConnect; |
|
|
|
|
|
|
|
RxBool isDownload = false.obs; |
|
|
|
RxDouble downloadProgress = 0.0.obs; |
|
|
|
RxInt totalReceived = 0.obs; |
|
|
|
RxInt fileSize = 0.obs; |
|
|
|
|
|
|
|
@override |
|
|
|
void onInit() { |
|
|
|
super.onInit(); |
|
|
|
@ -56,6 +69,7 @@ class MeetingConnectController extends GetxController { |
|
|
|
_scanResultsSubscription.cancel(); |
|
|
|
_isScanningSubscription.cancel(); |
|
|
|
_valueReceivedSubscription?.cancel(); |
|
|
|
_ftpConnect?.disconnect(); |
|
|
|
_stopScan(); |
|
|
|
_disconnect(); |
|
|
|
super.onClose(); |
|
|
|
@ -86,6 +100,7 @@ class MeetingConnectController extends GetxController { |
|
|
|
} |
|
|
|
|
|
|
|
Future<void> _disconnect() async { |
|
|
|
await WiFiForIoTPlugin.forceWifiUsage(false); |
|
|
|
await WiFiForIoTPlugin.disconnect(); |
|
|
|
await _device?.disconnect(); |
|
|
|
} |
|
|
|
@ -131,26 +146,25 @@ class MeetingConnectController extends GetxController { |
|
|
|
} |
|
|
|
|
|
|
|
void _listenData(List<int> value) { |
|
|
|
print('----$value--------'); |
|
|
|
int command = value[2]; |
|
|
|
switch (command) { |
|
|
|
case 0x0d: // 是否有导入文件 |
|
|
|
if (value[3] == 0x01) { |
|
|
|
isImportedFiles.value = true; |
|
|
|
importedFilesStr.value = '检查到有新文件,是否导入'; |
|
|
|
stateStr.value = '正在开启Wi-Fi...'; |
|
|
|
importedFilesStr.value = '检查到有新文件,正在准备导入'; |
|
|
|
sendData([0x5a, 0x02, 0x87, 0x01]); |
|
|
|
} else { |
|
|
|
isImportedFiles.value = false; |
|
|
|
importedFilesStr.value = '没有新文件需要导入'; |
|
|
|
} |
|
|
|
break; |
|
|
|
case 0x87: // Wi-Fi 开启/关闭 |
|
|
|
if (value[3] == 0x01 && value[4] == 0x01) { |
|
|
|
_getWifi(); |
|
|
|
sendData([0x5a, 0x01, 0x0b]); |
|
|
|
} |
|
|
|
break; |
|
|
|
case 0x0b: // WiFi 热点 SSID |
|
|
|
_wifiSSID = String.fromCharCodes(value.sublist(3, value.length - 2)); |
|
|
|
_connectWifi(); |
|
|
|
sendData([0x5a, 0x01, 0x0c]); |
|
|
|
break; |
|
|
|
case 0x0c: // WiFi 热点密码 |
|
|
|
_wifiPassword = _decodePassword(value); |
|
|
|
@ -176,11 +190,6 @@ class MeetingConnectController extends GetxController { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void _getWifi() async { |
|
|
|
await sendData([0x5a, 0x01, 0x0b]); |
|
|
|
await sendData([0x5a, 0x01, 0x0c]); |
|
|
|
} |
|
|
|
|
|
|
|
void _connectWifi() async { |
|
|
|
if (_wifiSSID.isNotEmpty && _wifiPassword.isNotEmpty) { |
|
|
|
stateStr.value = '正在连接 Wi-Fi...'; |
|
|
|
@ -189,16 +198,71 @@ class MeetingConnectController extends GetxController { |
|
|
|
password: _wifiPassword, |
|
|
|
security: NetworkSecurity.WPA, |
|
|
|
); |
|
|
|
await WiFiForIoTPlugin.forceWifiUsage(true); |
|
|
|
stateStr.value = 'Wi-Fi 连接成功'; |
|
|
|
sendData([0x5a, 0x01, 0x03]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void _connectFtp() { |
|
|
|
void _connectFtp() async { |
|
|
|
if (_ftpAddress.isNotEmpty && |
|
|
|
_ftpPort.isNotEmpty && |
|
|
|
_ftpAccount.isNotEmpty && |
|
|
|
_ftpPassword.isNotEmpty) {} |
|
|
|
_ftpPassword.isNotEmpty) { |
|
|
|
_ftpConnect = FTPConnect( |
|
|
|
_ftpAddress, |
|
|
|
port: int.tryParse(_ftpPort) ?? 21, |
|
|
|
user: _ftpAccount, |
|
|
|
pass: _ftpPassword, |
|
|
|
); |
|
|
|
await _ftpConnect?.connect(); |
|
|
|
_ftpConnect?.listCommand = ListCommand.LIST; |
|
|
|
List<FTPEntry>? listDirectory = await _ftpConnect?.listDirectoryContent(); |
|
|
|
if (listDirectory != null && listDirectory.isNotEmpty) { |
|
|
|
stateStr.value = '正在下载文件...'; |
|
|
|
isDownload.value = true; |
|
|
|
int totalSize = listDirectory.fold( |
|
|
|
0, |
|
|
|
(sum, entry) => sum + (entry.size ?? 0), |
|
|
|
); |
|
|
|
for (var i = 0; i < listDirectory.length; i++) { |
|
|
|
importedFilesStr.value = |
|
|
|
'共${listDirectory.length}个文件,正在下载第${i + 1}个文件'; |
|
|
|
int previousSize = i > 0 ? listDirectory[i - 1].size ?? 0 : 0; |
|
|
|
FTPEntry element = listDirectory[i]; |
|
|
|
await _downloadFile(totalSize, previousSize, element); |
|
|
|
await _ftpConnect?.deleteFile(element.name); |
|
|
|
} |
|
|
|
stateStr.value = '下载完成'; |
|
|
|
importedFilesStr.value = '下载完成,共${listDirectory.length}个文件,2秒后自动返回'; |
|
|
|
_disconnect(); |
|
|
|
Future.delayed(const Duration(seconds: 2), () { |
|
|
|
Get.back(); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Future<void> _downloadFile( |
|
|
|
int totalSize, int previousSize, FTPEntry entry) async { |
|
|
|
final directory = await getApplicationDocumentsDirectory(); |
|
|
|
final directoryDir = Directory('${directory.path}/RecordingPen'); |
|
|
|
if (!await directoryDir.exists()) { |
|
|
|
await directoryDir.create(recursive: true); |
|
|
|
} |
|
|
|
final String filePath = '${directory.path}/RecordingPen/${entry.name}'; |
|
|
|
final File localFile = File(filePath); |
|
|
|
await _ftpConnect?.downloadFileWithRetry( |
|
|
|
entry.name, |
|
|
|
localFile, |
|
|
|
pRetryCount: 3, |
|
|
|
onProgress: (double progress, int received, int size) { |
|
|
|
downloadProgress.value = (previousSize + received) / totalSize; |
|
|
|
totalReceived.value = received; |
|
|
|
fileSize.value = size; |
|
|
|
}, |
|
|
|
); |
|
|
|
await _meetingController.insertMeetingAudio(entry.name, filePath, ''); |
|
|
|
} |
|
|
|
|
|
|
|
String _decodePassword(List<int> data) { |
|
|
|
|