From bc2ead637b41e61f0787ab8e5cbb439a5aa79cec Mon Sep 17 00:00:00 2001 From: Gold87 Date: Sat, 27 Apr 2024 21:13:12 -0400 Subject: [PATCH] Added text displaying bandwidth usage --- lib/pages/dashboard_page.dart | 11 +++-- lib/services/nt4_client.dart | 45 ++++++++++++++++++- lib/services/nt_connection.dart | 4 ++ pubspec.lock | 8 ++++ pubspec.yaml | 1 + test/pages/dashboard_page_test.dart | 3 ++ .../shuffleboard_nt_listener_test.dart | 3 ++ test/test_util.dart | 6 +++ 8 files changed, 75 insertions(+), 6 deletions(-) diff --git a/lib/pages/dashboard_page.dart b/lib/pages/dashboard_page.dart index 66685dd0..0c9188ec 100644 --- a/lib/pages/dashboard_page.dart +++ b/lib/pages/dashboard_page.dart @@ -9,6 +9,7 @@ import 'package:collection/collection.dart'; import 'package:dot_cast/dot_cast.dart'; import 'package:elegant_notification/elegant_notification.dart'; import 'package:file_selector/file_selector.dart'; +import 'package:multiple_stream_builder/multiple_stream_builder.dart'; import 'package:popover/popover.dart'; import 'package:screen_retriever/screen_retriever.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -1559,13 +1560,15 @@ class _DashboardPageState extends State with WindowListener { ), ), Expanded( - child: StreamBuilder( - stream: ntConnection.latencyStream(), + child: StreamBuilder2( + streams: StreamTuple2(ntConnection.bandiwdthStream(), + ntConnection.latencyStream()), builder: (context, snapshot) { - int latency = snapshot.data ?? 0; + double bandwidth = snapshot.snapshot1.data ?? 0.0; + int latency = snapshot.snapshot2.data ?? 0; return Text( - 'Latency: ${latency.toString().padLeft(5)} ms', + '${bandwidth.toStringAsFixed(2).padLeft(5)} kb/s | ${latency.toString().padLeft(1)} ms', textAlign: TextAlign.right, ); }), diff --git a/lib/services/nt4_client.dart b/lib/services/nt4_client.dart index d0332abf..13d881ab 100644 --- a/lib/services/nt4_client.dart +++ b/lib/services/nt4_client.dart @@ -257,6 +257,8 @@ class NT4Client { int _clientId = 0; int _serverTimeOffsetUS = 0; int _latencyMs = 0; + int _bitUsage = 0; + double _dataRateKbPerSecond = 0; WebSocketChannel? _mainWebsocket; StreamSubscription? _mainWebsocketListener; @@ -310,6 +312,21 @@ class NT4Client { } } + Stream bandwidthStream() async* { + yield _dataRateKbPerSecond; + + double lastYielded = _dataRateKbPerSecond; + + while (true) { + await Future.delayed(const Duration(seconds: 1)); + + if (_dataRateKbPerSecond != lastYielded) { + yield _dataRateKbPerSecond; + lastYielded = _dataRateKbPerSecond; + } + } + } + void addTopicAnnounceListener(Function(NT4Topic topic) onAnnounce) { _topicAnnounceListeners.add(onAnnounce); } @@ -504,12 +521,17 @@ class NT4Client { var rawData = serialize([timeTopic.pubUID, 0, timeTopic.getTypeId(), timeToSend]); + _bitUsage += rawData.lengthInBytes * 8; + if (_useRTT) { _rttWebsocket?.sink.add(rawData); } else { _mainWebsocket?.sink.add(rawData); } } + + _dataRateKbPerSecond = (_bitUsage / 1000) / (_pingInterval / 1000); + _bitUsage = 0; } void _rttHandleRecieveTimestamp(int serverTimestamp, int clientTimestamp) { @@ -545,15 +567,22 @@ class NT4Client { } void _wsSendJSON(String method, Map params) { - _mainWebsocket?.sink.add(jsonEncode([ + String encodedJson = jsonEncode([ { 'method': method, 'params': params, } - ])); + ]); + + _bitUsage += encodedJson.length * 8; + + _mainWebsocket?.sink.add(encodedJson); } void _wsSendBinary(dynamic data) { + if (data is Uint8List) { + _bitUsage += data.lengthInBytes * 8; + } _mainWebsocket?.sink.add(data); } @@ -685,6 +714,10 @@ class NT4Client { return; } + if (data is Uint8List) { + _bitUsage += data.lengthInBytes * 8; + } + var msg = Unpacker.fromList(data).unpackList(); int topicID = msg[0] as int; @@ -758,6 +791,9 @@ class NT4Client { _lastPongTime = 0; _latencyMs = 0; + _bitUsage = 0; + _dataRateKbPerSecond = 0; + logger.info('Network Tables disconnected'); onDisconnect?.call(); @@ -770,6 +806,8 @@ class NT4Client { void _wsOnMessage(data) { if (data is String) { + _bitUsage += data.length * 8; + var rxArr = jsonDecode(data.toString()); if (rxArr is! List) { @@ -846,6 +884,9 @@ class NT4Client { } } } else { + if (data is Uint8List) { + _bitUsage += data.lengthInBytes * 8; + } var u = Unpacker.fromList(data); bool done = false; diff --git a/lib/services/nt_connection.dart b/lib/services/nt_connection.dart index cd617dfa..319c67c1 100644 --- a/lib/services/nt_connection.dart +++ b/lib/services/nt_connection.dart @@ -120,6 +120,10 @@ class NTConnection { return nt4Client.latencyStream(); } + Stream bandiwdthStream() { + return nt4Client.bandwidthStream(); + } + void changeIPAddress(String ipAddress) { if (_ntClient.serverBaseAddress == ipAddress) { return; diff --git a/pubspec.lock b/pubspec.lock index 015ae6aa..909383d1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -656,6 +656,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + multiple_stream_builder: + dependency: "direct main" + description: + name: multiple_stream_builder + sha256: fec7a8909d0942d1a8d726b7e3057bd73e2ab64a5ae2da6b7b44a959f17f09fb + url: "https://pub.dev" + source: hosted + version: "3.0.2" nested: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 2de79d2f..d1362637 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -29,6 +29,7 @@ dependencies: logger: ^2.0.2+1 messagepack: ^0.2.1 msgpack_dart: ^1.0.1 + multiple_stream_builder: ^3.0.2 package_info_plus: ^5.0.1 path: ^1.8.3 path_provider: ^2.0.15 diff --git a/test/pages/dashboard_page_test.dart b/test/pages/dashboard_page_test.dart index e33559d1..c13a93b9 100644 --- a/test/pages/dashboard_page_test.dart +++ b/test/pages/dashboard_page_test.dart @@ -356,6 +356,9 @@ void main() { .thenAnswer((_) => Stream.value(true)); when(mockNT4Connection.latencyStream()).thenAnswer((_) => Stream.value(0)); + when(mockNT4Connection.bandiwdthStream()) + .thenAnswer((_) => Stream.value(0.0)); + when(mockSubscription.periodicStream()) .thenAnswer((_) => Stream.value(null)); diff --git a/test/services/shuffleboard_nt_listener_test.dart b/test/services/shuffleboard_nt_listener_test.dart index c0d8bf55..a072426d 100644 --- a/test/services/shuffleboard_nt_listener_test.dart +++ b/test/services/shuffleboard_nt_listener_test.dart @@ -35,6 +35,9 @@ void main() { when(mockNT4Connection.latencyStream()).thenAnswer((_) => Stream.value(0)); + when(mockNT4Connection.bandiwdthStream()) + .thenAnswer((_) => Stream.value(0.0)); + when(mockNT4Connection.getLastAnnouncedValue(any)).thenAnswer( (realInvocation) => lastAnnouncedValues[realInvocation.positionalArguments[0]], diff --git a/test/test_util.dart b/test/test_util.dart index 2f117a4f..3c9ff247 100644 --- a/test/test_util.dart +++ b/test/test_util.dart @@ -35,6 +35,9 @@ void setupMockOfflineNT4() { when(mockNT4Connection.latencyStream()).thenAnswer((_) => Stream.value(0)); + when(mockNT4Connection.bandiwdthStream()) + .thenAnswer((_) => Stream.value(0.0)); + when(mockNT4Connection.getLastAnnouncedValue(any)).thenReturn(null); when(mockNT4Connection.subscribe(any, any)).thenReturn(mockSubscription); @@ -81,6 +84,9 @@ void setupMockOnlineNT4() { when(mockNT4Connection.latencyStream()).thenAnswer((_) => Stream.value(0)); + when(mockNT4Connection.bandiwdthStream()) + .thenAnswer((_) => Stream.value(0.0)); + when(mockNT4Connection.getLastAnnouncedValue(any)).thenReturn(null); when(mockNT4Connection.subscribe(any, any)).thenReturn(mockSubscription);