internal void UnexpectedTermination(Exception exception) { TerminateAsync(); OngoingInitialisation = false; var secondsOfActiveConnection = (DateTime.Now - (_currentConnectionStarted ?? DateTime.Now)).TotalSeconds; Debug.WriteLine($"Event Listener terminated unexpectedly after {secondsOfActiveConnection} seconds."); if (AutoReconnect) { Debug.WriteLine($"{exception.GetType()} occured."); if (_firstReconnectAttempt == null) { _firstReconnectAttempt = DateTime.Now; } if (((DateTime)_firstReconnectAttempt).AddMinutes(1) < DateTime.Now) { _abortionRequested = false; _attempts = 0; _firstReconnectAttempt = null; Debug.WriteLine("Attempting to reconnect..."); AttemptedReconnect?.Invoke(this, new AttemptedReconnectEvent(_attempts)); InitializeAsync(); } else //recently attempted to reconnect { _attempts++; Debug.WriteLine($"Attempting to reconnect... {_attempts}"); AttemptedReconnect?.Invoke(this, new AttemptedReconnectEvent(_attempts)); if (_attempts >= 3) { _abortionRequested = true; _attempts = 0; _firstReconnectAttempt = null; Debug.WriteLine($"Too many reconnection attempts ({_attempts})"); Debug.WriteLine($"Event subscription will be terminated. ({_attempts})"); TerminatedUnexpectedly?.Invoke(this, new TerminatedUnexpectedlyEvent(exception)); Debug.WriteLine("New initialisation required."); } else { InitializeAsync(); } } } else { Debug.WriteLine($"Event subscription will be terminated. ({_attempts})"); TerminatedUnexpectedly?.Invoke(this, new TerminatedUnexpectedlyEvent(exception)); AutoReconnect = false; Debug.WriteLine("New initialisation required."); } }
/// <summary> /// Initializes an asynchronous Rest prompt which is read and interpreted. /// Results can be aquired by listening to the relevant event /// </summary> public async void InitializeAsync(bool autoreconnect = true) { _abortionRequested = false; AutoReconnect = autoreconnect; if (IsInitialized || OngoingInitialisation) { return; } OngoingInitialisation = true; _currentConnectionStarted = null; Debug.WriteLine("Initialize Event Listener..."); await Task.Run(() => { // asynchronous stream reader using (var httpClient = new HttpClient()) { httpClient.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite); var requestUri = $"{OpenHab.RestClient.Url}/events"; try { var stream = httpClient.GetStreamAsync(requestUri).Result; using (var reader = new StreamReader(stream)) { IsInitialized = true; AttemptedReconnect?.Invoke(this, new AttemptedReconnectEvent(-1)); Debug.WriteLine("Event Listener initialized."); _currentConnectionStarted = DateTime.Now; var dataTemplate = new Regex(@"data:\s({.*})"); while (!_abortionRequested) { try { if (reader.EndOfStream) { TerminateAsync(); break; } } catch (Exception e) { UnexpectedTermination(e); break; } if (_abortionRequested) { break; } var currentLine = reader.ReadLine(); if (currentLine == null) { continue; } var data = dataTemplate.Match(currentLine).Groups[1]; if (!data.Success) { continue; } RaiseEvent(data.Value); } } } catch (AggregateException e) { UnexpectedTermination(e); } } if (_currentConnectionStarted == null) { return; } var secondsOfActiveConnection = (DateTime.Now - _currentConnectionStarted.Value).TotalSeconds; Debug.WriteLine($"Event Listener terminated after {secondsOfActiveConnection} seconds."); }); }