首次提交
This commit is contained in:
373
lib/controllers/ControlPanelController.dart
Normal file
373
lib/controllers/ControlPanelController.dart
Normal file
@@ -0,0 +1,373 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
33
lib/main.dart
Normal file
33
lib/main.dart
Normal file
@@ -0,0 +1,33 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:web_frontend/services/WebSocketService.dart';
|
||||
import 'package:web_frontend/views/ControlPanelView.dart';
|
||||
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// 初始化服务
|
||||
await Get.putAsync(() async => WebSocketService());
|
||||
|
||||
// 连接 WebSocket
|
||||
Get.find<WebSocketService>().connect();
|
||||
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'BLE Debug Control Panel',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: ControlPanelView(),
|
||||
);
|
||||
}
|
||||
}
|
||||
20
lib/models/DeviceInfo.dart
Normal file
20
lib/models/DeviceInfo.dart
Normal file
@@ -0,0 +1,20 @@
|
||||
// 设备信息模型
|
||||
class DeviceInfo {
|
||||
final String name;
|
||||
final String id;
|
||||
final int rssi;
|
||||
|
||||
DeviceInfo({
|
||||
required this.name,
|
||||
required this.id,
|
||||
required this.rssi,
|
||||
});
|
||||
|
||||
factory DeviceInfo.fromJson(Map<String, dynamic> json) {
|
||||
return DeviceInfo(
|
||||
name: json['name'] ?? '',
|
||||
id: json['id'] ?? '',
|
||||
rssi: json['rssi'] ?? 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
24
lib/models/LogType.dart
Normal file
24
lib/models/LogType.dart
Normal file
@@ -0,0 +1,24 @@
|
||||
// 日志类型
|
||||
enum LogType {
|
||||
info,
|
||||
success,
|
||||
error,
|
||||
warning,
|
||||
device, // 设备日志
|
||||
connection, // 连接日志
|
||||
}
|
||||
|
||||
// 日志条目模型
|
||||
class LogEntry {
|
||||
final String message;
|
||||
final DateTime time;
|
||||
final LogType type;
|
||||
final String? deviceId; // 可选,关联的设备ID
|
||||
|
||||
LogEntry({
|
||||
required this.message,
|
||||
required this.time,
|
||||
required this.type,
|
||||
this.deviceId,
|
||||
});
|
||||
}
|
||||
22
lib/models/UserInfo.dart
Normal file
22
lib/models/UserInfo.dart
Normal file
@@ -0,0 +1,22 @@
|
||||
// 用户信息模型
|
||||
class UserInfo {
|
||||
final String uuid;
|
||||
final String deviceModel;
|
||||
final String connectedAt;
|
||||
|
||||
UserInfo({
|
||||
required this.uuid,
|
||||
required this.deviceModel,
|
||||
required this.connectedAt,
|
||||
});
|
||||
|
||||
factory UserInfo.fromJson(Map<String, dynamic> json) {
|
||||
return UserInfo(
|
||||
uuid: json['uuid'] ?? '',
|
||||
deviceModel: json['deviceModel'] ?? '',
|
||||
connectedAt: json['connectedAt'] ?? '',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
197
lib/services/WebSocketService.dart
Normal file
197
lib/services/WebSocketService.dart
Normal file
@@ -0,0 +1,197 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
import 'package:web_socket_channel/status.dart' as status;
|
||||
|
||||
class WebSocketService extends GetxService {
|
||||
//webscoket地址
|
||||
static const String WS_URL = 'ws://192.168.1.129:8089/ws';
|
||||
|
||||
WebSocketChannel? _channel;
|
||||
final RxBool isConnected = false.obs;
|
||||
final RxString connectionStatus = '未连接'.obs;
|
||||
|
||||
// 当前选中的设备UUID
|
||||
final RxString selectedDeviceUuid = ''.obs;
|
||||
|
||||
Timer? _reconnectTimer;
|
||||
int _reconnectAttempts = 0;
|
||||
static const int MAX_RECONNECT_ATTEMPTS = 10;
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
disconnect();
|
||||
_reconnectTimer?.cancel();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
Future<void> connect() async {
|
||||
try {
|
||||
_channel = WebSocketChannel.connect(Uri.parse(WS_URL));
|
||||
isConnected.value = true;
|
||||
connectionStatus.value = '已连接';
|
||||
_reconnectAttempts = 0;
|
||||
|
||||
_sendMessage({
|
||||
'type': 'web_register',
|
||||
'clientId': 'web_client_${DateTime.now().millisecondsSinceEpoch}',
|
||||
});
|
||||
|
||||
_channel!.stream.listen(
|
||||
(message) {
|
||||
_handleMessage(message);
|
||||
},
|
||||
onError: (error) {
|
||||
print('WebSocket错误: $error');
|
||||
connectionStatus.value = '错误: $error';
|
||||
isConnected.value = false;
|
||||
_scheduleReconnect();
|
||||
},
|
||||
onDone: () {
|
||||
print('WebSocket连接断开');
|
||||
connectionStatus.value = '已断开';
|
||||
isConnected.value = false;
|
||||
_scheduleReconnect();
|
||||
},
|
||||
);
|
||||
|
||||
} catch (e) {
|
||||
print('WebSocket连接失败: $e');
|
||||
connectionStatus.value = '连接失败';
|
||||
isConnected.value = false;
|
||||
_scheduleReconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void _scheduleReconnect() {
|
||||
if (_reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
||||
connectionStatus.value = '重连失败,请手动刷新';
|
||||
return;
|
||||
}
|
||||
|
||||
_reconnectTimer?.cancel();
|
||||
_reconnectTimer = Timer(Duration(seconds: 5), () {
|
||||
_reconnectAttempts++;
|
||||
connectionStatus.value = '重连中 (${_reconnectAttempts}/$MAX_RECONNECT_ATTEMPTS)...';
|
||||
connect();
|
||||
});
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
_channel?.sink.close(status.goingAway);
|
||||
_channel = null;
|
||||
isConnected.value = false;
|
||||
connectionStatus.value = '已断开';
|
||||
}
|
||||
|
||||
void _sendMessage(Map<String, dynamic> message) {
|
||||
if (_channel != null && isConnected.value) {
|
||||
_channel!.sink.add(jsonEncode(message));
|
||||
} else {
|
||||
print('WebSocket未连接,无法发送消息: $message');
|
||||
}
|
||||
}
|
||||
|
||||
final List<Function(Map<String, dynamic>)> _messageHandlers = [];
|
||||
|
||||
void registerMessageHandler(Function(Map<String, dynamic>) handler) {
|
||||
_messageHandlers.add(handler);
|
||||
}
|
||||
|
||||
void _handleMessage(dynamic message) {
|
||||
try {
|
||||
final data = jsonDecode(message);
|
||||
for (var handler in _messageHandlers) {
|
||||
handler(data);
|
||||
}
|
||||
} catch (e) {
|
||||
print('解析消息失败: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 公开方法 ====================
|
||||
|
||||
// 选择要控制的设备(建立连接)
|
||||
void selectDevice(String uuid) {
|
||||
selectedDeviceUuid.value = uuid;
|
||||
_sendMessage({
|
||||
'type': 'select_device',
|
||||
'targetUuid': uuid,
|
||||
'timestamp': DateTime.now().toIso8601String(),
|
||||
});
|
||||
print('选择设备: $uuid');
|
||||
}
|
||||
|
||||
// 开始扫描
|
||||
void startScan() {
|
||||
if (selectedDeviceUuid.value.isEmpty) {
|
||||
print('请先选择设备');
|
||||
return;
|
||||
}
|
||||
_sendMessage({
|
||||
'type': 'scan',
|
||||
'targetUuid': selectedDeviceUuid.value,
|
||||
'timestamp': DateTime.now().toIso8601String(),
|
||||
});
|
||||
print('发送扫描命令');
|
||||
}
|
||||
|
||||
// 停止扫描
|
||||
void stopScan() {
|
||||
if (selectedDeviceUuid.value.isEmpty) {
|
||||
print('请先选择设备');
|
||||
return;
|
||||
}
|
||||
_sendMessage({
|
||||
'type': 'stop_scan',
|
||||
'targetUuid': selectedDeviceUuid.value,
|
||||
'timestamp': DateTime.now().toIso8601String(),
|
||||
});
|
||||
print('发送停止扫描命令');
|
||||
}
|
||||
|
||||
// 连接蓝牙设备
|
||||
void connectToDevice(String deviceId) {
|
||||
if (selectedDeviceUuid.value.isEmpty) {
|
||||
print('请先选择设备');
|
||||
return;
|
||||
}
|
||||
_sendMessage({
|
||||
'type': 'connect',
|
||||
'targetUuid': selectedDeviceUuid.value,
|
||||
'deviceId': deviceId,
|
||||
'timestamp': DateTime.now().toIso8601String(),
|
||||
});
|
||||
print('连接蓝牙设备: $deviceId');
|
||||
}
|
||||
|
||||
// 断开蓝牙设备
|
||||
void disconnectDevice() {
|
||||
if (selectedDeviceUuid.value.isEmpty) {
|
||||
print('请先选择设备');
|
||||
return;
|
||||
}
|
||||
_sendMessage({
|
||||
'type': 'disconnect',
|
||||
'targetUuid': selectedDeviceUuid.value,
|
||||
'timestamp': DateTime.now().toIso8601String(),
|
||||
});
|
||||
print('断开蓝牙设备');
|
||||
}
|
||||
|
||||
// 发送数据到设备
|
||||
void sendDataToDevice(String data) {
|
||||
if (selectedDeviceUuid.value.isEmpty) {
|
||||
print('请先选择设备');
|
||||
return;
|
||||
}
|
||||
_sendMessage({
|
||||
'type': 'send_data',
|
||||
'targetUuid': selectedDeviceUuid.value,
|
||||
'data': data,
|
||||
'timestamp': DateTime.now().toIso8601String(),
|
||||
});
|
||||
print('发送数据: $data');
|
||||
}
|
||||
}
|
||||
1097
lib/views/ControlPanelView.dart
Normal file
1097
lib/views/ControlPanelView.dart
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user