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 { }
}
}
}
}
}