599 lines
20 KiB
Dart
Executable File
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:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:network_info_plus/network_info_plus.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:star_lock/appRouters.dart';
import 'package:star_lock/app_settings/app_settings.dart';
import 'package:star_lock/blue/io_gateway/io_gateway_configuringWifi.dart';
import 'package:star_lock/blue/io_gateway/io_gateway_getStatus.dart';
import 'package:star_lock/blue/io_protocol/io_updataLockSet.dart';
import 'package:star_lock/login/login/entity/LoginEntity.dart';
import 'package:star_lock/main/lockDetail/lockDetail/device_network_info.dart';
import 'package:star_lock/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifiEntity.dart';
import 'package:star_lock/mine/gateway/addGateway/gatewayConfigurationWifi/gatewayConfigurationWifi_page.dart';
import 'package:star_lock/mine/gateway/addGateway/gatewayConfigurationWifi/getGatewayConfiguration_entity.dart';
import 'package:star_lock/mine/gateway/addGateway/selectGateway/getGatewayInfo_model.dart';
import 'package:star_lock/talk/starChart/entity/star_chart_register_node_entity.dart';
import 'package:star_lock/talk/starChart/star_chart_manage.dart';
import 'package:star_lock/tools/baseGetXController.dart';
import 'package:star_lock/tools/commonDataManage.dart';
import '../../../../../blue/blue_manage.dart';
import '../../../../../blue/io_protocol/io_configuringWifi.dart';
import '../../../../../blue/io_reply.dart';
import '../../../../../blue/io_tool/io_tool.dart';
import '../../../../../blue/io_tool/manager_event_bus.dart';
import '../../../../../blue/sender_manage.dart';
import '../../../../../network/api_repository.dart';
import '../../../../../tools/eventBusEventManage.dart';
import '../../../../../tools/storage.dart';
import 'configuringWifi_state.dart';
class ConfiguringWifiLogic extends BaseGetXController {
final ConfiguringWifiState state = ConfiguringWifiState();
final int _configurationTimeout = 60; // 配网超时时间(秒)
/// 获取WiFi锁服务IP和端口
Future<void> getWifiLockServiceIpAndPort() async {
try {
final ConfiguringWifiEntity entity =
await ApiRepository.to.getWifiLockServiceIpAndPort();
if (entity.errorCode! == 0) {
state.configuringWifiEntity.value = entity;
} else {
AppLog.log('获取WiFi锁服务IP和端口失败${entity.errorCode}');
}
} catch (e) {
AppLog.log('获取WiFi锁服务IP和端口异常$e');
}
}
/// 更新网络信息到服务器
Future<LoginEntity> updateNetworkInfo({
required String peerId,
required String wifiName,
required String secretKey,
required String deviceMac,
required String networkMac,
}) async {
try {
final LoginEntity entity = await ApiRepository.to.settingDeviceNetwork(
deviceType: 2,
deviceMac: deviceMac,
wifiName: wifiName,
networkMac: networkMac,
secretKey: secretKey,
peerId: peerId,
);
return entity;
} catch (e) {
dismissEasyLoading();
state.sureBtnState.value = 0;
AppLog.log('网络配置异常:$e');
return LoginEntity();
}
}
// 监听设备返回的数据
late StreamSubscription<Reply> _replySubscription;
void _initReplySubscription() {
_replySubscription =
EventBusManager().eventBus!.on<Reply>().listen((Reply reply) async {
// WIFI配网结果
if (reply is GatewayConfiguringWifiResultReply) {
_replySenderConfiguringWifiResult(reply);
}
// wifi配网命令应答结果
if (reply is GatewayConfiguringWifiReply) {
_replySenderConfiguringWifi(reply);
}
if (reply is GatewayGetStatusReply) {
_replyGatewayGetStatusReply(reply);
}
// 上传数据获取锁设置
if (reply is UpdataLockSetReply) {
_replyUpdataLockSetReply(reply);
}
});
}
// WIFI配网操作结果处理
Future<void> _replySenderConfiguringWifi(Reply reply) async {
final int status = reply.data[2];
switch (status) {
case 0x00:
AppLog.log('wifi配网命令回复结果:成功');
break;
default:
//失败
dismissEasyLoading(); // 关闭loading
showToast('配网失败'.tr);
state.isLoading.value = false;
break;
}
}
// WIFI配网结果处理
Future<void> _replySenderConfiguringWifiResult(Reply reply) async {
final int status = reply.data[2];
// 收到响应后,取消蓝牙超时计时器
cancelBlueConnetctToastTimer();
switch (status) {
case 0x00:
// 配网成功 - 不关闭loading保持状态直到全部完成
await Storage.removeLockNetWorkInfoCache();
try {
final int secretKeyJsonLength = (reply.data[4] << 8) + reply.data[3];
final List<int> secretKeyList =
reply.data.sublist(5, 5 + secretKeyJsonLength);
String result = utf8String(secretKeyList);
AppLog.log('解析配网信息: $result');
// 解析 JSON 字符串为 Map
Map<String, dynamic> jsonMap = json.decode(result);
// 提取网络信息
String? peerId = jsonMap['peerId'];
String? wifiName = jsonMap['wifiName'];
String? secretKey = jsonMap['secretKey'];
String? deviceMac = jsonMap['deviceMac'];
String? networkMac = jsonMap['networkMac'];
// 验证关键字段
if (peerId == null ||
peerId.isEmpty ||
secretKey == null ||
secretKey.isEmpty) {
throw Exception('Missing required network information');
}
// 上报服务器 - 注意: sureBtnState 状态将在 updateNetworkInfo 方法中或其回调中完成重置
final info = await updateNetworkInfo(
peerId: peerId,
wifiName: wifiName ?? '',
secretKey: secretKey,
deviceMac: deviceMac ?? '',
networkMac: networkMac ?? '');
if (info.errorCode!.codeIsSuccessful) {
// 设置锁的peerID
StartChartManage().lockNetworkInfo = DeviceNetworkInfo(
wifiName: wifiName,
networkMac: networkMac,
secretKey: secretKey,
peerId: peerId,
);
/// 配网成功后,赋值锁的peerId
StartChartManage().lockPeerId = peerId;
// 保存到缓存
await Storage.saveLockNetWorkInfo(jsonMap);
showToast('配网成功'.tr, something: () {
state.sureBtnState.value = 0; // 确保重置状态
if (state.pageName.value == 'lockSet') {
Get.close(2);
} else {
Get.offAllNamed(Routers.starLockMain);
}
eventBus.fire(SuccessfulDistributionNetwork());
eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true,isUnShowLoading: true));
});
// 获取锁设置
_getUploadLockSet();
} else {
dismissEasyLoading();
// showToast('网络配置失败,请重试'.tr);
state.sureBtnState.value = 0;
}
} catch (e) {
if (EasyLoading.isShow) {
dismissEasyLoading();
}
// showToast('解析配网信息失败,请重试'.tr);
state.sureBtnState.value = 0; // 确保重置状态
AppLog.log('解析配网信息失败: $e');
return; // 添加return阻止后续流程
}
break;
case 0x01:
// WiFi密码错误
if (EasyLoading.isShow) {
dismissEasyLoading();
}
// showToast('WiFi密码错误请重新输入'.tr);
state.sureBtnState.value = 0; // 确保重置状态
break;
case 0x02:
// 找不到WiFi
if (EasyLoading.isShow) {
dismissEasyLoading();
}
// showToast('找不到该WiFi网络请确认WiFi名称正确'.tr);
state.sureBtnState.value = 0; // 确保重置状态
break;
case 0x03:
// 网络连接超时
if (EasyLoading.isShow) {
dismissEasyLoading();
}
// showToast('连接WiFi超时请确保网络信号良好'.tr);
state.sureBtnState.value = 0; // 确保重置状态
break;
default:
// 其他错误
if (EasyLoading.isShow) {
dismissEasyLoading();
}
// showToast('配网失败 (错误码: $status),请重试'.tr);
state.sureBtnState.value = 0; // 确保重置状态
break;
}
}
// 辅助函数:美化 JSON 输出
String prettyPrintJson(String jsonString) {
var jsonObject = json.decode(jsonString);
return JsonEncoder.withIndent(' ').convert(jsonObject);
}
// 点击配置wifi
Future<void> senderConfiguringWifiAction() async {
AppLog.log('开始配网${EasyLoading.isShow}');
if (state.sureBtnState.value == 1) {
AppLog.log('正在配网中请勿重复点击');
return;
}
// 获取网关配置信息
try {
final GetGatewayConfigurationEntity entity = await ApiRepository.to
.getGatewayConfigurationNotLoading(timeout: _configurationTimeout);
if (entity.errorCode!.codeIsSuccessful) {
state.getGatewayConfigurationStr = entity.data ?? '';
} else {
// showToast('获取网关配置失败,请重试'.tr);
AppLog.log('获取网关配置失败,请重试');
return;
}
// 判断是否登录账户
final loginData = await Storage.getLoginData();
if (loginData == null) {
AppLog.log('未检测到登录信息,请重新登录'.tr);
return;
}
// 获取app用户的peerId
String appPeerId = loginData.starchart?.starchartId ?? '';
if (appPeerId.isEmpty) {
AppLog.log('用户ID获取失败请重新登录'.tr);
return;
}
// 处理配置字符串
if (state.getGatewayConfigurationStr.isNotEmpty) {
// 解析 JSON 字符串为 Map
Map<String, dynamic> jsonMap =
json.decode(state.getGatewayConfigurationStr);
// 移除指定的键
jsonMap.remove("starCloudUrl");
jsonMap.remove("starLockPeerId");
// 追加新的键值对
jsonMap['userPeerld'] = appPeerId;
// 将 Map 转换回 JSON 字符串
state.getGatewayConfigurationStr =
json.encode(jsonMap).replaceAll(',', ',\n');
// 确保格式化输出
state.getGatewayConfigurationStr =
prettyPrintJson(state.getGatewayConfigurationStr);
} else {
// 如果为空,则直接赋值
state.getGatewayConfigurationStr = "{\"userPeerld\": \"$appPeerId\"}";
}
} catch (e) {
AppLog.log('网关配置准备失败:${e.toString()}'.tr);
return;
}
// 先设置sureBtnState状态以禁用按钮
state.sureBtnState.value = 1;
// 显示loading如果已经显示则不再重复显示
if (!EasyLoading.isShow) {
showEasyLoading();
}
// 设置蓝牙操作超时处理
showBlueConnetctToastTimer(
action: () {
if (EasyLoading.isShow) {
dismissEasyLoading();
}
state.sureBtnState.value = 0; // 连接超时时重置状态
},
outTimer: 30,
);
// 发送配网指令
BlueManage().blueSendData(
BlueManage().connectDeviceName,
(BluetoothConnectionState connectionState) async {
if (connectionState == BluetoothConnectionState.connected) {
try {
IoSenderManage.gatewayConfiguringWifiCommand(
ssid: state.wifiNameController.text,
password: state.wifiPWDController.text,
gatewayConfigurationStr: state.getGatewayConfigurationStr,
);
// 注意此处不要重置sureBtnState状态等待配网结果回调
} catch (e) {
if (EasyLoading.isShow) {
dismissEasyLoading();
}
cancelBlueConnetctToastTimer();
state.sureBtnState.value = 0; // 发送命令失败时重置状态
// showToast('发送配网指令失败:${e.toString()}'.tr);
}
} else if (connectionState == BluetoothConnectionState.disconnected) {
if (EasyLoading.isShow) {
dismissEasyLoading();
}
cancelBlueConnetctToastTimer();
state.sureBtnState.value = 0; // 蓝牙断开时重置状态
if (state.ifCurrentScreen.value == true) {
showBlueConnetctToast();
}
}
},
isAddEquipment: false,
);
}
// 获取设备状态
Future<void> getDevicesStatusAction() async {
showEasyLoading();
showBlueConnetctToastTimer(action: () {
dismissEasyLoading();
});
BlueManage().blueSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState connectionState) async {
if (connectionState == BluetoothConnectionState.connected) {
IoSenderManage.gatewayGetStatusCommand(
lockID: BlueManage().connectDeviceName,
userID: await Storage.getUid(),
);
} else if (connectionState == BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
if (state.ifCurrentScreen.value == true) {
showBlueConnetctToast();
}
}
}, isAddEquipment: true);
}
final NetworkInfo _networkInfo = NetworkInfo();
Future<String> getWifiName() async {
try {
String? ssid = await _networkInfo.getWifiName();
ssid = ssid ?? '';
ssid = ssid.replaceAll(r'"', '');
return ssid;
} catch (e) {
AppLog.log('获取WiFi名称失败: $e');
return '';
}
}
///定位权限
Future<bool> checkLocationPermission() async {
final PermissionStatus value = await locationPermission();
final bool allow = value != PermissionStatus.permanentlyDenied &&
value != PermissionStatus.denied;
return allow;
}
Future<PermissionStatus> locationPermission() async =>
Permission.location.request();
@override
void onReady() {
super.onReady();
if (state.wifiName.value.isEmpty) {
getWifiName().then((String value) {
state.wifiNameController.text = value;
});
}
getWifiLockServiceIpAndPort();
_initReplySubscription();
}
@override
void onClose() {
_replySubscription.cancel();
cancelBlueConnetctToastTimer(); // 确保取消蓝牙超时计时器
super.onClose();
}
void _replyGatewayGetStatusReply(GatewayGetStatusReply reply) {
final int status = reply.data[2];
//成功
dismissEasyLoading();
cancelBlueConnetctToastTimer();
switch (status) {
case 0x00:
//成功
final GetGatewayInfoModel gatewayModel = GetGatewayInfoModel();
// 网关MAC地址
int index = 3;
final List<int> macList = reply.data.sublist(index, index + 20);
final String macStr = utf8String(macList);
// lockInfo['mac'] = macStr;
gatewayModel.mac = macStr;
index = index + 20;
AppLog.log('MAC地址 macList:$macList macStr:$macStr');
// 网关序列号
final List<int> serialNum = reply.data.sublist(index, index + 20);
final String serialNumStr = utf8String(serialNum);
// lockInfo['serialNum'] = serialNumStr;
gatewayModel.serialNum = serialNumStr;
index = index + 20;
AppLog.log('序列号 serialNum:$serialNum serialNumStr:$serialNumStr');
// 网关版本
final List<int> gatewayVersion = reply.data.sublist(index, index + 20);
final String gatewayVersionStr = utf8String(gatewayVersion);
// lockInfo['gatewayVersion'] = gatewayVersionStr;
gatewayModel.gatewayVersion = gatewayVersionStr;
index = index + 20;
// AppLog.log(
// '软件版本 gatewayVersion:$gatewayVersion gatewayVersionStr:$gatewayVersionStr');
// wifiMac地址
final List<int> wifiMac = reply.data.sublist(index, index + 20);
final String wifiMacStr = utf8String(wifiMac);
// lockInfo['wifiMac'] = wifiMacStr;
gatewayModel.wifiMac = wifiMacStr;
index = index + 20;
AppLog.log('wifiMac地址 wifiMac:$wifiMac wifiMacStr:$wifiMacStr');
// gatewayModel.wifiMac = '00:00:00:00:00:00';
break;
default:
//失败
dismissEasyLoading();
// showToast('获取设备状态失败'.tr);
break;
}
}
// 上传数据获取设置
Future<void> _getUploadLockSet() async {
final List<String>? token = await Storage.getStringList(saveBlueToken);
final List<int> getTokenList = changeStringListToIntList(token!);
// 蓝牙获取锁设置
await _uploadLockSet(getTokenList);
}
// 公共的上传锁设置
Future<void> _uploadLockSet(List<int> token) async {
final List<String>? privateKey =
await Storage.getStringList(saveBluePrivateKey);
if (privateKey == null || privateKey.isEmpty) {
throw Exception('Private key is empty');
}
final List<int> getPrivateKeyList = changeStringListToIntList(privateKey);
final List<String>? signKey = await Storage.getStringList(saveBlueSignKey);
if (signKey == null || signKey.isEmpty) {
throw Exception('Sign key is empty');
}
final List<int> signKeyDataList = changeStringListToIntList(signKey);
BlueManage().blueSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState connectionState) async {
if (connectionState == BluetoothConnectionState.connected) {
IoSenderManage.updataLockSetCommand(
lockID: BlueManage().connectDeviceName,
userID: await Storage.getUid(),
token: token,
needAuthor: 1,
signKey: signKeyDataList,
privateKey: getPrivateKeyList,
);
} else if (connectionState == BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
if (state.ifCurrentScreen.value == true) {
showBlueConnetctToast();
}
}
}, isAddEquipment: true);
}
// 上传数据获取锁设置解析
Future<void> _replyUpdataLockSetReply(Reply reply) async {
final int status = reply.data[2];
// 保持loading状态直到整个过程完成
cancelBlueConnetctToastTimer();
switch (status) {
case 0x00:
await _lockDataUpload(
uploadType: 1,
recordType: 0,
records: reply.data.sublist(7, reply.data.length));
break;
case 0x06:
//无权限尝试重新获取token
try {
final List<int> token = reply.data.sublist(3, 7);
final List<String> saveStrList = changeIntListToStringList(token);
await Storage.setStringList(saveBlueToken, saveStrList);
_uploadLockSet(token);
} catch (e) {
if (EasyLoading.isShow) {
dismissEasyLoading(); // 错误时关闭loading
}
// showToast('获取设置权限失败:${e.toString()}'.tr);
state.sureBtnState.value = 0; // 确保重置状态
}
break;
default:
if (EasyLoading.isShow) {
dismissEasyLoading(); // 错误时关闭loading
}
// showToast('获取锁设置失败 (错误码: $status)'.tr);
state.sureBtnState.value = 0; // 确保重置状态
break;
}
}
// 锁数据上传服务器
Future<void> _lockDataUpload(
{required int uploadType,
required int recordType,
required List records}) async {
final LoginEntity entity = await ApiRepository.to.lockDataUpload(
lockId: state.lockBasicInfo.value.lockId ?? -1,
uploadType: uploadType,
recordType: recordType,
records: records,
isUnShowLoading: true);
if (entity.errorCode!.codeIsSuccessful) {
eventBus
.fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value));
}
}
}