完成页面对接tcp推送的设备状态数据

完成页面测试解析tcp推送的设备状态数据的UI展示
This commit is contained in:
2026-03-03 19:34:17 +08:00
parent 0a3a062c04
commit 34b4c2bcbc
12 changed files with 676 additions and 230 deletions

View File

@@ -0,0 +1,108 @@
// lib/features/auth/data/datasources/auth_tcp_datasource.dart
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/cupertino.dart';
import 'package:fpdart/src/either.dart';
import 'package:maibu_satabot_v2/features/devices/domain/entities/device_entity.dart';
import 'package:maibu_satabot_v2/features/devices/domain/errors/device_failure.dart';
import '../../../../../core/network/tcp/tcp_client.dart';
import '../../../../../core/storage/user_storage.dart';
import '../../../../devices/domain/usecases/get_user_device_usecase.dart';
import '../../../../devices/domain/usecases/switch_device_usecase.dart';
import '../auth_tcp_datasource.dart';
class AuthTcpDatasourceImpl implements AuthTcpDatasource {
final TcpClient _tcpClient;
final UserStorage _userStorage;
final GetUserDeviceUseCase getUserDeviceUseCase;
final SwitchDeviceUseCase switchDeviceUseCase;
AuthTcpDatasourceImpl(this._tcpClient, this._userStorage, {required this.getUserDeviceUseCase, required this.switchDeviceUseCase});
@override
Future<void> sendAuthPacket() async {
if (!_tcpClient.isConnected) {
throw Exception('TCP 未连接,无法发送认证包');
}
final user = await _userStorage.getUser();
if (user == null || user.token == null || user.username == null) {
throw Exception('用户未登录,无法认证');
}
final username = user.username!;
final token = user.token!;
final authString = '$username:app:$token';
debugPrint('🔑 [AuthTcp] 准备发送认证包:$authString');
final authBytes = utf8.encode(authString);
// 构造协议包:AB AA 03 [Payload] CRC(00 00) AA AB
// 注意:如果服务端校验 CRC,需在此处计算真实 CRC
final builder = BytesBuilder()
..addByte(0xAB)
..addByte(0xAA)
..addByte(0x03)
..add(authBytes)
..addByte(0x00)
..addByte(0x00)
..addByte(0xAA)
..addByte(0xAB);
_tcpClient.sendRawBytes(builder.takeBytes()); // 假设 TcpClient 增加了此方法,或用 socket.add
debugPrint('✅ [AuthTcp] 认证包已发送');
// 获取用户设备列表
try {
// 1. 获取 Either 结果
final eitherResult = await getUserDeviceUseCase.repository.getUserDevice(username);
// 2. 使用 fold 解包 Either
// left: 处理错误情况 (DeviceFailure)
// right: 处理成功情况 (List<DeviceEntity>)
await eitherResult.fold(
(failure) {
// 处理失败:打印日志或抛出异常
debugPrint('❌ [AuthTcp] 获取设备列表失败:$failure');
throw Exception('获取设备列表失败:$failure');
},
(devices) async {
// 处理成功:devices 现在是真正的 List<DeviceEntity>
if (devices.isEmpty) {
debugPrint('⚠️ [AuthTcp] 当前用户无可用设备,跳过切换步骤');
return;
}
// 取第一个设备
final DeviceEntity targetDevice = devices.first;
debugPrint('📱 [AuthTcp] 准备切换至默认设备:${targetDevice.deviceName}');
// 切换设备 (同样,如果 switchDeviceUseCase 也返回 Either,也需要 fold 处理)
final switchResult = await switchDeviceUseCase.deviceRepository.switchDevice("app",targetDevice.deviceName);
await switchResult.fold(
(failure) {
debugPrint('❌ [AuthTcp] 切换设备失败:$failure');
throw Exception('切换设备失败:$failure');
},
(success) {
debugPrint('✅ [AuthTcp] 设备切换成功,服务端应开始推送数据');
},
);
},
);
} catch (e) {
debugPrint('❌ [AuthTcp] 设备订阅流程异常:$e');
rethrow;
}
}
}