修复眠花糖设置闹钟无效
This commit is contained in:
@@ -2,6 +2,6 @@
|
||||
# flutter.android.versionName=2.0.5
|
||||
# flutter.android.versionCode=11
|
||||
|
||||
# 智慧眠花糖版本信息
|
||||
flutter.android.versionName=2.0.8
|
||||
flutter.android.versionCode=12
|
||||
# 智慧眠花糖版本信息【最新,未提交商店】
|
||||
flutter.android.versionName=2.0.9
|
||||
flutter.android.versionCode=13
|
||||
@@ -1,3 +1,3 @@
|
||||
[
|
||||
"assets/miniapp/mhtControl_1.0.87.zip"
|
||||
"assets/miniapp/mhtControl_1.0.89.zip"
|
||||
]
|
||||
Binary file not shown.
@@ -2,7 +2,7 @@ class ServiceConstant {
|
||||
// static const String baseHost = "zhmht.swes.com.cn:27021"; //服务地址 眠花糖测试地址
|
||||
static const String baseHost = "zhmht.swes.com.cn:27020"; //服务地址 眠花糖正式地址
|
||||
// static const String baseHost = "vsbs-test.he-info.cn"; //服务地址 本地测试地址
|
||||
// static const String baseHost = "vsbst-api.he-info.cn";//服务地址
|
||||
// static const String baseHost = "vsbst-api.he-info.com";//服务地址
|
||||
// static const String service_address = "http://$baseHost";
|
||||
static const String service_address = "https://$baseHost";
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ Future<ApiResponse> requestWithLog({
|
||||
EasyDartModule.logger.error("$logTitle 失败->$e");
|
||||
DailyLogUtils.writeError("$logTitle 失败->$e");
|
||||
onFailure?.call(apiResponse);
|
||||
apiResponse.msg = e.toString();
|
||||
return apiResponse;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@ import 'package:EasyDartModule/base/logger/Logger.dart';
|
||||
import 'package:EasyDartModule/base/websocket/WebSocket.dart';
|
||||
import 'package:easyweb/utils/appmanger.dart';
|
||||
import 'package:ef/ef.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:fluwx/fluwx.dart';
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
@@ -98,6 +100,8 @@ Future<void> main() async {
|
||||
await initLanguageSetting();
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
initServiceAddress();
|
||||
|
||||
ApiService.init();
|
||||
await GetStorage.init();
|
||||
// 初始化登录
|
||||
@@ -111,7 +115,7 @@ Future<void> main() async {
|
||||
// 检查网络
|
||||
Checknetwork.checkNetwork();
|
||||
// 微信开放平台注册
|
||||
initWX();
|
||||
await initWX();
|
||||
// // 初始化 flutter_xupdate android app 更新
|
||||
// initXUpdate();
|
||||
|
||||
@@ -124,6 +128,20 @@ Future<void> main() async {
|
||||
});
|
||||
}
|
||||
|
||||
//初始化服务器地址
|
||||
void initServiceAddress() {
|
||||
if (AppConstants().ent_type == APPPackageType.MHT.code) {
|
||||
// 眠花糖
|
||||
ServiceConstant.baseHost = "zhmht.swes.com.cn:27020";
|
||||
} else if (AppConstants().ent_type == APPPackageType.TH.code) {
|
||||
// 太和
|
||||
ServiceConstant.baseHost = "vsbst-api.he-info.com";
|
||||
} else {
|
||||
//默认
|
||||
ServiceConstant.baseHost = "vsbst-api.he-info.com";
|
||||
}
|
||||
}
|
||||
|
||||
// languageCode 系统默认语言码 en/zh
|
||||
loadLanguageSetting(String? languageCode) async {
|
||||
int code = AppConstants().ent_type;
|
||||
@@ -185,17 +203,46 @@ initLanguageSetting() async {
|
||||
}
|
||||
|
||||
// 初始化微信开放平台注册
|
||||
// Future<void> initWX() async {
|
||||
// Fluwx fluwx = Fluwx();
|
||||
// fluwx.registerApi(
|
||||
// //请填写自己的微信appid
|
||||
// // appId: "wxeb2688220799e2c5", //太和
|
||||
// appId: "wx929c548fea6af9c7", //眠花糖
|
||||
// doOnAndroid: true,
|
||||
// doOnIOS: true,
|
||||
// // universalLink: "https://app.he-info.com/theh/",
|
||||
// universalLink: "https://zhmht.swes.com.cn/app/",
|
||||
// );
|
||||
// }
|
||||
|
||||
Future<void> initWX() async {
|
||||
Fluwx fluwx = Fluwx();
|
||||
fluwx.registerApi(
|
||||
//请填写自己的微信appid
|
||||
appId: "wxeb2688220799e2c5", //太和
|
||||
// appId: "wx929c548fea6af9c7", //眠花糖
|
||||
final fluwx = Fluwx();
|
||||
|
||||
String appId = "";
|
||||
String universalLink = "";
|
||||
|
||||
if (AppConstants().ent_type == APPPackageType.MHT.code) {
|
||||
// 眠花糖
|
||||
appId = "wx929c548fea6af9c7";
|
||||
universalLink = "https://zhmht.swes.com.cn/app/";
|
||||
} else if (AppConstants().ent_type == APPPackageType.TH.code) {
|
||||
// 太和
|
||||
appId = "wxeb2688220799e2c5";
|
||||
universalLink = "https://app.he-info.com/theh/";
|
||||
} else {
|
||||
ef.log("[initWX] 未匹配到有效的包类型 ent_type=${AppConstants().ent_type}");
|
||||
return;
|
||||
}
|
||||
|
||||
await fluwx.registerApi(
|
||||
appId: appId,
|
||||
doOnAndroid: true,
|
||||
doOnIOS: true,
|
||||
universalLink: "https://app.he-info.com/theh/",
|
||||
// universalLink: "https://zhmht.swes.com.cn/app/",
|
||||
universalLink: universalLink,
|
||||
);
|
||||
|
||||
ef.log("[initWX] 微信注册完成 -> appId: $appId, link: $universalLink");
|
||||
}
|
||||
|
||||
Timer? _messageTimer;
|
||||
@@ -628,11 +675,8 @@ messageStatus() async {
|
||||
void initEasyDartModule() {
|
||||
try {
|
||||
EasyDartModule.init(
|
||||
loggerConfig:
|
||||
// LoggerConfig(host: ServiceConstant.logService, serviceName: "智慧眠花糖在线2025-10-9"),
|
||||
LoggerConfig(
|
||||
host: ServiceConstant.logService,
|
||||
serviceName: "太和e护在线2025-10-14"),
|
||||
loggerConfig: LoggerConfig(
|
||||
host: ServiceConstant.logService, serviceName: "眠花糖在线2025-10-28"),
|
||||
webSocketConfig:
|
||||
WebSocketConfig(ServiceConstant.webSocketService, (data) {
|
||||
// 接收到服务消息
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:vbvs_app/common/util/MyUtils.dart';
|
||||
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
|
||||
import 'package:vbvs_app/controller/mh_controller/mh_language_controller.dart';
|
||||
import 'package:vbvs_app/controller/user_info_controller.dart';
|
||||
import 'package:vbvs_app/enum/APPPackageType.dart';
|
||||
import 'package:vbvs_app/model/WebSocketMessage.dart';
|
||||
import 'package:vbvs_app/pages/common/bezier_bottom_navigation_bar.dart';
|
||||
import 'package:vbvs_app/pages/common/selectDialog.dart';
|
||||
@@ -126,27 +127,29 @@ class _HomePageState extends State<MainPageBBottomChange>
|
||||
final getStorage = GetStorage();
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Future.delayed(const Duration(milliseconds: 0), () {
|
||||
String? isShowYingShiDialog = getStorage.read("isShowYingShiDialog");
|
||||
if (isShowYingShiDialog == null || isShowYingShiDialog != "true") {
|
||||
String btnName = "同意".tr;
|
||||
String cancelName = "取消".tr;
|
||||
if (Platform.isAndroid) {
|
||||
cancelName = "退出".tr;
|
||||
}
|
||||
showCustomConfirmOfWebViewDialog(context, "隐私协议".tr, getPrivacy(1),
|
||||
btnName: btnName, showCancel: true, cancelName: cancelName)
|
||||
.then((e) {
|
||||
if (e == "confirm") {
|
||||
getStorage.write("isShowYingShiDialog", "true");
|
||||
} else {
|
||||
if (cancelName == "退出") {
|
||||
SystemNavigator.pop();
|
||||
}
|
||||
if (AppConstants().ent_type == APPPackageType.MHT.code) {
|
||||
Future.delayed(const Duration(milliseconds: 0), () {
|
||||
String? isShowYingShiDialog = getStorage.read("isShowYingShiDialog");
|
||||
if (isShowYingShiDialog == null || isShowYingShiDialog != "true") {
|
||||
String btnName = "同意".tr;
|
||||
String cancelName = "取消".tr;
|
||||
if (Platform.isAndroid) {
|
||||
cancelName = "退出".tr;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
showCustomConfirmOfWebViewDialog(context, "隐私协议".tr, getPrivacy(1),
|
||||
btnName: btnName, showCancel: true, cancelName: cancelName)
|
||||
.then((e) {
|
||||
if (e == "confirm") {
|
||||
getStorage.write("isShowYingShiDialog", "true");
|
||||
} else {
|
||||
if (cancelName == "退出") {
|
||||
SystemNavigator.pop();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return Obx(() {
|
||||
final currentLanguage =
|
||||
languageController.selectLanguage.value; // 监听此变量变化
|
||||
|
||||
@@ -269,7 +269,6 @@
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
@@ -286,6 +285,7 @@ import 'package:vbvs_app/controller/main_bottom/main_page_controller.dart';
|
||||
import 'package:vbvs_app/controller/message/message_controller.dart';
|
||||
import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
|
||||
import 'package:vbvs_app/controller/user_info_controller.dart';
|
||||
import 'package:vbvs_app/enum/APPPackageType.dart';
|
||||
import 'package:vbvs_app/enum/LoginStatus.dart';
|
||||
import 'package:vbvs_app/pages/common/selectDialog.dart';
|
||||
import 'package:vbvs_app/pages/main_bottom/e_page.dart';
|
||||
@@ -315,12 +315,10 @@ class MainPageBottomChange extends GetView<MainPageController> {
|
||||
bottomItems = [
|
||||
getBottomNavigationBarItem("assets/img/menu/home.svg",
|
||||
"assets/img/menu/n_home.svg", "菜单.首页".tr),
|
||||
getBottomNavigationBarItem("assets/img/menu/e.svg",
|
||||
"assets/img/menu/n_e.svg", "菜单.小e".tr),
|
||||
getBottomNavigationBarItem(
|
||||
"assets/img/menu/message.svg",
|
||||
"assets/img/menu/n_message.svg",
|
||||
"菜单.消息".tr,
|
||||
"assets/img/menu/e.svg", "assets/img/menu/n_e.svg", "菜单.小e".tr),
|
||||
getBottomNavigationBarItem("assets/img/menu/message.svg",
|
||||
"assets/img/menu/n_message.svg", "菜单.消息".tr,
|
||||
showBadge: (messageController.model.body_message_read == 1 ||
|
||||
messageController.model.system_message_read == 1)),
|
||||
getBottomNavigationBarItem("assets/img/menu/mine.svg",
|
||||
@@ -335,10 +333,8 @@ class MainPageBottomChange extends GetView<MainPageController> {
|
||||
bottomItems = [
|
||||
getBottomNavigationBarItem("assets/img/menu/home.svg",
|
||||
"assets/img/menu/n_home.svg", "菜单.首页".tr),
|
||||
getBottomNavigationBarItem(
|
||||
"assets/img/menu/message.svg",
|
||||
"assets/img/menu/n_message.svg",
|
||||
"菜单.消息".tr,
|
||||
getBottomNavigationBarItem("assets/img/menu/message.svg",
|
||||
"assets/img/menu/n_message.svg", "菜单.消息".tr,
|
||||
showBadge: (messageController.model.body_message_read == 1 ||
|
||||
messageController.model.system_message_read == 1)),
|
||||
getBottomNavigationBarItem("assets/img/menu/mine.svg",
|
||||
@@ -391,24 +387,26 @@ class MainPageBottomChange extends GetView<MainPageController> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Future.delayed(const Duration(milliseconds: 0), () {
|
||||
String? isShowYingShiDialog = getStorage.read("isShowYingShiDialog");
|
||||
if (isShowYingShiDialog == null || isShowYingShiDialog != "true") {
|
||||
String btnName = "同意".tr;
|
||||
String cancelName = "取消".tr;
|
||||
if (Platform.isAndroid) cancelName = "退出".tr;
|
||||
if (AppConstants().ent_type == APPPackageType.TH.code) {
|
||||
Future.delayed(const Duration(milliseconds: 0), () {
|
||||
String? isShowYingShiDialog = getStorage.read("isShowYingShiDialog");
|
||||
if (isShowYingShiDialog == null || isShowYingShiDialog != "true") {
|
||||
String btnName = "同意".tr;
|
||||
String cancelName = "取消".tr;
|
||||
if (Platform.isAndroid) cancelName = "退出".tr;
|
||||
|
||||
showCustomConfirmOfWebViewDialog(context, "隐私协议".tr, getPrivacy(1),
|
||||
btnName: btnName, showCancel: true, cancelName: cancelName)
|
||||
.then((e) {
|
||||
if (e == "confirm") {
|
||||
getStorage.write("isShowYingShiDialog", "true");
|
||||
} else {
|
||||
if (cancelName == "退出") SystemNavigator.pop();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
showCustomConfirmOfWebViewDialog(context, "隐私协议".tr, getPrivacy(1),
|
||||
btnName: btnName, showCancel: true, cancelName: cancelName)
|
||||
.then((e) {
|
||||
if (e == "confirm") {
|
||||
getStorage.write("isShowYingShiDialog", "true");
|
||||
} else {
|
||||
if (cancelName == "退出") SystemNavigator.pop();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return PopScope(
|
||||
canPop: false,
|
||||
@@ -436,7 +434,8 @@ class MainPageBottomChange extends GetView<MainPageController> {
|
||||
return Scaffold(
|
||||
body: IndexedStack(
|
||||
index: currentIndex,
|
||||
children: arr.map((page) => SizedBox.expand(child: page)).toList(),
|
||||
children:
|
||||
arr.map((page) => SizedBox.expand(child: page)).toList(),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
@@ -451,7 +450,8 @@ class MainPageBottomChange extends GetView<MainPageController> {
|
||||
backgroundColor: Colors.transparent,
|
||||
body: IndexedStack(
|
||||
index: currentIndex,
|
||||
children: arr.map((page) => SizedBox.expand(child: page)).toList(),
|
||||
children:
|
||||
arr.map((page) => SizedBox.expand(child: page)).toList(),
|
||||
),
|
||||
bottomNavigationBar: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
@@ -497,7 +497,8 @@ class MainPageBottomChange extends GetView<MainPageController> {
|
||||
Get.currentRoute == '/messagePage') {
|
||||
Get.back();
|
||||
}
|
||||
Future.delayed(const Duration(milliseconds: 100), () {
|
||||
Future.delayed(const Duration(milliseconds: 100),
|
||||
() {
|
||||
Get.toNamed("/otherLoginPage");
|
||||
});
|
||||
});
|
||||
@@ -505,7 +506,8 @@ class MainPageBottomChange extends GetView<MainPageController> {
|
||||
}
|
||||
|
||||
if (controller.model.currentIndex != index) {
|
||||
globalController.model.hideBottomNavigationBar = false;
|
||||
globalController.model.hideBottomNavigationBar =
|
||||
false;
|
||||
globalController.updateAll();
|
||||
}
|
||||
|
||||
@@ -527,7 +529,8 @@ class MainPageBottomChange extends GetView<MainPageController> {
|
||||
Future<bool> _handleBackPressed(BuildContext context) async {
|
||||
final currentTime = DateTime.now();
|
||||
if (_lastBackPressedTime == null ||
|
||||
currentTime.difference(_lastBackPressedTime!) > const Duration(seconds: 2)) {
|
||||
currentTime.difference(_lastBackPressedTime!) >
|
||||
const Duration(seconds: 2)) {
|
||||
_lastBackPressedTime = currentTime;
|
||||
TopSlideNotification.show(context, text: "滑动退出提醒".tr);
|
||||
return false;
|
||||
|
||||
@@ -106,53 +106,53 @@ class _VitalSignsSensorState extends State<VitalSignsSensorPage> {
|
||||
left: 0.rpx,
|
||||
child: returnIconButtomNew(),
|
||||
),
|
||||
// Positioned(
|
||||
// right: 0.rpx,
|
||||
// child: ClickableContainer(
|
||||
// backgroundColor: Colors.transparent,
|
||||
// highlightColor: Colors.transparent,
|
||||
// padding: EdgeInsets.symmetric(
|
||||
// horizontal: 30.rpx, vertical: 30.rpx),
|
||||
// onTap: () {
|
||||
// // TopSlideNotification.show(context);
|
||||
// //检测蓝牙是否开启,没有开启提示开启蓝牙
|
||||
// //如果已经开启,则进行x秒的蓝牙扫描
|
||||
// BluetoothHelper.listenBluetoothState((isOn) {
|
||||
// mhtBlueToothController.model.bluetooth = isOn;
|
||||
// mhtBlueToothController.updateAll();
|
||||
// if (!isOn) {
|
||||
// mhtBlueToothController.model.blueRawData = [];
|
||||
// mhtBlueToothController
|
||||
// .model.deviceDataStatus = [];
|
||||
// mhtBlueToothController.updateAll();
|
||||
// _showBluetoothNotEnabledDialog();
|
||||
// }
|
||||
// });
|
||||
// _checkBluetoothPermission();
|
||||
// },
|
||||
// child: Obx(() {
|
||||
// return SizedBox(
|
||||
// width: 34.rpx,
|
||||
// height: mhtBlueToothController.isScanning.value
|
||||
// ? 34.rpx
|
||||
// : 24.rpx,
|
||||
// child: mhtBlueToothController.isScanning.value
|
||||
// ? CircularProgressIndicator(
|
||||
// strokeWidth: 2,
|
||||
// valueColor:
|
||||
// AlwaysStoppedAnimation<Color>(
|
||||
// themeController.currentColor.sc3,
|
||||
// ),
|
||||
// )
|
||||
// : SvgPicture.asset(
|
||||
// 'assets/img/icon/upgrade.svg',
|
||||
// fit: BoxFit.cover,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// );
|
||||
// }),
|
||||
// ),
|
||||
// ),
|
||||
Positioned(
|
||||
right: 0.rpx,
|
||||
child: ClickableContainer(
|
||||
backgroundColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 30.rpx, vertical: 30.rpx),
|
||||
onTap: () {
|
||||
// TopSlideNotification.show(context);
|
||||
//检测蓝牙是否开启,没有开启提示开启蓝牙
|
||||
//如果已经开启,则进行x秒的蓝牙扫描
|
||||
BluetoothHelper.listenBluetoothState((isOn) {
|
||||
mhtBlueToothController.model.bluetooth = isOn;
|
||||
mhtBlueToothController.updateAll();
|
||||
if (!isOn) {
|
||||
mhtBlueToothController.model.blueRawData = [];
|
||||
mhtBlueToothController
|
||||
.model.deviceDataStatus = [];
|
||||
mhtBlueToothController.updateAll();
|
||||
_showBluetoothNotEnabledDialog();
|
||||
}
|
||||
});
|
||||
_checkBluetoothPermission();
|
||||
},
|
||||
child: Obx(() {
|
||||
return SizedBox(
|
||||
width: 34.rpx,
|
||||
height: mhtBlueToothController.isScanning.value
|
||||
? 34.rpx
|
||||
: 24.rpx,
|
||||
child: mhtBlueToothController.isScanning.value
|
||||
? CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor:
|
||||
AlwaysStoppedAnimation<Color>(
|
||||
themeController.currentColor.sc3,
|
||||
),
|
||||
)
|
||||
: SvgPicture.asset(
|
||||
'assets/img/icon/upgrade.svg',
|
||||
fit: BoxFit.cover,
|
||||
color: Colors.white,
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:easydevice/easydevice.dart';
|
||||
import 'package:ef/ef.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutterflow_ui/flutterflow_ui.dart';
|
||||
import 'package:mhtctrl/mhtctrl.dart';
|
||||
import 'package:vbvs_app/common/color/ServiceConstant.dart';
|
||||
import 'package:vbvs_app/common/color/app_uri_status.dart';
|
||||
import 'package:vbvs_app/common/util/DailyLogUtils.dart';
|
||||
@@ -18,6 +19,8 @@ import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
|
||||
import 'package:vbvs_app/model/BleDeviceData.dart';
|
||||
import 'package:vbvs_app/model/api_response.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/component/mht_bind_dialog.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/component/tool/BedControlService.dart';
|
||||
import 'package:vbvs_app/pages/mh_page/device/component/tool/DeviceType.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/homepage/controller/mht_home_controller.dart';
|
||||
@@ -42,6 +45,8 @@ class _DeviceComponentWidgetState extends State<DeviceComponentWidget> {
|
||||
MHTBlueToothController blueteethBindController = Get.find();
|
||||
MHTHomeController homeController = Get.find();
|
||||
var lisObj;
|
||||
late MattressControlService service;
|
||||
late BedControlService bedService;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -232,6 +237,8 @@ class _DeviceComponentWidgetState extends State<DeviceComponentWidget> {
|
||||
TopSlideNotification.show(context,
|
||||
text: response.msg!);
|
||||
if (response.code == HttpStatusCodes.ok) {
|
||||
//关闭闹钟和打鼾干预
|
||||
// resetLastDeviceConfig(widget.bleDevice);
|
||||
homeController.getPersonList();
|
||||
//请求绑定设备列表
|
||||
// homeController.getSleepReport();
|
||||
@@ -761,6 +768,49 @@ class _DeviceComponentWidgetState extends State<DeviceComponentWidget> {
|
||||
|
||||
throw Exception("获取MAC超时".tr);
|
||||
}
|
||||
|
||||
//重置设备闹钟数据和打鼾干预
|
||||
// void resetLastDeviceConfig(BlueToothDataModel bleDevice) {
|
||||
// int deviceType = bleDevice.type;
|
||||
// if (deviceType == 2) {
|
||||
// //床垫
|
||||
// service = MattressControlService((pkg) async {
|
||||
// var bytes = pkg.toBytes();
|
||||
// String serviceCode = "";
|
||||
// if (bleDevice != null) {
|
||||
// if (deviceType == DeviceType.smartBed.value) {
|
||||
// serviceCode = "ffe0/ffe1";
|
||||
// }
|
||||
// if (deviceType == DeviceType.smartMattress.value) {
|
||||
// serviceCode = "fff0/fff2";
|
||||
// }
|
||||
// }
|
||||
// if (bytes[7] != 0x00) {
|
||||
// //打印bytes
|
||||
// String hex = bytes.toString();
|
||||
// print("--------->" + hex);
|
||||
// String hexString = bytes
|
||||
// .map((e) => e.toRadixString(16).padLeft(2, '0'))
|
||||
// .join(' ')
|
||||
// .toUpperCase();
|
||||
// print("--------->hex->" + hexString);
|
||||
// }
|
||||
// int aa = await blueteethBindController.currentDevice!
|
||||
// .write(bleDevice.mac, serviceCode, bytes, withresponse: true);
|
||||
// ef.log(bytes.toString());
|
||||
// return aa == 0 ? true : false;
|
||||
// });
|
||||
// } else if (deviceType == 3) {
|
||||
// //床
|
||||
// bedService = BedControlService(_writeToDevice); // 初始化
|
||||
// }
|
||||
// }
|
||||
|
||||
// Future<bool> _writeToDevice(Uint8List pkg) async {
|
||||
// int result = await bleToolController.ble
|
||||
// .write(macAddress.value, "ffe0/ffe1", pkg, withresponse: true);
|
||||
// return result == 0;
|
||||
// }
|
||||
}
|
||||
|
||||
String parseMacFromBleResponse(List<int> data) {
|
||||
|
||||
512
lib/pages/mh_page/device/component/tool/BedControlService.dart
Normal file
512
lib/pages/mh_page/device/component/tool/BedControlService.dart
Normal file
@@ -0,0 +1,512 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
import 'package:ef/ef.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mhtctrl/mhtctrl.dart';
|
||||
|
||||
class BedControlService {
|
||||
// 协议常量
|
||||
static const List<int> frameHeader = [0xFF, 0xFF, 0xFF, 0xFF, 0x05];
|
||||
static const int minFrameLength = 11;
|
||||
|
||||
final Future<bool> Function(Uint8List) _writeFn;
|
||||
final StreamController<BedStatus> _statusController =
|
||||
StreamController.broadcast();
|
||||
|
||||
Stream<BedStatus> get statusStream => _statusController.stream;
|
||||
|
||||
BedControlService(this._writeFn);
|
||||
|
||||
// 校验和计算(根据协议文档硬编码)
|
||||
static List<int> _getChecksum(int commandCode) {
|
||||
final checksumMap = {
|
||||
0x00: [0xD7, 0x00], // 停止
|
||||
0x01: [0x16, 0xC0], // 头部上升
|
||||
0x02: [0x56, 0xC1], // 头部下降
|
||||
0x03: [0x97, 0x01], // 背部上升
|
||||
0x04: [0xD6, 0xC3], // 背部下降
|
||||
0x05: [0x17, 0x03], // 观影模式
|
||||
0x06: [0x57, 0x02], // 腿部上升
|
||||
0x07: [0x96, 0xC2], // 腿部下降
|
||||
0x08: [0xD6, 0xC6], // 复位
|
||||
0x09: [0x17, 0x06], // 零重力
|
||||
0x0A: [0x57, 0x07], // 记忆1
|
||||
0x0B: [0x96, 0xC7], // 记忆2
|
||||
0x0C: [0xC7, 0x04], // 童锁
|
||||
0x0D: [0x16, 0xC5], // 臀部上升
|
||||
0x0E: [0x56, 0xC4], // 臀部下降
|
||||
0x0F: [0x97, 0x04], // 止鼾
|
||||
0x10: [0xD6, 0xCC], // 背部按摩+
|
||||
0x11: [0x17, 0x0C], // 背部按摩-
|
||||
0x12: [0x57, 0x0D], // 腿部按摩+
|
||||
0x13: [0x96, 0xCD], // 腿部按摩-
|
||||
0x14: [0xD7, 0x0F], // 按摩频率+
|
||||
0x15: [0x16, 0xCF], // 按摩频率-
|
||||
0x16: [0x56, 0xCE], // 按摩时间10min
|
||||
0x17: [0x97, 0x0E], // 按摩时间20min
|
||||
0x18: [0xD7, 0x0A], // 按摩时间30min
|
||||
0x19: [0x16, 0xCA], // 灯光10min
|
||||
0x1A: [0x56, 0xCB], // 灯光8H
|
||||
0x1B: [0x97, 0x0B], // 灯光10H
|
||||
0x1C: [0xD6, 0xC9], // 按摩停止
|
||||
0x2B: [0x97, 0x1F], // 背腿同上
|
||||
0x2C: [0xD6, 0xDD], // 背腿同下
|
||||
0x48: [0xD7, 0x36], // 阅读模式
|
||||
0x49: [0x16, 0xF6], // 舒压模式
|
||||
0x4E: [0x57, 0x34], // 瑜伽模式
|
||||
0x6A: [0x57, 0x2F], // 助眠模式
|
||||
0x50: [0xD7, 0x3C], // 背部按摩强度1
|
||||
0x51: [0x16, 0xFC], // 背部按摩强度2
|
||||
0x52: [0x56, 0xFD], // 背部按摩强度3
|
||||
0x54: [0xD6, 0xFF], // 腿部按摩强度1
|
||||
0x55: [0x17, 0x3F], // 腿部按摩强度2
|
||||
0x56: [0x57, 0x3E], // 腿部按摩强度3
|
||||
0x57: [0x96, 0xFE], // 按摩频率1
|
||||
0x58: [0xD6, 0xFA], // 按摩频率2
|
||||
0x59: [0x17, 0x3A], // 按摩频率3
|
||||
0x5A: [0x57, 0x3B], // 按摩频率4
|
||||
0x4F: [0x96, 0xF4], // 停止背
|
||||
0x53: [0x97, 0x3D], // 停止腿
|
||||
0x47: [0x87, 0x33], // 休闲模式
|
||||
0xE6: [0x46, 0x8B], // 腰部放松
|
||||
0xE5: [0x06, 0x8A], // 腿部放松
|
||||
};
|
||||
return checksumMap[commandCode] ?? [0x00, 0x00];
|
||||
}
|
||||
|
||||
// 基础指令构建(11字节完整格式)
|
||||
Uint8List _buildCommand(int byte5, int byte6, int byte7, int byte8) {
|
||||
final data = Uint8List(11);
|
||||
data.setAll(0, frameHeader); // FF FF FF FF 05
|
||||
data[5] = byte5;
|
||||
data[6] = byte6;
|
||||
data[7] = byte7;
|
||||
data[8] = byte8;
|
||||
final checksum = _getChecksum(byte8);
|
||||
data[9] = checksum[0]; // 校验和高字节
|
||||
data[10] = checksum[1]; // 校验和低字节
|
||||
return data;
|
||||
}
|
||||
|
||||
// 进度控制指令构建(特殊格式)
|
||||
Uint8List _buildProgressCommand(int progress, int baseCmd, int commandCode) {
|
||||
final data = Uint8List(11);
|
||||
data.setAll(0, frameHeader);
|
||||
data[5] = progress;
|
||||
data[6] = baseCmd >> 8;
|
||||
data[7] = baseCmd & 0xFF;
|
||||
data[8] = commandCode;
|
||||
final checksum = _getChecksum(commandCode);
|
||||
data[9] = checksum[0];
|
||||
data[10] = checksum[1];
|
||||
return data;
|
||||
}
|
||||
|
||||
//====== 指令集 ======//
|
||||
|
||||
// 1. 遥控器上报功能(固定10字节)
|
||||
Future<bool> enableRemoteReport() => _sendCommand(
|
||||
[0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x00, 0x00, 0xF2, 0x56, 0x85]);
|
||||
|
||||
// 2. 基础控制指令
|
||||
Future<bool> stop() => _sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x00));
|
||||
Future<bool> moveHeadUp() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x01));
|
||||
Future<bool> moveHeadDown() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x02));
|
||||
Future<bool> moveBackUp() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x03));
|
||||
Future<bool> moveBackDown() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x04));
|
||||
Future<bool> moveLegUp() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x06));
|
||||
Future<bool> moveLegDown() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x07));
|
||||
Future<bool> moveHipUp() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x0D));
|
||||
Future<bool> moveHipDown() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x0E));
|
||||
Future<bool> resetPosition() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x08));
|
||||
|
||||
// 3. 预设模式指令
|
||||
Future<bool> setMovieMode([int progress = 0]) => progress > 0
|
||||
? _sendCommand(_buildProgressCommand(progress, 0x0500, 0x05))
|
||||
: _sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x05));
|
||||
|
||||
Future<bool> setZeroGravity([int progress = 0]) => progress > 0
|
||||
? _sendCommand(_buildProgressCommand(progress, 0x0900, 0x09))
|
||||
: _sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x09));
|
||||
|
||||
Future<bool> setAntiSnore([int progress = 0]) => progress > 0
|
||||
? _sendCommand(_buildProgressCommand(progress, 0x0F00, 0x0F))
|
||||
: _sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x0F));
|
||||
|
||||
//一键放松
|
||||
Future<bool> setSleepAssist() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x6A));
|
||||
// 休闲模式
|
||||
Future<bool> setXiuxianMode() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x05, 0x00, 0x47));
|
||||
|
||||
// 腰部放松
|
||||
Future<bool> setYaoRelaxMode() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x05, 0x00, 0xE6));
|
||||
|
||||
// 腿部放松
|
||||
Future<bool> setLegRelaxMode() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x05, 0x00, 0xE5));
|
||||
Future<bool> setReadingMode() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x48));
|
||||
Future<bool> setRelaxMode() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x49));
|
||||
Future<bool> setYogaMode() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x4E));
|
||||
|
||||
// 4. 记忆功能
|
||||
Future<bool> saveMemory(int slot) {
|
||||
assert(slot >= 1 && slot <= 2);
|
||||
return _sendCommand(
|
||||
_buildCommand(0x00, 0x00, 0x00, slot == 1 ? 0x0A : 0x0B));
|
||||
}
|
||||
|
||||
// 5. 按摩控制
|
||||
Future<bool> increaseBackMassage() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x10));
|
||||
Future<bool> decreaseBackMassage() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x11));
|
||||
Future<bool> increaseLegMassage() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x12));
|
||||
Future<bool> decreaseLegMassage() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x13));
|
||||
Future<bool> increaseMassageFreq() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x14));
|
||||
Future<bool> decreaseMassageFreq() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x15));
|
||||
|
||||
Future<bool> setMassageTime(int minutes) {
|
||||
final cmd = switch (minutes) {
|
||||
10 => _buildCommand(0x00, 0x00, 0x00, 0x16),
|
||||
20 => _buildCommand(0x00, 0x00, 0x00, 0x17),
|
||||
30 => _buildCommand(0x00, 0x00, 0x00, 0x18),
|
||||
_ => _buildCommand(0x00, 0x00, 0x00, 0x16),
|
||||
};
|
||||
return _sendCommand(cmd);
|
||||
}
|
||||
|
||||
Future<bool> stopMassage() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x1C));
|
||||
|
||||
// 6. 灯光控制
|
||||
Future<bool> toggleLight10Min() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x19));
|
||||
Future<bool> toggleLight8H() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x1A));
|
||||
Future<bool> toggleLight10H() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x1B));
|
||||
|
||||
// 7. 组合控制
|
||||
Future<bool> moveBothUp() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x2B));
|
||||
Future<bool> moveBothDown() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x2C));
|
||||
|
||||
// 8. 童锁功能(固定11字节)
|
||||
Future<bool> toggleChildLock() => _sendCommand(
|
||||
[0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x00, 0x05, 0x00, 0x0C, 0xC7, 0x04]);
|
||||
|
||||
// 背部按摩强度控制
|
||||
Future<bool> setBackMassageLevel1() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x50));
|
||||
Future<bool> setBackMassageLevel2() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x51));
|
||||
Future<bool> setBackMassageLevel3() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x52));
|
||||
|
||||
// 腿部按摩强度控制
|
||||
Future<bool> setLegMassageLevel1() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x54));
|
||||
Future<bool> setLegMassageLevel2() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x55));
|
||||
Future<bool> setLegMassageLevel3() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x56));
|
||||
|
||||
//按摩时间
|
||||
Future<bool> setMassageTime10Min() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x16));
|
||||
Future<bool> setMassageTime20Min() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x17));
|
||||
Future<bool> setMassageTime30Min() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x18));
|
||||
|
||||
Future<bool> setMassageFrequency1() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x57));
|
||||
Future<bool> setMassageFrequency2() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x58));
|
||||
Future<bool> setMassageFrequency3() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x59));
|
||||
Future<bool> setMassageFrequency4() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x5A));
|
||||
|
||||
Future<bool> stopLeg() => _sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x53));
|
||||
Future<bool> stopBack() =>
|
||||
_sendCommand(_buildCommand(0x00, 0x00, 0x00, 0x4F));
|
||||
//====== 核心方法 ======//
|
||||
Future<bool> _sendCommand(List<int> command) async {
|
||||
debugPrint(
|
||||
'发送指令: ${command.map((e) => e.toRadixString(16).padLeft(2, '0'))}');
|
||||
try {
|
||||
return await _writeFn(Uint8List.fromList(command));
|
||||
} catch (e) {
|
||||
debugPrint('指令发送失败: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void parseResponse(List<int> data) {
|
||||
if (data.length >= minFrameLength && data[0] == 0xFF && data[1] == 0xFF) {
|
||||
// 设备上报帧处理(第7字节为0x06)
|
||||
if (data[7] == 0x06) {
|
||||
final functionCode = data[8];
|
||||
debugPrint('收到设备上报: 功能码=${functionCode.toRadixString(16)}');
|
||||
}
|
||||
_statusController.add(BedStatus.fromBytes(data));
|
||||
}
|
||||
}
|
||||
|
||||
void dispose() => _statusController.close();
|
||||
|
||||
Future<bool> setAlarm({
|
||||
required bool isStart,
|
||||
required List<String> wakeTime,
|
||||
required List<String> weeks,
|
||||
required bool isMassage,
|
||||
required bool isBell,
|
||||
}) async {
|
||||
// 1. 参数校验
|
||||
if (wakeTime.length != 2 || weeks.length != 7) {
|
||||
debugPrint('参数错误:唤醒时间或星期数不符'.tr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 构造指令(固定头 + 动态数据)
|
||||
final arr = <int>[
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x02, 0x13, // 固定头
|
||||
isStart ? 0x01 : 0xA1, // 开关状态
|
||||
int.parse(wakeTime[0], radix: 16), // 小时(16进制)
|
||||
int.parse(wakeTime[1], radix: 16), // 分钟(16进制)
|
||||
0x00, // 保留位
|
||||
];
|
||||
|
||||
// 3. 计算星期掩码
|
||||
final weekValues = weeks.map((w) => int.tryParse(w) ?? 0).toList();
|
||||
final weekMask = weekValues[0] * 2 + // 周一
|
||||
weekValues[1] * 4 + // 周二
|
||||
weekValues[2] * 8 + // 周三
|
||||
weekValues[3] * 16 + // 周四
|
||||
weekValues[4] * 32 + // 周五
|
||||
weekValues[5] * 64 + // 周六
|
||||
weekValues[6] * 128; // 周日
|
||||
arr.addAll([
|
||||
weekMask,
|
||||
weekMask > 1 ? 1 : 0, // 是否重复
|
||||
0x01, // 固定值
|
||||
isMassage ? 1 : 0,
|
||||
isBell ? 1 : 0,
|
||||
]);
|
||||
|
||||
// 4. 计算校验和(小端序)
|
||||
_addSumInEnd(arr);
|
||||
|
||||
// 5. 发送指令并等待响应
|
||||
debugPrint('闹钟指令: ${arr.map((e) => e.toRadixString(16).padLeft(2, '0'))}');
|
||||
return await _writeFn(Uint8List.fromList(arr));
|
||||
}
|
||||
|
||||
List<int> _calculateChecksum(List<int> data) {
|
||||
int sum = 0;
|
||||
for (var byte in data) {
|
||||
sum += byte;
|
||||
}
|
||||
return [sum & 0xFF, (sum >> 8) & 0xFF];
|
||||
}
|
||||
|
||||
void _addSumInEnd(List<int> arr) {
|
||||
int sum = arr.fold(0, (acc, byte) => acc + byte);
|
||||
arr.add(sum & 0xFF); // 低字节
|
||||
arr.add((sum >> 8) & 0xFF); // 高字节
|
||||
}
|
||||
|
||||
Future<bool> setDeviceTime(DateTime dateTime) async {
|
||||
// 1. 参数校验
|
||||
// if (dateTime.year < 2000 || dateTime.year > 2099) {
|
||||
// debugPrint('年份必须在2000-2099之间');
|
||||
// return false;
|
||||
// }
|
||||
|
||||
DateTime date = DateTime.now();
|
||||
// 2. 构造基础指令数据(不含校验和)
|
||||
final arr = <int>[
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 帧头 (0-3)
|
||||
0x01, 0x00, 0x01, 0x11, // 功能标识:时间校验 (4-7)
|
||||
];
|
||||
|
||||
arr.add(int.parse("${date.hour}", radix: 16));
|
||||
arr.add(int.parse("${date.minute}", radix: 16));
|
||||
arr.add(int.parse("${date.second}", radix: 16));
|
||||
arr.add(int.parse("${date.weekday}", radix: 16));
|
||||
arr.add(int.parse("${date.year}".substring(2), radix: 16));
|
||||
arr.add(int.parse("${date.month}", radix: 16));
|
||||
arr.add(int.parse("${date.day}", radix: 16));
|
||||
|
||||
// 3. 计算并添加校验和(低字节在前)
|
||||
_addSumInEnd(arr);
|
||||
|
||||
// 4. 发送指令
|
||||
debugPrint(
|
||||
'时间校验指令: ${arr.map((e) => e.toRadixString(16).padLeft(2, '0')).join(' ')}');
|
||||
debugPrint('设置时间: ${dateTime.toString()}');
|
||||
return _sendCommand(arr);
|
||||
}
|
||||
|
||||
/// 将DateTime的weekday(1-7)转换为协议要求的星期值
|
||||
/// DateTime.weekday: 1=Monday, 2=Tuesday, ..., 7=Sunday
|
||||
/// 协议要求: 1=周一, 2=周二, ..., 7=周日
|
||||
int _getWeekdayValue(int weekday) {
|
||||
// 由于DateTime的weekday已经是1=周一, 7=周日,直接返回即可
|
||||
return weekday;
|
||||
}
|
||||
|
||||
/// 使用当前系统时间同步设备时间
|
||||
Future<bool> syncDeviceTime() async {
|
||||
final now = DateTime.now();
|
||||
debugPrint('开始同步设备时间: ${now.toString()}');
|
||||
return await setDeviceTime(now);
|
||||
}
|
||||
|
||||
/// 设置自定义时间(部分参数可选)
|
||||
Future<bool> setCustomTime({
|
||||
int? hour,
|
||||
int? minute,
|
||||
int? second = 0,
|
||||
int? year,
|
||||
int? month,
|
||||
int? day,
|
||||
}) async {
|
||||
final now = DateTime.now();
|
||||
final targetTime = DateTime(
|
||||
year ?? now.year,
|
||||
month ?? now.month,
|
||||
day ?? now.day,
|
||||
hour ?? now.hour,
|
||||
minute ?? now.minute,
|
||||
second ?? 0,
|
||||
);
|
||||
|
||||
debugPrint('设置自定义时间: ${targetTime.toString()}');
|
||||
return await setDeviceTime(targetTime);
|
||||
}
|
||||
|
||||
/// 快速设置时间(仅小时和分钟)
|
||||
Future<bool> setTime(int hour, int minute) async {
|
||||
return await setCustomTime(hour: hour, minute: minute, second: 0);
|
||||
}
|
||||
|
||||
/// 设置日期(年、月、日)
|
||||
Future<bool> setDate(int year, int month, int day) async {
|
||||
return await setCustomTime(year: year, month: month, day: day);
|
||||
}
|
||||
|
||||
Future<bool> exec({
|
||||
required ProtocolDoExecFunc func,
|
||||
ProtocolOnStatusFunc? onstatus,
|
||||
int retry = 3,
|
||||
Duration timeout = const Duration(seconds: 3),
|
||||
}) async {
|
||||
for (int i = 0; i < retry; i++) {
|
||||
try {
|
||||
if (i > 0) {
|
||||
//缓一下
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
}
|
||||
var re = await func();
|
||||
if (onstatus == null || re == false) return re;
|
||||
//等待
|
||||
dynamic status = await statusStream.first.timeout(timeout);
|
||||
bool ok = onstatus(status);
|
||||
if (ok) {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
e;
|
||||
if (onstatus == null) return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// BedStatus类保持不变...
|
||||
|
||||
// 床状态模型
|
||||
class BedStatus {
|
||||
final bool headUp;
|
||||
final bool headDown;
|
||||
final bool backUp;
|
||||
final bool backDown;
|
||||
final bool legUp;
|
||||
final bool legDown;
|
||||
final bool hipUp;
|
||||
final bool hipDown;
|
||||
final bool massageOn;
|
||||
final int massageLevel;
|
||||
final int massageTimeRemaining;
|
||||
final bool isChildLocked;
|
||||
|
||||
const BedStatus({
|
||||
required this.headUp,
|
||||
required this.headDown,
|
||||
required this.backUp,
|
||||
required this.backDown,
|
||||
required this.legUp,
|
||||
required this.legDown,
|
||||
required this.hipUp,
|
||||
required this.hipDown,
|
||||
required this.massageOn,
|
||||
required this.massageLevel,
|
||||
required this.massageTimeRemaining,
|
||||
required this.isChildLocked,
|
||||
});
|
||||
|
||||
factory BedStatus.fromBytes(List<int> data) {
|
||||
return BedStatus(
|
||||
headUp: (data[5] & 0x01) != 0,
|
||||
headDown: (data[5] & 0x02) != 0,
|
||||
backUp: (data[6] & 0x01) != 0,
|
||||
backDown: (data[6] & 0x02) != 0,
|
||||
legUp: (data[7] & 0x01) != 0,
|
||||
legDown: (data[7] & 0x02) != 0,
|
||||
hipUp: (data[8] & 0x01) != 0,
|
||||
hipDown: (data[8] & 0x02) != 0,
|
||||
massageOn: (data[9] & 0x0F) != 0,
|
||||
massageLevel: (data[9] >> 4) & 0x0F,
|
||||
massageTimeRemaining: data.length > 10 ? data[10] : 0,
|
||||
isChildLocked: data.length > 11 ? (data[11] & 0x80) != 0 : false,
|
||||
);
|
||||
}
|
||||
|
||||
static const defaultStatus = BedStatus(
|
||||
headUp: false,
|
||||
headDown: false,
|
||||
backUp: false,
|
||||
backDown: false,
|
||||
legUp: false,
|
||||
legDown: false,
|
||||
hipUp: false,
|
||||
hipDown: false,
|
||||
massageOn: false,
|
||||
massageLevel: 0,
|
||||
massageTimeRemaining: 0,
|
||||
isChildLocked: false,
|
||||
);
|
||||
}
|
||||
40
lib/pages/mh_page/device/component/tool/DeviceType.dart
Normal file
40
lib/pages/mh_page/device/component/tool/DeviceType.dart
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
import 'package:ef/ef.dart';
|
||||
|
||||
enum DeviceType {
|
||||
smartBed, // 2: 智能床
|
||||
smartMattress // 3: 智能床垫
|
||||
}
|
||||
|
||||
extension DeviceTypeExtension on DeviceType {
|
||||
/// 获取整型值
|
||||
int get value {
|
||||
switch (this) {
|
||||
case DeviceType.smartBed:
|
||||
return 2;
|
||||
case DeviceType.smartMattress:
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
/// 根据整型值解析为枚举
|
||||
static DeviceType? fromInt(int? type) {
|
||||
switch (type) {
|
||||
case 2:
|
||||
return DeviceType.smartBed;
|
||||
case 3:
|
||||
return DeviceType.smartMattress;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String get description {
|
||||
switch (this) {
|
||||
case DeviceType.smartBed:
|
||||
return "智能电动床".tr;
|
||||
case DeviceType.smartMattress:
|
||||
return "律动智能床垫".tr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,9 +74,9 @@ class MHTBlueToothController extends GetControllerEx<MHTBlueToothModel> {
|
||||
|
||||
RxBool isScanning = false.obs;
|
||||
RxMap<String, Map> localUpgradeMac = <String, Map>{}.obs; //mac 进度
|
||||
String? currentUpgradeVersion;//最新版本号
|
||||
String? currentUpgradeName;//最新固件名
|
||||
String? currentUpgradeUrl;//最新固件名
|
||||
String? currentUpgradeVersion; //最新版本号
|
||||
String? currentUpgradeName; //最新固件名
|
||||
String? currentUpgradeUrl; //最新固件名
|
||||
|
||||
void startStatusPolling() {
|
||||
updateDeviceStatus().then((res) {
|
||||
@@ -264,7 +264,8 @@ class MHTBlueToothController extends GetControllerEx<MHTBlueToothModel> {
|
||||
return ApiResponse(code: -1, msg: "未知错误".tr);
|
||||
}
|
||||
|
||||
saveHabitData(sleepData) async {
|
||||
Future<bool> saveHabitData(sleepData) async {
|
||||
bool resFlag = false;
|
||||
String serviceAddress = ServiceConstant.service_address;
|
||||
String serviceName = ServiceConstant.server_service;
|
||||
String serviceApi = ServiceConstant.user_setting;
|
||||
@@ -281,7 +282,14 @@ class MHTBlueToothController extends GetControllerEx<MHTBlueToothModel> {
|
||||
method: MyHttpMethod.put,
|
||||
queryUrl: queryUrl,
|
||||
data: data,
|
||||
onSuccess: (res) {
|
||||
resFlag = true;
|
||||
},
|
||||
onFailure: (res) {
|
||||
resFlag = false;
|
||||
},
|
||||
);
|
||||
return resFlag;
|
||||
}
|
||||
|
||||
Future<Map> loadHabitDataApi(String mac, {int time = 3}) async {
|
||||
|
||||
@@ -24,6 +24,7 @@ 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';
|
||||
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:EasyDartModule/EasyDartModule.dart' as edm;
|
||||
|
||||
@@ -39,6 +40,7 @@ class _MHTWifiPageState extends State<MHTWifiPage> {
|
||||
GlobalController globalController = Get.find();
|
||||
UserInfoController userInfoController = Get.find();
|
||||
BlueteethBindController blueteethBindController = Get.find();
|
||||
MHTBlueToothController mhtBlueToothController = Get.find();
|
||||
PersonController personController = Get.find();
|
||||
ThemeController themeController = Get.find();
|
||||
var lisObj;
|
||||
@@ -226,6 +228,7 @@ class _MHTWifiPageState extends State<MHTWifiPage> {
|
||||
onBack: () {
|
||||
// Get.offAllNamed('/mHTBlueteethDevicePage',
|
||||
// arguments: widget.deviceInfo.type);
|
||||
blueteethBindController.currentDevice?.disconnect();
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
@@ -928,6 +931,14 @@ class _MHTWifiPageState extends State<MHTWifiPage> {
|
||||
}
|
||||
} else {
|
||||
wifiStatus = false;
|
||||
if (needSuccess) {
|
||||
haveSuccess = true;
|
||||
TopSlideNotification.show(
|
||||
context,
|
||||
text: "配网失败".tr,
|
||||
textColor: themeController.currentColor.sc9,
|
||||
);
|
||||
}
|
||||
}
|
||||
blueteethBindController.wifiStatus.value = wifiStatus ? 1 : 0;
|
||||
} catch (e) {
|
||||
@@ -1348,6 +1359,9 @@ class _MHTWifiPageState extends State<MHTWifiPage> {
|
||||
await blueteethBindController.currentDevice!.disconnect();
|
||||
// blueteethBindController.currentDevice = null;
|
||||
}
|
||||
if (mhtBlueToothController.currentDevice != null) {
|
||||
await mhtBlueToothController.currentDevice!.disconnect();
|
||||
}
|
||||
DailyLogUtils.writeLog("关闭蓝牙连接成功".tr);
|
||||
} catch (e) {
|
||||
DailyLogUtils.writeError("关闭蓝牙连接失败: $e");
|
||||
|
||||
@@ -891,6 +891,14 @@ class _MHTWifiAfterPageState extends State<MHTWifiAfterPage> {
|
||||
}
|
||||
} else {
|
||||
wifiStatus = false;
|
||||
if (needSuccess) {
|
||||
haveSuccess = true;
|
||||
TopSlideNotification.show(
|
||||
context,
|
||||
text: "配网失败".tr,
|
||||
textColor: themeController.currentColor.sc9,
|
||||
);
|
||||
}
|
||||
}
|
||||
blueteethBindController.wifiStatus.value = wifiStatus ? 1 : 0;
|
||||
} catch (e) {
|
||||
|
||||
@@ -87,6 +87,11 @@ class _NewHomePageState extends State<NewHomePage> {
|
||||
if (AppConstants().ent_type != APPPackageType.MHT.code) {
|
||||
return;
|
||||
}
|
||||
if (userInfoController.model.login! == null ||
|
||||
userInfoController.model.login! == 0) {
|
||||
//未登录
|
||||
return;
|
||||
}
|
||||
showTipUpgradeDialog(
|
||||
context,
|
||||
Column(
|
||||
|
||||
@@ -253,7 +253,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
),
|
||||
].divide(SizedBox(width: 22.rpx)),
|
||||
),
|
||||
Text('SWES2025.10.28',
|
||||
Text('SWES2025.10.31',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 26.rpx,
|
||||
|
||||
@@ -58,7 +58,7 @@ class WebviewTestController extends GetControllerEx<WebviewTestModel> {
|
||||
},
|
||||
onLoadResource: (controller, resource) {
|
||||
// sourceTime = web.requestTimestamp;
|
||||
// ef.log("[请求资源时间]${web.requestTimestamp}");`
|
||||
// ef.log("[请求资源时间]${web.requestTimestamp}");
|
||||
// _startMonitoringIfNeeded();
|
||||
},
|
||||
),
|
||||
@@ -216,7 +216,7 @@ class WebviewTestController extends GetControllerEx<WebviewTestModel> {
|
||||
ef.log('更新睡眠习惯: $args[0]');
|
||||
try {
|
||||
MHTBlueToothController blueToothController = Get.find();
|
||||
await blueToothController.saveHabitData(args[0]);
|
||||
return await blueToothController.saveHabitData(args[0]);
|
||||
} catch (e) {
|
||||
ef.log("[更新睡眠习惯失败]:$e");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user