更新太和e护配置wifi失败问题
This commit is contained in:
165
lib/pages/mh_page/device/upgrade/BatchUpgradeManager.dart
Normal file
165
lib/pages/mh_page/device/upgrade/BatchUpgradeManager.dart
Normal file
@@ -0,0 +1,165 @@
|
||||
// 批量升级封装类
|
||||
import 'package:easydevice/easydevice.dart';
|
||||
import 'package:ef/ef.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:vbvs_app/common/util/BluetoothFirmwareUpdater.dart';
|
||||
import 'package:vbvs_app/component/tool/NewTopSlideNotification.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/model/BlueToothDataModel.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/upgrade/device_upgrade_controller.dart';
|
||||
|
||||
class BatchUpgradeManager {
|
||||
static final BatchUpgradeManager _instance = BatchUpgradeManager._internal();
|
||||
factory BatchUpgradeManager() => _instance;
|
||||
BatchUpgradeManager._internal();
|
||||
|
||||
final MultiDeviceFirmwareUpdater _updater = MultiDeviceFirmwareUpdater();
|
||||
final MHTDeviceUpgradeController _upgradeController = Get.find();
|
||||
|
||||
bool _isBatchUpgrading = false;
|
||||
final List<BlueToothDataModel> _batchDevices = [];
|
||||
|
||||
// 开始批量升级
|
||||
Future<void> startBatchUpgrade(List<BlueToothDataModel> devices) async {
|
||||
if (_isBatchUpgrading) {
|
||||
throw Exception("批量升级正在进行中".tr);
|
||||
}
|
||||
|
||||
_isBatchUpgrading = true;
|
||||
_batchDevices.clear();
|
||||
_upgradeController.clearUpgradingList();
|
||||
|
||||
// 验证设备并添加到升级列表
|
||||
for (var device in devices) {
|
||||
if (device.selected == true) {
|
||||
_batchDevices.add(device);
|
||||
_upgradeController.addToUpgradingList(device);
|
||||
}
|
||||
}
|
||||
|
||||
if (_batchDevices.isEmpty) {
|
||||
_isBatchUpgrading = false;
|
||||
throw Exception("没有选择要升级的设备".tr);
|
||||
}
|
||||
|
||||
// 开始批量升级
|
||||
try {
|
||||
await _startBatchUpgradeInternal();
|
||||
} catch (e) {
|
||||
_isBatchUpgrading = false;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
// 内部批量升级实现
|
||||
Future<void> _startBatchUpgradeInternal() async {
|
||||
final List<Future> upgradeFutures = [];
|
||||
|
||||
for (var device in _batchDevices) {
|
||||
final future = _startSingleDeviceUpgrade(device);
|
||||
upgradeFutures.add(future);
|
||||
}
|
||||
|
||||
// 等待所有升级完成
|
||||
try {
|
||||
await Future.wait(upgradeFutures, eagerError: false);
|
||||
} finally {
|
||||
_isBatchUpgrading = false;
|
||||
_showBatchUpgradeCompleteNotification();
|
||||
}
|
||||
}
|
||||
|
||||
// 单个设备升级
|
||||
Future<void> _startSingleDeviceUpgrade(BlueToothDataModel device) async {
|
||||
try {
|
||||
// 创建 THapp 实例
|
||||
final thapp = THapp(device: device.scanResult.device);
|
||||
|
||||
// 获取固件URL - 需要您提供实现
|
||||
final firmwareUrl = await _getFirmwareUrl();
|
||||
if (firmwareUrl == null) {
|
||||
throw Exception("固件URL为空".tr);
|
||||
}
|
||||
|
||||
// 使用现有的升级器进行升级
|
||||
await _updater.startUpgrade(
|
||||
thapp: thapp,
|
||||
mac: device.mac,
|
||||
firmwareUrl: firmwareUrl,
|
||||
);
|
||||
|
||||
// 升级成功,从列表中移除
|
||||
_upgradeController.removeFromUpgradingList(device.mac);
|
||||
|
||||
} catch (e) {
|
||||
// 升级失败,也从列表中移除(或者您可以保留失败设备用于重试)
|
||||
_upgradeController.removeFromUpgradingList(device.mac);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取固件URL - 需要您根据实际情况实现
|
||||
Future<String?> _getFirmwareUrl() async {
|
||||
// 这里可以从配置、用户选择或其他地方获取固件URL
|
||||
// 例如:return _upgradeController.selectedFirmwareUrl;
|
||||
return null;
|
||||
}
|
||||
|
||||
// 取消批量升级
|
||||
void cancelBatchUpgrade() {
|
||||
for (var device in _batchDevices) {
|
||||
if (_updater.isDeviceUpgrading(device.mac)) {
|
||||
_updater.cancelUpgrade(device.mac);
|
||||
}
|
||||
_upgradeController.removeFromUpgradingList(device.mac);
|
||||
}
|
||||
|
||||
_isBatchUpgrading = false;
|
||||
_batchDevices.clear();
|
||||
|
||||
NewTopSlideNotification.show(
|
||||
text: "批量升级已取消".tr,
|
||||
textColor: Colors.orange,
|
||||
);
|
||||
}
|
||||
|
||||
// 显示批量升级完成通知
|
||||
void _showBatchUpgradeCompleteNotification() {
|
||||
final allStatus = _updater.getAllUpgradeStatus();
|
||||
final completedCount = allStatus.values.where((status) =>
|
||||
status['status'] == 'completed').length;
|
||||
final failedCount = allStatus.values.where((status) =>
|
||||
status['status'] == 'failed').length;
|
||||
|
||||
String message;
|
||||
if (failedCount == 0) {
|
||||
message = "批量升级完成,所有 ${_batchDevices.length} 个设备升级成功".tr;
|
||||
} else {
|
||||
message = "批量升级完成,$completedCount 个成功,$failedCount 个失败".tr;
|
||||
}
|
||||
|
||||
NewTopSlideNotification.show(
|
||||
text: message,
|
||||
textColor: failedCount == 0 ? Colors.green : Colors.orange,
|
||||
);
|
||||
}
|
||||
|
||||
// 检查是否正在批量升级
|
||||
bool get isBatchUpgrading => _isBatchUpgrading;
|
||||
|
||||
// 获取批量升级统计
|
||||
Map<String, int> getBatchUpgradeStatistics() {
|
||||
final allStatus = _updater.getAllUpgradeStatus();
|
||||
|
||||
return {
|
||||
'total': _batchDevices.length,
|
||||
'completed': allStatus.values.where((status) =>
|
||||
status['status'] == 'completed').length,
|
||||
'failed': allStatus.values.where((status) =>
|
||||
status['status'] == 'failed').length,
|
||||
'upgrading': allStatus.values.where((status) =>
|
||||
status['status'] == 'upgrading' || status['status'] == 'downloading').length,
|
||||
'waiting': allStatus.values.where((status) =>
|
||||
status['status'] == 'waiting').length,
|
||||
};
|
||||
}
|
||||
}
|
||||
1165
lib/pages/mh_page/device/upgrade/device_upgrade.dart
Normal file
1165
lib/pages/mh_page/device/upgrade/device_upgrade.dart
Normal file
File diff suppressed because it is too large
Load Diff
244
lib/pages/mh_page/device/upgrade/device_upgrade_controller.dart
Normal file
244
lib/pages/mh_page/device/upgrade/device_upgrade_controller.dart
Normal file
@@ -0,0 +1,244 @@
|
||||
import 'package:easydevice/easydevice.dart';
|
||||
import 'package:ef/ef.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:vbvs_app/common/util/BluetoothFirmwareUpdater.dart';
|
||||
import 'package:vbvs_app/common/util/FirmwareVersionService.dart';
|
||||
import 'package:vbvs_app/common/util/MyUtils.dart';
|
||||
import 'package:vbvs_app/component/tool/NewTopSlideNotification.dart';
|
||||
import 'package:vbvs_app/enum/APPDeviceUpgrade.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/controller/mht_bluetooth_controller.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/model/BlueToothDataModel.dart';
|
||||
|
||||
part 'device_upgrade_controller.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class MHTDeviceUpgradeModel {
|
||||
bool? bluetooth = false; // 蓝牙开关
|
||||
double? singal = -100;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
List<BlueToothDataModel>? blueRawData = []; //蓝牙原始数据
|
||||
@JsonKey(ignore: true)
|
||||
List<BlueToothDataModel>? upgradingDevices = []; // 正在升级的设备列表
|
||||
|
||||
MHTDeviceUpgradeModel();
|
||||
|
||||
static MHTDeviceUpgradeModel fromJson(Map<String, dynamic> json) =>
|
||||
_$MHTDeviceUpgradeModelFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$MHTDeviceUpgradeModelToJson(this);
|
||||
}
|
||||
|
||||
class MHTDeviceUpgradeController
|
||||
extends GetControllerEx<MHTDeviceUpgradeModel> {
|
||||
MHTDeviceUpgradeController() {
|
||||
attr = GetModel(MHTDeviceUpgradeModel()).obs;
|
||||
}
|
||||
|
||||
//选择的固件
|
||||
FirmwareVersionInfo? selectVerison; //当前选中的固件信息
|
||||
int maxLimit = 5;
|
||||
MHTBlueToothController mhtBlueToothController = Get.find();
|
||||
int? upgradeType = 1;
|
||||
|
||||
List<FirmwareVersionInfo>? firmwareList = [];
|
||||
|
||||
RxList? selectedDiseaseIds = [].obs; //已选中的列表
|
||||
RxList diseaseList = [].obs; //升级类型列表
|
||||
|
||||
// 添加设备到升级列表
|
||||
void addToUpgradingList(BlueToothDataModel device) {
|
||||
if (!model.upgradingDevices!.any((d) => d.mac == device.mac)) {
|
||||
model.upgradingDevices!.add(device);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
// 从升级列表移除设备
|
||||
void removeFromUpgradingList(String mac) {
|
||||
//todo 移除蓝牙连接
|
||||
model.upgradingDevices!.removeWhere((device) => device.mac == mac);
|
||||
update();
|
||||
}
|
||||
|
||||
// 清空升级列表
|
||||
void clearUpgradingList() {
|
||||
//todo 移除蓝牙连接
|
||||
model.upgradingDevices!.clear();
|
||||
update();
|
||||
}
|
||||
|
||||
// 获取正在升级的设备数量
|
||||
int get upgradingDeviceCount => model.upgradingDevices?.length ?? 0;
|
||||
|
||||
// 检查设备是否正在升级
|
||||
bool isDeviceUpgrading(String mac) {
|
||||
return model.upgradingDevices!.any((device) => device.mac == mac);
|
||||
}
|
||||
|
||||
//开始更新
|
||||
Future<void> startUpgrade() async {
|
||||
// 获取全部设备数据
|
||||
var allDevices = model.blueRawData;
|
||||
|
||||
// 获取正在升级的设备数据
|
||||
var upgradingDevices = model.upgradingDevices;
|
||||
|
||||
// 筛选出所有选中的设备
|
||||
var selectedDevices =
|
||||
allDevices!.where((device) => device.selected == true).toList();
|
||||
|
||||
// 排除正在升级的设备(即将已经在升级中的设备从选中的设备列表中移除)
|
||||
var devicesToUpgrade = selectedDevices.where((device) {
|
||||
// 检查设备是否在正在升级的设备列表中
|
||||
return !upgradingDevices!
|
||||
.any((upgradingDevice) => upgradingDevice.mac == device.mac);
|
||||
}).toList();
|
||||
|
||||
if (devicesToUpgrade.isEmpty) {
|
||||
NewTopSlideNotification.show(
|
||||
text: "没有需要升级的设备".tr, textColor: themeController.currentColor.sc9);
|
||||
ef.log("没有需要升级的设备");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查固件信息
|
||||
if (selectVerison == null || selectVerison!.downloadUrl.isEmpty) {
|
||||
NewTopSlideNotification.show(
|
||||
text: "请先选择有效的固件版本".tr, textColor: themeController.currentColor.sc9);
|
||||
throw Exception("请先选择有效的固件版本");
|
||||
}
|
||||
|
||||
// mhtBlueToothController.currentUpgradeUrl = selectVerison!.downloadUrl;
|
||||
// 打印最终需要升级的设备
|
||||
ef.log("需要升级的设备:${devicesToUpgrade}");
|
||||
|
||||
for (var device in devicesToUpgrade) {
|
||||
// await _startSingleDeviceUpgrade(device);
|
||||
_startSingleDeviceUpgrade(device);
|
||||
}
|
||||
if (devicesToUpgrade.isNotEmpty) {
|
||||
devicesToUpgrade.forEach((device) {
|
||||
// 添加设备到正在升级列表
|
||||
device.process = 0;
|
||||
device.upgradeInfo = selectVerison;
|
||||
addToUpgradingList(device);
|
||||
// 发送升级指令
|
||||
// mhtBlueToothController.sendUpgradeCommand(device);
|
||||
});
|
||||
}
|
||||
print(model.upgradingDevices!);
|
||||
}
|
||||
|
||||
// 启动单个设备升级
|
||||
Future<void> _startSingleDeviceUpgrade(BlueToothDataModel device) async {
|
||||
try {
|
||||
// 更新设备状态
|
||||
device.process = 0;
|
||||
device.upgradeInfo = selectVerison;
|
||||
device.selected = false; // 升级开始后取消选中状态
|
||||
device.upgradeStatus = APPDeviceUpgrade.upgrading.value;
|
||||
|
||||
// 添加到升级列表
|
||||
addToUpgradingList(device);
|
||||
|
||||
// 创建 THapp 实例
|
||||
final thapp = THapp(device: device.scanResult.device);
|
||||
|
||||
// 确保设备连接
|
||||
if (!thapp.isConnected) {
|
||||
await thapp.device.connect();
|
||||
}
|
||||
|
||||
// 使用 MultiDeviceFirmwareUpdater 开始升级
|
||||
await MultiDeviceFirmwareUpdater().startUpgrade(
|
||||
thapp: thapp,
|
||||
mac: device.mac,
|
||||
firmwareUrl: selectVerison!.downloadUrl,
|
||||
);
|
||||
|
||||
ef.log("设备 ${device.mac} 升级任务已启动");
|
||||
} catch (e, stack) {
|
||||
ef.log("设备 ${device.mac} 升级启动失败: $e\n$stack");
|
||||
|
||||
// 更新设备状态为失败
|
||||
device.process = -1;
|
||||
device.upgradeStatus = APPDeviceUpgrade.fail.value;
|
||||
update();
|
||||
|
||||
// 从升级列表中移除失败设备(可选,取决于业务需求)
|
||||
// removeFromUpgradingList(device.mac);
|
||||
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
// 取消单个设备升级
|
||||
void cancelUpgrade(String mac) {
|
||||
try {
|
||||
MultiDeviceFirmwareUpdater().cancelUpgrade(mac);
|
||||
removeFromUpgradingList(mac);
|
||||
ef.log("设备 $mac 升级已取消");
|
||||
|
||||
} catch (e, stack) {
|
||||
ef.log("取消设备 $mac 升级失败: $e\n$stack");
|
||||
}
|
||||
}
|
||||
|
||||
// 取消所有设备升级
|
||||
void cancelAllUpgrades() {
|
||||
try {
|
||||
MultiDeviceFirmwareUpdater().cancelAllUpgrades();
|
||||
clearUpgradingList();
|
||||
ef.log("所有设备升级已取消");
|
||||
} catch (e, stack) {
|
||||
ef.log("取消所有设备升级失败: $e\n$stack");
|
||||
}
|
||||
}
|
||||
|
||||
// 获取设备升级状态
|
||||
Map<String, dynamic>? getUpgradeStatus(String mac) {
|
||||
return MultiDeviceFirmwareUpdater().getUpgradeStatus(mac);
|
||||
}
|
||||
|
||||
// 获取所有设备升级状态
|
||||
Map<String, Map<String, dynamic>> getAllUpgradeStatus() {
|
||||
return MultiDeviceFirmwareUpdater().getAllUpgradeStatus();
|
||||
}
|
||||
|
||||
// 检查设备是否正在升级(包括底层状态)
|
||||
bool isDeviceInUpgrading(String mac) {
|
||||
return MultiDeviceFirmwareUpdater().isDeviceUpgrading(mac) ||
|
||||
isDeviceUpgrading(mac);
|
||||
}
|
||||
|
||||
// 清理已完成的任务
|
||||
void cleanupCompletedTasks() {
|
||||
MultiDeviceFirmwareUpdater().cleanupCompletedTasks();
|
||||
|
||||
// 同时清理本地升级列表中已完成的任务
|
||||
model.upgradingDevices!.removeWhere((device) {
|
||||
final status = getUpgradeStatus(device.mac);
|
||||
return status == null ||
|
||||
['completed', 'failed', 'cancelled'].contains(status['status']);
|
||||
});
|
||||
update();
|
||||
}
|
||||
|
||||
// 更新设备进度(供 MultiDeviceFirmwareUpdater 回调使用)
|
||||
void updateDeviceProgress(String mac, int progress, String status) {
|
||||
final device = model.upgradingDevices!.firstWhere((d) => d.mac == mac);
|
||||
|
||||
if (device != null) {
|
||||
device.process = progress;
|
||||
|
||||
// 如果升级完成或失败,更新相关状态
|
||||
if (status == 'completed' && progress == 100) {
|
||||
device.newVersion = int.parse(selectVerison?.version ?? '0');
|
||||
// 可以在这里添加其他完成后的逻辑
|
||||
} else if (status == 'failed') {
|
||||
device.process = -1;
|
||||
}
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'device_upgrade_controller.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
MHTDeviceUpgradeModel _$MHTDeviceUpgradeModelFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
MHTDeviceUpgradeModel()
|
||||
..bluetooth = json['bluetooth'] as bool?
|
||||
..singal = (json['singal'] as num?)?.toDouble();
|
||||
|
||||
Map<String, dynamic> _$MHTDeviceUpgradeModelToJson(
|
||||
MHTDeviceUpgradeModel instance) =>
|
||||
<String, dynamic>{
|
||||
'bluetooth': instance.bluetooth,
|
||||
'singal': instance.singal,
|
||||
};
|
||||
568
lib/pages/mh_page/device/upgrade/device_upgrade_list.dart
Normal file
568
lib/pages/mh_page/device/upgrade/device_upgrade_list.dart
Normal file
@@ -0,0 +1,568 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:ef/ef.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
|
||||
import 'package:flutterflow_ui/flutterflow_ui.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:vbvs_app/common/color/appConstants.dart';
|
||||
import 'package:vbvs_app/common/util/BluetoothHelper.dart';
|
||||
import 'package:vbvs_app/common/util/CommonVariables.dart';
|
||||
import 'package:vbvs_app/common/util/FirmwareVersionService.dart';
|
||||
import 'package:vbvs_app/common/util/FitTool.dart';
|
||||
import 'package:vbvs_app/common/util/MyUtils.dart';
|
||||
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
|
||||
import 'package:vbvs_app/controller/main_bottom/global_controller.dart';
|
||||
import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
|
||||
import 'package:vbvs_app/controller/user_info_controller.dart';
|
||||
import 'package:vbvs_app/pages/common/selectDialog.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/component/mht_bind_dialog.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/component/UpgradeDevice.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/controller/mht_bluetooth_controller.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/mht_blueteeth_device_page.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/model/BlueToothDataModel.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/upgrade/device_upgrade_controller.dart';
|
||||
|
||||
class DeviceUpgradeList extends StatefulWidget {
|
||||
DeviceUpgradeList({super.key});
|
||||
|
||||
@override
|
||||
State<DeviceUpgradeList> createState() => _DeviceUpgradeState();
|
||||
}
|
||||
|
||||
class _DeviceUpgradeState extends State<DeviceUpgradeList> {
|
||||
MHTBlueToothController mhtBlueToothController = Get.find();
|
||||
GlobalController globalController = Get.find();
|
||||
UserInfoController userInfoController = Get.find();
|
||||
ThemeController themeController = Get.find();
|
||||
late FlutterBluePlus flutterBlue;
|
||||
List<ScanResult> scanResults = [];
|
||||
bool isScanning = false;
|
||||
Timer? _timer;
|
||||
bool _isDialogShowing = false;
|
||||
|
||||
var currentConnectedDeviceProp;
|
||||
var connectDeviceCurrent = null;
|
||||
List bleDevice = [];
|
||||
String currentMsg = "寻找设备中...";
|
||||
Timer? connectTimer;
|
||||
bool isFind = false;
|
||||
StreamSubscription<List<ScanResult>>? _scanSubscription;
|
||||
var formFieldController = FormFieldController<String>(null);
|
||||
MHTDeviceUpgradeController mhtDeviceUpgradeController = Get.find();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
mhtBlueToothController.allSelect.value = false;
|
||||
mhtBlueToothController.model.blueRawData = [];
|
||||
mhtBlueToothController.model.deviceDataStatus = [];
|
||||
flutterBlue = FlutterBluePlus();
|
||||
_checkBluetoothPermission();
|
||||
mhtBlueToothController.search.value = "";
|
||||
mhtBlueToothController.currentDeviceMac?.value = "";
|
||||
BluetoothHelper.listenBluetoothState((isOn) {
|
||||
mhtBlueToothController.model.bluetooth = isOn;
|
||||
mhtBlueToothController.updateAll();
|
||||
if (!isOn && !_isDialogShowing) {
|
||||
_isDialogShowing = true;
|
||||
mhtBlueToothController.model.blueRawData = [];
|
||||
mhtBlueToothController.model.deviceDataStatus = [];
|
||||
mhtBlueToothController.updateAll();
|
||||
_showBluetoothNotEnabledDialog().then((_) {
|
||||
_isDialogShowing = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
_initFirmwareVersions();
|
||||
}
|
||||
|
||||
//扫描设备
|
||||
Future<void> _checkBluetoothPermission() async {
|
||||
PermissionStatus bluetoothStatus = await Permission.bluetooth.status;
|
||||
PermissionStatus locationStatus = await Permission.location.status;
|
||||
|
||||
if (bluetoothStatus.isGranted && locationStatus.isGranted) {
|
||||
_startScanning();
|
||||
_startPeriodicScan();
|
||||
} else {
|
||||
_requestBluetoothPermission();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _requestBluetoothPermission() async {
|
||||
Map<Permission, PermissionStatus> statuses = {};
|
||||
bool dialogShown = false; // 标记是否弹过权限提示弹窗
|
||||
if (Platform.isIOS) {
|
||||
PermissionStatus isBleGranted = await Permission.bluetooth.request();
|
||||
print('checkBlePermissions-ios, isBleGranted=$isBleGranted');
|
||||
if (isBleGranted.isGranted) {
|
||||
// startBluetoothScanning();
|
||||
_startScanning();
|
||||
_startPeriodicScan();
|
||||
} else {
|
||||
try {
|
||||
_startScanning();
|
||||
_startPeriodicScan();
|
||||
} catch (e) {
|
||||
TopSlideNotification.show(context,
|
||||
text: "蓝牙权限未开启,请在设置中开启蓝牙权限".tr,
|
||||
textColor: themeController.currentColor.sc9);
|
||||
}
|
||||
}
|
||||
} else if (Platform.isAndroid) {
|
||||
try {
|
||||
// 检查是否已授权
|
||||
bool alreadyGranted = await Permission.bluetoothScan.isGranted &&
|
||||
await Permission.bluetoothConnect.isGranted &&
|
||||
await Permission.location.isGranted;
|
||||
|
||||
if (!alreadyGranted) {
|
||||
// 弹出自定义提示
|
||||
showPermissionInfoDialog(
|
||||
Get.context!, CommonVariables().bluetoothpermissionInfo);
|
||||
dialogShown = true;
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
// 请求权限
|
||||
statuses = await [
|
||||
Permission.bluetoothScan,
|
||||
Permission.bluetoothConnect,
|
||||
Permission.location,
|
||||
].request();
|
||||
|
||||
ef.log("权限状态: $statuses");
|
||||
} else {
|
||||
statuses = {
|
||||
Permission.bluetoothScan: PermissionStatus.granted,
|
||||
Permission.bluetoothConnect: PermissionStatus.granted,
|
||||
Permission.location: PermissionStatus.granted,
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
ef.log("申请权限出错: $e");
|
||||
} finally {
|
||||
// 只有真的弹过提示才关闭
|
||||
if (dialogShown && Get.context != null) {
|
||||
Navigator.of(Get.context!, rootNavigator: true).pop();
|
||||
}
|
||||
}
|
||||
bool allGranted = statuses[Permission.bluetoothScan]?.isGranted == true &&
|
||||
statuses[Permission.bluetoothConnect]?.isGranted == true &&
|
||||
statuses[Permission.location]?.isGranted == true;
|
||||
|
||||
if (allGranted) {
|
||||
_startScanning();
|
||||
_startPeriodicScan();
|
||||
} else {
|
||||
_showPermissionDeniedDialog(context);
|
||||
}
|
||||
} else {
|
||||
TopSlideNotification.show(context,
|
||||
text: "当前系统不支持蓝牙,无法使用此功能".tr,
|
||||
textColor: themeController.currentColor.sc9);
|
||||
}
|
||||
}
|
||||
|
||||
void _showPermissionDeniedDialog(BuildContext context) {
|
||||
TopSlideNotification.show(context,
|
||||
text: "应用需要蓝牙和位置权限才能扫描设备。请授予权限。".tr,
|
||||
textColor: themeController.currentColor.sc9);
|
||||
}
|
||||
|
||||
void _startScanning() async {
|
||||
try {
|
||||
if (!mounted || isScanning || !mhtBlueToothController.shouldScan.value)
|
||||
return;
|
||||
|
||||
_scanSubscription?.cancel();
|
||||
mhtBlueToothController.updateAll();
|
||||
|
||||
if (!mhtBlueToothController.model.bluetooth!) return;
|
||||
|
||||
if (!isScanning) {
|
||||
setState(() {
|
||||
isScanning = true;
|
||||
});
|
||||
|
||||
await FlutterBluePlus.startScan(timeout: Duration(seconds: 10));
|
||||
|
||||
_scanSubscription = FlutterBluePlus.scanResults.listen((results) {
|
||||
if (!mounted) return;
|
||||
|
||||
final signalThreshold = mhtBlueToothController.model.singal!;
|
||||
final searchKey =
|
||||
mhtBlueToothController.search.value.trim().toLowerCase();
|
||||
|
||||
final filteredResults = results.map((r) {
|
||||
Map<String, dynamic> d = {
|
||||
"updateTime": DateTime.now().millisecondsSinceEpoch,
|
||||
"name": r.advertisementData.localName?.trim() ??
|
||||
r.advertisementData.advName?.trim() ??
|
||||
r.device.name ??
|
||||
"",
|
||||
"rssi": r.rssi,
|
||||
"device": r.device,
|
||||
"connectable": r.advertisementData.connectable
|
||||
};
|
||||
|
||||
// 从 manufacturerData 解析设备唯一 ID
|
||||
Map<int, List<int>> m_d = r.advertisementData.manufacturerData;
|
||||
String? deviceId;
|
||||
|
||||
m_d.forEach((key, value) {
|
||||
if (value == null || value.isEmpty) return;
|
||||
|
||||
if (key == 65517) {
|
||||
List<int> a = [0, 0, ...value];
|
||||
advertisDataFormatter(a, d); // 你原来的处理
|
||||
if (d['adData']?['deviceId'] != null)
|
||||
deviceId = d['adData']['deviceId'];
|
||||
} else if (key == 11125 && value.length == 8) {
|
||||
deviceId = ab2str(value.sublist(2, 8)).toUpperCase();
|
||||
}
|
||||
});
|
||||
|
||||
d['id'] = deviceId ?? r.device.remoteId.str; // fallback UUID
|
||||
return BlueToothDataModel.fromScanResult(
|
||||
r,
|
||||
1,
|
||||
bind: false,
|
||||
name: d['name'],
|
||||
mac: d['id'],
|
||||
version: d['adData']?['version'],
|
||||
rssi: d['rssi'],
|
||||
selected: mhtBlueToothController.allSelect.value,
|
||||
);
|
||||
}).where((d) {
|
||||
// 信号强度过滤(用 d.scanResult.rssi 或 d.rssi 都可以)
|
||||
if (d.scanResult.rssi <= signalThreshold) return false;
|
||||
|
||||
// 搜索关键字过滤
|
||||
if (searchKey.isNotEmpty) {
|
||||
String name = d.name.toLowerCase();
|
||||
String mac = d.mac.toLowerCase();
|
||||
if (!name.contains(searchKey) && !mac.contains(searchKey))
|
||||
return false;
|
||||
}
|
||||
|
||||
// 名称过滤规则,必须包含 deviceType['reg'] 列表中的某个字符串
|
||||
List<String> regList = [];
|
||||
if (regList.isNotEmpty) {
|
||||
String lowerName = d.name.toLowerCase();
|
||||
bool match =
|
||||
regList.any((reg) => lowerName.contains(reg.toLowerCase()));
|
||||
if (!match) return false;
|
||||
}
|
||||
|
||||
// 修正:不要使用外部的 r,改从 d.scanResult 读取广告数据
|
||||
final adv = d.scanResult.advertisementData;
|
||||
final isTarget = (d.rssi ?? d.scanResult.rssi) > signalThreshold &&
|
||||
(adv.localName == "AITH-V2" || adv.localName == "SLAVE") &&
|
||||
adv.manufacturerData.containsKey(0xFFED);
|
||||
|
||||
if (!isTarget) return false;
|
||||
|
||||
return true;
|
||||
}).toList();
|
||||
|
||||
final currentDevices = mhtBlueToothController.model.blueRawData ?? [];
|
||||
final newDevices = <BlueToothDataModel>[];
|
||||
|
||||
// for (var newDevice in filteredResults) {
|
||||
// final existingIndex =
|
||||
// currentDevices.indexWhere((d) => d.mac == newDevice.mac);
|
||||
// if (existingIndex >= 0) {
|
||||
// currentDevices[existingIndex] = newDevice;
|
||||
// } else {
|
||||
// newDevices.add(newDevice);
|
||||
// }
|
||||
// }
|
||||
|
||||
for (var newDevice in filteredResults) {
|
||||
final existingIndex =
|
||||
currentDevices.indexWhere((d) => d.mac == newDevice.mac);
|
||||
|
||||
if (existingIndex >= 0) {
|
||||
// 如果设备已存在,更新信号强度rssi
|
||||
currentDevices[existingIndex].rssi = newDevice.rssi;
|
||||
} else {
|
||||
// 如果设备不存在,添加到新设备列表
|
||||
newDevices.add(newDevice);
|
||||
}
|
||||
}
|
||||
|
||||
setState(() {
|
||||
mhtBlueToothController.model.blueRawData = [
|
||||
...currentDevices,
|
||||
...newDevices
|
||||
];
|
||||
mhtBlueToothController.updateAll();
|
||||
});
|
||||
});
|
||||
|
||||
await Future.delayed(Duration(seconds: 10));
|
||||
await FlutterBluePlus.stopScan();
|
||||
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
isScanning = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
ef.log("$e");
|
||||
} finally {
|
||||
setState(() {
|
||||
isScanning = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _startPeriodicScan() {
|
||||
_timer = Timer.periodic(Duration(seconds: 3), (timer) {
|
||||
if (mhtBlueToothController.shouldScan.value && !isScanning) {
|
||||
_removeOldDevices(); // 先清理老旧设备
|
||||
_startScanning();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _stopScanning() {
|
||||
if (isScanning) {
|
||||
FlutterBluePlus.stopScan();
|
||||
_scanSubscription?.cancel();
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
isScanning = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _stopPeriodicScan() {
|
||||
_timer?.cancel();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_stopPeriodicScan();
|
||||
_stopScanning();
|
||||
_scanSubscription?.cancel();
|
||||
connectTimer?.cancel();
|
||||
mhtBlueToothController.stopStatusPolling();
|
||||
mhtBlueToothController.model.blueRawData = [];
|
||||
mhtBlueToothController.model.deviceDataStatus = [];
|
||||
BluetoothHelper.cancelListener();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool isTargetDevice(String? name, List<String> keywords) {
|
||||
if (name == null) return false;
|
||||
return keywords.any((k) => name.contains(k));
|
||||
}
|
||||
|
||||
_showBluetoothNotEnabledDialog() async {
|
||||
await showTipDialog(
|
||||
backgroundColor: Colors.white,
|
||||
context,
|
||||
Column(
|
||||
children: [
|
||||
Text(
|
||||
"蓝牙未开启".tr,
|
||||
style: TextStyle(
|
||||
fontSize: AppConstants().title_text_fontSize,
|
||||
color: stringToColor("#333333"),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 20.rpx,
|
||||
),
|
||||
Text(
|
||||
"请先打开蓝牙在进行设备扫描".tr,
|
||||
style: TextStyle(
|
||||
fontSize: AppConstants().normal_text_fontSize,
|
||||
color: stringToColor("#333333"),
|
||||
),
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, boxConstraints) => GestureDetector(
|
||||
// onTap: () => FocusScope.of(context).unfocus(),,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage('assets/images/new_background.png'),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
backgroundColor: Colors.transparent,
|
||||
appBar: AppBar(
|
||||
iconTheme: IconThemeData(color: themeController.currentColor.sc3),
|
||||
backgroundColor: Colors.transparent,
|
||||
automaticallyImplyLeading: false,
|
||||
titleSpacing: 0,
|
||||
title: Container(
|
||||
width: double.infinity,
|
||||
height: 180.rpx,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'升级列表'.tr,
|
||||
style: TextStyle(
|
||||
fontFamily: 'Readex Pro',
|
||||
color: themeController.currentColor.sc3,
|
||||
letterSpacing: 0,
|
||||
fontSize: 30.rpx,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
child: returnIconButtom,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [],
|
||||
centerTitle: false,
|
||||
),
|
||||
body: SafeArea(
|
||||
top: true,
|
||||
child: Padding(
|
||||
padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 0, 30.rpx, 0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
Obx(() {
|
||||
if (mhtDeviceUpgradeController.model
|
||||
.upgradingDevices!.isNotEmpty) {
|
||||
final sortedList = mhtDeviceUpgradeController.model
|
||||
.upgradingDevices!
|
||||
.toList()
|
||||
..sort((a, b) => b.rssi!.compareTo(a.rssi!));
|
||||
// if (sortedList.length > 0) {
|
||||
// ef.log("[rssi变化]--》${sortedList[0].rssi}");
|
||||
// }
|
||||
return Expanded(
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
...sortedList
|
||||
.map((device) {
|
||||
return UpgradeDevice(
|
||||
bleDevice: device,
|
||||
deviceType: 1,
|
||||
);
|
||||
})
|
||||
.toList()
|
||||
.divide(SizedBox(height: 30.rpx))
|
||||
.addToEnd(SizedBox(height: 30.rpx)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Container();
|
||||
}),
|
||||
].divide(SizedBox(
|
||||
height: 30.rpx,
|
||||
)),
|
||||
)),
|
||||
].divide(SizedBox(height: 30.rpx)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _removeOldDevices() {
|
||||
final now = DateTime.now();
|
||||
final currentDevices = mhtBlueToothController.model.blueRawData ?? [];
|
||||
|
||||
// 移除30秒内未出现的设备
|
||||
final updatedDevices = currentDevices.where((device) {
|
||||
return now.difference(device.lastSeen) < Duration(seconds: 30);
|
||||
}).toList();
|
||||
|
||||
if (updatedDevices.length != currentDevices.length) {
|
||||
setState(() {
|
||||
mhtBlueToothController.model.blueRawData = updatedDevices;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
String getDeviceId(ScanResult result) {
|
||||
// Android:remoteId 就是 MAC
|
||||
if (Platform.isAndroid) {
|
||||
return result.device.remoteId.str.replaceAll(':', '').toUpperCase();
|
||||
}
|
||||
|
||||
// iOS:尝试从 manufacturerData 里解析
|
||||
Map<int, List<int>> mData = result.advertisementData.manufacturerData;
|
||||
for (var key in mData.keys) {
|
||||
List<int>? bytes = mData[key];
|
||||
if (bytes != null && bytes.length == 6) {
|
||||
// 假设这 6 个字节就是 MAC
|
||||
return bytes
|
||||
.map((b) => b.toRadixString(16).padLeft(2, '0'))
|
||||
.join('')
|
||||
.toUpperCase();
|
||||
}
|
||||
}
|
||||
return result.device.remoteId.str.toUpperCase();
|
||||
}
|
||||
|
||||
Future<void> _initFirmwareVersions() async {
|
||||
try {
|
||||
const baseUrl = "https://share.file.he-info.cn";
|
||||
const firmwarePath = "/ota/aithv2/";
|
||||
|
||||
final versions = await FirmwareVersionService.getAllFirmwareVersions(
|
||||
baseUrl: baseUrl,
|
||||
firmwarePath: firmwarePath,
|
||||
);
|
||||
|
||||
if (versions.isNotEmpty) {
|
||||
// 这里你可以存到控制器里
|
||||
mhtBlueToothController.firmwareList = versions;
|
||||
print("✅ 获取到 ${versions.length} 个固件版本:");
|
||||
for (final v in versions) {
|
||||
print("➡ ${v.fileName} (${v.version})");
|
||||
}
|
||||
if (mhtDeviceUpgradeController.selectVerison == null) {
|
||||
mhtDeviceUpgradeController.selectVerison = versions.first;
|
||||
formFieldController.value =
|
||||
mhtDeviceUpgradeController.selectVerison!.version!;
|
||||
mhtBlueToothController.updateAll();
|
||||
} else {
|
||||
formFieldController.value =
|
||||
mhtDeviceUpgradeController.selectVerison!.version!;
|
||||
}
|
||||
} else {
|
||||
print("⚠ 没有获取到固件版本文件");
|
||||
}
|
||||
} catch (e) {
|
||||
print("❌ 初始化获取固件版本失败: $e");
|
||||
}
|
||||
}
|
||||
}
|
||||
328
lib/pages/mh_page/device/upgrade/tool/device_upgrade_tool.dart
Normal file
328
lib/pages/mh_page/device/upgrade/tool/device_upgrade_tool.dart
Normal file
@@ -0,0 +1,328 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:ef/ef.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
|
||||
import 'package:vbvs_app/common/color/appConstants.dart';
|
||||
import 'package:vbvs_app/common/util/FirmwareVersionService.dart';
|
||||
import 'package:vbvs_app/common/util/FitTool.dart';
|
||||
import 'package:vbvs_app/common/util/MyUtils.dart';
|
||||
import 'package:vbvs_app/component/tool/SelectableTagButton.dart';
|
||||
import 'package:vbvs_app/enum/APPDeviceUpgrade.dart';
|
||||
import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/controller/mht_bluetooth_controller.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/model/BlueToothDataModel.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/upgrade/device_upgrade_controller.dart';
|
||||
|
||||
MHTDeviceUpgradeController mhtDeviceUpgradeController = Get.find();
|
||||
|
||||
Future<void> initDeviceUpgradeType() async {
|
||||
try {
|
||||
// 模拟异步加载
|
||||
// await Future.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
final dataList = APPDeviceUpgradeExtension.list;
|
||||
|
||||
ef.log("✅ 初始化固件升级类型成功,共 ${dataList.length} 项");
|
||||
for (var item in dataList) {
|
||||
ef.log(" ${item['id']} - ${item['name']}");
|
||||
}
|
||||
// 你可以在这里存入 controller 变量中,例如:
|
||||
mhtDeviceUpgradeController.diseaseList.value = dataList;
|
||||
} catch (e) {
|
||||
ef.log("❌ 初始化获取固件版本失败: $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> initFirmwareVersions(formFieldController) async {
|
||||
try {
|
||||
const baseUrl = "https://share.file.he-info.cn";
|
||||
const firmwarePath = "/ota/aithv2/";
|
||||
|
||||
final versions = await FirmwareVersionService.getAllFirmwareVersions(
|
||||
baseUrl: baseUrl,
|
||||
firmwarePath: firmwarePath,
|
||||
);
|
||||
|
||||
if (versions.isNotEmpty) {
|
||||
// 这里你可以存到控制器里
|
||||
mhtDeviceUpgradeController.firmwareList = versions;
|
||||
print("✅ 获取到 ${versions.length} 个固件版本:");
|
||||
for (final v in versions) {
|
||||
print("➡ ${v.fileName} (${v.version})");
|
||||
}
|
||||
if (mhtDeviceUpgradeController.selectVerison == null) {
|
||||
mhtDeviceUpgradeController.selectVerison = versions.first;
|
||||
formFieldController.value =
|
||||
mhtDeviceUpgradeController.selectVerison!.version!;
|
||||
|
||||
final MHTBlueToothController _btController = Get.find();
|
||||
_btController.currentUpgradeVersion =
|
||||
mhtDeviceUpgradeController.selectVerison!.version!;
|
||||
_btController.currentUpgradeName =
|
||||
mhtDeviceUpgradeController.selectVerison!.fileName!;
|
||||
_btController.currentUpgradeUrl =
|
||||
mhtDeviceUpgradeController.selectVerison!.downloadUrl!;
|
||||
|
||||
mhtDeviceUpgradeController.updateAll();
|
||||
} else {
|
||||
formFieldController.value =
|
||||
mhtDeviceUpgradeController.selectVerison!.version!;
|
||||
}
|
||||
mhtDeviceUpgradeController.updateAll();
|
||||
} else {
|
||||
print("⚠ 没有获取到固件版本文件");
|
||||
}
|
||||
} catch (e) {
|
||||
print("❌ 初始化获取固件版本失败: $e");
|
||||
}
|
||||
}
|
||||
|
||||
getQueryList() {
|
||||
return Padding(
|
||||
padding: EdgeInsets.all(AppConstants().content_left_right_padding),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"筛选条件".tr,
|
||||
style: TextStyle(
|
||||
fontSize: AppConstants().title_text_fontSize,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
Obx(() {
|
||||
final selectedIds = mhtDeviceUpgradeController.selectedDiseaseIds;
|
||||
final diseases = mhtDeviceUpgradeController.diseaseList;
|
||||
return Padding(
|
||||
padding: EdgeInsetsDirectional.fromSTEB(0.rpx, 40.rpx, 0.rpx, 0),
|
||||
child: Wrap(
|
||||
spacing: 20.rpx,
|
||||
runSpacing: 20.rpx,
|
||||
children: diseases.map<Widget>((disease) {
|
||||
final id = disease['id'];
|
||||
final name = disease['name'];
|
||||
final isSelected = selectedIds!.contains(id);
|
||||
return SelectableTagButton(
|
||||
selectedTextColor: Colors.black,
|
||||
unselectedTextColor: Colors.white,
|
||||
colors: [stringToColor("#84F5FF")],
|
||||
borderRadius: AppConstants().button_container_radius,
|
||||
label: name,
|
||||
selected: isSelected,
|
||||
onTap: () {
|
||||
final allId = APPDeviceUpgrade.ALL.value; // 全部的id(一般是1)
|
||||
|
||||
if (id == allId) {
|
||||
// 👉 点击的是“全部”
|
||||
if (isSelected) {
|
||||
// 当前是选中状态 → 取消“全部”选择(清空所有)
|
||||
selectedIds.clear();
|
||||
} else {
|
||||
// 当前未选中 → 全部选中(添加所有状态的id)
|
||||
selectedIds
|
||||
..clear()
|
||||
..addAll(APPDeviceUpgradeExtension.valueList);
|
||||
}
|
||||
} else {
|
||||
// 👉 点击的不是“全部”
|
||||
if (isSelected) {
|
||||
// 已选中 → 取消当前id
|
||||
selectedIds.remove(id);
|
||||
|
||||
// 若取消后,“全部”还在选中 → 去掉“全部”
|
||||
if (selectedIds.contains(allId)) {
|
||||
selectedIds.remove(allId);
|
||||
}
|
||||
} else {
|
||||
// 未选中 → 选中当前id
|
||||
selectedIds.add(id);
|
||||
|
||||
// 若选中的数量 == 除“全部”外的所有类型数 → 自动勾选“全部”
|
||||
final allOtherIds = APPDeviceUpgradeExtension
|
||||
.valueList
|
||||
.where((v) => v != allId);
|
||||
if (selectedIds.toSet().containsAll(allOtherIds)) {
|
||||
selectedIds
|
||||
..clear()
|
||||
..addAll(APPDeviceUpgradeExtension.valueList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mhtDeviceUpgradeController.updateAll();
|
||||
});
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// int getRemainingDeviceCount() {
|
||||
// // 获取所有设备数据
|
||||
// var allDevices = mhtDeviceUpgradeController.model.blueRawData!;
|
||||
|
||||
// // 获取正在升级的设备数据
|
||||
// var upgradingDevices = mhtDeviceUpgradeController.model.upgradingDevices;
|
||||
|
||||
// // 获取正在升级的设备 mac 地址列表
|
||||
// var upgradingMacs = upgradingDevices!.map((device) => device.mac).toList();
|
||||
|
||||
// // 计算所有设备中不在升级设备列表中的设备数量
|
||||
// var remainingDevices = allDevices
|
||||
// .where((device) => !upgradingMacs.contains(device.mac))
|
||||
// .toList();
|
||||
|
||||
// // 返回剩余设备的数量,最小为 0
|
||||
|
||||
// mhtDeviceUpgradeController.selectVerison;
|
||||
// return remainingDevices.length;
|
||||
// }
|
||||
int getRemainingDeviceCount() {
|
||||
// 获取所有设备数据
|
||||
var allDevices = mhtDeviceUpgradeController.model.blueRawData ?? [];
|
||||
|
||||
// 获取正在升级的设备数据
|
||||
var upgradingDevices =
|
||||
mhtDeviceUpgradeController.model.upgradingDevices ?? [];
|
||||
|
||||
// 获取当前选择的升级版本
|
||||
var selectedVersion = mhtDeviceUpgradeController.selectVerison;
|
||||
|
||||
// 获取正在升级的设备 mac 地址列表
|
||||
var upgradingMacs = upgradingDevices.map((device) => device.mac).toList();
|
||||
|
||||
// 过滤出:
|
||||
// 1. 不在正在升级的设备列表中;
|
||||
// 2. 且版本号不等于当前选中的版本(表示无需升级的排除掉)
|
||||
var remainingDevices = allDevices.where((device) {
|
||||
// bool notUpgrading = !upgradingMacs.contains(device.mac);
|
||||
bool notUpgrading = true;
|
||||
//todo wyf 恢复
|
||||
// bool needUpgrade = device.version.toString() != selectedVersion!.version;
|
||||
bool needUpgrade = true;
|
||||
return notUpgrading && needUpgrade;
|
||||
}).toList();
|
||||
|
||||
// 返回剩余需要升级的设备数量
|
||||
|
||||
List<BlueToothDataModel> displayDevices = [
|
||||
// 用 upgrading 覆盖 raw 中的相同 mac
|
||||
...allDevices.map((d) {
|
||||
final u = upgradingDevices.firstWhereOrNull((x) => x.mac == d.mac);
|
||||
return u ?? d;
|
||||
}),
|
||||
// 加入那些只在 upgradingDevices 中但不在 raw 的
|
||||
...upgradingDevices.where((u) => !allDevices.any((d) => d.mac == u.mac)),
|
||||
];
|
||||
return displayDevices.length;
|
||||
return remainingDevices.length;
|
||||
}
|
||||
|
||||
String judgeUpgradeDeviceCount() {
|
||||
List selectedDevices = mhtDeviceUpgradeController.model.blueRawData!
|
||||
.where((device) => device.selected == true)
|
||||
.toList();
|
||||
if (selectedDevices.length == 0) {
|
||||
return "请至少选择一项设备";
|
||||
}
|
||||
if (selectedDevices.length > mhtDeviceUpgradeController.maxLimit) {
|
||||
return "超出数量限制,请等待";
|
||||
}
|
||||
final devices = mhtDeviceUpgradeController.model.upgradingDevices;
|
||||
if (devices == null || devices.isEmpty) {
|
||||
return "";
|
||||
} else {
|
||||
if (devices.length >= mhtDeviceUpgradeController.maxLimit) {
|
||||
return "超出数量限制,请等待";
|
||||
}
|
||||
if (devices.length + selectedDevices.length >
|
||||
mhtDeviceUpgradeController.maxLimit) {
|
||||
return "超出数量限制,请等待";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
String getDeviceId(ScanResult result) {
|
||||
// Android:remoteId 就是 MAC
|
||||
if (Platform.isAndroid) {
|
||||
return result.device.remoteId.str.replaceAll(':', '').toUpperCase();
|
||||
}
|
||||
|
||||
// iOS:尝试从 manufacturerData 里解析
|
||||
Map<int, List<int>> mData = result.advertisementData.manufacturerData;
|
||||
for (var key in mData.keys) {
|
||||
List<int>? bytes = mData[key];
|
||||
if (bytes != null && bytes.length == 6) {
|
||||
// 假设这 6 个字节就是 MAC
|
||||
return bytes
|
||||
.map((b) => b.toRadixString(16).padLeft(2, '0'))
|
||||
.join('')
|
||||
.toUpperCase();
|
||||
}
|
||||
}
|
||||
return result.device.remoteId.str.toUpperCase();
|
||||
}
|
||||
|
||||
void removeOldDevices() {
|
||||
final now = DateTime.now();
|
||||
final currentDevices = mhtDeviceUpgradeController.model.blueRawData! ?? [];
|
||||
|
||||
// 移除30秒内未出现的设备
|
||||
final updatedDevices = currentDevices.where((device) {
|
||||
return now.difference(device.lastSeen) < Duration(seconds: 30);
|
||||
}).toList();
|
||||
|
||||
if (updatedDevices.length != currentDevices.length) {
|
||||
mhtDeviceUpgradeController.model.blueRawData = updatedDevices;
|
||||
mhtDeviceUpgradeController.updateAll();
|
||||
}
|
||||
}
|
||||
|
||||
showBluetoothNotEnabledDialog(BuildContext context) async {
|
||||
await showTipDialog(
|
||||
backgroundColor: Colors.white,
|
||||
context,
|
||||
Column(
|
||||
children: [
|
||||
Text(
|
||||
"蓝牙未开启".tr,
|
||||
style: TextStyle(
|
||||
fontSize: AppConstants().title_text_fontSize,
|
||||
color: stringToColor("#333333"),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 20.rpx,
|
||||
),
|
||||
Text(
|
||||
"请先打开蓝牙在进行设备扫描".tr,
|
||||
style: TextStyle(
|
||||
fontSize: AppConstants().normal_text_fontSize,
|
||||
color: stringToColor("#333333"),
|
||||
),
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
List<BlueToothDataModel> filterDeviceType(List<BlueToothDataModel> devices) {
|
||||
final selectedIds = mhtDeviceUpgradeController.selectedDiseaseIds;
|
||||
|
||||
// 如果未选择或包含“全部”,直接返回全部设备
|
||||
if (selectedIds!.isEmpty ||
|
||||
selectedIds.contains(APPDeviceUpgrade.ALL.value)) {
|
||||
return devices;
|
||||
}
|
||||
|
||||
// 否则按类型过滤
|
||||
return devices
|
||||
.where((device) => selectedIds.contains(device.upgradeStatus))
|
||||
.toList();
|
||||
}
|
||||
Reference in New Issue
Block a user