From b25315fc11e533846b72f010831f991fb9359366 Mon Sep 17 00:00:00 2001 From: Songzex <2402265378@qq.com> Date: Wed, 15 Apr 2026 08:43:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8E=89=E6=A0=B8=E5=BF=83?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=B8=ADprint=E6=89=93=E5=8D=B0=E5=BD=B1?= =?UTF-8?q?=E5=93=8D=E6=80=A7=E8=83=BD=E7=9A=84=E4=BB=A3=E7=A0=81=E7=94=A8?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E5=AF=B9=E8=B1=A1=E4=BB=A3=E6=9B=BF=E6=89=93?= =?UTF-8?q?=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/presentation/bloc/auth_cubit.dart | 36 ++++---- .../impl/device_http_datasource_impl.dart | 7 +- .../impl/path_http_datasource_impl.dart | 21 +++-- .../data/models/route_plan_send_entity.dart | 2 +- .../device_hostriry_work_impl.dart | 25 ++++-- .../route_planning_repository_impl.dart | 90 +++++++++++++------ .../presentation/bloc/device_status_bloc.dart | 24 +++-- .../presentation/bloc/devices_cubit.dart | 31 +++++-- .../services/path_planning_service.dart | 21 ++++- .../my/presentation/bloc/my_cubit.dart | 4 +- .../datasources/remote_http_datasource.dart | 16 ++-- .../remote_control_repository_impl.dart | 19 ++-- .../bloc/remote_control_cubit.dart | 81 +++++++++++------ 13 files changed, 256 insertions(+), 121 deletions(-) diff --git a/lib/features/auth/presentation/bloc/auth_cubit.dart b/lib/features/auth/presentation/bloc/auth_cubit.dart index 4c91f60f..020ea1c1 100644 --- a/lib/features/auth/presentation/bloc/auth_cubit.dart +++ b/lib/features/auth/presentation/bloc/auth_cubit.dart @@ -30,6 +30,7 @@ class AuthCubit extends Cubit { final AppUserCubit appCubit; final NetMessageDispatcher dispatcher; final AuthTcpDatasource _authTcpDatasource; + final ILoggerService _logger = GetIt.I(); StreamSubscription? _kickOutSub; // 新增:用于管理监听生命周期 @@ -74,7 +75,7 @@ class AuthCubit extends Cubit { /// 退出登录 (主动或被动) Future logout() async { - print("退出登录"); + //print("退出登录"); await storage.deleteUser(); tcp.disconnect(); appCubit.clearAuth(); @@ -99,13 +100,13 @@ class AuthCubit extends Cubit { // } /// TCP 指令监听 void _listenToAuthResponse() { - print('>>> [AUTH] begin 指令监听:'); + _logger.logWithLevel('[AUTH] 监听 TCP 0x12 指令...', level: 'DEBUG'); _kickOutSub?.cancel(); // 防止重复监听 // 直接监听原始数据包,自己处理 JSON 解析(去掉 CRC 字节) _kickOutSub = dispatcher.onCommand(0x12).listen((packet) { - print('>>> [AUTH] 收到 0x12 原始包,payload 长度=${packet.payload.length}, 内容=${packet.payload}'); - + _logger.logWithLevel('[AUTH] 获取原始包:$packet', level: 'DEBUG'); + _logger.logWithLevel('>>> [AUTH] 收到 0x12 原始包,payload 长度=${packet.payload.length}, 内容=${packet.payload}', level: 'DEBUG'); try { // 🔥 关键:手动去掉最后 2 个 CRC 字节 String jsonString; @@ -114,25 +115,23 @@ class AuthCubit extends Cubit { } else { jsonString = utf8.decode(packet.payload); } - - print('>>> [AUTH] 去除 CRC 后的 JSON: $jsonString'); + _logger.logWithLevel('[AUTH] 获取 JSON: $jsonString', level: 'DEBUG'); final jsonMap = jsonDecode(jsonString); - // print('>>> [AUTH] JSON 解析成功:$jsonMap'); + _logger.logWithLevel('[AUTH] 获取 JSON Map: $jsonMap', level: 'DEBUG'); final respond = jsonMap['respond'] ?? ''; if (respond == 'have_logged_in') { - print('>>> [AUTH] ⚠️ 检测到异地登录 (respond=have_logged_in),开始退出...'); + _logger.logWithLevel('[AUTH] ⚠️ 检测到异地登录 (respond=have_logged_in),开始退出...', level: 'WARN'); logout(); } else { - // print('>>> [AUTH] ℹ️ 收到其他 0x12 消息,忽略:respond=$respond'); + _logger.logWithLevel('[AUTH] ⚠️ 检测到异地登录 (respond=$respond),开始退出...', level: 'WARN'); } } catch (e) { - //print('>>> [AUTH] ❌ 解析失败:$e'); + _logger.logWithLevel('[AUTH] ❌ JSON 解析失败:$e', level: 'ERROR'); } }); - - print('>>> [AUTH] ✅ 0x12 监听器已建立完成'); + _logger.logWithLevel('[AUTH] 监听 TCP 0x12 指令...', level: 'DEBUG'); } @@ -146,21 +145,20 @@ class AuthCubit extends Cubit { /// 🔥 息屏/后台后恢复到前台时的重连方法 Future reconnectAfterResume() async { - print('📱 [AUTH] 检测到应用恢复到前台,检查 TCP 连接状态...'); - + _logger.logWithLevel('[AUTH] 检测到应用恢复到前台,检查 TCP 连接状态...', level: 'DEBUG'); // 如果 TCP 未连接,则执行重连 if (!tcp.isConnected) { - print('⚠️ [AUTH] TCP 未连接,开始重连...'); + _logger.logWithLevel('[AUTH] TCP 未连接,开始重连...', + level: 'DEBUG'); try { await tcp.connect(host: TCPConsts.TCP_IP, port: TCPConsts.TCP_PORT); tcp.startHeartbeat(interval: const Duration(seconds: 4)); - print('✅ [AUTH] TCP 重连成功!'); + _logger.logWithLevel('[AUTH] TCP 重连成功!', level: 'DEBUG'); } catch (e) { - print('❌ [AUTH] TCP 重连失败:$e'); - // 可以选择重试或者通知用户 + _logger.logWithLevel('[AUTH] TCP 重连失败:$e', level: 'ERROR'); } } else { - print('✅ [AUTH] TCP 连接正常,无需重连'); + _logger.logWithLevel('[AUTH] TCP 已连接,无需重连', level: 'DEBUG'); // 可选:发送一个心跳包确认连接有效 tcp.sendHeartbeat(); } diff --git a/lib/features/devices/data/datasources/impl/device_http_datasource_impl.dart b/lib/features/devices/data/datasources/impl/device_http_datasource_impl.dart index 7cc0f066..a141c4c0 100644 --- a/lib/features/devices/data/datasources/impl/device_http_datasource_impl.dart +++ b/lib/features/devices/data/datasources/impl/device_http_datasource_impl.dart @@ -15,6 +15,8 @@ import '../../../domain/entities/device_location_entity.dart'; class DeviceHttpDatasourceImpl implements DeviceHttpDatasource { final Dio dio; final UserStorage _userStorage; // 🔥 新增字段 + final ILoggerService _logger = GetIt.I(); + // 🔥 修改构造函数,注入 UserStorage DeviceHttpDatasourceImpl(this.dio, this._userStorage); @@ -22,7 +24,7 @@ class DeviceHttpDatasourceImpl implements DeviceHttpDatasource { // 🔥 辅助方法:获取 Token Future _getToken() async { final user = await _userStorage.getUser(); - debugPrint('用户信息: $user'); + _logger.logWithLevel('用户信息: $user', level: 'INFO'); return user?.token; } @@ -94,7 +96,8 @@ class DeviceHttpDatasourceImpl implements DeviceHttpDatasource { Future switchDevice(String platform, String deviceId) async { final logger = GetIt.I() as SentryLoggerImpl; final token = await _getToken(); - print('用户点击switchDevice方法开始触发: $token'); + // print('用户点击switchDevice方法开始触发: $token'); + _logger.logWithLevel('用户点击switchDevice方法开始触发', level: 'DEBUG'); logger.logWithLevel('用户点击switchDevice方法开始触发', level: 'DEBUG'); logger.logWithLevel('用户点击switchDevice方法API 请求开始', level: 'INFO', data: {'url': 'https://serviceri.satabot.com/iot/device/switchDevice'}); var response = await dio.post( diff --git a/lib/features/devices/data/datasources/impl/path_http_datasource_impl.dart b/lib/features/devices/data/datasources/impl/path_http_datasource_impl.dart index 96064cd0..c2e52623 100644 --- a/lib/features/devices/data/datasources/impl/path_http_datasource_impl.dart +++ b/lib/features/devices/data/datasources/impl/path_http_datasource_impl.dart @@ -1,7 +1,9 @@ import 'dart:convert'; +import 'package:get_it/get_it.dart'; import 'package:maibu_satabot_v2/common.dart'; +import '../../../../../core/logging/i_logger_service.dart'; import '../../../../../core/storage/user_storage.dart'; import '../../models/device_add_path_point_model.dart'; import '../path_http_datasource.dart'; @@ -10,21 +12,23 @@ import 'package:logger/logger.dart'; class PathHttpDatasourceImpl implements PathHttpDatasource { final UserStorage _userStorage; + final ILoggerService _logger = GetIt.I(); PathHttpDatasourceImpl(this._userStorage); + + @override Future> generatePathRaw({required Map body}) async { try { - // 1. 先打印基础信息 - print('=== 最终发送给后端的请求体 ==='); - print('请求体类型:${body.runtimeType}'); + _logger.logWithLevel( '请求体类型:${body.runtimeType}',level: 'INFO'); // 2. 格式化打印JSON(带缩进,清晰展示嵌套结构) final jsonString = const JsonEncoder.withIndent(' ').convert(body); final _jsonString = jsonEncode(body); - print('完整JSON请求体:\n$jsonString'); + // print('完整JSON请求体:\n$jsonString'); + _logger.logWithLevel( '请求体:$_jsonString',level: 'INFO'); // 3. 可选:单独打印holes的JSON(重点关注) //final holesJson = body['holes'] as List; @@ -38,9 +42,11 @@ class PathHttpDatasourceImpl implements PathHttpDatasource { //} } catch (e) { // 防止JSON序列化失败导致崩溃 - print('打印请求体失败:$e'); + //print('打印请求体失败:$e'); + _logger.logWithLevel( '打印请求体失败:$e',level: 'ERROR'); // 降级打印原始body(虽然格式乱,但能看基础数据) - print('原始body数据:$body'); + // print('原始body数据:$body'); + _logger.logWithLevel( '原始body数据:$body',level: 'ERROR'); } final token = (await _userStorage.getUser())?.token; @@ -58,7 +64,8 @@ class PathHttpDatasourceImpl implements PathHttpDatasource { final decoded = jsonDecode(response.body) as Map; if (decoded['success'] == true) { final pathJson = decoded['data']?['path']; - print('路径数据: $pathJson'); // 调试输出路径数据 + // print('路径数据: $pathJson'); // 调试输出路径数据 + _logger.logWithLevel( '路径数据: $pathJson',level: 'INFO'); if (pathJson == null) { throw Exception('API returned null for "path"'); } diff --git a/lib/features/devices/data/models/route_plan_send_entity.dart b/lib/features/devices/data/models/route_plan_send_entity.dart index 11673cd8..81602dcc 100644 --- a/lib/features/devices/data/models/route_plan_send_entity.dart +++ b/lib/features/devices/data/models/route_plan_send_entity.dart @@ -59,7 +59,7 @@ class RoutePlanSendEntity { byteData.setInt8(offset++, endFlag2); // 0xAB → -85 var uint8list = byteData.buffer.asUint8List(); // 关键:直接返回原始二进制字节(不做任何映射/转换) - print("发送的指令字节数组,$uint8list"); + // print("发送的指令字节数组,$uint8list"); return byteData.buffer.asUint8List(); } diff --git a/lib/features/devices/data/repositories/device_hostriry_work_impl.dart b/lib/features/devices/data/repositories/device_hostriry_work_impl.dart index d71a5d4f..a0c10fdf 100644 --- a/lib/features/devices/data/repositories/device_hostriry_work_impl.dart +++ b/lib/features/devices/data/repositories/device_hostriry_work_impl.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:flutter/cupertino.dart'; +import 'package:get_it/get_it.dart'; import 'package:http/http.dart' as http; import 'package:fpdart/fpdart.dart'; import 'package:maibu_satabot_v2/core/storage/user_storage.dart'; @@ -9,23 +10,29 @@ import 'package:maibu_satabot_v2/features/devices/domain/entities/device_run_hos import 'package:maibu_satabot_v2/features/devices/domain/errors/device_failure.dart'; import 'package:maibu_satabot_v2/features/devices/domain/repositories/device_hostrity_work_repository.dart'; +import '../../../../core/logging/i_logger_service.dart'; + class DeviceHostrityWorkRepositoryImpl implements DeviceHostrityWorkRepositoryRepository { final Dio client; final UserStorage userStorage; + final ILoggerService _logger = GetIt.I(); DeviceHostrityWorkRepositoryImpl({required this.client, required this.userStorage}); @override Future>> getDeviceHRunStatistics({required String deviceId}) async { try { - debugPrint('开始获取用户信息...'); + // debugPrint('开始获取用户信息...'); + _logger.logWithLevel('开始获取用户信息...', level: 'info'); final user = await userStorage.getUser(); if (user == null || user.token == null) { - debugPrint('用户未登录或缺少 token'); + // debugPrint('用户未登录或缺少 token'); + _logger.logWithLevel('用户未登录或缺少 token', level: 'error'); return Left(DeviceFailure.unauthorized(message: 'User not logged in or token is missing')); } final token = user.token!; - debugPrint('用户信息获取成功,Token: $token'); + // debugPrint('用户信息获取成功,Token: $token'); + _logger.logWithLevel('用户信息获取成功,Token: $token', level: 'info'); final response = await client.get( 'https://serviceri.satabot.com/iot/device/getDeviceRunStatistics?deviceId=$deviceId', @@ -49,18 +56,22 @@ class DeviceHostrityWorkRepositoryImpl implements DeviceHostrityWorkRepositoryRe .toList(); return Right(statistics); } else { - debugPrint('服务器返回错误码: ${jsonBody['code']}'); + //debugPrint('服务器返回错误码: ${jsonBody['code']}'); + _logger.logWithLevel('服务器返回错误码: ${jsonBody['code']}', level: 'error'); return Left(DeviceFailure.serverError(message: '服务器返回错误码: ${jsonBody['code']}')); } } else { - debugPrint('网络请求失败,状态码: ${response.statusCode}'); + // debugPrint('网络请求失败,状态码: ${response.statusCode}'); + _logger.logWithLevel('网络请求失败,状态码: ${response.statusCode}', level: 'error'); return Left(DeviceFailure.networkError(message: '网络请求失败,状态码: ${response.statusCode}')); } } on DioException catch (e) { - debugPrint('Dio 请求失败: ${e.message}'); + //debugPrint('Dio 请求失败: ${e.message}'); + _logger.logWithLevel('Dio 请求失败: ${e.message}', level: 'error'); return Left(DeviceFailure.networkError(message: e.message ?? '未知错误')); } catch (e) { - debugPrint('请求过程中发生异常: $e'); + // debugPrint('请求过程中发生异常: $e'); + _logger.logWithLevel('请求过程中发生异常: $e', level: 'error'); return Left(DeviceFailure.unknownError(message: e.toString())); } } diff --git a/lib/features/devices/data/repositories/route_planning_repository_impl.dart b/lib/features/devices/data/repositories/route_planning_repository_impl.dart index 12552ef6..460c8430 100644 --- a/lib/features/devices/data/repositories/route_planning_repository_impl.dart +++ b/lib/features/devices/data/repositories/route_planning_repository_impl.dart @@ -1,5 +1,6 @@ import 'dart:collection'; +import 'package:get_it/get_it.dart'; import 'package:isar_community/isar.dart'; import 'package:maibu_satabot_v2/core/logging/i_logger_service.dart'; import 'package:maibu_satabot_v2/features/devices/data/models/device_add_path_point_model.dart'; @@ -13,6 +14,8 @@ import '../models/route_plan_send_entity.dart'; class RoutePlanningRepositoryImpl implements RoutePlanningRepository { final TcpClient tcp; late PathPlanner _planner; + final ILoggerService _logger = GetIt.I(); + // 🔥 新增:存储 AppState 的引用 dynamic _appState; @@ -23,7 +26,8 @@ class RoutePlanningRepositoryImpl implements RoutePlanningRepository { @override Future startRoutePlanning(Queue locationQueue) async { // 直接传入 DeviceAddPathPointModel 列表(无需转换) - print("[底层开始发送指令了]"); + // print("[底层开始发送指令了]"); + _logger.log("开始路径规划"); final List locations = locationQueue.toList(); _planner.startRoutePlanning(locations); } @@ -60,6 +64,7 @@ class RoutePlanningRepositoryImpl implements RoutePlanningRepository { // true = 使用新的 ACK 握手机制 (将来) // false = 使用现有逻辑 (现在) class PathPlanningMode { + static bool useAckHandshake = false; // 默认使用现有逻辑 } @@ -68,7 +73,7 @@ class PathPlanner { final Queue locationQueue = Queue(); final TcpClient tcpClient; bool isStart = false; - + final ILoggerService _logger = GetIt.I(); // 新增:作业控制状态 bool _isPaused = false; bool _isStopped = false; @@ -80,7 +85,7 @@ class PathPlanner { PathPlanner(this.tcpClient); void sendNextLocation() { - print("[在发送指令sendNextLocation方法中]"); + _logger.log("[发送sendNextLocation方法指令]"); // if (isStart && locationQueue.isEmpty) { // isStart = false; // print("[track]"); @@ -89,17 +94,19 @@ class PathPlanner { // } // 关键检查:暂停或停止时不再发送 if (_isPaused) { - print("⏸️ 当前处于暂停状态,停止发送指令"); + _logger.log("[暂停状态],停止发送指令"); return; } if (_isStopped || (isStart && locationQueue.isEmpty)) { isStart = false; if (_isStopped) { - print("⏹️ 已停止作业,清空队列"); + //print("⏹️ 已停止作业,清空队列"); + _logger.log("[路径点发送完毕]"); locationQueue.clear(); // 清空剩余队列 } else { - print("[路径点发送完毕]"); + //print("[路径点发送完毕]"); + _logger.log("[路径点发送完毕]"); } _isStopped = false; // 重置停止标志 return; @@ -114,7 +121,8 @@ class PathPlanner { speed: 1000, ); - print("====Lat:${entity.latitude} ====Lng:${entity.longitude}"); + //print("====Lat:${entity.latitude} ====Lng:${entity.longitude}"); + _logger.log("[发送指令]"); tcpClient.sendPathPoint( routePlanSendEntity); isStart = true; } @@ -130,43 +138,51 @@ class PathPlanner { isStart = true; _isPaused = false; // 🔥 只在第一次调用时重置 _isStopped = false; // 🔥 只在第一次调用时重置 - print("[首次加载] 队列长度:${locations.length}"); + // print("[首次加载] 队列长度:${locations.length}"); + _logger.log("[首次加载] 队列长度:${locations.length}"); } else { // 🔥 后续调用(来自 Dispatcher)只更新队列,不重置状态 - print("[更新队列] 当前处于 ${_isPaused ? '暂停' : _isStopped ? '停止' : '工作'} 状态"); + //print("[更新队列] 当前处于 ${_isPaused ? '暂停' : _isStopped ? '停止' : '工作'} 状态"); + _logger.log("[更新队列] 当前处于 ${_isPaused ? '暂停' : _isStopped ? '停止' : '工作'} 状态"); if (!_isPaused && !_isStopped) { // 如果不是暂停/停止状态,才添加新数据 locationQueue.addAll(locations); } } - print("[发送指令要转换类型了完成]"); + // print("[发送指令要转换类型了完成]"); + _logger.log("[发送指令要转换类型了完成]"); // 🔥 关键检查:如果是暂停/停止状态,直接返回 if (_isPaused) { - print("⏸️ 当前处于暂停状态,拒绝发送指令"); + // print("⏸️ 当前处于暂停状态,拒绝发送指令"); + _logger.log("[暂停状态]"); return; } if (_isStopped) { - print("⏹️ 当前处于停止状态,拒绝发送指令"); + // print("⏹️ 当前处于停止状态,拒绝发送指令"); + _logger.log("[停止状态]"); return; } print("[发送指令要转换类型了完成]"); // sendNextLocation(); // 🔥 根据全局开关选择使用哪套发送逻辑 if (PathPlanningConfig.useAckHandshake) { - print("🔥 使用 ACK 握手机制发送路径点"); + // print("🔥 使用 ACK 握手机制发送路径点"); + _logger.log("[使用 ACK 握手机制发送路径点]"); sendNextLocationWithAck(sl()); } else { - print("🔥 使用现有逻辑发送路径点"); + // print("🔥 使用现有逻辑发送路径点"); + _logger.log("[使用现有逻辑发送路径点]"); sendNextLocation(); } } /// 暂停 void pauseRPWork() { - print("⏸️ 暂停作业,设置_isPaused = true"); + //print("⏸️ 暂停作业,设置_isPaused = true"); + _logger.log("[暂停作业,设置_isPaused = true]"); _isPaused = true; var entity = new RoutePlanSendEntity( @@ -176,12 +192,14 @@ class PathPlanner { targetLongitude: 0, speed: 0, ); - print("📡 发送暂停指令到设备..."); + // print("📡 发送暂停指令到设备..."); + _logger.log("[发送暂停指令到设备...]"); tcpClient.sendDeviceStateChange(entity); } /// 恢复 void resumeRPWork() { - print("▶️ 恢复作业,设置_isPaused = false"); + //print("▶️ 恢复作业,设置_isPaused = false"); + _logger.log("[恢复作业,设置_isPaused = false]"); _isPaused = false; var entity = new RoutePlanSendEntity( @@ -191,7 +209,8 @@ class PathPlanner { targetLongitude: 0, speed: 0, ); - print("📡 发送恢复指令到设备..."); + // print("📡 发送恢复指令到设备..."); + _logger.log("[发送恢复指令到设备...]"); tcpClient.sendDeviceStateChange(entity); // 恢复后继续发送下一个点 @@ -200,7 +219,8 @@ class PathPlanner { // sendNextLocation(); // } if (locationQueue.isNotEmpty) { - print("📍 恢复发送下一个路径点"); + //print("📍 恢复发送下一个路径点"); + _logger.log("[恢复发送下一个路径点]"); if (PathPlanningConfig.useAckHandshake) { sendNextLocationWithAck(sl()); } else { @@ -210,12 +230,14 @@ class PathPlanner { } /// 停止 void stopRoutePlanning() { - print("⏹️ 停止作业,设置_isStopped = true"); + // print("⏹️ 停止作业,设置_isStopped = true"); + _logger.log("[停止作业,设置_isStopped = true]"); _isStopped = true; _isPaused = false; // 清除暂停状态 // 🔥 核心修复:清空队列 - print("🗑️ 清空待发送队列,剩余 ${locationQueue.length} 个点"); + // print("🗑️ 清空待发送队列,剩余 ${locationQueue.length} 个点"); + _logger.log("[清空待发送队列,剩余 ${locationQueue.length} 个点]"); locationQueue.clear(); @@ -228,7 +250,8 @@ class PathPlanner { targetLongitude: 0, speed: 0, ); - print("📡 发送停止指令到设备..."); + // print("📡 发送停止指令到设备..."); + _logger.log("[发送停止指令到设备...]"); tcpClient.sendDeviceStateChange(entity); // 发送完成工作播报指令 sendWorkCompleteBroadcast(); @@ -243,32 +266,38 @@ class PathPlanner { targetLongitude: 0, speed: 0, ); - print("发送完成工作播报指令..."); + // print("发送完成工作播报指令..."); + _logger.log("[发送完成工作播报指令...]"); tcpClient.sendDeviceStateChange(entity); } // 🔥 新增:ACK 握手机制的发送方法 (新模式) void sendNextLocationWithAck(NetMessageDispatcher dispatcher) { - print("[在发送指令 sendNextLocationWithAck 方法中 - ACK 模式]"); + // print("[在发送指令 sendNextLocationWithAck 方法中 - ACK 模式]"); + _logger.log("[在发送指令 sendNextLocationWithAck 方法中 - ACK 模式]"); // 🔥 关键检查:如果正在等待 ACK,不要重复发送 if (_waitingForAck) { - print("⏳ 正在等待 ACK 确认,跳过发送"); + //print("⏳ 正在等待 ACK 确认,跳过发送"); + _logger.log("[正在等待 ACK 确认,跳过发送]"); return; } // 🔥 关键检查:暂停或停止时不再发送 if (_isPaused) { - print("⏸️ 当前处于暂停状态,停止发送指令"); + //print("⏸️ 当前处于暂停状态,停止发送指令"); + _logger.log("[暂停状态]"); return; } if (_isStopped || (isStart && locationQueue.isEmpty)) { isStart = false; if (_isStopped) { - print("️ 已停止作业,清空队列"); + // print("️ 已停止作业,清空队列"); + _logger.log("[已停止作业,清空队列]"); locationQueue.clear(); // 清空剩余队列 } else { print("[路径点发送完毕]"); + _logger.log("[路径点发送完毕]"); } _isStopped = false; // 重置停止标志 return; @@ -287,14 +316,17 @@ class PathPlanner { speed: 1000, ); - print("====Lat:${entity.latitude} ====Lng:${entity.longitude}"); + //print("====Lat:${entity.latitude} ====Lng:${entity.longitude}"); + _logger.log("[发送路径点] Lat:${entity.latitude} Lng:${entity.longitude}"); tcpClient.sendPathPoint( routePlanSendEntity); isStart = true; // 🔥 关键:标记为正在等待 ACK _waitingForAck = true; dispatcher.setExpectedPointIndex(pointIndex); // 🔥 通知 Dispatcher - print(" 已锁定发送,等待 ACK 确认 (0x02)..."); + //sprint(" 已锁定发送,等待 ACK 确认 (0x02)..."); + _logger.log("[已锁定发送,等待 ACK 确认 (0x02)...]"); + } } diff --git a/lib/features/devices/presentation/bloc/device_status_bloc.dart b/lib/features/devices/presentation/bloc/device_status_bloc.dart index aefd1cec..ee129c6a 100644 --- a/lib/features/devices/presentation/bloc/device_status_bloc.dart +++ b/lib/features/devices/presentation/bloc/device_status_bloc.dart @@ -2,16 +2,20 @@ import 'dart:async'; import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:get_it/get_it.dart'; import 'package:maibu_satabot_v2/features/devices/domain/entities/running_status_entity.dart'; import 'package:maibu_satabot_v2/features/devices/domain/entities/gps_entity.dart'; import 'package:maibu_satabot_v2/core/network/protocol_decoder.dart'; +import '../../../../core/logging/i_logger_service.dart'; import '../../../../core/network/net_message_dispatcher.dart'; import 'device_status_event.dart'; import 'device_status_state.dart'; class DeviceStatusBloc extends Bloc { final NetMessageDispatcher _dispatcher; + final ILoggerService _logger = GetIt.I(); + // 持有订阅引用,仅在 close 时取消 StreamSubscription? _stringSub; @@ -38,6 +42,7 @@ class DeviceStatusBloc extends Bloc { debugPrint('🔗 [DeviceStatusBloc] 初始化 TCP 数据流订阅(终身有效)'); + // 订阅字符串流 (0x02) _stringSub = _dispatcher.onStringMessage().listen( (jsonString) { @@ -63,12 +68,15 @@ class DeviceStatusBloc extends Bloc { // ); _isSubscribed = true; - debugPrint('✅ [DeviceStatusBloc] 订阅建立完成,将持续监听数据流'); + // debugPrint('✅ [DeviceStatusBloc] 订阅建立完成,将持续监听数据流'); + _logger.log('✅ [DeviceStatusBloc] 订阅建立完成,将持续监听数据流'); } // 🔥 核心修复:重置时仅清空状态,绝对不再触碰订阅关系 Future _handleReset(DeviceStatusReset event, Emitter emit) async { - debugPrint('🔄 收到重置事件:仅清空状态,保持订阅活跃(不重连)'); + // debugPrint('🔄 收到重置事件:仅清空状态,保持订阅活跃(不重连)'); + _logger.log('🔄 收到重置事件:仅清空状态,保持订阅活跃(不重连)'); + // 只 emit 初始状态,让 UI 清除旧设备的数据(如速度归零、轨迹清除) emit(DeviceStatusInitial()); @@ -82,7 +90,8 @@ class DeviceStatusBloc extends Bloc { Emitter emit, ) async { try { - debugPrint('🔍 开始解析数据:${event.jsonString}'); + // debugPrint('🔍 开始解析数据:${event.jsonString}'); + _logger.log('🔍 开始解析数据:${event.jsonString}'); final fields = event.jsonString.trim().split(','); if (fields.length < 18) { @@ -94,10 +103,12 @@ class DeviceStatusBloc extends Bloc { final status = RunningStatusEntity.fromFields(fields); final gps = GPSEntity(status.latitude, status.longitude); - debugPrint('✅ 解析成功,更新状态:Lat=${gps.latitude}, Lng=${gps.longitude}'); + //debugPrint('✅ 解析成功,更新状态:Lat=${gps.latitude}, Lng=${gps.longitude}'); + _logger.log('✅ 解析成功,更新状态:Lat=${gps.latitude}, Lng=${gps.longitude}'); emit(DeviceStatusUpdated(status, gps)); } catch (e, stack) { - debugPrint('❌ 解析异常:$e\n$stack'); + //debugPrint('❌ 解析异常:$e\n$stack'); + _logger.log('❌ 解析异常:$e\n$stack'); emit(DeviceStatusError('解析失败:$e')); } } @@ -109,7 +120,8 @@ class DeviceStatusBloc extends Bloc { try { final eventStr = event.jsonData['event'] ?? ''; final deviceId = event.jsonData['deviceId'] ?? '未知'; - debugPrint('收到推送事件:$eventStr, 设备:$deviceId'); + // debugPrint('收到推送事件:$eventStr, 设备:$deviceId'); + _logger.log('收到推送事件:$eventStr, 设备:$deviceId'); // 这里可以根据需要 emit 新状态 } catch (e) { emit(DeviceStatusError('解析推送消息失败:$e')); diff --git a/lib/features/devices/presentation/bloc/devices_cubit.dart b/lib/features/devices/presentation/bloc/devices_cubit.dart index 0ab17ef1..e3a934c4 100644 --- a/lib/features/devices/presentation/bloc/devices_cubit.dart +++ b/lib/features/devices/presentation/bloc/devices_cubit.dart @@ -13,6 +13,7 @@ import 'package:maibu_satabot_v2/features/devices/domain/usecases/unbind_device_ import 'package:maibu_satabot_v2/features/devices/domain/usecases/update_devicename_usecase.dart'; import '../../../../core/consts/tcp_consts.dart'; +import '../../../../core/logging/i_logger_service.dart'; import '../../../../core/network/tcp/tcp_client.dart'; import '../../data/models/device_add_path_point_model.dart'; import '../../data/models/device_work_area_param_model.dart'; @@ -44,6 +45,9 @@ class DevicesCubit extends Cubit { // 🔥 关键:注入全局服务 final PathPlanningService _pathPlanningService; + final ILoggerService _logger = GetIt.I(); + + DevicesCubit( this.repository, this._getUserDeviceUseCase, @@ -115,7 +119,8 @@ class DevicesCubit extends Cubit { successCode, ) { // 核心修复:int 转 bool 条件判断 - print('更新设备名称结果代码: $successCode'); // 调试输出结果代码 + //print('更新设备名称结果代码: $successCode'); // 调试输出结果代码 + _logger.logWithLevel('更新设备名称结果代码: $successCode'); final isSuccess = successCode == 1; // 显式转为 bool if (isSuccess) { //final updatedDevices = state.devices?.map((device) { @@ -218,7 +223,8 @@ class DevicesCubit extends Cubit { // 🔥 关键修复 1:先强制断开旧连接! // 这一步会销毁旧 Socket,清除旧 Listener,防止旧数据继续推送 if (_tcpClient.isConnected) { - debugPrint('🛑 检测到已连接,先断开旧 TCP 连接...'); + //debugPrint('🛑 检测到已连接,先断开旧 TCP 连接...'); + _logger.logWithLevel('🔥 检测到已连接,先断开旧 TCP 连接...'); _tcpClient.disconnects(forSwitch: true); // 稍微等待一下,确保底层 Socket 资源释放 (可选,但推荐) // await Future.delayed(const Duration(milliseconds: 100)); @@ -226,7 +232,8 @@ class DevicesCubit extends Cubit { // 🔥 关键修复 2:发起新连接 // connect 方法内部会自动调用 _sendAuthPacket -> 获取设备列表 -> 自动订阅当前选中的设备 - debugPrint('🔌 开始重新新连接 TCP,将自动订阅新设备:${device.deviceName}'); + // debugPrint('🔌 开始重新新连接 TCP,将自动订阅新设备:${device.deviceName}'); + _logger.logWithLevel('🔌 启动重新新连接 TCP,将自动订阅新设备:${device.deviceName}'); await _tcpClient.connectBySwitch(host: TCPConsts.TCP_IP, port: TCPConsts.TCP_PORT, deviceName: device.deviceName); // 🔥 关键修复 3:重置设备状态 Bloc,清除旧设备图表数据 _deviceStatusBloc.add(DeviceStatusReset()); @@ -347,20 +354,24 @@ class DevicesCubit extends Cubit { // 开始路径规划 Future startRoutePlanning(Queue locationQueue) async { - print("cubit层开始路径规划"); + /// print("cubit层开始路径规划"); + _logger.logWithLevel('开始路径规划'); // 清空全局 Service 中的队列 // _routePlanningUseCase.clearLocationQueue(); final List pathList = locationQueue.toList(); - print('✅ 队列转换为 List,长度:${pathList.length}'); + // print('✅ 队列转换为 List,长度:${pathList.length}'); + _logger.logWithLevel('队列转换为 List,长度:${pathList.length}'); _pathPlanningService.updateQueue(pathList); - print('✅ 队列更新成功'); + //print('✅ 队列更新成功'); + _logger.logWithLevel('队列更新成功'); // 开始路径规划 emit(state.copyWith(isLoading: true)); //传入全局的Service 中路径规划队列 Queue queue = _pathPlanningService.getQueue(); - print('📦 从 Service 获取的队列长度:${queue.length}'); + //print('📦 从 Service 获取的队列长度:${queue.length}'); + _logger.logWithLevel('从 Service 获取的队列长度:${queue.length}'); final result = await _routePlanningUseCase.startRoutePlanning(queue); result.fold( (failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message ?? '路径规划启动失败')), @@ -407,7 +418,8 @@ class DevicesCubit extends Cubit { void setArrivedLocation(double latitude, double longitude) { emit(state.copyWith(arriLatitude: latitude, arriLongitude: longitude)); - print('✅ [DevicesCubit] 监听更新已完成到达位置:Lat=$latitude, Lng=$longitude'); + // print('✅ [DevicesCubit] 监听更新已完成到达位置:Lat=$latitude, Lng=$longitude'); + _logger.logWithLevel('✅ [DevicesCubit] 监听更新已完成到达位置:Lat=$latitude, Lng=$longitude'); } //获取已到达的点的经纬度 @@ -418,6 +430,7 @@ class DevicesCubit extends Cubit { // 重置已到达记录 void resetArrivedLocation() { emit(state.copyWith(arriLatitude: null, arriLongitude: null)); - print('🔄 [DevicesCubit] 已重置到达位置'); + //print('🔄 [DevicesCubit] 已重置到达位置'); + _logger.logWithLevel('🔄 [DevicesCubit] 已重置到达位置'); } } diff --git a/lib/features/devices/services/path_planning_service.dart b/lib/features/devices/services/path_planning_service.dart index e8f0e835..74a60edf 100644 --- a/lib/features/devices/services/path_planning_service.dart +++ b/lib/features/devices/services/path_planning_service.dart @@ -1,6 +1,8 @@ // lib/features/devices/domain/services/path_planning_service.dart import 'dart:collection'; import 'package:flutter/cupertino.dart'; +import 'package:get_it/get_it.dart'; +import '../../../core/logging/i_logger_service.dart'; import '../data/models/device_add_path_point_model.dart'; class PathPlanningService { @@ -8,6 +10,8 @@ class PathPlanningService { factory PathPlanningService() => _instance; PathPlanningService._internal(); + final ILoggerService _logger = GetIt.I(); + // 🔥 核心:全局唯一的可变队列 final Queue locationQueue = Queue(); @@ -18,8 +22,10 @@ class PathPlanningService { /// 🔥 存:生成路径后立即存储 void updateQueue(List locations) { debugPrint('进入[PathPlanningService]updateQueue方法尝试更新空队列'); + _logger.logWithLevel('进入[PathPlanningService]updateQueue方法尝试更新空队列'); if (locations.isEmpty) { debugPrint('⚠️ [PathPlanningService] 尝试更新空队列'); + _logger.logWithLevel('⚠️ [PathPlanningService] 尝试更新空队列'); return; } @@ -28,20 +34,26 @@ class PathPlanningService { currentIndex = 0; totalCount = locations.length; - debugPrint('✅ [PathPlanningService] 队列已更新,共 $totalCount 个点'); + //debugPrint('✅ [PathPlanningService] 队列已更新,共 $totalCount 个点'); + _logger.logWithLevel('✅ [PathPlanningService] 队列已更新,共 $totalCount 个点'); } /// 🔥 取:发送时取出第一个点 DeviceAddPathPointModel? removeFirst() { if (locationQueue.isEmpty) { - debugPrint('⚠️ [PathPlanningService] 队列为空'); + //debugPrint('⚠️ [PathPlanningService] 队列为空'); + _logger.logWithLevel('⚠️ [PathPlanningService] 队列为空'); return null; } final point = locationQueue.removeFirst(); currentIndex++; - debugPrint( + // debugPrint( + // '📍 [PathPlanningService] 取出第 $currentIndex/$totalCount 个点:' + // '${point.latitude}, ${point.longitude}', + // ); + _logger.logWithLevel( '📍 [PathPlanningService] 取出第 $currentIndex/$totalCount 个点:' '${point.latitude}, ${point.longitude}', ); @@ -63,7 +75,8 @@ class PathPlanningService { isRunning = false; currentIndex = 0; totalCount = 0; - debugPrint('🧹 [PathPlanningService] 队列已清空'); + //debugPrint('🧹 [PathPlanningService] 队列已清空'); + _logger.logWithLevel('🧹 [PathPlanningService] 队列已清空'); } diff --git a/lib/features/my/presentation/bloc/my_cubit.dart b/lib/features/my/presentation/bloc/my_cubit.dart index 8c92e768..d8f0db92 100644 --- a/lib/features/my/presentation/bloc/my_cubit.dart +++ b/lib/features/my/presentation/bloc/my_cubit.dart @@ -23,11 +23,11 @@ class MyCubit extends Cubit { try { final params = UpdateNameParams(nickName); final result = await _updateNameUsecase(params); - print("$result 修改名称结构"); + //print("$result 修改名称结构"); // 4. 恢复 fold 逻辑,处理 UseCase 返回结果(关键:更新 UI 状态) result.fold((failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message ?? '修改昵称失败')), (successCode) { - print("$successCode 修改名称结构"); + //print("$successCode 修改名称结构"); final isSuccess = successCode == 200; if (isSuccess) { emit(state.copyWith(isLoading: false, errorMessage: '', nickName: nickName)); diff --git a/lib/features/remote_control/data/datasources/remote_http_datasource.dart b/lib/features/remote_control/data/datasources/remote_http_datasource.dart index 22431e23..624acd11 100644 --- a/lib/features/remote_control/data/datasources/remote_http_datasource.dart +++ b/lib/features/remote_control/data/datasources/remote_http_datasource.dart @@ -2,12 +2,15 @@ import 'dart:ffi'; import 'package:dio/dio.dart'; import 'package:flutter/cupertino.dart'; +import 'package:get_it/get_it.dart'; +import '../../../../core/logging/i_logger_service.dart'; import '../../../../core/storage/user_storage.dart'; class RemoteHttpDatasource { final Dio _dio; final UserStorage _userStorage; // 🔥 新增字段 + final ILoggerService _logger = GetIt.I(); RemoteHttpDatasource(this._dio, this._userStorage); @@ -44,23 +47,26 @@ class RemoteHttpDatasource { print("请求权限的数据,$deviceId,"); try { final responseData = response.data as Map; - debugPrint("📊 [HTTP 响应] 完整数据:$responseData"); + //debugPrint("📊 [HTTP 响应] 完整数据:$responseData"); + _logger.log("📊 [HTTP 响应] 完整数据:$responseData"); // 🔥 关键:先获取响应的 data 字段,再获取 remoteControl final dataField = responseData['data'] as Map?; if (dataField != null) { final bool hasRemoteControl = dataField['remoteControl'] as bool? ?? false; - debugPrint("✅ [HTTP 响应] remoteControl=$hasRemoteControl"); - + //debugPrint("✅ [HTTP 响应] remoteControl=$hasRemoteControl"); + _logger.log("✅ [HTTP 响应] remoteControl=$hasRemoteControl"); // 🔥 直接返回 remoteControl 的布尔值 return hasRemoteControl; } else { - debugPrint("❌ [HTTP 响应] 缺少 data 字段"); + //debugPrint("❌ [HTTP 响应] 缺少 data 字段"); + _logger.log("❌ [HTTP 响应] 缺少 data 字段"); return false; } } catch (e) { - debugPrint('❌ [RemoteHttp] 解析响应失败:$e'); + // debugPrint('❌ [RemoteHttp] 解析响应失败:$e'); + _logger.log('❌ [RemoteHttp] 解析响应失败:$e'); return false; } } diff --git a/lib/features/remote_control/data/repositories/remote_control_repository_impl.dart b/lib/features/remote_control/data/repositories/remote_control_repository_impl.dart index 7c8f9acf..ee4db7b0 100644 --- a/lib/features/remote_control/data/repositories/remote_control_repository_impl.dart +++ b/lib/features/remote_control/data/repositories/remote_control_repository_impl.dart @@ -3,7 +3,9 @@ import 'dart:convert'; import 'dart:ffi'; import 'package:flutter/cupertino.dart'; +import 'package:get_it/get_it.dart'; +import '../../../../core/logging/i_logger_service.dart'; import '../../../../core/network/protocol_decoder.dart'; import '../../../../core/network/tcp/tcp_client.dart'; import '../../../../core/protocol/machine_protocol_codec.dart'; @@ -19,6 +21,7 @@ class RemoteControlRepositoryImpl implements RemoteControlRepository { final DiffSteerUseCase _diffSteer; final RemoteHttpDatasource _remoteHttp; final RemoteTcpDatasource _remoteTcp; + final ILoggerService _logger = GetIt.I(); RemoteControlRepositoryImpl(this._tcpClient, this._diffSteer, this._remoteHttp, this._remoteTcp); @@ -34,9 +37,13 @@ class RemoteControlRepositoryImpl implements RemoteControlRepository { final speeds = _diffSteer.calculate(status.originX, status.originY); - debugPrint('🎮 [摇杆数据] originX: ${status.originX}, originY: ${status.originY}'); - debugPrint('⚙️ [电机速度] left: ${speeds['left']}, right: ${speeds['right']}'); - debugPrint('🚨 [急停状态] emergency: ${status.isEmergency ? 1 : 0}'); + //debugPrint('🎮 [摇杆数据] originX: ${status.originX}, originY: ${status.originY}'); + _logger.logWithLevel('⚙️ [电机速度] left: ${speeds['left']}, right: ${speeds['right']}'); + + //debugPrint('⚙️ [电机速度] left: ${speeds['left']}, right: ${speeds['right']}'); + _logger.logWithLevel('⚙️ [电机速度] left: ${speeds['left']}, right: ${speeds['right']}'); + //debugPrint('🚨 [急停状态] emergency: ${status.isEmergency ? 1 : 0}'); + _logger.logWithLevel('🚨 [急停状态] emergency: ${status.isEmergency ? 1 : 0}'); // 2. 调用 Codec:仅生成协议要求的 8 字节 Payload 负载数据 final payload = MachineProtocolCodec.encodeRemoteControlPayload( @@ -65,10 +72,12 @@ class RemoteControlRepositoryImpl implements RemoteControlRepository { Future requestControlPermission( String deviceName, String deviceId) async { try { _remoteTcp.sendSwitchControlRequest(deviceName); - debugPrint('🔑 [RemoteControl] TCP已发送权限请求'); + // debugPrint('🔑 [RemoteControl] TCP已发送权限请求'); + _logger.logWithLevel('🔑 [RemoteControl] TCP已发送权限请求'); return await _remoteHttp.requestRemoteControlViaHttp(deviceName, deviceId); } catch (e) { - debugPrint('❌ [RemoteControl] 权限请求失败:$e'); + //sdebugPrint('❌ [RemoteControl] 权限请求失败:$e'); + _logger.logWithLevel('❌ [RemoteControl] 权限请求失败:$e'); rethrow; } } diff --git a/lib/features/remote_control/presentation/bloc/remote_control_cubit.dart b/lib/features/remote_control/presentation/bloc/remote_control_cubit.dart index d5de9e68..92552850 100644 --- a/lib/features/remote_control/presentation/bloc/remote_control_cubit.dart +++ b/lib/features/remote_control/presentation/bloc/remote_control_cubit.dart @@ -7,9 +7,11 @@ import 'package:dart_ping/dart_ping.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:get_it/get_it.dart'; import 'package:maibu_satabot_v2/features/remote_control/data/models/running_status_model.dart'; import 'package:maibu_satabot_v2/features/remote_control/presentation/bloc/remote_control_state.dart'; +import '../../../../core/logging/i_logger_service.dart'; import '../../../../core/network/net_message_dispatcher.dart'; import '../../../devices/domain/entities/running_status_entity.dart'; import '../../domain/entities/machine_control_status_entity.dart'; @@ -25,6 +27,8 @@ class RemoteControlCubit extends Cubit { StreamSubscription? _stringMessageSub; // static const platform = MethodChannel('com.maibu.satabot/ping'); int _currentPing = 50; + final ILoggerService _logger = GetIt.I(); + RemoteControlCubit(this._repository, this._requestControlPermissionUseCase, this.dispatcher) @@ -39,26 +43,32 @@ class RemoteControlCubit extends Cubit { } void _initStringMessageListener() { - print('>>> [RemoteControl] begin 初始化 0x02 字符串监听器'); + //print('>>> [RemoteControl] begin 初始化 0x02 字符串监听器'); + _logger.logWithLevel('>>> [RemoteControl] begin 初始化 0x02 字符串监听器'); _stringMessageSub?.cancel(); _stringMessageSub = dispatcher.onStringMessage().listen((message) async { - print('>>> [RemoteControl] 收到 0x02 字符串推送:$message'); + // print('>>> [RemoteControl] 收到 0x02 字符串推送:$message'); + _logger.logWithLevel('>>> [RemoteControl] 收到 0x02 字符串推送:$message'); if (message.isEmpty) { - print('⚠️ [RemoteControl] 消息为空,跳过解析'); + //print('⚠️ [RemoteControl] 消息为空,跳过解析'); + _logger.logWithLevel('⚠️ [RemoteControl] 消息为为空,跳过解析'); return; } try { // 🔥 关键:使用与 DeviceStatusBloc 相同的解析方法 - print('>>> [RemoteControl] 🔍 开始解析数据(使用 fromFields)...'); + // print('>>> [RemoteControl] 🔍 开始解析数据(使用 fromFields)...'); + _logger.logWithLevel('>>> [RemoteControl] 🔍 开始解析数据(使用 fromFields)...'); final fields = message.trim().split(','); - print('>>> [RemoteControl] 字段数量:${fields.length}'); + //print('>>> [RemoteControl] 字段数量:${fields.length}'); + _logger.logWithLevel('>>> [RemoteControl] 字段数量:${fields.length}'); if (fields.length < 18) { - print('⚠️ [RemoteControl] 字段不足:${fields.length},期望 ≥18'); + //print('⚠️ [RemoteControl] 字段不足:${fields.length},期望 ≥18'); + _logger.logWithLevel('⚠️ [RemoteControl] 字段不足:${fields.length},期望 ≥18'); return; } @@ -83,13 +93,15 @@ class RemoteControlCubit extends Cubit { } catch (e, stackTrace) { - print('>>> [RemoteControl] ❌ 解析失败:$e'); + // print('>>> [RemoteControl] ❌ 解析失败:$e'); + _logger.logWithLevel('>>> [RemoteControl] ❌ 解析失败:$e'); // print('>>> [RemoteControl] ❌ 堆栈跟踪:$stackTrace'); // print('>>> [RemoteControl] ❌ 原始消息:$message'); } }); - print('>>> [RemoteControl] ✅ 0x02 字符串监听器已建立完成'); + //print('>>> [RemoteControl] ✅ 0x02 字符串监听器已建立完成'); + _logger.logWithLevel('>>> [RemoteControl] ✅ 0x02 字符串监听器已建立完成'); } @@ -109,7 +121,8 @@ class RemoteControlCubit extends Cubit { battery: int.tryParse(newStatus.battery) ?? 0, )); - debugPrint('✅ [更新运行状态] 电压:${newStatus.voltage}V, 电量:${newStatus.battery}%'); + // debugPrint('✅ [更新运行状态] 电压:${newStatus.voltage}V, 电量:${newStatus.battery}%'); + _logger.logWithLevel('✅ [更新运行状态] 电压:${newStatus.voltage}V, 电量:${newStatus.battery}%'); } } @@ -124,11 +137,13 @@ class RemoteControlCubit extends Cubit { // }); // } Future _initPacketListener() async { - print('>>> [RemoteControl] begin 初始化 0x12 监听器'); + //print('>>> [RemoteControl] begin 初始化 0x12 监听器'); + _logger.logWithLevel('>>> [RemoteControl] begin 0x12 监听器'); _kickOutSub?.cancel(); // 防止重复监听 _kickOutSub = dispatcher.onCommand(0x12).listen((packet) { - print('>>> [RemoteControl] 收到 0x12 原始包,payload 长度=${packet.payload.length}'); + //print('>>> [RemoteControl] 收到 0x12 原始包,payload 长度=${packet.payload.length}'); + _logger.logWithLevel('>>> [RemoteControl] 收到 0x12 原始包,payload 长度=${packet.payload.length}'); try { // 🔥 关键:手动去掉最后 2 个 CRC 字节 @@ -139,7 +154,8 @@ class RemoteControlCubit extends Cubit { jsonString = utf8.decode(packet.payload); } - print('>>> [RemoteControl] 去除 CRC 后的 JSON: $jsonString'); + //print('>>> [RemoteControl] 去除 CRC 后的 JSON: $jsonString'); + _logger.logWithLevel('>>> [RemoteControl] 去除 CRC 后的 JSON: $jsonString'); final jsonMap = jsonDecode(jsonString); @@ -148,12 +164,14 @@ class RemoteControlCubit extends Cubit { final platform = jsonMap['platform']; final respondData = jsonMap['respond']; - print('>>> [RemoteControl] 📋 requestType=$requestType, platform=$platform'); + //print('>>> [RemoteControl] 📋 requestType=$requestType, platform=$platform'); + _logger.logWithLevel('>>> [RemoteControl] 📋 requestType=$requestType, platform=$platform'); // 情况 1: 响应格式 - {"respond":{"switchResult":true,"deviceId":"...","holder":"you"}} if (respondData != null && respondData is Map) { final switchResult = respondData['switchResult']; - print('>>> [RemoteControl] 📊 收到切换结果响应:switchResult = $switchResult'); + //print('>>> [RemoteControl] 📊 收到切换结果响应:switchResult = $switchResult'); + _logger.logWithLevel('>>> [RemoteControl] 📊 收到切换结果响应:switchResult = $switchResult'); if (!isClosed) { if (switchResult == true) { @@ -171,33 +189,39 @@ class RemoteControlCubit extends Cubit { else if (requestType == 'switch_control') { // 🔥 关键判断:只有当是其他平台(web)请求时才弹窗 if (platform != null && platform.toString().toLowerCase() != 'app') { - print('>>> [RemoteControl] 🚨 $platform 端请求控制权,打开弹窗询问用户'); + //print('>>> [RemoteControl] 🚨 $platform 端请求控制权,打开弹窗询问用户'); + _logger.logWithLevel('>>> [RemoteControl] 🚨 $platform 端请求控制权,打开弹窗询问用户'); if (!isClosed) { emit(state.copyWith(showPermissionRequestDialog: true)); } } else { - print('>>> [RemoteControl] ℹ️ APP 自己的请求回显,忽略不弹窗'); + //print('>>> [RemoteControl] ℹ️ APP 自己的请求回显,忽略不弹窗'); + _logger.logWithLevel('>>> [RemoteControl] ℹ️ APP 自己的请求回显,忽略不弹窗'); } } // 情况 3: 异地登录通知 - {"request":"have_logged_in",...} else if (requestType == 'have_logged_in') { - print('>>> [RemoteControl] ⚠️ 检测到异地登录,打开弹窗提示'); + //print('>>> [RemoteControl] ⚠️ 检测到异地登录,打开弹窗提示'); + _logger.logWithLevel('>>> [RemoteControl] ⚠️ 检测到异地登录,打开弹窗提示'); if (!isClosed) { emit(state.copyWith(showPermissionRequestDialog: true)); } } else { - print('>>> [RemoteControl] ℹ️ 未知类型的 0x12 包,忽略'); + // print('>>> [RemoteControl] ℹ️ 未知类型的 0x12 包,忽略'); + _logger.logWithLevel('>>> [RemoteControl] ℹ️ 未知类型的 0x12 包,忽略'); } } catch (e) { - print('>>> [RemoteControl] ❌ 解析失败:$e'); + //print('>>> [RemoteControl] ❌ 解析失败:$e'); + _logger.logWithLevel('>>> [RemoteControl] ❌ 解析失败:$e'); } }); final c = getNetworkDelay(); emit(state.copyWith( ping: await c, // 这里直接使用异步返回的数值 )); - print('>>> [RemoteControl] ✅ 0x12 监听器已建立完成'); + //print('>>> [RemoteControl] ✅ 0x12 监听器已建立完成'); + _logger.logWithLevel('>>> [RemoteControl] ✅ 0x12 监听器已建立完成'); } @@ -222,7 +246,8 @@ class RemoteControlCubit extends Cubit { // 4. 更新功能开关 (比如割刀速度、灯光、点火等) void updateFunction({int? mower, int? lift, int? ignition, bool? emergency}) { - debugPrint('🔧 [updateFunction] 调用 - mower: $mower, lift: $lift, ignition: $ignition, emergency: $emergency'); + // debugPrint('🔧 [updateFunction] 调用 - mower: $mower, lift: $lift, ignition: $ignition, emergency: $emergency'); + _logger.logWithLevel('🔧 [updateFunction] 调用 - mower: $mower, lift: $lift, ignition: $ignition, emergency: $emergency'); final updatedEntity = state.controlEntity.copyWith( mower: mower, lift: lift, @@ -235,6 +260,7 @@ class RemoteControlCubit extends Cubit { isEmergency: emergency ?? state.isEmergency, )); debugPrint('✅ [updateFunction] 状态已更新并 emit'); + _logger.logWithLevel('✅ [updateFunction] 状态已更新并 emit'); } void updateOriginY(int y) { @@ -322,14 +348,16 @@ class RemoteControlCubit extends Cubit { // 3. 处理结果 result.fold( (failure) { - print('❌ [RemoteControl] 请求控制权限失败:${failure.message}'); + //print('❌ [RemoteControl] 请求控制权限失败:${failure.message}'); + _logger.logWithLevel('❌ [RemoteControl] 请求控制权限失败:${failure.message}'); // 可以在这里显示错误提示或重新打开弹窗 emit(state.copyWith(showPermissionRequestDialog: true)); }, (success) { // 更新状态 - print('✅ [RemoteControl] 请求控制权限成功:$success'); + //print('✅ [RemoteControl] 请求控制权限成功:$success'); + _logger.logWithLevel('✅ [RemoteControl] 请求控制权限成功:$success'); ///处理result if(success){ emit(state.copyWith(hasPermission: true)); @@ -343,12 +371,14 @@ class RemoteControlCubit extends Cubit { } /// 发送底盘指令 void sendChassisCommand(int i) { - debugPrint(' [底盘指令] ${i}'); + // debugPrint(' [底盘指令] ${i}'); + _logger.logWithLevel(' [底盘指令] ${i}'); updateFunction(lift: i); } /// 发送割刀指令 void sendMowerCommand(int i) { - debugPrint(' [割刀指令] ${i}'); + // debugPrint(' [割刀指令] ${i}'); + _logger.logWithLevel(' [割刀指令] ${i}'); updateFunction(mower: i); } /// 发送点火指令 @@ -356,6 +386,7 @@ class RemoteControlCubit extends Cubit { //void updateFunction({int? mower, int? lift, int? ignition, bool? emergency}) // updateFunction(mower:0, lift: 0, ignition: i, emergency: false); debugPrint(' [点火指令] ${i}'); + _logger.logWithLevel(' [点火指令] ${i}'); updateFunction(ignition: i); } // 发送障碍物识别指令