Files
ble_web_front/lib/controllers/ControlPanelController.dart
2026-04-25 17:45:10 +08:00

374 lines
9.9 KiB
Dart
Raw Permalink 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 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:web_frontend/models/DeviceInfo.dart';
import 'package:web_frontend/models/LogType.dart';
import 'package:web_frontend/models/UserInfo.dart';
import 'package:web_frontend/services/WebSocketService.dart';
class ControlPanelController extends GetxController {
final WebSocketService webSocketService = Get.find<WebSocketService>();
// 用户相关
final users = <UserInfo>[].obs;
final selectedUser = Rx<UserInfo?>(null);
// 设备相关
final devices = <DeviceInfo>[].obs;
final searchKeyword = ''.obs;
// 信号强度过滤
final rssiFilterValue = (-70).obs; // 默认-70dBm
// 日志相关
final connectionLogs = <LogEntry>[].obs;
final deviceLogs = <LogEntry>[].obs;
final allLogs = <LogEntry>[].obs;
final autoScroll = true.obs;
final ScrollController logScrollController = ScrollController();
// 命令输入
final commandController = TextEditingController();
// 日志过滤器
final showAllLogs = true.obs;
final showConnectionLogs = true.obs;
final showDeviceLogs = true.obs;
// 过滤后的设备列表(包含名称搜索和信号强度过滤)
List<DeviceInfo> get filteredDevices {
List<DeviceInfo> result = devices.toList();
// 名称/ID 模糊查询
if (searchKeyword.value.isNotEmpty) {
result = result
.where((device) =>
device.name
.toLowerCase()
.contains(searchKeyword.value.toLowerCase()) ||
device.id
.toLowerCase()
.contains(searchKeyword.value.toLowerCase()))
.toList();
}
// 信号强度过滤(只显示信号强度大于等于设定值的设备)
result =
result.where((device) => device.rssi >= rssiFilterValue.value).toList();
// 按信号强度排序(从强到弱)
result.sort((a, b) => b.rssi.compareTo(a.rssi));
return result;
}
// 获取当前显示的日志
List<LogEntry> get displayLogs {
if (showAllLogs.value) {
return allLogs.toList();
}
final logs = <LogEntry>[];
if (showConnectionLogs.value) {
logs.addAll(connectionLogs);
}
if (showDeviceLogs.value) {
logs.addAll(deviceLogs);
}
logs.sort((a, b) => a.time.compareTo(b.time));
return logs;
}
@override
void onInit() {
super.onInit();
_initWebSocketHandlers();
}
@override
void onClose() {
commandController.dispose();
logScrollController.dispose();
super.onClose();
}
void _initWebSocketHandlers() {
webSocketService.registerMessageHandler(_handleWebSocketMessage);
}
// void _handleWebSocketMessage(Map<String, dynamic> data) {
// final type = data['type'] as String?;
// switch (type) {
// case 'user_list':
// _updateUserList(data['users']);
// break;
// case 'device_selected':
// _addConnectionLog('已连接到设备: ${data['targetUuid']}', LogType.success);
// break;
// case 'device_message':
// _handleDeviceMessage(data['data']);
// break;
// case 'error':
// _addConnectionLog('错误: ${data['message']}', LogType.error);
// break;
// default:
// if (type != null) {
// _addConnectionLog('收到消息类型: $type', LogType.info);
// }
// }
// }
void _handleWebSocketMessage(Map<String, dynamic> data) {
final type = data['type'] as String?;
switch (type) {
case 'user_list':
_updateUserList(data['users']);
break;
case 'device_selected':
_addConnectionLog('已连接到设备: ${data['targetUuid']}', LogType.success);
// 设备连接成功后,自动触发扫描
_addConnectionLog('设备已就绪,自动开始扫描...', LogType.info);
webSocketService.startScan();
_addDeviceLog('自动发送扫描命令', LogType.info);
break;
case 'device_message':
_handleDeviceMessage(data['data']);
break;
case 'error':
_addConnectionLog('错误: ${data['message']}', LogType.error);
break;
default:
if (type != null) {
_addConnectionLog('收到消息类型: $type', LogType.info);
}
}
}
void _updateUserList(List<dynamic> usersData) {
users.value = usersData.map((u) => UserInfo.fromJson(u)).toList();
if (selectedUser.value != null &&
!users.any((u) => u.uuid == selectedUser.value!.uuid)) {
selectedUser.value = null;
devices.clear();
}
_addConnectionLog('设备列表更新: ${users.length} 个在线设备', LogType.info);
}
void _handleDeviceMessage(Map<String, dynamic> data) {
final deviceDataType = data['type'] as String?;
switch (deviceDataType) {
case 'device_list':
_updateDeviceList(data['devices']);
break;
case 'bluetooth_data':
_addDeviceLog('收到蓝牙数据: ${data['data']}', LogType.device);
break;
case 'bluetooth_status':
final isConnected = data['isConnected'] as bool? ?? false;
_addDeviceLog('蓝牙状态: ${isConnected ? "已连接" : "未连接"}',
isConnected ? LogType.success : LogType.warning);
break;
case 'scan_start':
_addDeviceLog('开始扫描蓝牙设备...', LogType.info);
break;
case 'scan_stop':
_addDeviceLog('停止扫描', LogType.info);
break;
default:
_addDeviceLog('设备消息: $data', LogType.device);
}
}
void _updateDeviceList(List<dynamic> devicesData) {
devices.value = devicesData.map((d) => DeviceInfo.fromJson(d)).toList();
// _addDeviceLog('发现 ${devices.length} 个蓝牙设备', LogType.success);
}
// 添加连接日志WebSocket相关
void _addConnectionLog(String message, LogType type) {
final log = LogEntry(
message: message,
time: DateTime.now(),
type: type,
);
connectionLogs.add(log);
_updateAllLogs(log);
_scrollToBottom();
// 限制日志数量
if (connectionLogs.length > 500) {
connectionLogs.removeAt(0);
}
}
// 添加设备日志
void _addDeviceLog(String message, LogType type) {
final log = LogEntry(
message: message,
time: DateTime.now(),
type: type,
deviceId: selectedUser.value?.uuid,
);
deviceLogs.add(log);
_updateAllLogs(log);
_scrollToBottom();
if (deviceLogs.length > 500) {
deviceLogs.removeAt(0);
}
}
// 添加日志(供外部调用)
void addLog(String message, LogType type) {
_addConnectionLog(message, type);
}
void _updateAllLogs(LogEntry log) {
allLogs.add(log);
if (allLogs.length > 1000) {
allLogs.removeAt(0);
}
}
void _scrollToBottom() {
if (autoScroll.value) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (logScrollController.hasClients) {
logScrollController.animateTo(
logScrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 300),
curve: Curves.easeOut,
);
}
});
}
}
// ==================== 公共方法 ====================
// 更新信号强度过滤值
void updateRssiFilter(int value) {
rssiFilterValue.value = value;
_addConnectionLog('信号强度过滤设置为: ${value} dBm', LogType.info);
}
// 重置信号强度过滤
void resetRssiFilter() {
rssiFilterValue.value = -100;
_addConnectionLog('信号强度过滤已重置', LogType.info);
}
// 选择设备并建立连接
void selectUser(UserInfo? user) {
if (user == null) return;
selectedUser.value = user;
devices.clear();
// 通过 WebSocket 选择设备,建立连接
webSocketService.selectDevice(user.uuid);
_addConnectionLog('正在连接设备: ${user.deviceModel}', LogType.info);
}
// 发送自定义数据
void sendCustomData() {
if (selectedUser.value == null) {
_addConnectionLog('请先选择设备', LogType.warning);
return;
}
final command = commandController.text.trim();
if (command.isEmpty) {
_addConnectionLog('请输入命令或数据', LogType.warning);
return;
}
webSocketService.sendDataToDevice(command);
_addDeviceLog('发送数据: $command', LogType.info);
commandController.clear();
}
// 开始扫描蓝牙设备
void sendScanCommand() {
if (selectedUser.value == null) {
_addConnectionLog('请先选择设备', LogType.warning);
return;
}
webSocketService.startScan();
_addDeviceLog('发送扫描命令', LogType.info);
}
// 停止扫描
void sendStopScanCommand() {
if (selectedUser.value == null) {
_addConnectionLog('请先选择设备', LogType.warning);
return;
}
webSocketService.stopScan();
_addDeviceLog('发送停止扫描命令', LogType.info);
}
// 连接蓝牙设备
void connectToDevice(DeviceInfo device) {
if (selectedUser.value == null) {
_addConnectionLog('请先选择设备', LogType.warning);
return;
}
webSocketService.connectToDevice(device.id);
_addDeviceLog('连接蓝牙设备: ${device.name}', LogType.info);
}
// 断开蓝牙设备
void disconnectDevice() {
if (selectedUser.value == null) {
_addConnectionLog('请先选择设备', LogType.warning);
return;
}
webSocketService.disconnectDevice();
_addDeviceLog('断开蓝牙设备连接', LogType.info);
}
// 清空日志
void clearLogs() {
allLogs.clear();
connectionLogs.clear();
deviceLogs.clear();
_addConnectionLog('日志已清空', LogType.info);
}
// 切换自动滚动
void toggleAutoScroll(bool value) {
autoScroll.value = value;
}
// 切换日志过滤器
void toggleShowAllLogs(bool value) {
showAllLogs.value = value;
}
void toggleShowConnectionLogs(bool value) {
showConnectionLogs.value = value;
}
void toggleShowDeviceLogs(bool value) {
showDeviceLogs.value = value;
}
}