app-starlock/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart

367 lines
13 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:star_lock/app_settings/app_settings.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_otaUpgrade.dart';
import 'package:star_lock/blue/io_protocol/io_processOtaUpgrade.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';
import 'package:star_lock/blue/io_tool/io_tool.dart';
import 'package:star_lock/blue/io_tool/manager_event_bus.dart';
import 'package:star_lock/login/login/entity/LoginEntity.dart';
import 'package:star_lock/login/selectCountryRegion/common/index.dart';
import 'package:star_lock/main/lockDetail/lockDetail/passthrough_item.dart';
import 'package:star_lock/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_state.dart';
import 'package:star_lock/network/api_repository.dart';
import 'package:star_lock/tools/baseGetXController.dart';
import 'package:http/http.dart' as http;
import 'package:star_lock/tools/commonDataManage.dart';
import 'package:star_lock/tools/eventBusEventManage.dart';
import 'package:star_lock/tools/storage.dart';
class SpeechLanguageSettingsLogic extends BaseGetXController {
final SpeechLanguageSettingsState state = SpeechLanguageSettingsState();
StreamSubscription<Reply>? _replySubscription;
@override
void onInit() async {
super.onInit();
_replySubscription =
EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
if (reply is GetDeviceModelReply) {
// 获取设备型号
_handlerDeviceModelReply(reply);
}
if (reply is VoicePackageConfigureReply) {
// 语言包配置开始
_handlerStartVoicePackageConfigure(reply);
} else if (reply is VoicePackageConfigureProcessReply) {
_handlerVoicePackageConfigureProcess(reply);
} else if (reply is VoicePackageConfigureConfirmationReply) {
final PassthroughItem item =
state.languages[state.selectPassthroughListIndex.value];
final timbre = item.timbres[state.selectLanguageIndex.value];
final LoginEntity entity =
await ApiRepository.to.settingCurrentVoiceTimbre(
data: {
'lang': item.lang,
'timbre': timbre.timbre,
},
lockId: state.lockSetInfoData.value.lockId!,
);
if (entity.errorCode!.codeIsSuccessful) {
showSuccess('设置成功'.tr, something: () {
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre
?.lang = item.lang;
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre
?.timbre = timbre.timbre;
eventBus.fire(
PassCurrentLockInformationEvent(state.lockSetInfoData.value));
});
}
dismissEasyLoading();
}
});
state.deviceModel.value = await Storage.getString(deviceModel) ?? '';
debugPrint('设备型号:${state.deviceModel.value}');
if (state.deviceModel.value != null) {
await initList();
}
// await sendGetDeviceModelBleMessage();
}
/// 获取列表
initList() async {
showEasyLoading();
try {
final PassthroughListResponse entity = await ApiRepository.to
.getPassthroughList(data: {'deviceType': state.deviceModel.value});
if (entity.errorCode!.codeIsSuccessful) {
state.languages.value = entity.data!!;
final oldTimbre = state
.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre;
final oldLang = state
.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang;
for (int index = 0; index < state.languages.value.length; index++) {
final element = state.languages.value[index];
final timbres = element.timbres;
for (int i = 0; i < timbres.length; i++) {
final timbre = timbres[i].timbre;
if ((oldLang != null && oldLang == element.lang) &&
(oldTimbre != null && oldTimbre == timbre)) {
state.selectPassthroughListIndex.value = index;
state.selectLanguageIndex.value = i;
}
}
}
}
} catch (e) {
debugPrint('获取语音包出现错误:$e');
} finally {
dismissEasyLoading();
}
}
void saveSpeechLanguageSettings() async {
// 如果已经开始发送中则不处理保存点击事件
if (state.progress.value > 0) {
return;
}
final oldTimbre =
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre;
final oldLang =
state.lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang;
EasyLoading.showProgress(state.progress.value, status: '正在发送数据');
final PassthroughItem item =
state.languages[state.selectPassthroughListIndex.value];
final timbre = item.timbres[state.selectLanguageIndex.value];
debugPrint('选中的语音是:${timbre}');
if ((oldLang != null && oldLang == item.lang) &&
(oldTimbre != null && oldTimbre == timbre.timbre)) {
showToast('已设置为当前选择的语音包'.tr);
}
await downloadFile(timbre.timbrePackUrl);
}
void changeSelectIndex(int index) {
state.selectLanguageIndex.value = index;
}
//下载语音包
Future<void> downloadFile(String url) async {
final http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
state.data = response.bodyBytes;
sendFileToDevice(response.bodyBytes, <int>[0, 0, 0, 0]);
}
}
sendFileToDevice(Uint8List data, List<int> token) {
showEasyLoading();
showBlueConnetctToastTimer(action: () {
dismissEasyLoading();
});
BlueManage().blueSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState deviceConnectionState) async {
if (deviceConnectionState == BluetoothConnectionState.connected) {
final List<String>? privateKey =
await Storage.getStringList(saveBluePrivateKey);
final List<int> getPrivateKeyList =
changeStringListToIntList(privateKey!);
final List<String>? signKey =
await Storage.getStringList(saveBlueSignKey);
final List<int> signKeyDataList = changeStringListToIntList(signKey!);
final String uid = await Storage.getUid() ?? '';
final String md5Str = md5.convert(data).toString().toUpperCase();
BlueManage().writeCharacteristicWithResponse(
VoicePackageConfigure(
lockID: BlueManage().connectDeviceName,
userID: uid,
keyID: BlueManage().connectDeviceName,
platform: 0,
product: 0,
fwSize: data.length,
fwMD5: md5Str,
needAuthor: 1,
token: token,
signKey: signKeyDataList,
privateKey: getPrivateKeyList)
.packageData(),
);
} else if (deviceConnectionState ==
BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
}
});
}
// 发送获取型号蓝牙命令
sendGetDeviceModelBleMessage() {
showEasyLoading();
showBlueConnetctToastTimer(action: () {
dismissEasyLoading();
});
BlueManage().blueSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState deviceConnectionState) async {
if (deviceConnectionState == BluetoothConnectionState.connected) {
BlueManage().writeCharacteristicWithResponse(
GetDeviceModelCommand(
lockID: BlueManage().connectDeviceName,
).packageData(),
);
} else if (deviceConnectionState ==
BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
showBlueConnetctToast();
}
});
}
void _handlerDeviceModelReply(GetDeviceModelReply reply) async {
final int status = reply.data[2];
switch (status) {
case 0x00:
//成功
cancelBlueConnetctToastTimer();
// 3. 解析DeviceModel40字节索引3~42
int startIndex = 3;
int length = 40;
List<int> deviceModelBytes =
reply.data.sublist(startIndex, startIndex + length);
String rawData = String.fromCharCodes(deviceModelBytes);
int firstNullIndex = rawData.indexOf('\u0000');
String deviceModel = rawData.substring(0, firstNullIndex);
print(deviceModel); // 输出: 2403
print('获取到 DeviceModel (原始): $deviceModel');
state.deviceModel.value = deviceModel;
await initList();
break;
default:
showToast('获取设备型号失败'.tr);
break;
}
}
// 开始配置语音包
void _handlerStartVoicePackageConfigure(
VoicePackageConfigureReply reply) async {
final int status = reply.data[6];
switch (status) {
case 0x00:
//成功
cancelBlueConnetctToastTimer();
_startSendLanguageFile();
break;
case 0x06:
//无权限
final List<int> token = reply.data.sublist(2, 6);
print('收到token:$token');
if (state.data != null) {
sendFileToDevice(state.data!, token);
}
break;
default:
showToast('获取设备型号失败'.tr);
break;
}
}
void _startSendLanguageFile() {
if (state.data == null) return;
state.voiceSubcontractingIndex = 0;
state.voiceSubcontractingCount =
(state.data!.length + state.voiceSubcontractingSize - 1) ~/
state.voiceSubcontractingSize;
state.progress.value = 0.0; // 开始前重置进度
_sendNextPackage();
}
void _sendNextPackage() {
if (state.voiceSubcontractingIndex >= state.voiceSubcontractingCount) {
print('所有分包已发送完成');
state.progress.value = 1.0; // 发送完成
// 可在此处通知UI或做后续处理
return;
}
int start = state.voiceSubcontractingIndex * state.voiceSubcontractingSize;
int end = start + state.voiceSubcontractingSize;
if (end > state.data!.length) end = state.data!.length;
Uint8List packageData = state.data!.sublist(start, end);
// 更新分包进度
state.progress.value =
(state.voiceSubcontractingIndex + 1) / state.voiceSubcontractingCount;
EasyLoading.showProgress(state.progress.value,
status: '正在发送数据 ${(state.progress.value * 100).toStringAsFixed(0)}%');
_sendLanguageFileBleMessage(
index: state.voiceSubcontractingIndex,
data: packageData,
);
}
_sendLanguageFileBleMessage({required int index, required Uint8List data}) {
BlueManage().blueSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState deviceConnectionState) async {
if (deviceConnectionState == BluetoothConnectionState.connected) {
BlueManage().writeCharacteristicWithResponse(
VoicePackageConfigureProcess(
index: index,
size: data.length,
data: data,
).packageData(),
);
} else if (deviceConnectionState ==
BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
showBlueConnetctToast();
}
});
}
void _handlerVoicePackageConfigureProcess(
VoicePackageConfigureProcessReply reply) {
final int status = reply.data[2];
switch (status) {
case 0x00:
cancelBlueConnetctToastTimer();
state.voiceSubcontractingIndex++;
_sendNextPackage();
break;
default:
showToast('发送分包数据不成功'.tr);
break;
}
}
@override
void dispose() async {
await _replySubscription?.cancel();
_replySubscription = null;
await BlueManage().disconnect();
dismissEasyLoading();
cancelBlueConnetctToastTimer();
EasyLoading.dismiss();
// 清理分包相关状态
state.progress.value = 0.0;
state.voiceSubcontractingIndex = 0;
state.voiceSubcontractingCount = 0;
state.data = null;
super.dispose();
}
@override
void onClose() async {
await _replySubscription?.cancel();
_replySubscription = null;
await BlueManage().disconnect();
dismissEasyLoading();
cancelBlueConnetctToastTimer();
EasyLoading.dismiss();
// 清理分包相关状态
state.progress.value = 0.0;
state.voiceSubcontractingIndex = 0;
state.voiceSubcontractingCount = 0;
state.data = null;
super.onClose();
}
}