Files
flutterApp/lib/features/remote_control/data/datasources/remote_tcp_datasource.dart
2026-03-16 15:31:14 +08:00

157 lines
5.5 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:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import '../../../../core/network/protocol_decoder.dart';
import '../../../../core/network/tcp/tcp_client.dart';
import '../../../../core/protocol/machine_protocol_constants.dart';
import '../../../../core/storage/user_storage.dart';
/// 远程遥控 TCP 数据源
/// 负责通过 TCP 协议发送控制指令和权限请求
class RemoteTcpDatasource {
final TcpClient _tcpClient;
final UserStorage _userStorage;
RemoteTcpDatasource(this._tcpClient, this._userStorage);
/// 发送 switch_control 权限请求(对应 Android 的 requestSwitchControl)
///
/// 这是获取设备控制权的第一步:
/// 1. 先发送 TCP 0x12 指令携带 switch_control 请求
/// 2. 等待服务端响应
/// 3. 再调用 HTTP API 确认控制权
Future<void> sendSwitchControlRequest(String deviceName) async {
if (!_tcpClient.isConnected) {
debugPrint('❌sendSwitchControlRequest [TCP] 无法发送权限请求:Socket 未连接');
throw Exception('sendSwitchControlRequest TCP 未连接');
}
try {
// 获取用户信息
final user = await _userStorage.getUser();
if (user == null || user.token == null) {
debugPrint('❌ sendSwitchControlRequest[TCP] 认证失败:用户未登录或 Token 为空,无法发送认证包');
throw Exception('用户未登录或 Token 无效');
}
final username = user.username;
final token = user.token;
final currentDeviceId = deviceName;
// 构造 JSON 请求体(参考 Android 代码)
final request = {
'request': 'switch_control',
'deviceId': currentDeviceId,
'userId': username,
'platform': 'app',
'token': token,
};
final jsonStr = jsonEncode(request);
final jsonBytes = utf8.encode(jsonStr);
debugPrint('sendSwitchControlRequest[TCP] 发送权限请求指令:$jsonStr');
debugPrint('sendSwitchControlRequest[TCP] 发送权限请求指令:$jsonBytes');
// 使用 0x12 指令发送(cmdGetAuth)
// 注意:根据你的协议文档,这里可能是 0x04 或 0x12
// Android 代码中使用的是 0x12
// _tcpClient.sendnew(
// // MachineProtocolConstants.cmdGetAuth, // 0x04 或 0x12,根据实际协议调整
// jsonBytes,
// );
// 构造完整的协议包
final packet = buildSwitchControlPacket(jsonBytes);
debugPrint('sendSwitchControlRequest[TCP] 完整数据包:${packet.map((b) => '0x${b.toRadixString(16)}').join(' ')}');
// 发送数据包
_tcpClient.sendnew(packet);
debugPrint('✅ sendSwitchControlRequest[TCP] 已发送 switch_control 权限请求 (0x${MachineProtocolConstants.cmdGetAuth.toRadixString(16)})');
} catch (e) {
debugPrint('❌ sendSwitchControlRequest[TCP] 发送权限请求失败:$e');
rethrow;
}
}
/// 监听 TCP 回包流
/// 用于接收权限响应、状态更新等
Stream<RawPacket> get responseStream => _tcpClient.packetStream;
/// 检查 TCP 连接状态
bool get isConnected => _tcpClient.isConnected;
/// 构建 switch_control 协议包
///
/// 包结构:
/// - 帧头:0xAB, 0xAA (2 字节)
/// - 命令字:0x12 (1 字节)
/// - 数据载荷:JSON UTF-8 字节 (N 字节)
/// - 帧尾:0x00, 0x00, 0xAA, 0xAB (4 字节)
List<int> buildSwitchControlPacket(List<int> jsonBytes) {
final builder = BytesBuilder()
..addByte(MachineProtocolConstants.header1) // 0xAB
..addByte(MachineProtocolConstants.header2) // 0xAA
..addByte(0x12) // 命令字:switch_control
..add(jsonBytes) // JSON 数据
..addByte(0x00) // CRC 占位 1
..addByte(0x00) // CRC 占位 2
..addByte(MachineProtocolConstants.endFlag1) // 0xAA
..addByte(MachineProtocolConstants.endFlag2); // 0xAB
return builder.takeBytes();
}
// TODO: 同意授权和拒绝授权
void sendSwitchControlResponse(bool bool, String deviceId) {
if (!_tcpClient.isConnected) {
debugPrint('❌sendSwitchControlResponse [TCP] 无法发送权限响应:Socket 未连接');
throw Exception('sendSwitchControlResponse TCP 未连接');
}
try {
// 构造响应 JSON(参考 Android 代码)
final response = bool
? {
'respond': {
'switchResult': true,
'deviceId': deviceId,
'holder': 'you',
},
}
: {
'respond': {
'switchResult': false,
'deviceId': deviceId,
'reason': 'holder_denied',
},
};
if(!bool){
debugPrint('sendSwitchControlResponse[TCP] 拒绝授权:$deviceId');
}else{
debugPrint('sendSwitchControlResponse[TCP] 同意授权:$deviceId');
}
//debugPrint('sendSwitchControlResponse[TCP] 同意授权:$deviceId');
final jsonStr = jsonEncode(response);
final jsonBytes = utf8.encode(jsonStr);
debugPrint('sendSwitchControlResponse[TCP] 响应权限请求:$jsonStr');
// 构造完整的协议包
final packet = buildSwitchControlPacket(jsonBytes);
debugPrint('sendSwitchControlResponse[TCP] 完整数据包:${packet.map((b) => '0x${b.toRadixString(16)}').join(' ')}');
// 发送数据包
_tcpClient.sendnew(packet);
}
catch (e) {
debugPrint('❌ sendSwitchControlResponse[TCP] 响应权限请求失败:$e');
rethrow;
}
}
}