Merge branch 'develop_liyi' into 'canary_release'
Develop liyi See merge request StarlockTeam/app-starlock!4
This commit is contained in:
commit
1a235bcb62
@ -68,6 +68,7 @@ class LoginData {
|
|||||||
void updateStarchart(
|
void updateStarchart(
|
||||||
StarChartRegisterNodeEntity starChartRegisterNodeEntity) {
|
StarChartRegisterNodeEntity starChartRegisterNodeEntity) {
|
||||||
starchart = Starchart(
|
starchart = Starchart(
|
||||||
|
scdUrl: this.starchart?.scdUrl,
|
||||||
starchartId: starChartRegisterNodeEntity.peer?.id,
|
starchartId: starChartRegisterNodeEntity.peer?.id,
|
||||||
starchartPeerPublicKey: starChartRegisterNodeEntity.peer?.publicKey,
|
starchartPeerPublicKey: starChartRegisterNodeEntity.peer?.publicKey,
|
||||||
starchartPeerPrivateKey: starChartRegisterNodeEntity.peer?.privateKey,
|
starchartPeerPrivateKey: starChartRegisterNodeEntity.peer?.privateKey,
|
||||||
|
|||||||
@ -80,7 +80,7 @@ class StarLockLoginLogic extends BaseGetXController {
|
|||||||
Storage.saveStarChartRegisterNodeInfo(starChartRegisterNodeEntity);
|
Storage.saveStarChartRegisterNodeInfo(starChartRegisterNodeEntity);
|
||||||
entity.data!.updateStarchart(starChartRegisterNodeEntity);
|
entity.data!.updateStarchart(starChartRegisterNodeEntity);
|
||||||
}
|
}
|
||||||
Storage.saveLoginData(entity.data);
|
await Storage.saveLoginData(entity.data);
|
||||||
Storage.setBool(saveIsVip, entity.data!.isVip == 1);
|
Storage.setBool(saveIsVip, entity.data!.isVip == 1);
|
||||||
eventBus.fire(MineInfoChangeRefreshUI());
|
eventBus.fire(MineInfoChangeRefreshUI());
|
||||||
if (Get.isRegistered<LockMainLogic>()) {
|
if (Get.isRegistered<LockMainLogic>()) {
|
||||||
|
|||||||
@ -212,7 +212,15 @@ class ConfiguringWifiLogic extends BaseGetXController {
|
|||||||
// 显示加载指示器
|
// 显示加载指示器
|
||||||
showEasyLoading();
|
showEasyLoading();
|
||||||
state.isLoading.value = true;
|
state.isLoading.value = true;
|
||||||
// 模拟异步请求
|
// 添加15秒超时检查
|
||||||
|
Future.delayed(const Duration(seconds: 15), () {
|
||||||
|
if (state.isLoading.isTrue) {
|
||||||
|
EasyLoading.dismiss();
|
||||||
|
state.isLoading.value = false;
|
||||||
|
state.sureBtnState.value = 0;
|
||||||
|
showToast('配网失败'.tr);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取设备状态
|
// 获取设备状态
|
||||||
|
|||||||
@ -158,7 +158,8 @@ class Starchart {
|
|||||||
String? starchartPeerPrivateKey;
|
String? starchartPeerPrivateKey;
|
||||||
|
|
||||||
Starchart(
|
Starchart(
|
||||||
{this.scdUrl,this.starchartId,
|
{this.scdUrl,
|
||||||
|
this.starchartId,
|
||||||
this.starchartPeerPublicKey,
|
this.starchartPeerPublicKey,
|
||||||
this.starchartPeerPrivateKey});
|
this.starchartPeerPrivateKey});
|
||||||
|
|
||||||
|
|||||||
@ -6,10 +6,11 @@ import 'package:star_lock/network/api_provider_base.dart';
|
|||||||
import 'package:star_lock/talk/starChart/entity/relay_info_entity.dart';
|
import 'package:star_lock/talk/starChart/entity/relay_info_entity.dart';
|
||||||
import 'package:star_lock/talk/starChart/entity/report_information_data.dart';
|
import 'package:star_lock/talk/starChart/entity/report_information_data.dart';
|
||||||
import 'package:star_lock/talk/starChart/entity/star_chart_register_node_entity.dart';
|
import 'package:star_lock/talk/starChart/entity/star_chart_register_node_entity.dart';
|
||||||
|
import 'package:star_lock/tools/storage.dart';
|
||||||
|
|
||||||
class StartChartApi extends BaseProvider {
|
class StartChartApi extends BaseProvider {
|
||||||
// 星图url
|
// 星图url
|
||||||
String _startChartHost = 'http://sls1-scd.star-lock.cn:8080';
|
String _startChartHost = '';
|
||||||
|
|
||||||
static StartChartApi get to => Get.put(StartChartApi());
|
static StartChartApi get to => Get.put(StartChartApi());
|
||||||
|
|
||||||
@ -28,6 +29,17 @@ class StartChartApi extends BaseProvider {
|
|||||||
required String name,
|
required String name,
|
||||||
required String unique,
|
required String unique,
|
||||||
}) async {
|
}) async {
|
||||||
|
final loginData = await Storage.getLoginData();
|
||||||
|
|
||||||
|
// 获取星图url
|
||||||
|
if (loginData != null &&
|
||||||
|
loginData?.starchart != null &&
|
||||||
|
loginData?.starchart?.scdUrl != null &&
|
||||||
|
loginData?.starchart?.scdUrl != '') {
|
||||||
|
StartChartApi.to.startChartHost =
|
||||||
|
loginData!.starchart!.scdUrl ?? StartChartApi.to.startChartHost;
|
||||||
|
}
|
||||||
|
|
||||||
final response = await post(
|
final response = await post(
|
||||||
_startChartHost + starChartRegisterNodeURL.toUrl,
|
_startChartHost + starChartRegisterNodeURL.toUrl,
|
||||||
jsonEncode(<String, dynamic>{
|
jsonEncode(<String, dynamic>{
|
||||||
@ -44,6 +56,17 @@ class StartChartApi extends BaseProvider {
|
|||||||
|
|
||||||
// 星图--中继查询
|
// 星图--中继查询
|
||||||
Future<RelayInfoEntity> relayQueryInfo() async {
|
Future<RelayInfoEntity> relayQueryInfo() async {
|
||||||
|
final loginData = await Storage.getLoginData();
|
||||||
|
|
||||||
|
// 获取星图url
|
||||||
|
if (loginData != null &&
|
||||||
|
loginData?.starchart != null &&
|
||||||
|
loginData?.starchart?.scdUrl != null &&
|
||||||
|
loginData?.starchart?.scdUrl != '') {
|
||||||
|
StartChartApi.to.startChartHost =
|
||||||
|
loginData!.starchart!.scdUrl ?? StartChartApi.to.startChartHost;
|
||||||
|
}
|
||||||
|
|
||||||
final response = await get(
|
final response = await get(
|
||||||
_startChartHost + relayQueryInfoURL.toUrl,
|
_startChartHost + relayQueryInfoURL.toUrl,
|
||||||
isUnShowLoading: true,
|
isUnShowLoading: true,
|
||||||
@ -56,6 +79,17 @@ class StartChartApi extends BaseProvider {
|
|||||||
Future<Response> reportInformation({
|
Future<Response> reportInformation({
|
||||||
required ReportInformationData reportInformationData,
|
required ReportInformationData reportInformationData,
|
||||||
}) async {
|
}) async {
|
||||||
|
final loginData = await Storage.getLoginData();
|
||||||
|
|
||||||
|
// 获取星图url
|
||||||
|
if (loginData != null &&
|
||||||
|
loginData?.starchart != null &&
|
||||||
|
loginData?.starchart?.scdUrl != null &&
|
||||||
|
loginData?.starchart?.scdUrl != '') {
|
||||||
|
StartChartApi.to.startChartHost =
|
||||||
|
loginData!.starchart!.scdUrl ?? StartChartApi.to.startChartHost;
|
||||||
|
}
|
||||||
|
|
||||||
final response = await post(
|
final response = await post(
|
||||||
_startChartHost + reportInformationDataURL.toUrl,
|
_startChartHost + reportInformationDataURL.toUrl,
|
||||||
jsonEncode(reportInformationData.toJson()),
|
jsonEncode(reportInformationData.toJson()),
|
||||||
@ -69,6 +103,17 @@ class StartChartApi extends BaseProvider {
|
|||||||
Future<Response> analyzeInformationOtherEnd({
|
Future<Response> analyzeInformationOtherEnd({
|
||||||
required String peerId,
|
required String peerId,
|
||||||
}) async {
|
}) async {
|
||||||
|
final loginData = await Storage.getLoginData();
|
||||||
|
|
||||||
|
// 获取星图url
|
||||||
|
if (loginData != null &&
|
||||||
|
loginData?.starchart != null &&
|
||||||
|
loginData?.starchart?.scdUrl != null &&
|
||||||
|
loginData?.starchart?.scdUrl != '') {
|
||||||
|
StartChartApi.to.startChartHost =
|
||||||
|
loginData!.starchart!.scdUrl ?? StartChartApi.to.startChartHost;
|
||||||
|
}
|
||||||
|
|
||||||
final response = await get(
|
final response = await get(
|
||||||
_startChartHost + analyzeInformationOtherEndURL.toUrl + '?id=$peerId',
|
_startChartHost + analyzeInformationOtherEndURL.toUrl + '?id=$peerId',
|
||||||
isUnShowLoading: true,
|
isUnShowLoading: true,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:convert/convert.dart';
|
import 'package:convert/convert.dart';
|
||||||
import 'package:fast_rsa/fast_rsa.dart' as fastRsa;
|
// import 'package:fast_rsa/fast_rsa.dart' as fastRsa;
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:pointycastle/export.dart' as pc;
|
import 'package:pointycastle/export.dart' as pc;
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
@ -11,6 +11,31 @@ import 'package:star_lock/talk/starChart/exception/start_chart_message_exception
|
|||||||
|
|
||||||
class DoSign {
|
class DoSign {
|
||||||
// 生成签名sing
|
// 生成签名sing
|
||||||
|
// Future<String> generateSign({
|
||||||
|
// required int currentTimestamp,
|
||||||
|
// required String privateKeyHex,
|
||||||
|
// }) async {
|
||||||
|
// String resultSign = '';
|
||||||
|
// try {
|
||||||
|
// // 1. 将 32 位时间戳以小端字节序编码为二进制数据
|
||||||
|
// Uint8List signData = encodeTimestampToLittleEndianBytes(currentTimestamp);
|
||||||
|
//
|
||||||
|
// // 2.将十六进制字符串转换为字节数组
|
||||||
|
// List<int> privateKeyBytes = hexToBytes(privateKeyHex);
|
||||||
|
//
|
||||||
|
// // 3.将私钥转换为 PEM 格式
|
||||||
|
// final pemPrivateKey =
|
||||||
|
// convertToPemPrivateKey(privateKeyBytes, isPKCS8: true);
|
||||||
|
// // 4.签名
|
||||||
|
// var result = await fastRsa.RSA
|
||||||
|
// .signPKCS1v15Bytes(signData, fastRsa.Hash.SHA256, pemPrivateKey);
|
||||||
|
// resultSign = hex.encode(result);
|
||||||
|
// } catch (e) {
|
||||||
|
// throw StartChartMessageException('❌--->上报信息生成签名时出现错误: $e');
|
||||||
|
// }
|
||||||
|
// return resultSign ?? '';
|
||||||
|
// }
|
||||||
|
|
||||||
Future<String> generateSign({
|
Future<String> generateSign({
|
||||||
required int currentTimestamp,
|
required int currentTimestamp,
|
||||||
required String privateKeyHex,
|
required String privateKeyHex,
|
||||||
@ -20,20 +45,20 @@ class DoSign {
|
|||||||
// 1. 将 32 位时间戳以小端字节序编码为二进制数据
|
// 1. 将 32 位时间戳以小端字节序编码为二进制数据
|
||||||
Uint8List signData = encodeTimestampToLittleEndianBytes(currentTimestamp);
|
Uint8List signData = encodeTimestampToLittleEndianBytes(currentTimestamp);
|
||||||
|
|
||||||
// 2.将十六进制字符串转换为字节数组
|
// 2. 加载私钥
|
||||||
List<int> privateKeyBytes = hexToBytes(privateKeyHex);
|
final privateKey = loadPrivateKey(privateKeyHex);
|
||||||
|
|
||||||
// 3.将私钥转换为 PEM 格式
|
// 3. 创建 RSA 签名器
|
||||||
final pemPrivateKey =
|
final signer = pc.RSASigner(pc.SHA256Digest(), '0609608648016503040201');
|
||||||
convertToPemPrivateKey(privateKeyBytes, isPKCS8: true);
|
signer.init(true, pc.PrivateKeyParameter<pc.RSAPrivateKey>(privateKey));
|
||||||
// 4.签名
|
|
||||||
var result = await fastRsa.RSA
|
// 4. 生成签名
|
||||||
.signPKCS1v15Bytes(signData, fastRsa.Hash.SHA256, pemPrivateKey);
|
final signature = signer.generateSignature(signData);
|
||||||
resultSign = hex.encode(result);
|
resultSign = hex.encode(signature.bytes);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw StartChartMessageException('❌--->上报信息生成签名时出现错误: $e');
|
throw StartChartMessageException('❌--->上报信息生成签名时出现错误: $e');
|
||||||
}
|
}
|
||||||
return resultSign ?? '';
|
return resultSign;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将 32 位时间戳以小端字节序编码为二进制数据
|
// 将 32 位时间戳以小端字节序编码为二进制数据
|
||||||
|
|||||||
@ -186,7 +186,7 @@ class StartChartManage {
|
|||||||
for (int i = 0; i <= relayInfoEntity.relay_list!.length; i++) {
|
for (int i = 0; i <= relayInfoEntity.relay_list!.length; i++) {
|
||||||
final data = relayInfoEntity.relay_list?[i];
|
final data = relayInfoEntity.relay_list?[i];
|
||||||
if (data?.peerID != FromPeerId) {
|
if (data?.peerID != FromPeerId) {
|
||||||
final parseUdpUrl = _parseUdpUrl(data?.listenAddr ?? '');
|
final parseUdpUrl = await _parseUdpUrl(data?.listenAddr ?? '');
|
||||||
remoteHost = parseUdpUrl['host'] ?? '';
|
remoteHost = parseUdpUrl['host'] ?? '';
|
||||||
remotePort = parseUdpUrl['port'] ?? '';
|
remotePort = parseUdpUrl['port'] ?? '';
|
||||||
relayPeerId = data?.peerID ?? '';
|
relayPeerId = data?.peerID ?? '';
|
||||||
@ -893,18 +893,30 @@ class StartChartManage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 解析 UDP URL 并提取 IP 地址和端口号
|
/// 解析 UDP URL 并提取 IP 地址和端口号
|
||||||
Map<String, dynamic> _parseUdpUrl(String url) {
|
/// 解析 UDP URL 并提取 IP 地址和端口号,同时处理域名解析
|
||||||
// 使用正则表达式匹配 IP 地址和端口号
|
Future<Map<String, dynamic>> _parseUdpUrl(String url) async {
|
||||||
final regex = RegExp(r'udp://(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d+)')
|
final regex = RegExp(r'udp://([a-zA-Z0-9.-]+):(\d+)').firstMatch(url);
|
||||||
.firstMatch(url);
|
|
||||||
|
|
||||||
if (regex != null) {
|
if (regex != null) {
|
||||||
final ip = regex.group(1);
|
final host = regex.group(1);
|
||||||
final portStr = regex.group(2);
|
final portStr = regex.group(2);
|
||||||
final port = int.tryParse(portStr ?? '');
|
final port = int.tryParse(portStr ?? '');
|
||||||
|
|
||||||
if (ip != null && port != null) {
|
if (host != null && port != null) {
|
||||||
return {'host': ip, 'port': port};
|
try {
|
||||||
|
// 尝试进行 DNS 解析
|
||||||
|
final List<InternetAddress> addresses =
|
||||||
|
await InternetAddress.lookup(host);
|
||||||
|
if (addresses.isEmpty) {
|
||||||
|
throw FormatException('DNS resolution failed for $host');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用解析后的第一个 IP 地址
|
||||||
|
final String resolvedIp = addresses.first.address;
|
||||||
|
return {'host': resolvedIp, 'port': port};
|
||||||
|
} catch (e) {
|
||||||
|
throw FormatException('DNS resolution error for $host: $e');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw FormatException('无法解析 URL 格式: $url');
|
throw FormatException('无法解析 URL 格式: $url');
|
||||||
@ -1063,6 +1075,13 @@ class StartChartManage {
|
|||||||
reStartTalkExpectMessageTimer();
|
reStartTalkExpectMessageTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reSetDefaultTalkExpect() {
|
||||||
|
_defaultTalkExpect = TalkExpectReq(
|
||||||
|
videoType: [VideoTypeE.IMAGE],
|
||||||
|
audioType: [AudioTypeE.G711],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// 修改预期接收到的数据
|
/// 修改预期接收到的数据
|
||||||
void sendOnlyImageVideoTalkExpectData() {
|
void sendOnlyImageVideoTalkExpectData() {
|
||||||
final talkExpectReq = TalkExpectReq(
|
final talkExpectReq = TalkExpectReq(
|
||||||
@ -1141,10 +1160,7 @@ class StartChartManage {
|
|||||||
|
|
||||||
/// 重置数据
|
/// 重置数据
|
||||||
void _resetData() {
|
void _resetData() {
|
||||||
_defaultTalkExpect = TalkExpectReq(
|
reSetDefaultTalkExpect();
|
||||||
videoType: [VideoTypeE.IMAGE],
|
|
||||||
audioType: [AudioTypeE.G711],
|
|
||||||
);
|
|
||||||
isOnlineStarChartServer = false;
|
isOnlineStarChartServer = false;
|
||||||
talkStatus.setUninitialized();
|
talkStatus.setUninitialized();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -426,6 +426,8 @@ class TalkViewLogic extends BaseGetXController {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
stopProcessingAudio();
|
stopProcessingAudio();
|
||||||
|
// 重置期望数据
|
||||||
|
StartChartManage().reSetDefaultTalkExpect();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
pubspec.yaml
12
pubspec.yaml
@ -185,9 +185,9 @@ dependencies:
|
|||||||
common_utils: ^2.0.0
|
common_utils: ^2.0.0
|
||||||
lpinyin: ^2.0.3
|
lpinyin: ^2.0.3
|
||||||
#加密解密
|
#加密解密
|
||||||
encrypt: ^5.0.1
|
# encrypt: ^5.0.1
|
||||||
crypto: ^3.0.3
|
# crypto: ^3.0.3
|
||||||
pointycastle: ^3.4.0
|
pointycastle: ^3.7.3 # 使用最新版本
|
||||||
date_format: ^2.0.7
|
date_format: ^2.0.7
|
||||||
|
|
||||||
# 下拉刷新
|
# 下拉刷新
|
||||||
@ -257,9 +257,9 @@ dependencies:
|
|||||||
firebase_analytics: 11.3.0
|
firebase_analytics: 11.3.0
|
||||||
#</com>
|
#</com>
|
||||||
|
|
||||||
cryptography: ^2.7.0
|
# cryptography: ^2.7.0
|
||||||
asn1lib: ^1.0.0
|
# asn1lib: ^1.0.0
|
||||||
fast_rsa: ^3.6.6
|
# fast_rsa: ^3.6.6
|
||||||
protobuf: ^3.1.0
|
protobuf: ^3.1.0
|
||||||
#录屏
|
#录屏
|
||||||
flutter_screen_recording: 2.0.16
|
flutter_screen_recording: 2.0.16
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user