/// <summary> /// Read from the LSL stream for server status /// </summary> async Task RunReadStatusPortAsync(CancellationToken cancelToken) { ReportNetworkTimeInterval.Restart(); StreamInlet inlet = null; try { inlet = new StreamInlet(StatusStream); cancelToken.Register(() => inlet.close_stream()); inlet.open_stream(); SyncedTime = false; SetBoardProperties(inlet); Log?.Invoke(this, new LogEventArgs(HostName, this, "RunReadStatusPortAsync", $"Create LSL stream for status on host {HostName}.", LogLevel.DEBUG)); HatConnectionChanged?.Invoke(this, new HatConnectionEventArgs(HatConnectionState.Discovered, HostName, "", BoardId, SampleRate)); string[,] samples = new string[32, 1]; double[] timestamps = new double[32]; // spin until canceled while (!cancelToken.IsCancellationRequested) { await Task.Delay(StatusReadingDelay); try { var sampleCount = inlet.pull_chunk(samples, timestamps); if (sampleCount > 0 && (samples[sampleCount - 1, 0].Length > 0)) { await ParseServerStatus(samples[sampleCount - 1, 0]); } } catch (ObjectDisposedException) { } catch (Exception ex) { Log?.Invoke(this, new LogEventArgs(HostName, this, "RunReadStatusPortAsync", ex, LogLevel.WARN)); } } } catch (OperationCanceledException) { } catch (Exception e) { Log?.Invoke(this, new LogEventArgs(this, "RunReadStatusPortAsync", e, LogLevel.FATAL)); } finally { if (inlet != null) { inlet.close_stream(); } } }
/// <summary> /// Task to monitor when discovered servers go stale (disconnected) /// </summary> async Task RunConnectionStatusMonitorAsync(CancellationToken cancelToken) { try { while (!cancelToken.IsCancellationRequested) { await Task.Delay(TimeSpan.FromSeconds(1)); var oldConnections = DiscoveredServers.Where(x => (DateTimeOffset.UtcNow - x.Value.TimeStamp) > TimeSpan.FromSeconds(30)); if (oldConnections.Any()) { foreach (var nextConnection in oldConnections) { if (nextConnection.Value.SecondsSinceLastSample < 30) { // glitch in the matrix, lost server status but it is still receiving streaming data continue; } try { // remove this server Log?.Invoke(this, new LogEventArgs(nextConnection.Key, this, "RunConnectionStatusMonitor", $"Lost connection to brainHat server {nextConnection.Key}.", LogLevel.INFO)); HatConnectionChanged?.Invoke(this, new HatConnectionEventArgs(HatConnectionState.Lost, nextConnection.Key)); DiscoveredServers.TryRemove(nextConnection.Key, out var discard); await discard.StopHatClientAsync(); RegisterHatClientEvents(discard, false); DiscoveredLslStreams.TryRemove(nextConnection.Key, out var discardLsl); } catch (Exception ex) { Log?.Invoke(this, new LogEventArgs(this, "RunConnectionStatusMonitor", ex, LogLevel.ERROR)); } } } } } catch (OperationCanceledException) { } catch (Exception e) { Log?.Invoke(this, new LogEventArgs(this, "RunConnectionStatusMonitor", e, LogLevel.ERROR)); } }
private void OnHatConnectionChanged(object sender, HatConnectionEventArgs e) { HatConnectionChanged?.Invoke(sender, e); }