首次提交
This commit is contained in:
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');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user