Merge remote-tracking branch 'origin/develop_sky_liyi' into develop_sky_liyi
This commit is contained in:
commit
8a5e997262
54
lib/blue/io_protocol/io_readVoicePackageFinalResult.dart
Normal file
54
lib/blue/io_protocol/io_readVoicePackageFinalResult.dart
Normal file
@ -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<int> messageDetail() {
|
||||
List<int> data = <int>[];
|
||||
|
||||
// 指令类型
|
||||
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<int> dataDetail)
|
||||
: super.parseData(commandType, dataDetail) {
|
||||
data = dataDetail;
|
||||
status = data[6];
|
||||
errorWithStstus(status);
|
||||
}
|
||||
}
|
||||
61
lib/blue/io_protocol/io_setVoicePackageFinalResult.dart
Normal file
61
lib/blue/io_protocol/io_setVoicePackageFinalResult.dart
Normal file
@ -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<int> messageDetail() {
|
||||
List<int> data = <int>[];
|
||||
|
||||
// 指令类型
|
||||
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<int> dataDetail)
|
||||
: super.parseData(commandType, dataDetail) {
|
||||
data = dataDetail;
|
||||
status = data[6];
|
||||
errorWithStstus(status);
|
||||
}
|
||||
}
|
||||
@ -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 = '读星锁状态信息';
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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<int> 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<int> token = reply.data.sublist(2, 6);
|
||||
if (state.data != null) {
|
||||
sendFileToDevice(state.data!, token);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,6 +95,12 @@ class _LockVoiceSettingState extends State<LockVoiceSetting> {
|
||||
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<LockVoiceSetting> {
|
||||
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,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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行
|
||||
),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user