Files
tuiche/lib/pages/mh_page/test/WebviewTestModel.dart
2026-02-05 15:25:20 +08:00

788 lines
28 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:EasyDartModule/EasyDartModule.dart' as edm;
import 'package:easydevice/easydevice.dart';
import 'package:easyweb/base/easyws.dart';
import 'package:easyweb/base/minisdk.dart';
import 'package:easyweb/easyweb.dart';
import 'package:ef/ef.dart';
import 'package:flutter/material.dart';
import 'package:vbvs_app/common/color/ServiceConstant.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/MyUtils.dart';
import 'package:vbvs_app/common/util/base64Tool.dart';
import 'package:vbvs_app/common/util/requestWithLog.dart';
import 'package:vbvs_app/controller/user_info_controller.dart';
import 'package:vbvs_app/model/WebSocketMessage.dart';
import 'package:vbvs_app/pages/main_bottom/component/main_page_b_bottom_change.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/homepage/component/HomeDeviceStausWidget.dart';
import 'package:vbvs_app/pages/mh_page/homepage/controller/mht_home_controller.dart';
class WebviewTestModel {
WebviewTestModel();
//EasyFlutter Start[Model]
//EasyFlutter End
}
class WebviewTestController extends GetControllerEx<WebviewTestModel> {
var selectDevice = {};
var lastSelectDevice = {};
var bluetooth = 0;
List personList = [];
List instantData = [];
RxBool initFlag = false.obs;
Timer? _resourceLoadTimer;
Widget webviewWidget = Container();
var wifiResponseData;
WebviewTestController() : super(WebviewTestModel()) {
web = WebviewHelper(
isheadless: false,
jsbridge: buildsdk(
father: this,
// clientId: '494641114',
// clientId: '123',
// dbgserverUrl: 'ws://192.168.1.2:9001',
),
settings: buildsettings(),
params: PlatformHeadlessInAppWebViewCreationParams(
onLoadStop: (controller, url) {
setState(() {
ready.value = true;
});
},
onLoadResource: (controller, resource) {
// sourceTime = web.requestTimestamp;
// ef.log("[请求资源时间]${web.requestTimestamp}");
// _startMonitoringIfNeeded();
},
),
);
try {
web.jsbridge!.bind((bridge) {
var minible = Minibleapp(
bridge: bridge,
onConnect: (args1, args2) {
final devices = args1.devices as Map<String, dynamic>;
final mac = args2 as String;
if (devices.containsKey(mac)) {
final device = devices[mac];
ef.log('Minibleapp connected(Android): $mac -> $device');
return device;
}
// iOS: 遍历所有设备,解析 manufacturerData 拿真实 deviceId(mac)
for (final entry in devices.entries) {
final manufacturerData = entry.value.manufacturerData;
String? deviceId;
if (manufacturerData != null) {
manufacturerData.forEach((key, data) {
if (data.isEmpty) return;
if (key == 65517) {
List<int> a = [0, 0, ...data];
final d = {};
advertisDataFormatter(a, d);
if (d['adData']?['deviceId'] != null) {
deviceId = d['adData']['deviceId'];
}
} else if (key == 11125 && data.length == 8) {
deviceId = ab2str(data.sublist(2, 8)).toUpperCase();
} else if (data.length == 8 &&
isQuanShiDevice(entry.value.name)) {
deviceId = ab2str(data.sublist(2, 8)).toUpperCase();
} else if ((data.length == 4 || data.length == 6) &&
isMHTSWES(entry.value.name)) {
List<int> a;
if (data.length == 4) {
ByteData bd = ByteData(2);
bd.setUint16(0, key, Endian.little);
a = [bd.getUint8(0), bd.getUint8(1), ...data];
} else {
a = [...data];
}
deviceId = ab2str(a).toUpperCase();
}
});
}
final normalizedMac = mac.replaceAll(":", "").toUpperCase();
if (deviceId != null &&
deviceId!.toUpperCase() == normalizedMac) {
return entry.value; // 返回匹配的设备
}
}
ef.log('Minibleapp connected: $mac not found in devices');
return null;
},
);
// ef.kvroot.devicelist.listen((x) {});
bridge.sdk.updateDeviceRoute((args) async {
ef.log('updateDeviceRoute: $args');
selectDevice['blueToothStatus'] = bluetooth;
Get.toNamed("${args[0]}", arguments: selectDevice);
return true;
});
bridge.sdk.selectDevice((args) async {
try {
ef.log('selectDevice: $args');
selectDevice = args[0];
await queryPersonInfoByMac();
if (selectDevice != null &&
selectDevice.isNotEmpty &&
selectDevice['mac'.tr] != null &&
(selectDevice['mac'.tr] != args[0]['mac'.tr])) {
lastSelectDevice = selectDevice;
}
edm.EasyDartModule.websocket.sendData(jsonEncode(
WebSocketMessage(path: "/smartbed/connect", type: 5, data: {
'mac'.tr: selectDevice['mac'.tr],
})));
dealInstantData(selectDevice);
dealDeviceData(selectDevice);
} catch (e) {
ef.log("[切换设备失败]$e");
}
//查询人员信息
return true;
});
bridge.sdk.updateBlueToothStatus((args) async {
ef.log('updateBlueToothStatus: $args');
bluetooth = args[0];
selectDevice['blueToothStatus'] = bluetooth;
return true;
});
//sdk定义接口
bridge.sdk.querySelectDevice((args) async {
ef.log('querySelectDevice: $args');
// bluetooth = args[0];
MHTHomeController deviceController = Get.find();
await deviceController.getDeviceList(group: 'room');
final allDevices = deviceController.deviceList.values
.expand((list) => list)
.toList();
return allDevices;
});
//请求token信息
bridge.sdk.queryUserToken((args) async {
ef.log('queryUserToken: $args');
// bluetooth = args[0];
return edm.EasyDartModule.dio.token;
});
//请求设备人员信息
bridge.sdk.queryPersonInfo((args) async {
ef.log('queryPersonInfo: $args');
// bluetooth = args[0];
return personList;
});
//请求实时体征数据
bridge.sdk.queryInstantData((args) async {
ef.log('queryInstantData: $args');
// bluetooth = args[0];
return instantData;
});
bridge.sdk.startTimer((args) async {
ef.log('开启定时: $args');
MHTHomeController homeController = Get.find();
homeController.startTimer(args);
return true;
});
bridge.sdk.cancelTimer((args) async {
ef.log('退出定时: $args');
MHTHomeController homeController = Get.find();
homeController.cancelTimer(args);
return true;
});
bridge.sdk.restoreTimer((args) async {
ef.log('更新定时: $args[0]');
ef.log('更新定时: $args');
MHTHomeController homeController = Get.find();
var data = await homeController.restoreTimer(args);
return data;
});
bridge.sdk.toBindDevice((args) async {
ef.log('绑定设备: $args');
Get.toNamed("/mHTDeviceTypePage");
return true;
});
bridge.sdk.saveSleepHabit((args) async {
ef.log('更新睡眠习惯: $args[0]');
try {
MHTBlueToothController blueToothController = Get.find();
return await blueToothController.saveHabitData(args[0]);
} catch (e) {
ef.log("[更新睡眠习惯失败]:$e");
}
return true;
});
bridge.sdk.loadSleepHabit((args) async {
ef.log('查询睡眠习惯: $args[0]');
try {
MHTBlueToothController blueToothController = Get.find();
var sleepData = await blueToothController.loadHabitDataApi(args[0]);
return sleepData['data'];
} catch (e) {
ef.log("[查询睡眠习惯失败]:$e");
}
return true;
});
//--
bridge.sdk.saveMattressTimeData((args) async {
ef.log('更新睡眠习惯: $args[0]');
try {
MHTBlueToothController blueToothController = Get.find();
await blueToothController.saveMattressTimeData(args[0]);
} catch (e) {
ef.log("[更新睡眠习惯失败]:$e");
}
return true;
});
bridge.sdk.loadMattressTimeData((args) async {
ef.log('查询睡眠习惯: $args[0]');
try {
MHTBlueToothController blueToothController = Get.find();
var sleepData =
await blueToothController.loadMattressTimeData(args[0]);
return sleepData['data'];
} catch (e) {
ef.log("[查询睡眠习惯失败]:$e");
}
return true;
});
bridge.sdk.saveMemory((args) async {
ef.log('更新记忆: $args[0]');
try {
MHTBlueToothController blueToothController = Get.find();
// await blueToothController.saveHabitData(args[0]);
await blueToothController.saveJiYiData(args[0]);
} catch (e) {
ef.log("[更新记忆失败]:$e");
}
return true;
});
bridge.sdk.loadMemory((args) async {
try {
ef.log('查询记忆: $args[0]');
MHTBlueToothController blueToothController = Get.find();
var sleepData = await blueToothController.loadJiYiData(args[0]);
return sleepData['data'];
} catch (e) {
ef.log("[查询记忆失败]:$e");
}
return true;
});
bridge.sdk.webPageBuild((args) async {
ef.log('网页加载完成: $args[0]');
try {
initFlag.value = true;
return true;
} catch (e) {
ef.log("[网页加载失败]:$e");
}
return true;
});
bridge.sdk.updatePermisson((args) async {
// ef.log('获取权限: $args[0]');
try {
if (MainPageBBottomChange.getCurrentIndex() != 2) {
return false;
}
Map data = await checkBlueToothPermissin();
if (data == null || data.isEmpty) {
return false;
}
if (Platform.isIOS) {
if (!data['bluetoothScanGranted'] ||
!data['bluetoothConnectGranted']) {
return false;
}
} else if (Platform.isAndroid) {
if (!data['bluetoothScanGranted'] ||
!data['bluetoothConnectGranted'] ||
!data['locationGranted']) {
return false;
}
} else {
return false;
}
return true;
} catch (e) {
ef.log("[网页加载失败]:$e");
}
return true;
});
// bridge.sdk.bluetoothConnect((args) async {
// ef.log('[蓝牙连接失败]: $args[0]');
// try {
// selectDevice['blueToothStatus'] = 2;
// return true;
// } catch (e) {
// ef.log("[蓝牙连接失败]:$e");
// }
// return true;
// });
bridge.sdk.loadFinish((args) async {
ef.log('[资源加载完成]: $args[0]');
try {
loadRecource.value = true;
updateAll();
return true;
} catch (e) {
ef.log("[资源加载完成]:$e");
}
return true;
});
bridge.sdk.sendCommand((args) async {
ef.log('wifi控制指令: $args[0]');
try {
MHTBlueToothController blueToothController = Get.find();
// await blueToothController.saveHabitData(args[0]);
await blueToothController.sendCommand(args[0]);
} catch (e) {
ef.log("[wifi控制下发指令失败]:$e");
}
return true;
});
});
} catch (e, s) {
ef.log('$e,$s');
}
}
late WebviewHelper web;
var ready = false.obs;
var cnt = 0.obs;
var loadRecource = false.obs;
int sourceTime = 0;
Future<void> queryPersonInfoByMac() async {
UserInfoController userInfoController = Get.find();
String serviceAddress = ServiceConstant.service_address;
String serviceName = ServiceConstant.server_service;
String serviceApi = ServiceConstant.person_info;
String queryUrl =
"${serviceAddress}${serviceName}${serviceApi}?mac=${selectDevice['mac']}";
try {
final res = await requestWithLog(
logTitle: "查询设备绑定人员列表".tr,
method: MyHttpMethod.get,
queryUrl: queryUrl,
onSuccess: (res) {
personList = res.data;
});
} catch (e) {
print("查询设备绑定列表失败: $e");
}
}
void dealInstantData(selectDevice) {
//处理实时数据
// edm.EasyDartModule.websocket.sendData(
// jsonEncode(WebSocketMessage(path: "/vsbs/web/rt/marttress", type: 2)));
lastSelectDevice;
var ws;
ws = Easyws(
url: ServiceConstant.webSocketService,
onData: (data) {
// ef.log("ws recv =>$data");
try {
var tmp;
if (data is String) {
tmp = jsonDecode(data);
} else if (data is Map<String, dynamic>) {
tmp = data; // 直接用
} else {
print("未知数据格式".tr);
}
if (tmp['data'] != null && tmp['data'] is Map) {
var newData = tmp['data'];
var mac = newData['mac'.tr];
if (mac != null) {
// 删除已有的同 mac 项
instantData.removeWhere((element) => element['mac'.tr] == mac);
// 添加新的数据
instantData.add(newData);
}
}
} catch (e) {
ef.log("ws error =>$e");
}
},
onStateChange: (x) {
ef.log("ws =>$x");
if (x == EasywsState.connected) {
try {
if (lastSelectDevice != null && lastSelectDevice.isNotEmpty) {
List<String?> oldMacList = [
lastSelectDevice['bind_mac_a'],
lastSelectDevice['bind_mac_b'],
];
for (String? mac in oldMacList) {
if (mac != null && mac.isNotEmpty) {
bool success = ws.send({
"type": 2,
"path": "/vsbs/web/rt/marttress",
"data": {"mac".tr: mac},
});
if (success) {
// ef.log("✅ 已取消监听:$mac");
}
}
}
}
} catch (e) {
ef.log("❌ 取消旧设备监听失败: $e");
}
try {
// 2. 开始监听新设备A/B 都监听)
if (selectDevice != null && selectDevice.isNotEmpty) {
List<String?> newMacList = [
selectDevice['bind_mac_a'],
selectDevice['bind_mac_b'],
];
for (String? mac in newMacList) {
if (mac != null && mac.isNotEmpty) {
bool success = ws.send({
"type": 1,
"path": "/vsbs/web/rt/marttress",
"data": {"mac".tr: mac},
});
if (success) {
// ef.log("✅ 开始监听新设备:$mac");
}
}
}
// 更新记录
lastSelectDevice = selectDevice;
}
} catch (e) {
ef.log("❌ 监听新设备失败: $e");
}
}
},
);
ws.connect();
}
void dealDeviceData(selectDevice) {
// 处理设备本身的数据
var ws;
ws = Easyws(
url: ServiceConstant.webSocketService,
onData: (data) {
try {
var tmp;
if (data is String) {
tmp = jsonDecode(data);
} else if (data is Map<String, dynamic>) {
tmp = data; // 直接用
} else {
print("未知数据格式".tr);
return;
}
if (tmp['data'] != null && tmp['data'] is Map) {
var newData = tmp['data'];
var mac = newData['mac'];
String order = Base64Tool.decode(newData['data']);
final webviewTestController = Get.find<WebviewTestController>();
webviewTestController.web.jsbridge?.dart
?.updateDeviceStatusByWifi(order);
}
} catch (e) {
ef.log("ws error =>$e");
}
},
onStateChange: (x) {
ef.log("ws状态变化 =>$x");
if (x == EasywsState.connected) {
try {
// 1. 先取消可能存在的旧设备监听
if (lastSelectDevice != null && lastSelectDevice.isNotEmpty) {
String? oldMac = lastSelectDevice['mac'];
if (oldMac != null &&
oldMac.isNotEmpty &&
oldMac != selectDevice['mac']) {
bool success = ws.send({
"type": 2, // 取消监听
"path": "/vsbs/web/rt/marttress", // 注意:可能需要不同的路径
"data": {"mac": oldMac},
});
if (success) {
ef.log("✅ 已取消监听旧设备:$oldMac");
}
}
}
} catch (e) {
ef.log("❌ 取消旧设备监听失败: $e");
}
try {
// 2. 开始监听新设备
if (selectDevice != null && selectDevice.isNotEmpty) {
String? newMac = selectDevice['mac'];
if (newMac != null && newMac.isNotEmpty) {
bool success = ws.send({
"type": 1, // 开始监听
"path": "/vsbs/web/rt/marttress", // 设备数据的路径,可能需要确认
"data": {"mac": newMac},
});
if (success) {
ef.log("✅ 开始监听设备:$newMac");
// 更新记录
lastSelectDevice = selectDevice;
}
}
}
} catch (e) {
ef.log("❌ 监听新设备失败: $e");
}
}
},
);
ws.connect();
}
@override
void onInit() {
ef.log("webview test init =>${DateTime.now()}");
super.onInit();
try {
web.runApp('mhtControl').then((x) {
ready.value = true;
});
// web
// .network('https://wyf.it.real.he-info.cn:94/goods-front/index.html')
// .then((x) {
// ready.value = true;
// });
} catch (e, s) {
ef.log('$e,$s');
}
}
}
class WebviewTestView extends GetComponent<WebviewTestController> {
WebviewTestView({super.key, super.oncreate});
@override
WebviewTestController newinstance() {
if (ef.kvRoot.WebviewTestController == null) {
ef.kvRoot.WebviewTestController = WebviewTestController();
if (Get.isRegistered<WebviewTestController>() == false) {
Get.put<WebviewTestController>(ef.kvRoot.WebviewTestController);
WebviewTestController webviewTestController = Get.find();
webviewTestController.global = true;
return webviewTestController;
}
}
return ef.kvRoot.WebviewTestController;
}
@override
Widget build(BuildContext context) {
// controller.webviewWidget = controller.web.build();
return Obx(() {
UserInfoController userInfoController = Get.find();
MHTHomeController deviceController = Get.find();
final isLoggedIn = userInfoController.model.login == 1;
final hasDevice = deviceController.deviceList.values.isNotEmpty;
final showWeb = isLoggedIn && hasDevice;
final mainAxisAlignment =
showWeb ? MainAxisAlignment.start : MainAxisAlignment.center;
return Scaffold(
backgroundColor: Colors.transparent,
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: mainAxisAlignment,
children: [
// 未登录提示
if (!isLoggedIn)
Center(
child: InkWell(
onTap: () => Get.toNamed("/loginPage"),
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: "请先".tr,
style: TextStyle(
color: Colors.white,
fontSize: 30.rpx,
),
),
WidgetSpan(
child: Stack(
children: [
Text(
"登录".tr,
style: TextStyle(
color: stringToColor("#84F5FF"),
fontSize: 30.rpx,
),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 1,
color: stringToColor("#84F5FF"),
),
),
],
),
),
TextSpan(
text: "后,再进行设备控制".tr,
style: TextStyle(
color: Colors.white,
fontSize: 30.rpx,
),
),
],
),
),
),
),
// 已登录但无设备提示
if (isLoggedIn && !hasDevice)
Center(
child: InkWell(
onTap: () => Get.toNamed("/mHTDeviceTypePage"),
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: "请先".tr,
style: TextStyle(
color: Colors.white,
fontSize: 30.rpx,
),
),
WidgetSpan(
child: Stack(
children: [
Text(
"绑定设备".tr,
style: TextStyle(
color: stringToColor("#84F5FF"),
fontSize: 30.rpx,
),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 1,
color: stringToColor("#84F5FF"),
),
),
],
),
),
TextSpan(
text: "后,再进行设备控制".tr,
style: TextStyle(
color: Colors.white,
fontSize: 30.rpx,
),
),
],
),
),
),
),
// 显示 WebView
if (showWeb)
Expanded(
child: Align(
alignment: Alignment.topLeft,
child: Obx(() {
// return (controller.ready.value && (MainPageBBottomChange.getCurrentIndex() == 2))
// return (controller.ready.value && (MainPageBBottomChange.getCurrentIndex() == 2)&& controller.loadRecource.value == true)
// return Stack(children: [
// controller.ready.value
// ? controller.web.build()
// : Container(),
// Text("1222121212"),
// ]);
// return Stack(
// children: [
// controller.ready.value
// ? controller.web.build()
// : Container(),
// // 只有 loadRecource == false 时才显示覆盖文字
// if (!controller.loadRecource.value)
// Positioned.fill(
// child: Container(
// color: Colors.black54, // 半透明遮罩,可选
// alignment: Alignment.center,
// child: Text(
// "资源加载中...",
// style: TextStyle(
// color: Colors.red,
// fontSize: 30.rpx,
// fontWeight: FontWeight.bold,
// ),
// ),
// ),
// ),
// ],
// );
return Stack(
children: [
controller.ready.value
? controller.web.build()
: Container(),
if (!controller.loadRecource.value)
Positioned.fill(
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
'assets/images/new_background.png'),
fit: BoxFit.fill,
),
),
alignment: Alignment.center,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
Colors.white),
),
],
),
),
),
],
);
}),
),
),
],
),
);
});
}
}