513 lines
17 KiB
Dart
513 lines
17 KiB
Dart
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,
|
||
);
|
||
}
|