更新控制跳转

This commit is contained in:
wyf
2025-07-02 14:33:08 +08:00
parent a4aa105a3a
commit 58b2bebe93
9 changed files with 131 additions and 75 deletions

View File

@@ -138,7 +138,7 @@ class _HomePageState extends State<MainPageBBottomChange>
Future<void> dealWebSource(int index) async { Future<void> dealWebSource(int index) async {
WebviewTestController webviewTestController = Get.find(); WebviewTestController webviewTestController = Get.find();
if (index == 2) { if (index == 2) {
await webviewTestController.web.jsbridge?.dart.pageActive(); await webviewTestController.web.jsbridge?.dart.pageActive(true);
} else { } else {
await webviewTestController.web.jsbridge?.dart.pageInActive(); await webviewTestController.web.jsbridge?.dart.pageInActive();
} }

View File

@@ -25,10 +25,12 @@ import 'package:vbvs_app/pages/mh_page/test/WebviewTestModel.dart';
class DeviceComponentWidget extends StatefulWidget { class DeviceComponentWidget extends StatefulWidget {
BlueToothDataModel bleDevice; BlueToothDataModel bleDevice;
var deviceType;
DeviceComponentWidget({ DeviceComponentWidget({
super.key, super.key,
required this.bleDevice, required this.bleDevice,
required this.deviceType,
}); });
@override @override
@@ -212,8 +214,8 @@ class _DeviceComponentWidgetState extends State<DeviceComponentWidget> {
blueteethBindController.currentDeviceMac.value = blueteethBindController.currentDeviceMac.value =
widget.bleDevice.mac; widget.bleDevice.mac;
blueteethBindController.updateAll(); blueteethBindController.updateAll();
String mac = String mac = await getBindTHMAC(
await getBindTHMAC(context, widget.bleDevice); context, widget.bleDevice, widget.deviceType);
if (mac != null && mac.isNotEmpty) { if (mac != null && mac.isNotEmpty) {
bool flag = bool flag =
await fillTHMac(mac, widget.bleDevice, context); await fillTHMac(mac, widget.bleDevice, context);
@@ -481,19 +483,17 @@ class _DeviceComponentWidgetState extends State<DeviceComponentWidget> {
); );
} }
//获取传感器mac //获取智能床/床垫mac
Future<String> getBindTHMAC( Future<String> getBindTHMAC(
BuildContext context, BlueToothDataModel device) async { BuildContext context, BlueToothDataModel device, Map deviceType) async {
const int maxRetries = 2; const int maxRetries = 2;
const Duration timeout = Duration(seconds: 5); const Duration timeout = Duration(seconds: 5);
String? macAddress; String? macAddress;
try { try {
// 连接设备 // 连接设备
THapp bledevice = THapp(device: device.scanResult.device); THapp bledevice = THapp(device: device.scanResult.device);
await bledevice.connect(); await bledevice.connect();
var res2 = bledevice.isConnected; var res2 = bledevice.isConnected;
if (!res2) { if (!res2) {
edm.EasyDartModule.logger.error("蓝牙连接失败"); edm.EasyDartModule.logger.error("蓝牙连接失败");
DailyLogUtils.printLog("蓝牙连接失败"); DailyLogUtils.printLog("蓝牙连接失败");
@@ -504,58 +504,18 @@ class _DeviceComponentWidgetState extends State<DeviceComponentWidget> {
); );
throw Exception("蓝牙连接失败"); throw Exception("蓝牙连接失败");
} }
blueteethBindController.blueConnectFlag.value = 2; blueteethBindController.blueConnectFlag.value = 2;
blueteethBindController.currentDevice = bledevice; blueteethBindController.currentDevice = bledevice;
await Future.delayed(Duration(seconds: 2)); await Future.delayed(Duration(seconds: 2));
var read = bledevice.getresource('fff0/fff1');
await read!.characteristic.setNotifyValue(true);
var write = bledevice.getresource('fff0/fff2');
for (int attempt = 0; attempt < maxRetries; attempt++) { if (deviceType['type'] == 3) {
var completer = Completer<String>(); //智能床垫
macAddress = await getMacFromType3(bledevice, timeout);
StreamSubscription? subscription; } else if (deviceType['type'] == 2) {
subscription = read.characteristic.onValueReceived.listen((onData) { //智能床
if (onData.length >= 14) { macAddress = await getMacFromType2(bledevice, timeout);
// 按照你提供的协议,返回数据长度至少 17字节这里保险起见 14起步 } else {
String parsedMac = parseMacFromBleResponse(onData); throw Exception("不支持的设备类型");
completer.complete(parsedMac);
}
});
// 发送查询命令
var order = [
0xFF,
0xFF,
0xFF,
0xFF,
0x00,
0x03,
0x40,
0x01,
0x01,
0x00,
0x45,
0xFD
];
await write!.characteristic.write(order);
try {
macAddress = await completer.future.timeout(timeout);
await subscription.cancel();
break; // 成功拿到,跳出重试
} catch (e) {
await subscription.cancel();
if (attempt == maxRetries - 1) {
TopSlideNotification.show(
context,
text: "获取MAC地址超时请重试".tr,
textColor: themeController.currentColor.sc9,
);
throw Exception("获取MAC地址失败");
}
}
} }
if (macAddress == null) { if (macAddress == null) {
@@ -629,6 +589,87 @@ class _DeviceComponentWidgetState extends State<DeviceComponentWidget> {
); );
return flag; return flag;
} }
Future<String> getMacFromType3(THapp bledevice, Duration timeout) async {
final read = bledevice.getresource('fff0/fff1');
await read!.characteristic.setNotifyValue(true);
final write = bledevice.getresource('fff0/fff2');
const int maxRetries = 2;
for (int attempt = 0; attempt < maxRetries; attempt++) {
final completer = Completer<String>();
final subscription = read.characteristic.onValueReceived.listen((data) {
if (data.length >= 14) {
completer.complete(parseMacFromBleResponse(data));
}
});
final order = [
0xFF,
0xFF,
0xFF,
0xFF,
0x00,
0x03,
0x40,
0x01,
0x01,
0x00,
0x45,
0xFD
];
await write!.characteristic.write(order);
try {
final mac = await completer.future.timeout(timeout);
await subscription.cancel();
return mac;
} catch (_) {
await subscription.cancel();
if (attempt == maxRetries - 1) rethrow;
}
}
throw Exception("获取MAC超时");
}
Future<String> getMacFromType2(THapp bledevice, Duration timeout) async {
try {
final read = bledevice.getresource('ffe0/ffe1');
await read!.characteristic.setNotifyValue(true);
final write =
bledevice.getresource('ffe0/ffe1'); // 与 read 同 characteristic
const int maxRetries = 2;
for (int attempt = 0; attempt < maxRetries; attempt++) {
final completer = Completer<String>();
final subscription = read.characteristic.onValueReceived.listen((data) {
if (data.length >= 17) {
completer.complete(parseMacFromTH2Response(data));
}
});
final order = [0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x0C, 0x0B, 0x0A];
int checksum = order.reduce((a, b) => a + b) & 0xFFFF;
order.add(checksum & 0xFF); // 低位
order.add((checksum >> 8) & 0xFF); // 高位
await write!.characteristic.write(order);
try {
final mac = await completer.future.timeout(timeout);
await subscription.cancel();
return mac;
} catch (_) {
await subscription.cancel();
if (attempt == maxRetries - 1) rethrow;
}
}
} catch (e) {
ef.log("[获取设备 MAC]:失败:$e");
}
throw Exception("获取MAC超时");
}
} }
String parseMacFromBleResponse(List<int> data) { String parseMacFromBleResponse(List<int> data) {
@@ -650,3 +691,21 @@ String parseMacFromBleResponse(List<int> data) {
throw Exception("BLE返回数据格式不正确"); throw Exception("BLE返回数据格式不正确");
} }
} }
String parseMacFromTH2Response(List<int> data) {
if (data.length < 17) {
throw Exception("数据长度不足无法解析MAC");
}
int status = data[8];
if (status != 0x03 && status != 0x04) {
throw Exception("未连接心率带");
}
// 提取9~14字节的MAC地址
List<int> macBytes = data.sublist(9, 15);
return macBytes
.map((b) => b.toRadixString(16).padLeft(2, '0'))
.join(":")
.toUpperCase();
}

View File

@@ -215,7 +215,7 @@ class DeviceInfoWidget extends GetView {
}); });
await future; await future;
await webviewTestController.web.jsbridge?.dart await webviewTestController.web.jsbridge?.dart
.pageActive(); .pageActive(false);
MainPageBBottomChange.jumpTo(2); MainPageBBottomChange.jumpTo(2);
Get.until((route) => Get.until((route) =>
Get.currentRoute == Get.currentRoute ==

View File

@@ -124,7 +124,7 @@ class _MHTBindDeviceTypePageState extends State<MHTBindDeviceTypePage> {
bottom: 26.rpx), // 添加每个设备之间的间隔 bottom: 26.rpx), // 添加每个设备之间的间隔
child: _buildDeviceCard( child: _buildDeviceCard(
context, context,
title: device['name'], // 这里假设 device 是一个 Map title: device['name'],
imageUrl: device['image'], imageUrl: device['image'],
type: device['type'], type: device['type'],
desc: device['desc'] ?? [], desc: device['desc'] ?? [],

View File

@@ -19,8 +19,8 @@ import 'package:vbvs_app/pages/mh_page/device/controller/mht_bluetooth_controlle
import 'package:vbvs_app/pages/mh_page/device/model/BlueToothDataModel.dart'; import 'package:vbvs_app/pages/mh_page/device/model/BlueToothDataModel.dart';
class MHTBlueteethDevicePage extends StatefulWidget { class MHTBlueteethDevicePage extends StatefulWidget {
var data; var deviceType;
MHTBlueteethDevicePage({super.key, required this.data}); MHTBlueteethDevicePage({super.key, required this.deviceType});
@override @override
State<MHTBlueteethDevicePage> createState() => _MHTBlueteethDevicePageState(); State<MHTBlueteethDevicePage> createState() => _MHTBlueteethDevicePageState();
@@ -146,10 +146,8 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
final filteredResults = results.where((r) { final filteredResults = results.where((r) {
final localName = r.advertisementData.localName; final localName = r.advertisementData.localName;
final isTarget = r.rssi > signalThreshold && final isTarget = r.rssi > signalThreshold &&
isTargetDevice(localName, widget.data['reg'].cast<String>()); isTargetDevice(localName, widget.deviceType['reg'].cast<String>());
if (!isTarget) return false; if (!isTarget) return false;
final name = r.advertisementData.advName.toLowerCase(); final name = r.advertisementData.advName.toLowerCase();
String macAddress = r.device.remoteId.str; String macAddress = r.device.remoteId.str;
final mac = macAddress.replaceAll(':', ''); final mac = macAddress.replaceAll(':', '');
@@ -164,7 +162,7 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
return true; return true;
}).map((r) { }).map((r) {
return BlueToothDataModel.fromScanResult( return BlueToothDataModel.fromScanResult(
r, widget.data['type']?.toInt(), r, widget.deviceType['type']?.toInt(),
bind: false, bind: false,
name: r.advertisementData.localName, name: r.advertisementData.localName,
mac: r.device.remoteId.str.replaceAll(':', '')); mac: r.device.remoteId.str.replaceAll(':', ''));
@@ -638,6 +636,7 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
.map((device) { .map((device) {
return DeviceComponentWidget( return DeviceComponentWidget(
bleDevice: device, bleDevice: device,
deviceType: widget.deviceType,
); );
}) })
.toList() .toList()

View File

@@ -379,7 +379,8 @@ class _MHTPeopleInfoPageState extends State<MHTPeopleInfoPage> {
decoration: BoxDecoration(), decoration: BoxDecoration(),
child: InkWell( child: InkWell(
onTap: () { onTap: () {
FocusScope.of(context).unfocus(); FocusScope.of(context)
.requestFocus(FocusNode());
Future.delayed( Future.delayed(
const Duration(milliseconds: 250), const Duration(milliseconds: 250),
() { () {
@@ -444,13 +445,14 @@ class _MHTPeopleInfoPageState extends State<MHTPeopleInfoPage> {
decoration: BoxDecoration(), decoration: BoxDecoration(),
child: InkWell( child: InkWell(
onTap: () { onTap: () {
FocusScope.of(context).unfocus(); FocusScope.of(context)
.requestFocus(FocusNode());
Future.delayed( Future.delayed(
const Duration(milliseconds: 250), const Duration(milliseconds: 250),
() { () {
showWeightPickerDialog( showWeightPickerDialog(
context, context,
initialWeight: "0", initialWeight: "50",
onConfirm: (int selectedWeight) { onConfirm: (int selectedWeight) {
setState(() { setState(() {
peopleList[index]['weight'] = peopleList[index]['weight'] =

View File

@@ -86,7 +86,7 @@ class _HomeDeviceStausWidgetState extends State<HomeDeviceStausWidget> {
}); });
await future; await future;
await webviewTestController.web.jsbridge?.dart await webviewTestController.web.jsbridge?.dart
.pageActive(); .pageActive(false);
MainPageBBottomChange.jumpTo(2); MainPageBBottomChange.jumpTo(2);
} catch (e) { } catch (e) {
DailyLogUtils.writeError("发生异常: $e"); DailyLogUtils.writeError("发生异常: $e");

View File

@@ -90,6 +90,7 @@ class WebviewTestController extends GetControllerEx<WebviewTestModel> {
ef.log('updateBlueToothStatus: $args'); ef.log('updateBlueToothStatus: $args');
// bluetooth = args[0]; // bluetooth = args[0];
MHTHomeController deviceController = Get.find(); MHTHomeController deviceController = Get.find();
await deviceController.getDeviceList(group: 'room');
final allDevices = deviceController.deviceList.values final allDevices = deviceController.deviceList.values
.expand((list) => list) .expand((list) => list)
.toList(); .toList();
@@ -113,11 +114,6 @@ class WebviewTestController extends GetControllerEx<WebviewTestModel> {
// bluetooth = args[0]; // bluetooth = args[0];
return instantData; return instantData;
}); });
bridge.sdk.queryInstantData((args) async {
ef.log('queryInstantData: $args');
// bluetooth = args[0];
return instantData;
});
bridge.sdk.startTimer((args) async { bridge.sdk.startTimer((args) async {
ef.log('queryInstantData: $args'); ef.log('queryInstantData: $args');
MHTHomeController homeController = Get.find(); MHTHomeController homeController = Get.find();

View File

@@ -94,7 +94,7 @@ var mhroutes = {
"/deviceListPage": (context) => DeviceListPage(), "/deviceListPage": (context) => DeviceListPage(),
"/mHTDeviceTypePage": (context, {arguments}) => MHTBindDeviceTypePage(), "/mHTDeviceTypePage": (context, {arguments}) => MHTBindDeviceTypePage(),
"/mHTBlueteethDevicePage": (context, {arguments}) => "/mHTBlueteethDevicePage": (context, {arguments}) =>
MHTBlueteethDevicePage(data: arguments), MHTBlueteethDevicePage(deviceType: arguments),
"/mHTwifiPage": (contxt, {arguments}) => MHTWifiPage(deviceInfo: arguments), "/mHTwifiPage": (contxt, {arguments}) => MHTWifiPage(deviceInfo: arguments),
"/calibrationPage": (contxt) => MHTCalibrationPage(), "/calibrationPage": (contxt) => MHTCalibrationPage(),
"/bindDeviceSuccess": (contxt) => MHTBindDeviceSuccess(), "/bindDeviceSuccess": (contxt) => MHTBindDeviceSuccess(),