diff --git a/lib/pages/dashboard_page.dart b/lib/pages/dashboard_page.dart index 422a6db2..18dfb656 100644 --- a/lib/pages/dashboard_page.dart +++ b/lib/pages/dashboard_page.dart @@ -114,6 +114,11 @@ class _DashboardPageState extends State with WindowListener { }, ); + if (widget.preferences.getBool(PrefKeys.autoResizeToDS) ?? + Defaults.autoResizeToDS) { + widget.ntConnection.startDBModeServer(); + } + widget.ntConnection.addConnectedListener(() { setState(() { for (TabGridModel grid in _tabData.map((e) => e.tabGrid)) { @@ -1101,15 +1106,16 @@ class _DashboardPageState extends State with WindowListener { }); }, onResizeToDSChanged: (value) async { + await preferences.setBool(PrefKeys.autoResizeToDS, value); + setState(() { - if (value && widget.ntConnection.dsClient.driverStationDocked) { - _onDriverStationDocked(); + if (value) { + widget.ntConnection.startDBModeServer(); } else { + widget.ntConnection.stopDBModeServer(); _onDriverStationUndocked(); } }); - - await preferences.setBool(PrefKeys.autoResizeToDS, value); }, onRememberWindowPositionChanged: (value) async { await preferences.setBool(PrefKeys.rememberWindowPosition, value); @@ -1182,7 +1188,6 @@ class _DashboardPageState extends State with WindowListener { pixelRatio; await windowManager.setSize(newScreenSize); - await windowManager.setAlignment(Alignment.topCenter); Settings.isWindowMaximizable = false; diff --git a/lib/services/ds_interop.dart b/lib/services/ds_interop.dart index 3cca0ffe..e3ca9d42 100644 --- a/lib/services/ds_interop.dart +++ b/lib/services/ds_interop.dart @@ -9,7 +9,7 @@ import 'package:elastic_dashboard/services/log.dart'; class DSInteropClient { final String serverBaseAddress = '127.0.0.1'; bool _serverConnectionActive = false; - bool _dbModeConnectionActive = false; + bool _dbModeServerRunning = false; Function()? onConnect; Function()? onDisconnect; @@ -20,6 +20,8 @@ class DSInteropClient { Socket? _socket; ServerSocket? _dbModeServer; + final List _connectedSockets = []; + List _tcpBuffer = []; String? _lastAnnouncedIP; @@ -28,21 +30,34 @@ class DSInteropClient { String? get lastAnnouncedIP => _lastAnnouncedIP; bool get driverStationDocked => _driverStationDocked; + bool _attemptServerStart = true; + + DateTime serverStopTime = DateTime.now(); + DSInteropClient({ this.onNewIPAnnounced, this.onDriverStationDockChanged, this.onConnect, this.onDisconnect, }) { - _connect(); + _tcpSocketConnect(); } - void _connect() { - if (_serverConnectionActive) { - return; + void startDBModeServer() { + // For some reason if the server is quickly stopped then started there's a 5 second delay + // The workaround is to use the cached value of the docked state + if (DateTime.now().microsecondsSinceEpoch - + serverStopTime.microsecondsSinceEpoch <= + 5 * 1e6) { + onDriverStationDockChanged?.call(_driverStationDocked); } - _tcpSocketConnect(); - _dbModeServerConnect(); + _attemptServerStart = true; + _startDBModeServer(); + } + + void stopDBModeServer() { + serverStopTime = DateTime.now(); + _dbModeServerClose(false); } void _tcpSocketConnect() async { @@ -74,30 +89,36 @@ class DSInteropClient { ); } - void _dbModeServerConnect() async { - if (_dbModeConnectionActive) { + Future _startDBModeServer() async { + if (_dbModeServerRunning || !_attemptServerStart) { return; } try { _dbModeServer = await ServerSocket.bind(serverBaseAddress, 1741); } catch (e) { - logger.info( - 'Failed to start TCP server on port 1741, attempting to reconnect in 5 seconds'); - Future.delayed(const Duration(seconds: 5), _dbModeServerConnect); + if (_attemptServerStart) { + logger.info( + 'Failed to start TCP server on port 1741, attempting to restart in 5 seconds'); + Future.delayed(const Duration(seconds: 5), _startDBModeServer); + } else { + logger.info('Failed to start TCP server on port 1741'); + } return; } + _attemptServerStart = false; + _dbModeServerRunning = true; + _dbModeServer!.listen( (socket) { logger.info('Received connection from Driver Station on TCP port 1741'); + _connectedSockets.add(socket); socket.listen( (data) { - if (!_dbModeConnectionActive) { - _dbModeConnectionActive = true; - } _dbModeServerOnMessage(data); }, onDone: () { + _connectedSockets.remove(socket); logger.info('Lost connection from Driver Station on TCP port 1741'); }, ); @@ -172,39 +193,53 @@ class DSInteropClient { } } - void _socketClose() { + void _socketClose() async { if (!_serverConnectionActive) { return; } - _socket?.close(); + await _socket?.close(); _socket = null; _serverConnectionActive = false; - _driverStationDocked = false; - onDriverStationDockChanged?.call(false); onDisconnect?.call(); logger.info( 'Driver Station connection on TCP port 1742 closed, attempting to reconnect in 5 seconds.'); - Future.delayed(const Duration(seconds: 5), _connect); + Future.delayed(const Duration(seconds: 5), _tcpSocketConnect); } - void _dbModeServerClose() { - if (!_dbModeConnectionActive) { + void _dbModeServerClose([bool reconnect = true]) async { + if (!_dbModeServerRunning) { return; } - _dbModeServer?.close(); + _dbModeServerRunning = false; + + // Cloning the list because closing each socket changes the size of the list + for (Socket socket in _connectedSockets.toList()) { + await socket.close(); + socket.destroy(); + } + + await _dbModeServer?.close(); _dbModeServer = null; - _dbModeConnectionActive = false; + onDriverStationDockChanged?.call(false); - logger.info( - 'Driver Station TCP Server on Port 1741 closed, attempting to reconnect in 5 seconds.'); + _tcpBuffer.clear(); + + _attemptServerStart = reconnect; - Future.delayed(const Duration(seconds: 5), _dbModeServerConnect); + if (reconnect) { + logger.info( + 'Driver Station TCP Server on Port 1741 closed, attempting to reconnect in 5 seconds.'); + + Future.delayed(const Duration(seconds: 5), _startDBModeServer); + } else { + logger.info('Driver Station TCP Server on Port 1741 closed'); + } } } diff --git a/lib/services/nt_connection.dart b/lib/services/nt_connection.dart index 1bdb8a69..5f838b29 100644 --- a/lib/services/nt_connection.dart +++ b/lib/services/nt_connection.dart @@ -74,6 +74,14 @@ class NTConnection { ); } + void startDBModeServer() { + _dsClient.startDBModeServer(); + } + + void stopDBModeServer() { + _dsClient.stopDBModeServer(); + } + void addConnectedListener(VoidCallback callback) { onConnectedListeners.add(callback); }