From 97226ae96bf3b932b4522f8b33dc774c6000d1fd Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Tue, 29 Jul 2025 18:13:26 +0800 Subject: [PATCH] :sparkles: Websocket hearbeat --- lib/pods/websocket.dart | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/pods/websocket.dart b/lib/pods/websocket.dart index 1504140..dc6f958 100644 --- a/lib/pods/websocket.dart +++ b/lib/pods/websocket.dart @@ -46,6 +46,10 @@ class WebSocketService { final StreamController _statusStreamController = StreamController.broadcast(); Timer? _reconnectTimer; + Timer? _heartbeatTimer; + + DateTime? _heartbeatAt; + Duration? _heartbeatDelay; Stream get dataStream => _streamController.stream; Stream get statusStream => _statusStreamController.stream; @@ -71,6 +75,7 @@ class WebSocketService { } await _channel!.ready; _statusStreamController.sink.add(WebSocketState.connected()); + _scheduleHeartbeat(); _channel!.stream.listen( (data) { final dataStr = @@ -80,6 +85,13 @@ class WebSocketService { log( "[WebSocket] Received packet: ${packet.type} ${packet.errorMessage}", ); + if (packet.type == 'pong' && _heartbeatAt != null) { + var now = DateTime.now(); + _heartbeatDelay = now.difference(_heartbeatAt!); + log( + "[WebSocket] Server respond last heartbeat for ${_heartbeatDelay!.inMilliseconds} ms", + ); + } }, onDone: () { log('[WebSocket] Connection closed, attempting to reconnect...'); @@ -108,6 +120,19 @@ class WebSocketService { }); } + void _scheduleHeartbeat() { + _heartbeatTimer?.cancel(); + _heartbeatTimer = Timer.periodic(const Duration(seconds: 3), (_) { + _beatTheHeart(); + }); + } + + void _beatTheHeart() { + _heartbeatAt = DateTime.now(); + log('[WebSocket] We\'re beating the heart! $_heartbeatAt'); + sendMessage(jsonEncode(WebSocketPacket(type: 'ping', data: null))); + } + WebSocketChannel? get ws => _channel; void sendMessage(String message) {