using DTS.Common.DAS.Concepts; using DTS.DASLib.Command; using DTS.DASLib.Command.TDAS; using DTS.DASLib.Service; using DTS.Common.Utilities.Logging; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO.Ports; using System.Text; using System.Threading; using ArmStatus = DTS.DASLib.Service.ArmStatus; using DTS.Common.Interface.DASFactory; using DTS.Common.SerialConnection; using DTS.Common.Enums.DASFactory; using DTS.Common.ICommunication; namespace DTS.DASLib.DASFactory { internal abstract class SerialTDASSetup : IDeviceSetup { private readonly bool UtilityMode; protected SerialTDASSetup(bool _utilMode) { UtilityMode = _utilMode; } #region TDAS information functions public const int DEFAULTMEMORYSIZE_PRO = 16000000; public const int DEFAULTMEMORYSIZE_G5 = 47600068; public const int DEFAULTMEMORYSIZE_DIM = 2000000; private bool NeedsModuleIndex(string serialNumber) { return serialNumber.StartsWith("5M") || serialNumber.StartsWith("PI"); } private void SetupDASInfo(DTS.Common.Interface.DASFactory.ICommunication dev, string name) { try { APILogger.Log("DasFactory.SerialTDAS::SetupDASInfo enter"); // shortcut var DASComm = dev as IDASCommunication; uint MaxNumberOfModules = 1; DateTime? rackCalDate = null; System.Threading.Thread.Sleep(1000); try { DASComm.MaxModules = 1; List moduleSerialNumbers = new List(); List moduleFirmwareVersions = new List(); List moduleIndices = new List(); TDASConfig tEntireConfig = null; bool RackIsUnreadable = false; dev.SerialNumber = (_handler as SerialTDASHandling).RackSerialNumber; if (dev.SerialNumber.ToUpper().Contains("NONE")) { SetupClear sc = new SetupClear(dev, 5000); sc.SyncExecute(); } QuerySerialNumber qsn = new QuerySerialNumber(dev); qsn.SyncExecute(); //dev.SerialNumber = qsn.SerialNumber; QueryFirmwareVersion qfv = new QueryFirmwareVersion(dev); qfv.SyncExecute(); dev.FirmwareVersion = qfv.FirmwareVersion; if (string.IsNullOrEmpty(qsn.SerialNumber)) { //Must be an armed TDAS rack, so no module information was returned RackIsUnreadable = true; tEntireConfig = new TDASConfig(dev.SerialNumber + ".xml", false); foreach (TDASModuleConfig moduleConfig in tEntireConfig.Modules.Values) { //Serial numbers moduleSerialNumbers.Add(moduleConfig.SerialNumber); //Module indices moduleIndices.Add(moduleConfig.ModuleArrayIndex + 1); //Module firmware TDASModuleConfig module = new TDASModuleConfig { SerialNumber = moduleConfig.SerialNumber }; TDASModuleConfig mod = tEntireConfig.GetModule(module); //Strange that GetModule does basically a SetModule if not found...requiring a module to be passed instead of just a string moduleFirmwareVersions.Add(mod.FirmwareVersion); } } else if (dev.SerialNumber.ToUpper().Contains("NONE")) { moduleSerialNumbers.Add(qsn.SerialNumber); moduleFirmwareVersions.Add(qfv.FirmwareVersion); moduleIndices.Add(1); } else { QueryCalDate qcd = new QueryCalDate(dev); qcd.SyncExecute(); rackCalDate = qcd.CalDate; } // get the stack contents dev.DASInfo = new Communication_DASInfo(moduleSerialNumbers.ToArray(), moduleFirmwareVersions.ToArray()); InfoResult ir = new InfoResult { NumberOfBridgeChannels = 8, MaxNumberOfModules = MaxNumberOfModules, OwningDAS = DASComm, CalibrationDate = rackCalDate }; List modules = new List(); for (int i = 0; i < moduleSerialNumbers.Count; i++) { int moduleArrayIndex = moduleIndices[i] - 1; while (moduleArrayIndex > modules.Count) { modules.Add(new InfoResult.Module()); int index = modules.Count - 1; modules[index].SerialNumber = "EMPTY"; modules[index].TypeOfModule = DFConstantsAndEnums.ModuleType.EMPTYBANK; modules[index].NumberOfChannels = 0; // 8; modules[index].NumberOfBytesPerSampleClock = 1; modules[index].MaxEventStorageSpaceInBytes = DEFAULTMEMORYSIZE_DIM; modules[index].SupportedModes = new[]{DFConstantsAndEnums.RecordingMode.CircularBuffer, DFConstantsAndEnums.RecordingMode.RecorderMode}; modules[index].OwningInfoResult = ir; modules[index].ModuleArrayIndex = index; } modules.Add(new InfoResult.Module()); modules[moduleArrayIndex].ModuleArrayIndex = moduleArrayIndex; modules[moduleArrayIndex].OwningInfoResult = ir; modules[moduleArrayIndex].NumberOfChannels = 8; if (!qsn.SerialNumber.StartsWith("5M")) { try { QueryCalDate qcd = new QueryCalDate(dev); // { ModuleIndex = moduleArrayIndex }; qcd.SyncExecute(); modules[moduleArrayIndex].CalibrationDate = qcd.CalDate; } catch (Exception ex) { APILogger.Log(ex); } } modules[moduleArrayIndex].SerialNumber = moduleSerialNumbers[i]; if (NeedsModuleIndex(modules[moduleArrayIndex].SerialNumber)) { modules[moduleArrayIndex].SerialNumber += i.ToString(); } modules[moduleArrayIndex].FirmwareVersion = moduleFirmwareVersions[i]; modules[moduleArrayIndex].SupportedModes = new[]{DFConstantsAndEnums.RecordingMode.CircularBuffer, DFConstantsAndEnums.RecordingMode.RecorderMode}; if (moduleSerialNumbers[i].Contains("TOM")) { modules[moduleArrayIndex].TypeOfModule = DFConstantsAndEnums.ModuleType.ProTOM; modules[moduleArrayIndex].MaxEventStorageSpaceInBytes = DEFAULTMEMORYSIZE_PRO; modules[moduleArrayIndex].NumberOfBytesPerSampleClock = 2; modules[moduleArrayIndex].NumberOfChannels = 16; } else if (moduleSerialNumbers[i].Contains("DigitalInput")) { modules[moduleArrayIndex].TypeOfModule = DFConstantsAndEnums.ModuleType.ProDIM; modules[moduleArrayIndex].MaxEventStorageSpaceInBytes = DEFAULTMEMORYSIZE_DIM; modules[moduleArrayIndex].NumberOfBytesPerSampleClock = 2; } else if (moduleSerialNumbers[i].StartsWith("5M")) { //the G5 has memory at the rack, not at the modules modules[moduleArrayIndex].TypeOfModule = DFConstantsAndEnums.ModuleType.G5Analog; ir.MaxEventStorageSpaceInBytes = DEFAULTMEMORYSIZE_G5; ir.NumberOfBytesPerSampleClock = 68; //always samples all channels plus the "2" digitals } else { modules[moduleArrayIndex].TypeOfModule = DFConstantsAndEnums.ModuleType.ProSIM; modules[moduleArrayIndex].MaxEventStorageSpaceInBytes = DEFAULTMEMORYSIZE_PRO; modules[moduleArrayIndex].NumberOfBytesPerSampleClock = 16; // In reality this is dynamic for a SIM based on the number of channels configured. } try { QueryMemoryCommand qmc = new QueryMemoryCommand(dev, AbstractCommandBase.Default_IO_Timeout); UInt64? availableRamBytes; if (RackIsUnreadable) { TDASModuleConfig module = new TDASModuleConfig { SerialNumber = modules[moduleArrayIndex].SerialNumber }; TDASModuleConfig mod = tEntireConfig.GetModule(module); //Strange that GetModule does basically a SetModule if not found...requiring a module to be passed instead of just a string modules[moduleArrayIndex].RackIsUnreadable = true; availableRamBytes = mod.MaxEventStorageSpaceInBytes; } else { modules[moduleArrayIndex].RackIsUnreadable = false; qmc.SyncExecute(); availableRamBytes = qmc.AvailableRamBytes; } if (DFConstantsAndEnums.ModuleType.G5Analog == modules[moduleArrayIndex].TypeOfModule) { // There is a bit of a mis-match in domain here. qmc is named RAM bytes, but in older G5 firmware is returning flash bytes (which is less // than RAM). Unravel the mess here. ir.MaxEventStorageSpaceInBytes = 6000000 > qmc.AvailableRamBytes ? DEFAULTMEMORYSIZE_G5 : qmc.AvailableRamBytes; //System.Diagnostics.Trace.WriteLine("stoage space in bytes = " + qmc.AvailableRamBytes); ir.NumberOfBytesPerSampleClock = 2 * 34;//always samples all channels plus the "2" digitals modules[moduleArrayIndex].NumberOfBytesPerSampleClock = null; modules[moduleArrayIndex].NumberOfBytesPerSampleClock = null; } else { modules[moduleArrayIndex].MaxEventStorageSpaceInBytes = availableRamBytes; } } catch (Exception ex) { APILogger.Log("Exception getting available memory, will use defaults", ex); } } if (qsn.SerialNumber.StartsWith("5M")) { //TDAS.G5Modes g5Mode = GetG5Mode(dev); //if (dev is EthernetTDAS) { (dev as EthernetTDAS).G5Mode = g5Mode; } //if (g5Mode == TDAS.G5Modes.VDS) //{ // int i = 4; // int moduleArrayIndex = i; // modules.Add(new InfoResult.Module()); // modules[moduleArrayIndex].ModuleArrayIndex = moduleArrayIndex; // modules[moduleArrayIndex].OwningInfoResult = ir; // modules[moduleArrayIndex].NumberOfChannels = 16; // modules[moduleArrayIndex].SerialNumber = qsn.SerialNumber + i; // modules[moduleArrayIndex].FirmwareVersion = " NA "; // modules[moduleArrayIndex].SupportedModes = new[]{Test.Module.RecordingMode.CircularBuffer, //Test.Module.RecordingMode.RecorderMode}; // modules[moduleArrayIndex].TypeOfModule = InfoResult.Module.ModuleType.G5Digital; // modules[moduleArrayIndex].MaxEventStorageSpaceInBytes = DEFAULTMEMORYSIZE_DIM; // modules[moduleArrayIndex].NumberOfBytesPerSampleClock = 2; //} try { QueryCalDate qc = new QueryCalDate(dev); qc.SyncExecute(); ir.CalibrationDate = qc.CalDate; } catch (Exception ex) { APILogger.Log(ex); } } ir.Modules = modules.ToArray(); DASComm.SetDASInfo(ir); try { //QueryArmStatus qsa = new QueryArmStatus(dev); //qsa.SyncExecute(); if (null == DASComm.DASArmStatus) { DASComm.SetDASArmStatus(new ArmStatus { IsArmed = false }, false); } //switch (qsa.Status) //{ // case QueryArmStatus.ARMStatus.ARMED: // case QueryArmStatus.ARMStatus.ARMING: // case QueryArmStatus.ARMStatus.CAL: // case QueryArmStatus.ARMStatus.FLASHWRITE: // case QueryArmStatus.ARMStatus.REC: // case QueryArmStatus.ARMStatus.TRIG: // DASComm.DASArmStatus.IsArmed = true; // break; //} } catch (Exception ex) { APILogger.Log(ex); } } catch (Exception ex) { APILogger.LogString("TDASSetup.SetupDASInfo exception: " + name); APILogger.LogException(ex); // if we're not in util mode we bail out if (!UtilityMode) { throw; } // if we are, we must fill in something // dev.FirmwareVersion // DASComm.SerialNumber // dev.DASInfo // DASComm.DASInfo dev.FirmwareVersion = "UNKNOWN"; DASComm.SerialNumber = "UNKNOWN"; dev.DASInfo = new Communication_DASInfo { SerialNumbers = new[] { DASComm.SerialNumber }, FirmwareVersions = new[] { dev.FirmwareVersion } }; var dasInfo = new InfoResult { MaxNumberOfModules = MaxNumberOfModules, NumberOfBytesPerSampleClock = 0, MaxEventStorageSpaceInBytes = 0, OwningDAS = DASComm, Modules = new InfoResult.Module[0] }; DASComm.SetDASInfo(dasInfo); } } catch (Exception ex) { APILogger.Log("DASFactory::SerialTDASSetup failed because: ", ex); throw ex; } finally { APILogger.Log("DasFactory.SerialTDAS::SetupDASInfo exit"); } } /// /// per rollin, iPort is pass through, so check VDS, then iDummy, then assume iPort /// iDummy should apparently have two ids /// /// /// //private TDAS.G5Modes GetG5Mode(DTS.Common.Interface.DASFactory.ICommunication idas) //{ // try // { // G5DockStat dockstat = new G5DockStat(idas); // dockstat.SyncExecute(); // } // catch (Exception ex) // { // if (ex.Message.Contains("DOCKING STATION not present")) // { // //Command.TDAS.AUXID auxid = new Command.TDAS.AUXID(idas); // //auxid.SyncExecute(); // //if (auxid.Ids.Length > 1) // //{ // // return TDAS.G5Modes.INDUMMY; // //} // //else { return TDAS.G5Modes.IPORT; } // //per CPB, TK // return TDAS.G5Modes.INDUMMY; // } // APILogger.Log(ex); // } // return TDAS.G5Modes.VDS; //} private void ReadProtocolVersion(DTS.Common.Interface.DASFactory.ICommunication dev, string name) { dev.ProtocolVersion = 1; } private bool IsInUpdateMode(DTS.Common.Interface.DASFactory.ICommunication dev, string name) { return false; } public bool QueryInformation(ConnectedDevice dev) { // don't assume anything... if (dev == null || dev.Dev == null || string.IsNullOrEmpty(dev.Dev.ConnectString)) { APILogger.LogString("TDASSetup.QueryInformation: Invalid parameter passed1"); return false; } if (!(dev.Dev is IConnectedDAS) || !((dev.Dev as IConnectedDAS).DASComm is ICommunication) || !((dev.Dev as IConnectedDAS).DASComm is IDASCommunication)) { APILogger.LogString("SerialTDASSetup.QueryInformation: Invalid parameter passed2"); return false; } // make shortcuts ICommunication CommDev = (dev.Dev as IConnectedDAS).DASComm as ICommunication; string DevName = dev.Dev.ConnectString; try { APILogger.LogString("SerialTDASHandling.QueryInformation: " + DevName); // First get protocol version ... ReadProtocolVersion(CommDev, DevName); // check how stack is configured SetupDASInfo(CommDev, DevName); // now pickup some stuff for the log //DummyRetriveGainCodes(CommDev); //DummyRetreiveDasBootCount(CommDev); // get the stored events //RetriveEventGuids(CommDev); try { if (dev.Dev is IConnectedDAS idas) { idas.DASComm?.ReadFirstUseDate(); } } catch (Exception ex) { APILogger.Log(ex); } return true; } catch (Exception ex) { try { APILogger.LogException(ex); if (IsInUpdateMode(CommDev, DevName)) { var dasInfo = new InfoResult { MaxNumberOfModules = 10, Modules = new InfoResult.Module[0] }; (dev.Dev as IConnectedDAS).DASComm.SetDASInfo(dasInfo); dev.InUpdateMode = true; return true; } return false; } catch (Exception eex) { APILogger.LogString("DASFactory.QuerySliceInformation.EX exception: " + dev.Dev.ConnectString); APILogger.LogException(eex); return false; } } } #endregion public abstract ICommunication GetICommunication(); public abstract ICommunication GetICommunication(ConnectedDevice dev); public abstract IConnectedDevice GetIConnectedDevice(DTS.Common.Interface.DASFactory.ICommunication comm); public abstract bool IsCorrectType(ConnectedDevice dev); public abstract DFConstantsAndEnums.DASType GetDASType(); public abstract Guid GetGuid(); public virtual int GetProductId() { return 0; } public virtual string GetProductIdString() { return string.Empty; } protected DeviceHandling _handler; public virtual void SetHandler(DeviceHandling handler) { _handler = handler; } } internal class TDASSerialSetup : SerialTDASSetup { public override ICommunication GetICommunication() { SerialTDAS st = new SerialTDAS(); st.OnDisconnected += st_OnDisconnected; return st; } void st_OnDisconnected(object sender, EventArgs e) { _handler.ReportDisconnect(sender); //System.Diagnostics.Trace.WriteLine("failed " + DateTime.Now); } public override ICommunication GetICommunication(ConnectedDevice dev) { return (dev.Dev as ConnectedSerialTDAS).Comm; } public override IConnectedDevice GetIConnectedDevice(DTS.Common.Interface.DASFactory.ICommunication comm) { return new ConnectedSerialTDAS(comm as SerialTDAS); } public override bool IsCorrectType(ConnectedDevice dev) { return dev.Dev is ConnectedSerialTDAS; } public override DFConstantsAndEnums.DASType GetDASType() { return DFConstantsAndEnums.DASType.SERIAL_TDAS; } public override Guid GetGuid() { return Guid.Empty; } public override string GetProductIdString() { return string.Empty; } public TDASSerialSetup(bool bInUtilityMode) : base(bInUtilityMode) { } } internal class SerialTDASHandling : DeviceHandling { public override void ReportDisconnect(object obj) { var o = obj as TDAS; if (null != o) { //foreach (var s in _sockets) //{ // if (s.ConnectString == o.ConnectString) // { // s.SetDisconnected(); // break; // } //} foreach (var port in _ports) { if (port.ConnectString == o.ConnectString) { //port.SetDisconnected(); break; } } } } /// /// Timeout in milliseconds to connect a Serial TDAS device /// public int ConnectSerialTDASTimeout { get; set; } private Thread TDASListenerThread; private readonly ManualResetEvent TDASSignalEvent = new ManualResetEvent(false); // device type 1 private IDeviceSetup tdasSetup { get; set; } private static readonly object TDASPORTSLOCK = new object(); private readonly ManualResetEvent _interrupt = new ManualResetEvent(false); public void Interrupt() { _interrupt.Set(); } private string _RackSerialNumber = string.Empty; public string RackSerialNumber { get { return _RackSerialNumber; } set { _RackSerialNumber = value; } } private string[] _TDASPortNames; public string[] TDASPortNames { get { lock (TDASPORTSLOCK) { return _TDASPortNames; } } set { if (TDASListenerThread == null) { // SLICEDBListenerThread is not running if (null == value || value.Length < 1 || string.Empty == value[0]) { // no-op return; } } else { // it's already running, we need to stop it TDASSignalEvent.Reset(); _bKeepGoing = false; _interrupt.Set(); //TDASListenerThread.Interrupt(); // wait for it to die TDASSignalEvent.WaitOne(3000, false); //// was this a close only? // CLH 2/23/2018 safe to use this for close??? if (null == value || value.Length < 1 || string.Empty == value[0]) { //yes return; } } lock (TDASPORTSLOCK) { _TDASPortNames = value; } // start it up TDASSignalEvent.Reset(); _interrupt.Reset(); TDASListenerThread = new Thread(TDASEventListenerTask) { IsBackground = true }; TDASListenerThread.Start(); // wait for it to start TDASSignalEvent.WaitOne(); } } public SerialTDASHandling(DASFactory _factory, UpdateFinishedEventHandler _SerialUpdateFinished, IDeviceSetup _tdas) : base(_factory, _SerialUpdateFinished) { tdasSetup = _tdas; ConnectSerialTDASTimeout = 15000; } public override void Dispose() { //try { if (null != TDASListenerThread) { TDASListenerThread.Abort(); } } //catch (Exception) { } //base.Dispose(); try { Thread.Sleep(100); if (null != TDASListenerThread) { if (TDASListenerThread.IsAlive) { TDASListenerThread.Abort(); } } } catch (Exception) { } base.Dispose(); } internal override bool DetachAllDevices() { bool bDevicesRemoved = false; lock (ConnectedDevicesLock) { foreach (var dev in ConnectedDevices) { dev.Dispose(); bDevicesRemoved = true; } ConnectedDevices.Clear(); } return bDevicesRemoved; } internal delegate void PortConnected(TDASSerialPort port); internal delegate void PortDisconnected(TDASSerialPort port); internal void OnPortConnect(TDASSerialPort port) { lock (_ConnectedDASLock) { if (!_connectedTDAS.Contains(port.ConnectString)) { _connectedTDAS.Add(port.ConnectString); } } UpdateConnectedDevices(); } internal void OnPortDisconnect(TDASSerialPort port) { bool updated = false; lock (_ConnectedDASLock) { if (_connectedTDAS.Contains(port.ConnectString)) { updated = true; _connectedTDAS.Remove(port.ConnectString); } } if (updated) { UpdateDisconnectedDevices(); } } internal class TDASSerialPort : IDisposable { private volatile bool _haveConnected; private volatile bool _connectStarted; private readonly PortConnected _portConnect; private readonly PortDisconnected _portDisconnect; private string _TdasRackSerialNumber = string.Empty; private readonly string _portName; public string PortName { get { return _portName; } } private int _BaudRate = 38400; public int BaudRate { get { return _BaudRate; } set { _BaudRate = value; } } //private const int TDAS_PORT = 8000; //private readonly int _port = TDAS_PORT; //public int Port { get { return _port; } } public string ConnectString { get { return _portName; } // string.Format("{0}:{1}", _hostName, _port); } } private SerialPort _serialPort; void port_DataReceived(object sender, SerialDataReceivedEventArgs e) { APILogger.Log("DasFactory.SerialTDAS::port_DataReceived enter"); string message = ""; try { if (null != _serialPort) { try { if (_serialPort.BytesToRead > 0) { message = _serialPort.ReadLine(); APILogger.Log("Serial TDAS Reply: " + message + " on Comm Port " + _serialPort.PortName); _serialPort.DataReceived -= port_DataReceived; _serialPort.Close(); _serialPort.Dispose(); // uneeded? } } catch (Exception) { _portDisconnect(this); } } _serialPort = null; _haveConnected = true; _portConnect(this); _connectStarted = false; } catch (Exception) { Thread.Sleep(100); _portDisconnect(this); Connect(); //likely a timeout, either way, we can't connect //try again. } } public void SetDisconnected() { _haveConnected = false; } //private void OnConnect(IAsyncResult ar) //{ // try // { // if (null != _serialPort) // { // try // { // _serialPort.EndConnect(ar); // _serialPort.Shutdown(SocketShutdown.Both); // _serialPort.Disconnect(false); // //_socket.Disconnect(true); // _serialPort.Close(); // } // catch (Exception) // { // _portDisconnect(this); // } // } // _serialPort = null; // _haveConnected = true; // _portConnect(this); // _connectStarted = false; // } // catch (Exception ex) // { // Thread.Sleep(100); // _portDisconnect(this); // Connect(); //likely a timeout, either way, we can't connect // //try again. // } //} private void CreatePort() { if (_serialPort != null) { APILogger.Log("DasFactory.SerialTDAS:: Closing Serial Port " + _portName + "..."); if (_serialPort.IsOpen) { _serialPort.Close(); } _serialPort.Dispose(); _serialPort = null; } APILogger.Log("DasFactory.SerialTDAS:: Creating Serial Port " + _portName + "..."); Thread.Sleep(3000); _serialPort = new SerialPort(_portName, _BaudRate, Parity.None, 8, StopBits.One); _serialPort.Open(); _serialPort.ReadTimeout = 5000; //wait for TCR etc. _serialPort.WriteTimeout = 5000; // 1000; _serialPort.DataReceived += port_DataReceived; APILogger.Log("DasFactory.SerialTDAS::Serial Port: " + _serialPort.PortName + " Created."); } private void Connect() { APILogger.Log("DasFactory.SerialTDAS::Connect enter"); _connectStarted = true; if (null == _serialPort) { CreatePort(); } // flush serial port _serialPort.Write(Encoding.ASCII.GetBytes("\\"), 0, 1); _serialPort.Write(Encoding.ASCII.GetBytes("\r"), 0, 1); APILogger.Log("DasFactory.SerialTDAS::Serial Port: " + _serialPort.PortName + " Flushed."); // trun off the checksum requirement string message = string.Empty; if (_TdasRackSerialNumber.ToUpper().Contains("NONE")) { message = _TdasRackSerialNumber + "|0" + "OSE"; //message = "NONE|0OSE: OFF"; } else { message = _TdasRackSerialNumber + "|OSE"; // message = _TdasRackSerialNumber + "|OSE: OFF"; } int check = checkSum(message); message += "~" + check.ToString("X"); //send message APILogger.Log("Serial TDAS Command " + message + " Sent on Comm Port: " + _serialPort.PortName); _serialPort.WriteLine(message); } public TDASSerialPort(string portName, PortConnected portConnect, PortDisconnected portDisconnect, string SerialRackId) { _portName = portName; _TdasRackSerialNumber = (string.IsNullOrEmpty(SerialRackId)) ? "NONE" : SerialRackId; _portConnect = portConnect; _portDisconnect = portDisconnect; Connect(); } public void CheckConnection2() { if (_connectStarted) { return; } if (null != _serialPort && _serialPort.IsOpen) { return; } if (!_haveConnected) { Connect(); } } public void CheckConnection() { //we've never connected, so we are done already if (!_haveConnected) { return; } _haveConnected = false; if (!_connectStarted) { _connectStarted = true; Connect(); } } public void Dispose() { try { //_serialPort.Disconnect(false); _serialPort.Close(); } catch (Exception) { // don't care } } private int checkSum(string message) { int sum = 0; byte[] asciiBytes = Encoding.ASCII.GetBytes(message); foreach (byte b in asciiBytes) { sum += b; } return sum; } } /// /// Here we keep track of connected TDAS devices /// private readonly List _connectedTDAS = new List(); //private TDASSocket[] _sockets; private TDASSerialPort[] _ports; private volatile bool _bKeepGoing; private void TDASEventListenerTask() { lock (_ConnectedDASLock) { _connectedTDAS.Clear(); } _ActiveDAS.Clear(); // signal that we're alive _bKeepGoing = true; TDASSignalEvent.Set(); try { if (null == _TDASPortNames || _TDASPortNames.Length < 1) { return; } { _ports = new TDASSerialPort[_TDASPortNames.Length]; } for (int i = 0; i < TDASPortNames.Length; i++) { _ports[i] = new TDASSerialPort(TDASPortNames[i], OnPortConnect, OnPortDisconnect, _RackSerialNumber); } try { while (_bKeepGoing) { bool bInterrupted = _interrupt.WaitOne(5000, false); //there's been a disconnect, try connecting and removing any failed ones now for (int i = 0; i < TDASPortNames.Length; i++) { _ports[i].CheckConnection2(); } if (bInterrupted) { _bKeepGoing = false; _interrupt.Reset(); } //if (bInterrupted) { _interrupt.Reset(); } } } catch (ThreadInterruptedException) { Trace.WriteLine("TDASListening thread interrupted, exitting thread"); } } catch (ThreadAbortException ex) { // we must exit Trace.WriteLine(ex.ToString()); } catch (Exception ex) { Trace.WriteLine(ex.ToString()); // don't care } finally { RemoveAll(); TDASListenerThread = null; _TDASPortNames = null; // signal that we're dying TDASSignalEvent.Set(); } } private readonly object _ConnectedDASLock = new object(); private List _ActiveDAS = new List(); private List GetConnectedEthernetDeviceString(bool slice) { List list = new List(); lock (_ConnectedDASLock) { if (null == _connectedTDAS || _connectedTDAS.Count < 1) { return list; } if (slice) { list.AddRange(_connectedTDAS); } } return list; } private List GetActiveConnectedEthernetDeviceStrings(bool slice) { var list = new List(); lock (_ConnectedDASLock) { if (null == _connectedTDAS || _connectedTDAS.Count < 1) { return list; } } var devs = ConnectedDevices.ToArray(); foreach (var dev in devs) { if (slice) { list.Add(dev.Dev.ConnectString); } } return list; } private List GetConnectedDeviceStrings() { return GetConnectedEthernetDeviceString(true); } private List GetAllActiveDeviceStrings() { return GetActiveConnectedEthernetDeviceStrings(true); } private ICommunication GetICommunication() { return tdasSetup.GetICommunication(); } private IConnectedDevice GetIConnectedDevice(DTS.Common.Interface.DASFactory.ICommunication com) { return tdasSetup.GetIConnectedDevice(com); } private void UpdateConnectedTDAS() { ConnectNewDevices(GetConnectedDeviceStrings, GetAllActiveDeviceStrings, GetICommunication, GetIConnectedDevice, tdasSetup.GetDASType(), tdasSetup, ConnectSerialTDASTimeout); } public override void UpdateConnectedDevices() { UpdateConnectedTDAS(); } private bool IsCorrectType(ConnectedDevice dev) { return tdasSetup.IsCorrectType(dev); } private ICommunication ConnectedDevice2Communication(ConnectedDevice dev) { return tdasSetup.GetICommunication(dev); } private void UpdateDisconnectedTDAS() { DisconnectRemovedDevices(GetConnectedDeviceStrings, IsCorrectType, ConnectedDevice2Communication, tdasSetup.GetDASType(), ConnectSerialTDASTimeout); } public override void UpdateDisconnectedDevices() { UpdateDisconnectedTDAS(); } private void RemoveAll() { EnqueueDisconnect(); //ConnectedDevices.Clear(); lock (_ConnectedDASLock) { _connectedTDAS.Clear(); } _ActiveDAS.Clear(); } public override void UpdateDeviceSetups() { tdasSetup.SetHandler(this); } } }