using System; using System.Collections.Generic; using System.Diagnostics; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Timers; namespace Tango.Integration.Emergency { /// /// Represents a USB serial port emergency switch notification provider. /// /// public class UsbEmergencyNotificationProvider : IEmergencyNotificationProvider { private Timer _timer; private bool _busy; /// /// Gets or sets a value indicating whether to enable emergency detection and notification. /// public bool IsEnabled { get; set; } /// /// Gets or sets the current emergency status. /// public EmergencyStatus Status { get; set; } /// /// Gets or sets the address/port of the detection device. /// public string Address { get; set; } /// /// Gets or sets the read timeout for the loop-back signal. /// public TimeSpan ReadTimeout { get; set; } /// /// Gets or sets the signal output. /// public String SignalOutput { get; set; } /// /// Occurs when the emergency status has changed. /// public event EventHandler StatusChanged; /// /// Initializes a new instance of the class. /// /// The port. public UsbEmergencyNotificationProvider(String port) { SignalOutput = "1"; Address = port; ReadTimeout = TimeSpan.FromMilliseconds(500); _timer = new Timer(2000); _timer.Elapsed += _timer_Elapsed; _timer.Start(); } /// /// Called when the status has been changed. /// /// The status. /// The error exception. protected virtual void OnStatusChanged(EmergencyStatus status, Exception errorException = null) { if (Status != status) { Status = status; StatusChanged?.Invoke(this, new EmergencyStatusChangedEventArgs() { Status = status, ErrorException = errorException, }); } } /// /// Handles the Elapsed event of the _timer. /// /// The source of the event. /// The instance containing the event data. [DebuggerNonUserCode] private void _timer_Elapsed(object sender, ElapsedEventArgs e) { if (IsEnabled && !_busy) { _busy = true; SerialPort serial = new SerialPort(Address); try { serial.ReadTimeout = (int)ReadTimeout.TotalMilliseconds; serial.Open(); serial.Write(SignalOutput + "\n"); try { string output = serial.ReadLine(); if (output == SignalOutput) { OnStatusChanged(EmergencyStatus.On); } else { OnStatusChanged(EmergencyStatus.Off); } } catch (TimeoutException) { OnStatusChanged(EmergencyStatus.Off); } catch (Exception ex) { OnStatusChanged(EmergencyStatus.Error, ex); } } catch (Exception ex) { OnStatusChanged(EmergencyStatus.Error, ex); } finally { try { serial.Dispose(); _busy = false; } catch { } } } } } }