diff --git a/assets/file.json b/assets/file.json index 0930d34..9ba0083 100644 --- a/assets/file.json +++ b/assets/file.json @@ -1,3 +1,3 @@ [ - "assets/miniapp/mhtControl_1.0.28.zip" + "assets/miniapp/mhtControl_1.0.30.zip" ] \ No newline at end of file diff --git a/assets/mhlangs/zh_CN.json b/assets/mhlangs/zh_CN.json index 13fa1a0..7d6841a 100644 --- a/assets/mhlangs/zh_CN.json +++ b/assets/mhlangs/zh_CN.json @@ -213,5 +213,6 @@ "每日得分": "每日得分", "每日得分介绍": "每日得分介绍", "与上月对比": "与上月对比", - "设备状态":"设备状态" + "设备状态":"设备状态", + "校准未完成提示":"校准还未完成,是否确认退出校准流程?" } \ No newline at end of file diff --git a/assets/miniapp/mhtControl_1.0.0.zip b/assets/miniapp/mhtControl_1.0.0.zip deleted file mode 100644 index 1ad0088..0000000 Binary files a/assets/miniapp/mhtControl_1.0.0.zip and /dev/null differ diff --git a/assets/miniapp/mhtControl_1.0.28.zip b/assets/miniapp/mhtControl_1.0.30.zip similarity index 96% rename from assets/miniapp/mhtControl_1.0.28.zip rename to assets/miniapp/mhtControl_1.0.30.zip index d62ed6d..674e0d9 100644 Binary files a/assets/miniapp/mhtControl_1.0.28.zip and b/assets/miniapp/mhtControl_1.0.30.zip differ diff --git a/lib/pages/mh_page/bluetooth.dart b/lib/pages/mh_page/bluetooth.dart index 5966406..1a720e4 100644 --- a/lib/pages/mh_page/bluetooth.dart +++ b/lib/pages/mh_page/bluetooth.dart @@ -236,11 +236,11 @@ class _BluetoothPageState extends State { }); } }), - _buildMenuButton(context, '设备校准', ""), + _buildMenuButton(context, '设备校准', "/mhtCalibrationAfterPage", arguments: obsData,), _buildMenuButton( context, '体征传感器', "/vitalSignsSensorPage", arguments: obsData), - _buildMenuButton(context, 'WIFI配置', ""), + _buildMenuButton(context, 'WIFI配置', "/mhtWifiAfterPage",arguments: obsData,), // _buildMenuButton( // context, '睡眠习惯', "/sleepHabitPage"), _buildMenuButton( diff --git a/lib/pages/mh_page/device/mht_device_calibration_after.dart b/lib/pages/mh_page/device/mht_device_calibration_after.dart new file mode 100644 index 0000000..ad5c42c --- /dev/null +++ b/lib/pages/mh_page/device/mht_device_calibration_after.dart @@ -0,0 +1,1016 @@ +import 'dart:async'; + +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/color/ServiceConstant.dart'; +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/common/util/requestWithLog.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; +import 'package:vbvs_app/component/tool/CustomCard.dart'; +import 'package:vbvs_app/component/tool/TopSlideNotification.dart'; +import 'package:vbvs_app/pages/device_bind/componnet/CalibrationProgressWidget.dart'; +import 'package:vbvs_app/pages/mh_page/component/mht_bind_dialog.dart'; +import 'package:vbvs_app/pages/mh_page/device/component/mht_device_calibration_controller.dart'; +import 'package:vbvs_app/pages/mh_page/device/controller/mht_bluetooth_controller.dart'; + +class MHTCalibrationAfterPage extends StatefulWidget { + var deviceInfo; + MHTCalibrationAfterPage({super.key, required this.deviceInfo}); + + @override + State createState() => + _MHTCalibrationAfterPageState(); +} + +class _MHTCalibrationAfterPageState extends State { + final MHTDeviceCalibrationController deviceCalibrationController = Get.find(); + final MHTBlueToothController blueteethBindController = Get.find(); + final ValueNotifier progressNotifier = ValueNotifier(0.0); + final ValueNotifier failureNotifier = ValueNotifier(false); + Timer? _pollingTimer; + + bool exit = false; + final currentCalibrationStep = 0.obs; // 0:离床校准 1:A侧位置校准 2:B侧位置校准 + + @override + void initState() { + super.initState(); + _resetCalibrationState(); + + final macA = widget.deviceInfo.value['bind_mac_a']; + final macB = widget.deviceInfo.value['bind_mac_b']; + + deviceCalibrationController.bed_type.value = (macA != null && + macA.toString().isNotEmpty && + macB != null && + macB.toString().isNotEmpty) + ? 1 + : 0; + } + + @override + void dispose() { + _pollingTimer?.cancel(); + blueteethBindController.cid!.value = ""; + super.dispose(); + } + + void _resetCalibrationState() { + deviceCalibrationController.process.value = 0; + deviceCalibrationController.cd.value = 10000; + deviceCalibrationController.flag.value = 0; + deviceCalibrationController.bed_calibration.value = 0; + deviceCalibrationController.position_calibration.value = 0; + blueteethBindController.cid!.value = ""; + deviceCalibrationController.motionTips.value = 0; + deviceCalibrationController.inBedTips.value = 0; + deviceCalibrationController.statusContext.value = ""; + currentCalibrationStep.value = 0; + deviceCalibrationController.another.value = false; + deviceCalibrationController.updateAll(); + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + child: LayoutBuilder( + builder: (context, bodySize) => GestureDetector( + // onTap: () => FocusScope.of(context).unfocus(),, + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), + fit: BoxFit.fill, + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: + IconThemeData(color: themeController.currentColor.sc3), + 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: returnIconButtomAddCallback(() { + if (deviceCalibrationController.flag.value != 2) { + try { + showConfirmDialog( + context, Container(), "校准未完成提示".tr, + onConfirm: () async { + exit = true; + _resetCalibrationState(); + Get.back(); + }, onCancel: () { + exit = false; + }); + } catch (e) { + print(e); + } + } else { + exit = true; + } + if (exit) { + Get.back(); + } + }, enableBack: exit), + ), + // Positioned( + // right: 20.rpx, + // child: CustomCard( + // borderRadius: 20.rpx, + // onTap: () async { + // if (deviceCalibrationController.flag.value != 2) { + // showConfirmDialog( + // context, Container(), "校准未完成提示".tr, + // onConfirm: () async { + // // Get.offNamed("/bindDeviceSuccess"); + // Get.toNamed("/mHTPeopleInfoPage"); + // _resetCalibrationState(); + // }, onCancel: () {}); + // } else { + // // Get.offNamed("/bindDeviceSuccess"); + // Get.toNamed("/mHTPeopleInfoPage"); + // _resetCalibrationState(); + // } + // }, + // colors: AppConstants().mhtButtongradientColors, + // gradientDirection: GradientDirection.vertical, + // child: Container( + // width: 140.rpx, + // height: 60.rpx, + // alignment: Alignment.center, + // padding: EdgeInsetsDirectional.fromSTEB( + // 16.rpx, 0, 16.rpx, 0), + // child: Text( + // '下一步'.tr, + // style: TextStyle( + // fontFamily: 'Inter Tight', + // color: stringToColor("#003058"), + // letterSpacing: 0.0, + // ), + // ), + // ), + // ), + // ), + + ], + ), + ), + actions: [], + centerTitle: false, + ), + body: SafeArea( + top: true, + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 30.rpx, 0.rpx, 30.rpx, 0.rpx), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(0.rpx, 30.rpx, 0, 0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: stringToColor("#003058"), + borderRadius: BorderRadius.circular(16.rpx), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 10.rpx, 20.rpx, 34.rpx, 20.rpx), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: + themeController.currentColor.sc21, + borderRadius: 0, + padding: + EdgeInsets.symmetric(vertical: 10.rpx), + onTap: () {}, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Obx(() { + return Visibility( + maintainState: true, + maintainAnimation: true, + maintainSize: true, + visible: + deviceCalibrationController + .process.value == + 0, + child: SvgPicture.asset( + 'assets/img/icon/select_arrow.svg', + width: 17.rpx, + height: 17.rpx, + color: themeController + .currentColor.sc9, + ), + ); + }), + SizedBox(width: 8.rpx), + Text( + '离床校准'.tr, + style: TextStyle( + fontSize: 30.rpx, + letterSpacing: 0.0, + color: themeController + .currentColor.sc3, + ), + ), + ], + ), + Obx(() { + return Text( + deviceCalibrationController + .bed_calibration.value == + 0 + ? '未完成'.tr + : "已完成".tr, + style: TextStyle( + fontSize: 26.rpx, + letterSpacing: 0.0, + color: deviceCalibrationController + .bed_calibration + .value == + 0 + ? themeController + .currentColor.sc3 + : themeController + .currentColor.sc1, + ), + ); + }), + ], + ), + ), + SizedBox(height: 41.rpx), + ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: + themeController.currentColor.sc21, + borderRadius: 0, + padding: + EdgeInsets.symmetric(vertical: 10.rpx), + onTap: () {}, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Obx(() { + return Visibility( + maintainState: true, + maintainAnimation: true, + maintainSize: true, + visible: + deviceCalibrationController + .process.value == + 1, + child: SvgPicture.asset( + 'assets/img/icon/select_arrow.svg', + width: 17.rpx, + height: 17.rpx, + color: themeController + .currentColor.sc9, + ), + ); + }), + SizedBox(width: 8.rpx), + Text( + '位置校准'.tr, + style: TextStyle( + fontSize: 30.rpx, + letterSpacing: 0.0, + color: themeController + .currentColor.sc3, + ), + ), + ], + ), + Obx(() { + return Text( + deviceCalibrationController + .position_calibration + .value == + 0 + ? '未完成'.tr + : "已完成".tr, + style: TextStyle( + fontSize: 26.rpx, + letterSpacing: 0.0, + color: deviceCalibrationController + .position_calibration + .value == + 0 + ? themeController + .currentColor.sc3 + : themeController + .currentColor.sc1, + ), + ); + }), + ], + ), + ), + ], + ), + ), + ), + ), + Obx(() { + return Expanded( + child: SizedBox( + width: double.infinity, + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 100.rpx, 55.rpx, 100.rpx, 0), + child: Stack( + clipBehavior: Clip.none, + children: [ + Container( + width: + MediaQuery.sizeOf(context).width * 0.65, + height: + MediaQuery.sizeOf(context).height * 0.3, + child: Stack( + children: [ + Image.asset( + deviceCalibrationController + .process.value == + 1 && + deviceCalibrationController + .position_calibration + .value == + 1 + ? (deviceCalibrationController + .bed_type.value == + 0 + ? "assets/img/single_person.png" + : "assets/img/double_person.png") + : (deviceCalibrationController + .bed_type.value == + 0 + ? "assets/img/single_pillow.png" + : "assets/img/double_pillow.png"), + width: double.infinity, + height: double.infinity, + fit: BoxFit.contain, + ), + Positioned( + top: 23.rpx, + left: (MediaQuery.sizeOf(context) + .width * + 0.65) / + 2 - + 26.rpx, + child: Text( + '床头'.tr, + style: TextStyle( + fontSize: 26.rpx, + color: themeController + .currentColor.sc4, + ), + ), + ), + ], + ), + ), + Obx(() { + final double centerLeft = + (bodySize.maxWidth * 0.56) / 2; + if (deviceCalibrationController + .bed_type.value == + 0 && + deviceCalibrationController + .process.value == + 1) { + return Positioned( + top: -40.rpx, + left: centerLeft - 0.rpx, + child: Container( + width: bodySize.maxWidth * 0.087, + height: bodySize.maxHeight * 0.06, + constraints: BoxConstraints( + minWidth: 65.rpx, + minHeight: 76.rpx, + ), + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + 'assets/img/tip_arrow.gif'), + fit: BoxFit.cover, + ), + ), + ), + ); + } + if (deviceCalibrationController + .bed_type.value == + 1 && + deviceCalibrationController + .process.value == + 1 && + deviceCalibrationController + .another.value == + false) { + return Positioned( + top: -40.rpx, + left: + (MediaQuery.sizeOf(context).width * + 0.65) * + 0.22 - + 0.rpx, + child: Container( + width: bodySize.maxWidth * 0.087, + height: bodySize.maxHeight * 0.06, + constraints: BoxConstraints( + minWidth: 65.rpx, + minHeight: 76.rpx, + ), + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + 'assets/img/tip_arrow.gif'), + fit: BoxFit.cover, + ), + ), + ), + ); + } + if (deviceCalibrationController + .bed_type.value == + 1 && + deviceCalibrationController + .process.value == + 1 && + deviceCalibrationController + .another.value == + true) { + return Positioned( + top: -40.rpx, + left: + (MediaQuery.sizeOf(context).width * + 0.65) * + 0.22 * + 3 - + 0.rpx, + child: Container( + width: bodySize.maxWidth * 0.087, + height: bodySize.maxHeight * 0.06, + constraints: BoxConstraints( + minWidth: 65.rpx, + minHeight: 76.rpx, + ), + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage( + 'assets/img/tip_arrow.gif'), + fit: BoxFit.cover, + ), + ), + ), + ); + } + return Container(); + }), + Positioned( + top: MediaQuery.sizeOf(context).height * + 0.3 + + 82.rpx, + left: 0, + right: 0, + child: Obx(() { + return Column( + children: [ + getBodyMontion(), + SizedBox(height: 10.rpx), + getInBedMontion(), + SizedBox(height: 10.rpx), + Text( + (deviceCalibrationController.cd.value == + 10000) + ? ((deviceCalibrationController.process.value == 0 && + deviceCalibrationController + .bed_calibration + .value == + 1) || + (deviceCalibrationController + .process + .value == + 1 && + deviceCalibrationController + .position_calibration + .value == + 1) + ? (deviceCalibrationController.flag.value == 2 + ? '校准完成'.tr + : (deviceCalibrationController.bed_type.value == 1 && currentCalibrationStep.value == 2 + ? '请开始B侧校准'.tr + : "校准失败".tr)) + : deviceCalibrationController + .statusContext + .value + .isEmpty == + true + ? (deviceCalibrationController.process.value == 0 + ? '离床校准提示'.tr + : (deviceCalibrationController.bed_type.value == 1 && currentCalibrationStep.value == 1 + ? '请校准人员到箭头指定一侧平躺 保持静止后点击开始,保持10秒' + .tr + : '位置校准提示'.tr)) + : deviceCalibrationController + .statusContext + .value) + : "${deviceCalibrationController.cd.value}" + + "s后超时".tr, + style: TextStyle( + fontSize: 38.rpx, + letterSpacing: 0.0, + color: ((deviceCalibrationController + .process + .value == + 0 && + deviceCalibrationController + .bed_calibration.value == + 1) || + (deviceCalibrationController + .process + .value == + 1 && + deviceCalibrationController + .position_calibration + .value == + 1)) + ? (deviceCalibrationController + .flag.value == + 2 + ? themeController + .currentColor.sc1 + : themeController + .currentColor.sc9) + : themeController + .currentColor.sc9, + ), + ), + ], + ); + }), + ), + ], + ), + ), + ), + ); + }), + Obx(() { + if (deviceCalibrationController.flag.value == 1) { + return Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 100.rpx, 0.rpx, 100.rpx, 60.rpx), + child: CalibrationProgressWidget( + progressNotifier: progressNotifier, + failureNotifier: failureNotifier, + ), + ); + } + return Container(); + }), + Obx(() { + if (deviceCalibrationController.flag.value != 1) { + return Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 100.rpx, 0.rpx, 100.rpx, 60.rpx), + child: CustomCard( + borderRadius: + AppConstants().normal_container_radius, + onTap: () async { + if (deviceCalibrationController.flag.value == + 2) { + _resetCalibrationState(); + deviceCalibrationController.flag.value = 1; + _startCalibration(false); + } else { + deviceCalibrationController.flag.value = 1; + progressNotifier.value = 0; + failureNotifier.value = false; + _pollingTimer?.cancel(); + _startCalibration(blueteethBindController + .cid?.value.isNotEmpty ?? + false); + } + }, + colors: AppConstants().mhtButtongradientColors, + gradientDirection: GradientDirection.vertical, + child: Container( + width: bodySize.maxWidth, + height: + MediaQuery.sizeOf(context).height * 0.055, + constraints: BoxConstraints( + minWidth: 500.rpx, + minHeight: 90.rpx, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Obx(() { + if (deviceCalibrationController + .flag.value == + 0) { + if (deviceCalibrationController + .bed_type.value == + 1 && + currentCalibrationStep.value == 2) { + return Text( + '开始另外一侧校准'.tr, + style: TextStyle( + color: stringToColor("#003058"), + fontFamily: 'Inter', + fontSize: AppConstants() + .normal_text_fontSize, + letterSpacing: 0.0, + ), + ); + } + return Text( + '开始校准'.tr, + style: TextStyle( + color: stringToColor("#003058"), + fontFamily: 'Inter', + fontSize: AppConstants() + .normal_text_fontSize, + letterSpacing: 0.0, + ), + ); + } + if (deviceCalibrationController + .flag.value == + 1) { + deviceCalibrationController + .statusContext.value = ""; + return Text( + '校准中...'.tr, + style: TextStyle( + color: themeController + .currentColor.sc3, + fontFamily: 'Inter', + fontSize: AppConstants() + .normal_text_fontSize, + letterSpacing: 0.0, + ), + ); + } + if (deviceCalibrationController + .flag.value == + 2) { + return Text( + '重新校准'.tr, + style: TextStyle( + color: stringToColor("#003058"), + fontFamily: 'Inter', + fontSize: AppConstants() + .normal_text_fontSize, + letterSpacing: 0.0, + ), + ); + } + return Container(); + }), + ].divide(SizedBox(width: 17.rpx)), + ), + ), + ), + ); + } + return Container(); + }), + ], + ), + ), + ), + ), + ), + ), + ), + onWillPop: () async { + bool exit = false; + if (deviceCalibrationController.flag.value != 2) { + showConfirmDialog(context, Container(), "校准未完成提示".tr, + onConfirm: () async { + exit = true; + _resetCalibrationState(); + }, onCancel: () { + exit = false; + }); + } else { + exit = true; + } + return exit; + }, + ); + } + + void _startPollingProgress( + String serviceAddress, String progressApi, bool isSecondStep) { + // _requestProgress(serviceAddress, progressApi, isSecondStep); + _pollingTimer = Timer.periodic(Duration(seconds: 1), (_) { + _requestProgress(serviceAddress, progressApi, isSecondStep); + }); + } + + void _requestProgress( + String serviceAddress, String progressApi, bool isSecondStep) { + String cid = blueteethBindController.cid!.value; + String progressUrl = "$serviceAddress$progressApi?id=$cid"; + + requestWithLog( + logTitle: "设备校准进度", + method: MyHttpMethod.get, + queryUrl: progressUrl, + onSuccess: (res) { + final data = res.data; + double per = (data['per'] ?? 0).toDouble(); + int currStep = data['currStep'] ?? -1; + String tips = data['statusText'] ?? ''; + + try { + if (data['mattress'] != null) { + deviceCalibrationController.inBedTips.value = + data['mattress']['inBed']; + deviceCalibrationController.motionTips.value = + data['mattress']['bm']; + } + } catch (e) { + print(e); + } + + if (data['status'] == null) { + if (data['cd'] != null) { + int cd = data['cd'] ?? 0; + deviceCalibrationController.cd.value = cd; + deviceCalibrationController.statusContext.value = ""; + } + } else { + if (data['status'] == true) { + deviceCalibrationController.tips.value = ""; + deviceCalibrationController.cd.value = 10000; + if (isSecondStep) { + deviceCalibrationController.statusContext.value = + data['statusText']; + deviceCalibrationController.updateAll(); + } + } else { + _handleCalibrationFailure(tips); + return; + } + } + + bool status = data['status'] ?? false; + progressNotifier.value = per; + + if (per != 100 && per != 20 && per != 40) { + deviceCalibrationController.tips.value = tips; + } else { + deviceCalibrationController.tips.value = ""; + } + deviceCalibrationController.updateAll(); + + if (deviceCalibrationController.bed_type.value == 0) { + _handleSingleBedProgress(isSecondStep, per, currStep, status, tips); + } else { + _handleDoubleBedProgress(isSecondStep, per, currStep, status, tips); + } + }, + onFailure: (res) { + _handleCalibrationFailure(res.msg ?? "服务器.失败".tr); + }, + ); + } + + void _handleSingleBedProgress( + bool isSecondStep, double per, int currStep, bool status, String tips) { + if (!isSecondStep && per >= 20) { + _pollingTimer?.cancel(); + progressNotifier.value = 100; + TopSlideNotification.show(context, text: tips); + deviceCalibrationController.process.value = 1; + deviceCalibrationController.bed_calibration.value = 1; + deviceCalibrationController.flag.value = 0; + currentCalibrationStep.value = 1; + } else if (isSecondStep && per >= 100 && currStep == 5 && status) { + _completeCalibration(); + } + } + + void _handleDoubleBedProgress( + bool isSecondStep, double per, int currStep, bool status, String tips) { + if (!isSecondStep && per >= 20) { + _pollingTimer?.cancel(); + progressNotifier.value = 100; + TopSlideNotification.show(context, text: tips); + deviceCalibrationController.process.value = 1; + deviceCalibrationController.bed_calibration.value = 1; + deviceCalibrationController.flag.value = 0; + currentCalibrationStep.value = 1; + } else if (isSecondStep && per >= 40 && currentCalibrationStep.value == 1) { + _pollingTimer?.cancel(); + TopSlideNotification.show(context, text: "单侧校准完成,请移动到另外一侧".tr); + deviceCalibrationController.flag.value = 0; + currentCalibrationStep.value = 2; + progressNotifier.value = 0; + failureNotifier.value = false; + deviceCalibrationController.another.value = true; + } else if (isSecondStep && + per >= 100 && + currStep == 5 && + status && + currentCalibrationStep.value == 2) { + _completeCalibration(); + } + } + + void _completeCalibration() { + _pollingTimer?.cancel(); + TopSlideNotification.show(context, text: "设备校准完成".tr); + deviceCalibrationController.bed_calibration.value = 1; + deviceCalibrationController.position_calibration.value = 1; + deviceCalibrationController.process.value = 1; + deviceCalibrationController.flag.value = 2; + deviceCalibrationController.another.value = false; + progressNotifier.value = 0; + failureNotifier.value = false; + updateDeviceBindStatus(blueteethBindController.currentDeviceMac!.value); + } + + void _handleCalibrationFailure(String message) { + _pollingTimer?.cancel(); + if (deviceCalibrationController.cd.value != 10000) { + TopSlideNotification.show( + context, + text: message, + textColor: themeController.currentColor.sc9, + ); + } + deviceCalibrationController.statusContext.value = ""; + deviceCalibrationController.bed_calibration.value == 0; + blueteethBindController.cid?.value = ""; + deviceCalibrationController.process.value = 0; + deviceCalibrationController.flag.value = 0; + deviceCalibrationController.tips.value = ""; + deviceCalibrationController.cd.value = 10000; + deviceCalibrationController.updateAll(); + failureNotifier.value = true; + } + + void _startCalibration(bool isSecondStep) { + String serviceAddress = "https://caibration.he-info.cn"; + String calibrationApi = ServiceConstant.start_calibration; + String progressApi = ServiceConstant.calibration_process; + + String queryUrl = "$serviceAddress$calibrationApi"; + + Map data = { + "macA": widget.deviceInfo.value['bind_mac_a'], + }; + + if (deviceCalibrationController.bed_type.value == 1) { + data["macB"] = + widget.deviceInfo.value['bind_mac_b']; + } + + if (isSecondStep) { + data["id"] = blueteethBindController.cid!.value; + if (deviceCalibrationController.bed_type.value == 1) { + data["side"] = currentCalibrationStep.value == 1 ? "A" : "B"; + } + } + // data['cancel'] = true; + requestWithLog( + logTitle: "设备校准", + method: MyHttpMethod.post, + queryUrl: queryUrl, + data: data, + onSuccess: (res) { + if (!isSecondStep) { + String cid = res.rawResponse.data['cid']; + blueteethBindController.cid!.value = cid; + } + _startPollingProgress(serviceAddress, progressApi, isSecondStep); + }, + onFailure: (res) { + _handleCalibrationFailure(res.msg ?? "服务器.失败".tr); + }, + ); + } + + Widget getInBedMontion() { + if (deviceCalibrationController.cd.value == 10000) { + return Container(); + } + + if (deviceCalibrationController.process.value == 1) { + if (deviceCalibrationController.inBedTips.value == 0) { + return Text( + "请校准人员保持在床状态".tr, + style: TextStyle( + fontSize: AppConstants().normal_text_fontSize, + color: themeController.currentColor.sc9, + ), + ); + } + } else { + if (deviceCalibrationController.inBedTips.value != 0) { + return Text( + "请校准人员暂时离开床铺".tr, + style: TextStyle( + fontSize: AppConstants().normal_text_fontSize, + color: themeController.currentColor.sc9, + ), + ); + } + } + + return Container(); + } + + Widget getBodyMontion() { + if (deviceCalibrationController.cd.value == 10000) { + return Container(); + } + if (deviceCalibrationController.process.value == 1) { + if (deviceCalibrationController.motionTips.value != 0) { + return Text( + "请保持身体静止".tr, + style: TextStyle( + fontSize: AppConstants().normal_text_fontSize, + color: themeController.currentColor.sc9, + ), + ); + } + } + return Container(); + } + + void updateDeviceBindStatus(String mac) { + String serviceAddress = ServiceConstant.service_address; + String serviceName = ServiceConstant.server_service; + String serviceApi = ServiceConstant.user_setting; + String type = "device_bind_status_$mac"; + String queryUrl = + "${serviceAddress}${serviceName}${serviceApi}?type=${type}"; + + requestWithLog( + logTitle: "查询绑定流程", + method: MyHttpMethod.get, + queryUrl: queryUrl, + onSuccess: (res) { + Map data = { + "type": type, + "mac": mac, + "wifi": res.data['wifi'], + "celibration": true, + "person_info": false, + "time": DateTime.now().millisecondsSinceEpoch, + }; + requestWithLog( + logTitle: "更新绑定流程", + method: MyHttpMethod.put, + queryUrl: queryUrl, + data: data, + onSuccess: (res) {}, + onFailure: (res) {}, + ); + }, + onFailure: (res) {}, + ); + } +} diff --git a/lib/pages/mh_page/device/mht_wifi_page.dart b/lib/pages/mh_page/device/mht_wifi_page.dart index 09bdbca..3cda23e 100644 --- a/lib/pages/mh_page/device/mht_wifi_page.dart +++ b/lib/pages/mh_page/device/mht_wifi_page.dart @@ -68,7 +68,6 @@ class _MHTWifiPageState extends State { blueteethBindController.updateAll(); } - @override @override void dispose() { _isDisposed = true; diff --git a/lib/pages/mh_page/device/mht_wifi_page_after.dart b/lib/pages/mh_page/device/mht_wifi_page_after.dart new file mode 100644 index 0000000..bb7ebde --- /dev/null +++ b/lib/pages/mh_page/device/mht_wifi_page_after.dart @@ -0,0 +1,1089 @@ +import 'dart:async'; + +import 'package:easydevice/easydevice.dart'; +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_blue_plus/flutter_blue_plus.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/color/ServiceConstant.dart'; +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/util/DailyLogUtils.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/common/util/requestWithLog.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; +import 'package:vbvs_app/component/tool/TopSlideNotification.dart'; +import 'package:vbvs_app/component/tool/cmd.dart'; +import 'package:vbvs_app/controller/device/blueteeth_bind_controller.dart'; +import 'package:vbvs_app/controller/main_bottom/global_controller.dart'; +import 'package:vbvs_app/controller/person/person_controller.dart'; +import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; +import 'package:vbvs_app/controller/user_info_controller.dart'; +import 'package:vbvs_app/model/BleDeviceData.dart'; +import 'package:vbvs_app/pages/device_bind/blueteeth_device_page.dart'; +import 'package:vbvs_app/pages/mh_page/component/mht_bind_dialog.dart'; + +class MHTWifiAfterPage extends StatefulWidget { + var deviceInfo; + MHTWifiAfterPage({super.key, required this.deviceInfo}); + + @override + State createState() => _MHTWifiAfterPageState(); +} + +class _MHTWifiAfterPageState extends State { + GlobalController globalController = Get.find(); + UserInfoController userInfoController = Get.find(); + BlueteethBindController blueteethBindController = Get.find(); + PersonController personController = Get.find(); + ThemeController themeController = Get.find(); + var lisObj; + Timer? _timeoutTimer; + StreamSubscription>? _scanSubscription; + bool _isDisposed = false; + + @override + void initState() { + super.initState(); + _initController(); + dealWifi(widget.deviceInfo.value['bind_mac_a']).then((aa) { + print("object"); + }); + } + + void _initController() { + blueteethBindController.netType.value = 0; + blueteethBindController.connectStatus.value = 0; + blueteethBindController.wifiList = [].obs; + blueteethBindController.wifiStatus = 0.obs; + blueteethBindController.connect_wifi.value = {}; + blueteethBindController.selectWifi.value = {}; + blueteethBindController.wifiStatus.value = 0; + blueteethBindController.blueConnectFlag.value = 0; + blueteethBindController.wifiConnectStatus.value = 1; + blueteethBindController.updateAll(); + } + + @override + void dispose() { + _isDisposed = true; + _cleanupResources(); + _disconnectDevice(); + super.dispose(); + } + + void _cleanupResources() { + // 取消监听器 + lisObj?.cancel(); + lisObj = null; + + // 取消定时器 + _timeoutTimer?.cancel(); + _timeoutTimer = null; + + // 取消扫描订阅 + _scanSubscription?.cancel(); + _scanSubscription = null; + + // 断开蓝牙连接 + if (blueteethBindController.currentDevice != null) { + blueteethBindController.currentDevice!.disconnect(); + blueteethBindController.currentDevice = null; + } + + // 停止扫描 + FlutterBluePlus.stopScan(); + } + + Future _navigateToNextPage() async { + // 清理资源 + _cleanupResources(); + + if (_isDisposed) return; + + // 导航到下一页 + if (blueteethBindController.wifiStatus.value != 1) { + showConfirmDialog(context, Container(), "未配置网络提示".tr, + onConfirm: () async { + _cleanupResources(); + await _disconnectDevice(); + Get.toNamed("/calibrationPage"); + }, onCancel: () {}); + } else { + _cleanupResources(); + await _disconnectDevice(); + Get.toNamed("/calibrationPage"); + } + } + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, bodySize) => GestureDetector( + // onTap: () => FocusScope.of(context).unfocus(),, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), + fit: BoxFit.fill, + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: IconThemeData(color: themeController.currentColor.sc3), + titleSpacing: 0, + title: Container( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'wifi配置'.tr, + style: TextStyle( + fontFamily: 'Readex Pro', + color: themeController.currentColor.sc3, + letterSpacing: 0, + fontSize: 30.rpx, + ), + ), + SizedBox( + width: 14.rpx, + ), + Obx(() { + if (!blueteethBindController.bluetoothStatus.value) { + return Container(); + } + if (blueteethBindController.blueConnectFlag.value == + 0) { + return SizedBox( + width: 24.rpx, + height: 24.rpx, + child: CircularProgressIndicator( + strokeWidth: 1, + valueColor: + AlwaysStoppedAnimation(Colors.white), + ), + ); + } + if (blueteethBindController.netType.value == 0) { + return SizedBox( + width: 24.rpx, + height: 24.rpx, + child: CircularProgressIndicator( + strokeWidth: 1, + valueColor: + AlwaysStoppedAnimation(Colors.white), + ), + ); + } + if (blueteethBindController.wifiConnectStatus.value == + 0) { + return SizedBox( + width: 24.rpx, + height: 24.rpx, + child: CircularProgressIndicator( + strokeWidth: 1, + valueColor: + AlwaysStoppedAnimation(Colors.white), + ), + ); + } + return Container(); + }), + ], + ), + Positioned( + left: 0, + child: returnIconButtom, + ), + ], + ), + ), + actions: [], + centerTitle: false, + ), + body: SafeArea( + top: true, + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 0, 30.rpx, 0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + EdgeInsetsDirectional.fromSTEB(0, 30.rpx, 0, 0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: stringToColor("#003058"), + borderRadius: BorderRadius.circular(20.rpx), + ), + child: Column( + children: [ + Align( + alignment: AlignmentDirectional(0, 0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 30.rpx, 30.rpx, 30.rpx, 30.rpx), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "WLAN".tr, + style: TextStyle( + color: themeController + .currentColor.sc3, + fontSize: AppConstants() + .title_text_fontSize, + ), + ), + Obx(() { + return Text( + blueteethBindController + .wifiStatus.value == + 0 + ? "未连接".tr + : "已连接".tr, + style: TextStyle( + color: blueteethBindController + .wifiStatus.value == + 0 + ? themeController + .currentColor.sc4 + : themeController + .currentColor.sc2, + fontSize: AppConstants() + .normal_text_fontSize, + ), + ); + }), + ], + ), + ), + ), + Obx(() { + if (blueteethBindController + .connect_wifi.value == + null || + blueteethBindController + .connect_wifi.value.isEmpty) { + return Container(); + } else { + return Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 30.rpx, 0.rpx, 30.rpx, 30.rpx), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + blueteethBindController.connect_wifi + .value['ssid'] ?? + '未命名'.tr, + style: TextStyle( + color: themeController + .currentColor.sc3, + fontSize: AppConstants() + .title_text_fontSize, + ), + ), + getWifiIconByRsso( + blueteethBindController + .connect_wifi.value), + ], + ), + ); + } + }) + ], + )), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.rpx, 25.rpx, 0.rpx, 0.rpx), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: stringToColor("#003058"), + borderRadius: BorderRadius.circular(20.rpx), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 30.rpx, 30.rpx, 30.rpx, 30.rpx), + child: Container( + width: double.infinity, + decoration: BoxDecoration(), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Text( + '可用WLAN'.tr, + style: TextStyle( + fontFamily: 'Inter', + fontSize: 30.rpx, + letterSpacing: 0.0, + color: + themeController.currentColor.sc3, + ), + ), + ], + ), + Obx(() { + final sortedList = [ + ...blueteethBindController.wifiList.value + ]..sort((a, b) => + b['rssi'].compareTo(a['rssi'])); + + return Column( + mainAxisSize: MainAxisSize.max, + children: sortedList + .map((wifiItem) => ClickableContainer( + backgroundColor: + Colors.transparent, + highlightColor: themeController + .currentColor.sc3, + padding: EdgeInsets.symmetric( + vertical: 0.rpx, + horizontal: 0.rpx), + borderRadius: 16.rpx, + onTap: () { + showWifiDialog( + context, + Padding( + padding: + EdgeInsetsDirectional + .fromSTEB( + 0.rpx, + 41.rpx, + 0.rpx, + 0), + child: Container( + height: 80.rpx, + decoration: + BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius + .circular( + 12.rpx), + ), + child: Align( + alignment: + AlignmentDirectional( + -1, 0), + child: Obx(() { + return TextFormField( + onChanged: + (value) { + blueteethBindController + .model + .wifiPass = + value; + }, + autofocus: + false, + obscureText: + blueteethBindController + .model + .wifiPassShow, + decoration: + InputDecoration( + isDense: + true, + labelStyle: + TextStyle( + fontFamily: + 'Inter', + fontSize: + 26.rpx, + letterSpacing: + 0.0, + ), + hintText: + '输入wifi密码' + .tr, + hintStyle: TextStyle( + fontFamily: + 'Inter', + fontSize: 26 + .rpx, + letterSpacing: + 0.0, + color: themeController + .currentColor + .sc4), + enabledBorder: + OutlineInputBorder( + borderSide: + BorderSide( + color: Color( + 0x00000000), + width: 1 + .rpx, + ), + borderRadius: + BorderRadius.circular( + 8.rpx), + ), + focusedBorder: + OutlineInputBorder( + borderSide: + BorderSide( + color: Color( + 0x00000000), + width: 1 + .rpx, + ), + borderRadius: + BorderRadius.circular( + 8.rpx), + ), + errorBorder: + OutlineInputBorder( + borderSide: + BorderSide( + width: 1 + .rpx, + ), + borderRadius: + BorderRadius.circular( + 8.rpx), + ), + focusedErrorBorder: + OutlineInputBorder( + borderSide: + BorderSide( + width: 1 + .rpx, + ), + borderRadius: + BorderRadius.circular( + 8.rpx), + ), + filled: + true, + fillColor: + stringToColor( + "#F3F5F6"), + suffixIcon: + InkWell( + onTap: + () { + blueteethBindController + .model + .wifiPassShow = !blueteethBindController.model.wifiPassShow; + blueteethBindController + .updateAll(); + }, + focusNode: + FocusNode( + skipTraversal: true), + child: + Icon( + blueteethBindController.model.wifiPassShow + ? Icons.visibility_outlined + : Icons.visibility_off_outlined, + size: 30 + .rpx, + ), + ), + ), + style: TextStyle( + fontFamily: + 'Inter', + fontSize: 26 + .rpx, + letterSpacing: + 0.0, + color: Colors + .black), + cursorColor: + themeController + .currentColor + .sc3, + ); + })), + ), + ), + wifiItem['ssid'] ?? + '未命名'.tr, + onConfirm: () async { + blueteethBindController + .selectWifi + .value = wifiItem; + bool flag = await sendWifiSetting( + wifiItem, + blueteethBindController + .model.wifiPass!, + blueteethBindController + .currentDevice!); + if (flag) { + var aa = await getDeviceWifiStatus( + blueteethBindController + .currentDevice!, + 1); + blueteethBindController + .selectWifi + .value = {}; + if (aa != null && + aa is Map) { + blueteethBindController + .connect_wifi + .value = aa; + } else { + blueteethBindController + .connect_wifi + .value = {}; + } + blueteethBindController + .wifiStatus + .value = + aa != null ? 1 : 0; + if (aa != null) { + updateDeviceBindStatus( + blueteethBindController + .currentDeviceMac! + .value); + TopSlideNotification + .show( + context, + text: "wifi页.配网成功".tr, + textColor: + themeController + .currentColor + .sc2, + ); + } else { + TopSlideNotification + .show( + context, + text: "wifi页.配网失败".tr, + textColor: + themeController + .currentColor + .sc9, + ); + } + } else { + TopSlideNotification.show( + context, + text: "wifi页.配网失败".tr, + textColor: + themeController + .currentColor + .sc9, + ); + } + }); + }, + child: Row( + mainAxisSize: + MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text( + wifiItem['ssid'] ?? '', + style: TextStyle( + fontFamily: 'Inter', + fontSize: 30.rpx, + letterSpacing: 0.0, + color: themeController + .currentColor.sc3, + ), + ), + if (blueteethBindController + .selectWifi.value == + wifiItem) + SizedBox( + width: 32.rpx, + height: 32.rpx, + child: + CircularProgressIndicator( + strokeWidth: 1, + valueColor: + AlwaysStoppedAnimation< + Color>( + Colors.white), + ), + ) + else + getWifiIconByRsso( + wifiItem), + ], + ), + )) + .toList() + .divide(SizedBox(height: 67.rpx)), + ); + }), + ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Colors.white, + padding: EdgeInsets.symmetric( + horizontal: 20.rpx, vertical: 10.rpx), + borderRadius: 20.rpx, + onTap: () async { + var bluetoothState = + await FlutterBluePlus.isOn; + blueteethBindController.bluetoothStatus + .value = bluetoothState; + if (!bluetoothState) { + await _showBluetoothNotEnabledDialog(); + return; + } + if (blueteethBindController + .blueConnectFlag.value == + 0 || + blueteethBindController + .blueConnectFlag.value == + 1) { + blueteethBindController + .blueConnectFlag.value = 0; + dealWifi(widget.deviceInfo.macA) + .then((aa) { + print("object"); + }); + return; + } + + if (blueteethBindController + .netType.value == + 0) { + return; + } + blueteethBindController.netType.value = 0; + blueteethBindController.updateAll(); + var aa = await getDeviceNetVersion( + blueteethBindController + .currentDevice!, + 1); + if (aa == "4g") { + updateDeviceBindStatus( + blueteethBindController + .currentDeviceMac!.value); + TopSlideNotification.show( + context, + text: "4g设备配置wifi提示".tr, + textColor: + themeController.currentColor.sc2, + ); + blueteethBindController.netType.value = + 2; + blueteethBindController + .connectStatus.value = 1; + blueteethBindController.updateAll(); + Future.delayed( + const Duration(seconds: 1), () { + _cleanupResources(); + Get.toNamed("/calibrationPage", + arguments: 1); + }); + } else if (aa == 'unknown') { + blueteethBindController.netType.value = + 3; + blueteethBindController.updateAll(); + WidgetsBinding.instance + .addPostFrameCallback((_) { + TopSlideNotification.show( + context, + text: "获取设备网络类型失败".tr, + textColor: themeController + .currentColor.sc9, + ); + }); + } else { + blueteethBindController.netType.value = + 1; + blueteethBindController.updateAll(); + await initWifiStatusAndWifiList(); + } + }, + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Container( + width: 25.rpx, + height: 25.rpx, + decoration: BoxDecoration(), + child: SvgPicture.asset( + 'assets/img/icon/refresh.svg', + fit: BoxFit.cover, + color: Colors.white, + ), + ), + Text( + '刷新'.tr, + style: TextStyle( + fontFamily: 'Inter', + fontSize: 30.rpx, + letterSpacing: 0.0, + color: themeController + .currentColor.sc3, + ), + ), + ].divide(SizedBox(width: 26.rpx)), + ), + ), + ].divide(SizedBox(height: 65.rpx)), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ), + ), + ); + } + + Future initWifiStatusAndWifiList() async { + if (_isDisposed) return; + + if (lisObj != null) { + lisObj!.cancel(); + } + + bool wifiStatus = false; + var aa = + await getDeviceWifiStatus(blueteethBindController.currentDevice!, 0); + if (aa != null && aa is Map) { + updateDeviceBindStatus(blueteethBindController.currentDeviceMac!.value); + wifiStatus = true; + blueteethBindController.connect_wifi.value = aa; + } else { + wifiStatus = false; + } + blueteethBindController.wifiStatus.value = wifiStatus ? 1 : 0; + + List wifiList = []; + try { + final result = await getWifiList(blueteethBindController.currentDevice!); + blueteethBindController.wifiConnectStatus.value = 1; + blueteethBindController.updateAll(); + if (result is List) { + wifiList = result; + } + } catch (e) { + print("异常: $e"); + blueteethBindController.wifiConnectStatus.value = 0; + blueteethBindController.updateAll(); + } + + if (_isDisposed) return; + + if (wifiList.isNotEmpty) { + blueteethBindController.connectStatus.value = 1; + blueteethBindController.updateAll(); + TopSlideNotification.show( + context, + text: "获取wifi列表成功".tr, + textColor: themeController.currentColor.sc2, + ); + blueteethBindController.wifiList.value = wifiList; + blueteethBindController.updateAll(); + } else { + TopSlideNotification.show( + context, + text: "获取wifi列表失败".tr, + textColor: themeController.currentColor.sc9, + ); + } + + lisObj = blueteethBindController.currentDevice!.statusStream + .listen((onData) async { + if (onData.status == BleEventType.recvLineLog) { + final line = onData.val; + print("[bleee]:" + line); + } + }); + } + + Widget getWifiIconByRsso(wifiItem) { + int? rssi = int.tryParse(wifiItem['rssi'].toString()); + + if (rssi != null) { + if (rssi >= -30) { + return Container( + width: 40.rpx, + height: 40.rpx, + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration(shape: BoxShape.circle), + child: Image.asset("assets/img/wifi4.png"), + ); + } else if (rssi >= -45) { + return Container( + width: 40.rpx, + height: 40.rpx, + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration(shape: BoxShape.circle), + child: Image.asset("assets/img/wifi3.png"), + ); + } else if (rssi >= -60) { + return Container( + width: 40.rpx, + height: 40.rpx, + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration(shape: BoxShape.circle), + child: Image.asset("assets/img/wifi3.png"), + ); + } else { + return Container( + width: 40.rpx, + height: 40.rpx, + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration(shape: BoxShape.circle), + child: Image.asset("assets/img/wifi1.png"), + ); + } + } else { + return Container( + width: 40.rpx, + height: 40.rpx, + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration(shape: BoxShape.circle), + child: Image.asset("assets/img/wifi1.png"), + ); + } + } + + Future dealWifi(String mac) async { + if (_isDisposed) return; + + final blueteethBindController = Get.find(); + final themeController = Get.find(); + + // 清理之前的资源 + _cleanupResources(); + + try { + // 检查蓝牙状态 + var bluetoothState = await FlutterBluePlus.isOn; + blueteethBindController.bluetoothStatus.value = bluetoothState; + blueteethBindController.updateAll(); + if (!bluetoothState) { + await _showBluetoothNotEnabledDialog(); + return; + } + + // 开始扫描 + await FlutterBluePlus.startScan(timeout: Duration(seconds: 10)); + + bool isConnected = false; + + // 设置超时定时器 + _timeoutTimer = Timer(Duration(seconds: 20), () { + if (!isConnected && !_isDisposed) { + blueteethBindController.blueConnectFlag.value = 1; + blueteethBindController.updateAll(); + TopSlideNotification.show( + context, + text: "设备连接超时,请重试".tr, + textColor: themeController.currentColor.sc9, + ); + FlutterBluePlus.stopScan(); + } + }); + + // 监听扫描结果 + _scanSubscription = FlutterBluePlus.scanResults.listen((results) async { + if (_isDisposed) return; + + ScanResult? targetDevice; + + for (var r in results) { + if (r.advertisementData.manufacturerData.containsKey(0xFFED)) { + List rawData = r.advertisementData.manufacturerData[0xFFED]!; + BleDeviceData deviceData = parseBleData(rawData); + String deviceMac = + deviceData.deviceId.replaceAll(':', '').toLowerCase(); + if (deviceMac == mac.toLowerCase()) { + targetDevice = r; + break; + } + } + } + + if (targetDevice != null && !isConnected) { + isConnected = true; + _timeoutTimer?.cancel(); + _scanSubscription?.cancel(); + + try { + THapp bledevice = THapp(device: targetDevice.device); + await bledevice.device.connect(); + var res2 = bledevice.isConnected; + + if (res2 && !_isDisposed) { + blueteethBindController.blueConnectFlag.value = 2; + TopSlideNotification.show( + context, + text: "蓝牙绑定.连接成功".tr, + textColor: themeController.currentColor.sc2, + ); + blueteethBindController.currentDevice = bledevice; + + lisObj = blueteethBindController.currentDevice!.statusStream + .listen((onData) async { + if (_isDisposed) return; + + if (onData.status == BleEventType.recvLineLog) { + final line = onData.val; + print("[bleee]:" + line); + } + if (onData.status == BleEventType.ready) { + var aa = await getDeviceNetVersion( + blueteethBindController.currentDevice!, 0); + if (aa == "4g") { + blueteethBindController.netType.value = 2; + blueteethBindController.updateAll(); + updateDeviceBindStatus( + blueteethBindController.currentDeviceMac!.value); + await showTipDialog( + context, + Text( + "4g设备配置wifi提示".tr, + style: TextStyle( + color: themeController.currentColor.sc3, + fontSize: AppConstants().title_text_fontSize), + )); + } else if (aa == 'unknown') { + blueteethBindController.netType.value = 3; + blueteethBindController.updateAll(); + TopSlideNotification.show( + context, + text: "获取设备网络类型失败".tr, + textColor: themeController.currentColor.sc9, + ); + } else { + blueteethBindController.netType.value = 1; + blueteethBindController.updateAll(); + blueteethBindController.wifiConnectStatus.value = 0; + blueteethBindController.updateAll(); + await initWifiStatusAndWifiList(); + } + } + }); + } else { + TopSlideNotification.show( + context, + text: "蓝牙绑定.连接失败".tr, + textColor: themeController.currentColor.sc9, + ); + } + } catch (e) { + TopSlideNotification.show( + context, + text: "设备连接失败".tr, + textColor: themeController.currentColor.sc9, + ); + } + } + }); + + await Future.delayed(Duration(seconds: 20)); + } catch (e) { + if (!_isDisposed) { + TopSlideNotification.show( + context, + text: "扫描过程中发生错误".tr, + textColor: themeController.currentColor.sc9, + ); + } + } finally { + _timeoutTimer?.cancel(); + await FlutterBluePlus.stopScan(); + } + } + + Future _showBluetoothNotEnabledDialog() async { + if (_isDisposed) return; + + await showTipDialog( + context, + Column( + children: [ + Text( + "蓝牙未开启".tr, + style: TextStyle( + fontSize: AppConstants().title_text_fontSize, + color: themeController.currentColor.sc3), + ), + SizedBox( + height: 20.rpx, + ), + Text( + "请先打开蓝牙在进行设备扫描".tr, + style: TextStyle( + fontSize: AppConstants().normal_text_fontSize, + color: themeController.currentColor.sc3), + ), + ], + )); + } + + void updateDeviceBindStatus(String mac) { + String serviceAddress = ServiceConstant.service_address; + String serviceName = ServiceConstant.server_service; + String serviceApi = ServiceConstant.user_setting; + String type = "device_bind_status_$mac"; + String queryUrl = + "${serviceAddress}${serviceName}${serviceApi}?type=${type}"; + requestWithLog( + logTitle: "查询绑定流程", + method: MyHttpMethod.get, + queryUrl: queryUrl, + onSuccess: (res) { + print(res); + Map data = { + "type": type, + "mac": mac, + "wifi": true, + "celibration": res.data['celibration'], + "person_info": res.data['person_info'], + "time": DateTime.now().millisecondsSinceEpoch, + }; + requestWithLog( + logTitle: "更新绑定流程", + method: MyHttpMethod.put, + queryUrl: queryUrl, + data: data, + onSuccess: (res) {}, + onFailure: (res) {}, + ); + }, + onFailure: (res) {}, + ); + } + + Future _disconnectDevice() async { + try { + THapp bledevice = THapp(device: widget.deviceInfo.scanResult.device); + await bledevice.disconnect(); + DailyLogUtils.writeLog("关闭蓝牙连接成功"); + } catch (e) { + DailyLogUtils.writeError("关闭蓝牙连接失败: $e"); + } + } +} diff --git a/lib/routers/mh_routers.dart b/lib/routers/mh_routers.dart index a3bd205..dc65f00 100644 --- a/lib/routers/mh_routers.dart +++ b/lib/routers/mh_routers.dart @@ -21,8 +21,10 @@ import 'package:vbvs_app/pages/mh_page/device/mht_bind_device_success.dart'; import 'package:vbvs_app/pages/mh_page/device/mht_bind_device_type.dart'; import 'package:vbvs_app/pages/mh_page/device/mht_blueteeth_device_page.dart'; import 'package:vbvs_app/pages/mh_page/device/mht_device_calibration.dart'; +import 'package:vbvs_app/pages/mh_page/device/mht_device_calibration_after.dart'; import 'package:vbvs_app/pages/mh_page/device/mht_people_info.dart'; import 'package:vbvs_app/pages/mh_page/device/mht_wifi_page.dart'; +import 'package:vbvs_app/pages/mh_page/device/mht_wifi_page_after.dart'; import 'package:vbvs_app/pages/mh_page/device_list.dart'; import 'package:vbvs_app/pages/mh_page/device_people_info.dart'; import 'package:vbvs_app/pages/mh_page/device_share_page.dart'; @@ -100,6 +102,8 @@ var mhroutes = { MHTBlueteethDevicePage(deviceType: arguments), "/mHTwifiPage": (contxt, {arguments}) => MHTWifiPage(deviceInfo: arguments), "/calibrationPage": (contxt) => MHTCalibrationPage(), + "/mhtCalibrationAfterPage": (contxt, {arguments}) => + MHTCalibrationAfterPage(deviceInfo: arguments), "/bindDeviceSuccess": (contxt) => MHTBindDeviceSuccess(), "/newSleepReportPage": (contxt, {arguments}) => NewSleepReportPage(data: arguments), @@ -119,6 +123,8 @@ var mhroutes = { "/vitalSignsSensorPage": (context, {arguments}) => VitalSignsSensorPage( data: arguments, ), + "/mhtWifiAfterPage": (contxt, {arguments}) => + MHTWifiAfterPage(deviceInfo: arguments), }; var mhonGenerateRoute = (RouteSettings settings) { final String? name = settings.name; // 获取路由名称,如 /news 或 /search