From 103737cec0c9a606b0b11e1bfdea08988e1a84fb Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 20 Aug 2025 14:20:06 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E8=AF=BB=E5=8F=96?= =?UTF-8?q?=E9=94=81=E8=AF=AD=E9=9F=B3=E5=8C=85=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io_readVoicePackageFinalResult.dart | 54 ++++++++++++++ .../io_setVoicePackageFinalResult.dart | 61 ++++++++++++++++ lib/blue/io_type.dart | 24 ++++-- .../speech_language_settings_logic.dart | 32 +++++++- .../lock_voice_setting_logic.dart | 73 ++++++++++++++++++- .../lock_voice_setting_page.dart | 13 ++++ lib/tools/commonItem.dart | 6 +- 7 files changed, 254 insertions(+), 9 deletions(-) create mode 100644 lib/blue/io_protocol/io_readVoicePackageFinalResult.dart create mode 100644 lib/blue/io_protocol/io_setVoicePackageFinalResult.dart diff --git a/lib/blue/io_protocol/io_readVoicePackageFinalResult.dart b/lib/blue/io_protocol/io_readVoicePackageFinalResult.dart new file mode 100644 index 00000000..ac89d688 --- /dev/null +++ b/lib/blue/io_protocol/io_readVoicePackageFinalResult.dart @@ -0,0 +1,54 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:crypto/crypto.dart' as crypto; + +import '../io_reply.dart'; +import '../io_sender.dart'; +import '../io_tool/io_tool.dart'; +import '../io_type.dart'; +import '../sm4Encipher/sm4.dart'; + +//oat升级 +class ReadLockCurrentVoicePacket extends SenderProtocol { + ReadLockCurrentVoicePacket({ + this.lockID, + }) : super(CommandType.readLockCurrentVoicePacket); + String? lockID; + + @override + String toString() { + return 'ReadLockCurrentVoicePacket{lockID: $lockID}'; + } + + @override + List messageDetail() { + List data = []; + + // 指令类型 + final int type = commandType!.typeValue; + final double typeDouble = type / 256; + final int type1 = typeDouble.toInt(); + final int type2 = type % 256; + data.add(type1); + data.add(type2); + + // 锁id 40 + final int lockIDLength = utf8.encode(lockID!).length; + data.addAll(utf8.encode(lockID!)); + data = getFixedLengthList(data, 40 - lockIDLength); + + printLog(data); + return data; + } +} + +class ReadLockCurrentVoicePacketReply extends Reply { + ReadLockCurrentVoicePacketReply.parseData( + CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + status = data[6]; + errorWithStstus(status); + } +} diff --git a/lib/blue/io_protocol/io_setVoicePackageFinalResult.dart b/lib/blue/io_protocol/io_setVoicePackageFinalResult.dart new file mode 100644 index 00000000..962a9fa3 --- /dev/null +++ b/lib/blue/io_protocol/io_setVoicePackageFinalResult.dart @@ -0,0 +1,61 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:crypto/crypto.dart' as crypto; + +import '../io_reply.dart'; +import '../io_sender.dart'; +import '../io_tool/io_tool.dart'; +import '../io_type.dart'; +import '../sm4Encipher/sm4.dart'; + +//oat升级 +class SetVoicePackageFinalResult extends SenderProtocol { + SetVoicePackageFinalResult({ + this.lockID, + this.languageCode, + }) : super(CommandType.setLockCurrentVoicePacket); + String? lockID; + String? languageCode; + + @override + String toString() { + return 'SetVoicePackageFinalResult{lockID: $lockID, languageCode: $languageCode}'; + } + + @override + List messageDetail() { + List data = []; + + // 指令类型 + final int type = commandType!.typeValue; + final double typeDouble = type / 256; + final int type1 = typeDouble.toInt(); + final int type2 = type % 256; + data.add(type1); + data.add(type2); + + // 锁id 40 + final int lockIDLength = utf8.encode(lockID!).length; + data.addAll(utf8.encode(lockID!)); + data = getFixedLengthList(data, 40 - lockIDLength); + + //languageCode 20 + final int languageCodeLength = utf8.encode(languageCode!).length; + data.addAll(utf8.encode(languageCode!)); + data = getFixedLengthList(data, 20 - languageCodeLength); + + printLog(data); + return data; + } +} + +class SetVoicePackageFinalResultReply extends Reply { + SetVoicePackageFinalResultReply.parseData( + CommandType commandType, List dataDetail) + : super.parseData(commandType, dataDetail) { + data = dataDetail; + status = data[6]; + errorWithStstus(status); + } +} diff --git a/lib/blue/io_type.dart b/lib/blue/io_type.dart index ac261daf..33364400 100755 --- a/lib/blue/io_type.dart +++ b/lib/blue/io_type.dart @@ -44,7 +44,9 @@ enum CommandType { startVoicePackageConfigure, //语音包配置开始 0x30A1 voicePackageConfigureProcess, //语音包配置过程 0x30A2 voicePackageConfigureConfirmation, //语音包配置确认 0x30A3 - getDeviceModel, //获取设备型号 0x30A4 + readLockCurrentVoicePacket, //读取锁当前语音包 0x30A4 + setLockCurrentVoicePacket, //设置锁当前语音包 0x30A5 + getDeviceModel, //读取设备型号 (已废弃)0x30A4 gatewayConfiguringWifi, //网关配网 0x30F4 gatewayConfiguringWifiResult, //网关配网结果 0x30F5 @@ -210,7 +212,12 @@ extension ExtensionCommandType on CommandType { break; case 0x30A4: { - type = CommandType.getDeviceModel; + type = CommandType.readLockCurrentVoicePacket; + } + break; + case 0x30A5: + { + type = CommandType.setLockCurrentVoicePacket; } break; case 0x30F4: @@ -340,9 +347,12 @@ extension ExtensionCommandType on CommandType { case CommandType.voicePackageConfigureConfirmation: type = 0x30A3; break; - case CommandType.getDeviceModel: + case CommandType.readLockCurrentVoicePacket: type = 0x30A4; break; + case CommandType.setLockCurrentVoicePacket: + type = 0x30A5; + break; default: type = 0x300A; break; @@ -362,7 +372,8 @@ extension ExtensionCommandType on CommandType { case CommandType.gatewayGetWifiList: case CommandType.gatewayConfiguringWifi: case CommandType.gatewayGetStatus: - case CommandType.getDeviceModel: + case CommandType.readLockCurrentVoicePacket: + case CommandType.setLockCurrentVoicePacket: //不加密 type = 0x20; break; @@ -476,7 +487,10 @@ extension ExtensionCommandType on CommandType { t = '语音包配置确认'; break; case 0x30A4: - t = '获取设备型号'; + t = '读取锁当前语音包'; + break; + case 0x30A5: + t = '设置锁当前语音包'; break; default: t = '读星锁状态信息'; diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart index d98e1992..10636305 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart @@ -12,6 +12,7 @@ import 'package:star_lock/blue/blue_manage.dart'; import 'package:star_lock/blue/io_protocol/io_getDeviceModel.dart'; import 'package:star_lock/blue/io_protocol/io_otaUpgrade.dart'; import 'package:star_lock/blue/io_protocol/io_processOtaUpgrade.dart'; +import 'package:star_lock/blue/io_protocol/io_setVoicePackageFinalResult.dart'; import 'package:star_lock/blue/io_protocol/io_voicePackageConfigure.dart'; import 'package:star_lock/blue/io_protocol/io_voicePackageConfigureProcess.dart'; import 'package:star_lock/blue/io_reply.dart'; @@ -52,6 +53,8 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { _handlerVoicePackageConfigureProcess(reply); } else if (reply is VoicePackageConfigureConfirmationReply) { handleVoiceConfigureThrottled(reply); + } else if (reply is SetVoicePackageFinalResultReply) { + handleSetResult(reply); } }); await initList(); @@ -93,7 +96,7 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { final passthroughItem = PassthroughItem( lang: element.lang, timbres: element.timbres, - langText: '简体中文'.tr + '(中国台湾)'.tr+'(Simplified Chinese TW)', + langText: '简体中文'.tr + '(中国台湾)'.tr + '(Simplified Chinese TW)', name: element.name, ); state.languages.add(passthroughItem); @@ -432,6 +435,33 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { _handlerVoicePackageConfigureConfirmation( VoicePackageConfigureConfirmationReply reply, ) async { + final int status = reply.data[2]; + switch (status) { + case 0x00: + await BlueManage().blueSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState deviceConnectionState) async { + if (deviceConnectionState == BluetoothConnectionState.connected) { + await BlueManage().writeCharacteristicWithResponse( + SetVoicePackageFinalResult( + lockID: BlueManage().connectDeviceName, + languageCode: state.tempLangStr.value, + ).packageData(), + ); + } else if (deviceConnectionState == + BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + showBlueConnetctToast(); + } + }); + break; + default: + showToast('设置'.tr + '失败'.tr); + break; + } + } + + void handleSetResult(SetVoicePackageFinalResultReply reply) async { final int status = reply.data[2]; switch (status) { case 0x00: diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart index 986c7fb6..4d265f54 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart @@ -11,6 +11,7 @@ import 'package:star_lock/appRouters.dart'; import 'package:star_lock/app_settings/app_colors.dart'; import 'package:star_lock/blue/blue_manage.dart'; import 'package:star_lock/blue/io_protocol/io_getDeviceModel.dart'; +import 'package:star_lock/blue/io_protocol/io_readVoicePackageFinalResult.dart'; import 'package:star_lock/blue/io_protocol/io_voicePackageConfigure.dart'; import 'package:star_lock/blue/io_protocol/io_voicePackageConfigureProcess.dart'; import 'package:star_lock/blue/io_reply.dart'; @@ -50,9 +51,12 @@ class LockVoiceSettingLogic extends BaseGetXController { _handlerVoicePackageConfigureProcess(reply); } else if (reply is VoicePackageConfigureConfirmationReply) { handleVoiceConfigureThrottled(reply); + } else if (reply is ReadLockCurrentVoicePacketReply) { + handleLockCurrentVoicePacketResult(reply); } }); initList(); + readLockLanguage(); } void handleVoiceConfigureThrottled( @@ -197,7 +201,7 @@ class LockVoiceSettingLogic extends BaseGetXController { // 开始配置语音包 void _handlerStartVoicePackageConfigure( VoicePackageConfigureReply reply) async { - final int status = reply.data[6]; + final int status = reply.data[3]; switch (status) { case 0x00: //成功 @@ -403,4 +407,71 @@ class LockVoiceSettingLogic extends BaseGetXController { state.data = null; super.onClose(); } + + void readLockLanguage() async { + await BlueManage().blueSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState deviceConnectionState) async { + if (deviceConnectionState == BluetoothConnectionState.connected) { + await BlueManage().writeCharacteristicWithResponse( + ReadLockCurrentVoicePacket( + lockID: BlueManage().connectDeviceName, + ).packageData(), + ); + } else if (deviceConnectionState == + BluetoothConnectionState.disconnected) { + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + showBlueConnetctToast(); + } + }); + } + + void handleLockCurrentVoicePacketResult( + ReadLockCurrentVoicePacketReply reply) { + final int status = reply.data[6]; + switch (status) { + case 0x00: + //成功 + cancelBlueConnetctToastTimer(); + +// 1. 计算 LanguageCode 在字节数组中的起始和结束索引 +// CmdID (2 bytes) + Status (1 byte) = 3 bytes -> LanguageCode 从索引 3 开始 + const int languageCodeStartIndex = 3; + const int languageCodeLength = 20; + const int languageCodeEndIndex = + languageCodeStartIndex + languageCodeLength; // 23 + +// 2. 检查数据长度是否足够 + if (reply.data.length < languageCodeEndIndex) { + throw Exception( + 'Reply data is too short to contain LanguageCode. Expected at least $languageCodeEndIndex bytes, got ${reply.data.length}'); + } +// 3. 从字节数组中截取 LanguageCode 对应的字节段 + List languageCodeBytes = + reply.data.sublist(languageCodeStartIndex, languageCodeEndIndex); + +// 4. 将字节列表转换为字符串 +// 通常这种编码是 UTF-8 或 ASCII + String languageCode = String.fromCharCodes(languageCodeBytes); + +// 5. (可选) 清理字符串:移除可能的填充字符(如空字符 '\0' 或空格) +// 因为字段长度固定为20,不足的部分可能用 '\0' 填充 + languageCode = languageCode.trim(); // 移除首尾空格 + languageCode = + languageCode.replaceAll('\u0000', ''); // 移除空字符 (null bytes) + +// 6. 使用提取到的 languageCode + print('LanguageCode: $languageCode'); // 例如: zh_CN, en_US + break; + case 0x06: + //无权限 + final List token = reply.data.sublist(2, 6); + if (state.data != null) { + sendFileToDevice(state.data!, token); + } + break; + default: + break; + } + } } diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart index eb551980..84502622 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_page.dart @@ -95,6 +95,12 @@ class _LockVoiceSettingState extends State { final soundType = state.soundTypeList.value[index]; return CommonItem( leftTitel: soundType, + leftTitleStyle: TextStyle( + fontSize: 22.sp, + fontWeight: state.selectSoundTypeIndex.value == index + ? FontWeight.bold + : null, + ), rightTitle: '', isHaveLine: !isLastItem, isHaveDirection: false, @@ -135,6 +141,13 @@ class _LockVoiceSettingState extends State { final item = state.languages[index]; return CommonItem( leftTitel: item.langText, + leftTitleStyle: TextStyle( + fontSize: 22.sp, + fontWeight: + state.selectPassthroughListIndex.value == index + ? FontWeight.bold + : null, + ), rightTitle: '', isHaveLine: true, isHaveDirection: false, diff --git a/lib/tools/commonItem.dart b/lib/tools/commonItem.dart index b5c40036..b67615c4 100755 --- a/lib/tools/commonItem.dart +++ b/lib/tools/commonItem.dart @@ -20,7 +20,8 @@ class CommonItem extends StatelessWidget { this.rightWidget, this.isTipsImg, this.action, - this.leftTitleMaxWidth, // 新增属性 + this.leftTitleMaxWidth, // 新增属性 + this.leftTitleStyle, // 新增属性 this.tipsImgAction}) : super(key: key); String? leftTitel; @@ -35,6 +36,7 @@ class CommonItem extends StatelessWidget { bool? setHeight; bool? isTipsImg; bool? isPadding; + TextStyle? leftTitleStyle; // 新增属性 final double? leftTitleMaxWidth; // 新增属性声明 @override @@ -65,7 +67,7 @@ class CommonItem extends StatelessWidget { ), child: Text( leftTitel!, - style: TextStyle(fontSize: 22.sp), + style: leftTitleStyle ?? TextStyle(fontSize: 22.sp), overflow: TextOverflow.ellipsis, // 超出部分显示省略号 maxLines: 3, // 最多显示2行 ), From 6e853024dc33eeaa313c9383c8c5aac8e0750887 Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 20 Aug 2025 14:22:09 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=AF=B9=E8=AE=B2?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E6=97=B6=E4=BD=BF=E7=94=A8=E5=AE=9E=E9=99=85?= =?UTF-8?q?=E6=AC=BE=E9=AB=98=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../views/native/talk_view_native_decode_logic.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart b/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart index c6cb292e..6f93699e 100644 --- a/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart +++ b/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart @@ -98,12 +98,16 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { state.isLoading.value = true; // 创建解码器配置 final config = VideoDecoderConfig( - width: 864, + width: StartChartManage().videoWidth, // 实际视频宽度 - height: 480, + height: StartChartManage().videoHeight, codecType: 'h264', ); // 初始化解码器并获取textureId + AppLog.log('StartChartManage().videoWidth:${StartChartManage() + .videoWidth}'); + AppLog.log('StartChartManage().videoHeight:${StartChartManage() + .videoHeight}'); final textureId = await VideoDecodePlugin.initDecoder(config); if (textureId != null) { Future.microtask(() => state.textureId.value = textureId);