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

197 lines
5.1 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 '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');
}
}