using System; using System.Collections.Generic; using System.Text; using DTS.Common.Enums.DASFactory; using DTS.Common.Utilities.Logging; namespace DTS.DASLib.Command.SLICE { public abstract class ArmCommands : CommandBase { protected enum Commands { Reserved = 0x00, Arm = 0x01, Disarm = 0x02, EnableFaultChecking = 0x03, DisableFaultChecking = 0x04, QueryArmAndTriggerStatus = 0x05, PrepareForDiagnostics = 0x06, PrepareForDataCollection = 0x07, BeginFlashErase = 0x08, QueryFlashEraseStatus = 0x09, InitializeHardwareLines = 0x0a, }; protected abstract Commands _Command { get; } protected ArmCommands(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Type = CommandPacket.CommandType.Arm; command.SetCommand((byte)_Command, _Command.ToString()); } protected ArmCommands(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Type = CommandPacket.CommandType.Arm; command.SetCommand((byte)_Command, _Command.ToString()); } } public class Arm : ArmCommands { protected override Commands _Command => Commands.Arm; public Arm(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { } public Arm(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { } public DFConstantsAndEnums.CommandStatus ArmStatus { get; private set; } = DFConstantsAndEnums.CommandStatus.StatusNoError; protected override CommandReceiveAction WholePackage() { switch (response.Status) { case DFConstantsAndEnums.CommandStatus.StatusNoError: break; default: ArmStatus = response.Status; break; } return CommandReceiveAction.StopReceiving; } } public class EnableFaultChecking : ArmCommands { protected override Commands _Command => Commands.EnableFaultChecking; public EnableFaultChecking(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { } public EnableFaultChecking(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { } } public class DisableFaultChecking : ArmCommands { protected override Commands _Command => Commands.DisableFaultChecking; public DisableFaultChecking(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { } public DisableFaultChecking(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { } } public class QueryArmAndTriggerStatus : ArmCommands { protected override Commands _Command => Commands.QueryArmAndTriggerStatus; public enum FaultFlags { IncomingStatusLineDropped = (1 << 0), ADCBufferOverrun = (1 << 1), FlashCRCError = (1 << 2), TriggerBeforeStart = (1 << 3), InputVoltageLow = (1 << 4), InputVoltageHigh = (1 << 5), BackupVoltageLow = (1 << 6), BackupVoltageHigh = (1 << 7), OutOfMemory = (1 << 8), SquibResistanceOutOfRange = (1 << 9), SafeSwitchUnplugged = (1 << 10), SquibPowerOutOfRange = (1 << 11), AutoSquibDisableActivated = (1 << 12) } private float _inputVoltage = 0; public float InputVoltage => _inputVoltage; private float _backupVoltage = 0; public float BackupVoltage => _backupVoltage; private byte _armstate; private byte _armmode; private byte _startrecordstatus; private byte _triggerstatus; private byte _faultstatus; private uint _eventsamplerate; private ulong _totalsamples; private ulong _currentsample; private ushort _currenteventnumber; private ulong _faultsamplenumber; private ushort _faultbits; private float _batterySoc; private float _systemTempC; private ulong _actualCurrentSample; private ulong _maxSampleAvailable; private short _tsChannel1; private short _tsChannel2; private short _tsChannel3; private short _sensorChannelA; private short _sensorChannelB; private short _sensorChannelC; private short _sensorChannelD; private short _sensorChannelE; private short _sensorChannelF; // for TOM private float _squib1; private float _squib2; private float _squib3; private float _squib4; private float _squibP17V; private float _squibP5V; private float _squibP3p3V; private float _squibN5V; private bool _ptpEnable; private bool _adcPtpClkEnable; private bool _ptpSyncStatus; private bool _adcClkSyncStatus; private uint _extFaultId; public ArmStates ArmState => (ArmStates)_armstate; public enum ArmStates { Disarmed, Armed, Realtime, Diagnostics, FlashClear, Arming }; public byte ArmMode => _armmode; public bool IsDiagnostics => (ArmStates)_armstate == ArmStates.Diagnostics; public bool IsFlashClear => (ArmStates)_armstate == ArmStates.FlashClear; public bool IsArming => (ArmStates)_armstate == ArmStates.Arming; public bool IsArmed => (ArmStates)_armstate == ArmStates.Armed; public bool IsInRealtime => (ArmStates)_armstate == ArmStates.Realtime; public bool IsRecording => _startrecordstatus == 0x01; public bool IsTriggered => _triggerstatus == 0x01; public bool IsFaulted => _faultstatus == 0x01; public uint EventSampleRate => _eventsamplerate; public ulong TotalSamples => _totalsamples; public ulong CurrentSample => _currentsample; public ushort EventNumber => _currenteventnumber; public ulong FaultSampleNumber => _faultsamplenumber; public List CurrentFaultFlags { get; } = new List(); public int BatterySoc => (int)_batterySoc; public float SystemTempC => _systemTempC; public ulong ActualCurrentSample => _actualCurrentSample; public ulong MaxSampleAvailable => _maxSampleAvailable; public short TiltSensorChannel1 => _tsChannel1; public short TiltSensorChannel2 => _tsChannel2; public short TiltSensorChannel3 => _tsChannel3; public short SensorChannelA => _sensorChannelA; public short SensorChannelB => _sensorChannelB; public short SensorChannelC => _sensorChannelC; public short SensorChannelD => _sensorChannelD; public short SensorChannelE => _sensorChannelE; public short SensorChannelF => _sensorChannelF; public float SquibResistance1 { get { return _squib1; } } public float SquibResistance2 { get { return _squib2; } } public float SquibResistance3 { get { return _squib3; } } public float SquibResistance4 { get { return _squib4; } } public float SquibPowerP17V { get { return _squibP17V; } } public float SquibPowerP5V { get { return _squibP5V; } } public float SquibPowerP3p3V { get { return _squibP3p3V; } } public float SquibPowerN5V { get { return _squibN5V; } } public bool PtpFunctionEnable { get { return _ptpEnable; } } public bool AdcPtpClkEnable { get { return _adcPtpClkEnable; } } public bool PtpClkSyncStatus { get { return _ptpSyncStatus; } } public bool AdcClkSyncStatus { get { return _adcClkSyncStatus; } } private List _extendedFaultFlags = new List(); public List ExtendedFaultFlags { get { return _extendedFaultFlags; } } public uint ExtendedFaultId { get { return _extFaultId; } } public QueryArmAndTriggerStatus(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { } public QueryArmAndTriggerStatus(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { } private const int QUATS_MIN_LENGTH_INPUTVOLTAGE = 38; private const int QUATS_MIN_LENGTH_BACKUPVOLTAGE = 42; private const int QUATS_MIN_LENGTH_BATTERYSOC = 49; private const int QUATS_MIN_LENGTH_ACTUALCURRENTSAMPLE = 57; private const int QUATS_MIN_LENGTH_MAXSAMPLEAVAILABLE = 65; private const int QUATS_MIN_LENGTH_TILTCHANNELDATA = 71; private const int QUATS_MIN_LENGTH_SYSTEMTEMP = 75; private const int QUATS_MIN_LENGTH_CHANNELADC = 87; private const int QUATS_MIN_LENGTH_TOMSTATUS = 119; private const int QUATS_MIN_LENGTH_CLKSTATUS = 123; private const int QUATS_MIN_LENGTH_EXTFAULTID = 127; protected override CommandReceiveAction WholePackage() { if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError) { if (response.ParameterLength > 1) { response.GetParameter(0, out _armstate); response.GetParameter(1, out _armmode); response.GetParameter(2, out _startrecordstatus); response.GetParameter(3, out _triggerstatus); response.GetParameter(4, out _faultstatus); response.GetParameter(5, out _eventsamplerate); response.GetParameter(9, out _totalsamples); response.GetParameter(17, out _currentsample); response.GetParameter(25, out _currenteventnumber); response.GetParameter(27, out _faultsamplenumber); //this is only valid for > 00E7, but that's long retired, so I'm enforcing it now response.GetParameter(35, out _faultbits); for (int i = 0; i < 16; i++) { if (0 != (_faultbits & (1 << i))) { CurrentFaultFlags.Add((FaultFlags)(1 << i)); } } if (response.ParameterLength >= QUATS_MIN_LENGTH_INPUTVOLTAGE) { response.GetParameter(37, out _inputVoltage); } else { _inputVoltage = 0; } if (response.ParameterLength >= QUATS_MIN_LENGTH_BACKUPVOLTAGE) { response.GetParameter(41, out _backupVoltage); } else { _backupVoltage = 0; } if (recorder.IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.QueryBatterySOC) && response.ParameterLength >= QUATS_MIN_LENGTH_BATTERYSOC) { response.GetParameter(45, out _batterySoc); } else { _batterySoc = 0; } if (response.ParameterLength >= QUATS_MIN_LENGTH_ACTUALCURRENTSAMPLE) { response.GetParameter(49, out _actualCurrentSample); } else { _actualCurrentSample = 0; } if (response.ParameterLength >= QUATS_MIN_LENGTH_MAXSAMPLEAVAILABLE) { response.GetParameter(57, out _maxSampleAvailable); } else { _maxSampleAvailable = 0; } if (response.ParameterLength >= QUATS_MIN_LENGTH_TILTCHANNELDATA) { response.GetParameter(65, out _tsChannel1); response.GetParameter(67, out _tsChannel2); response.GetParameter(69, out _tsChannel3); } else { _tsChannel1 = 0; _tsChannel2 = 0; _tsChannel3 = 0; } if (response.ParameterLength >= QUATS_MIN_LENGTH_SYSTEMTEMP) { response.GetParameter(71, out _systemTempC); } else { _systemTempC = 0; } if (response.ParameterLength >= QUATS_MIN_LENGTH_CHANNELADC) { response.GetParameter(75, out _sensorChannelA); response.GetParameter(77, out _sensorChannelB); response.GetParameter(79, out _sensorChannelC); response.GetParameter(81, out _sensorChannelD); response.GetParameter(83, out _sensorChannelE); response.GetParameter(85, out _sensorChannelF); } else { _sensorChannelA = 0; _sensorChannelB = 0; _sensorChannelC = 0; _sensorChannelD = 0; _sensorChannelE = 0; _sensorChannelF = 0; } // hack for TOM if (response.ParameterLength >= QUATS_MIN_LENGTH_TOMSTATUS) { response.GetParameter(87, out _squib1); response.GetParameter(91, out _squib2); response.GetParameter(95, out _squib3); response.GetParameter(99, out _squib4); response.GetParameter(103, out _squibP17V); response.GetParameter(107, out _squibP5V); response.GetParameter(111, out _squibP3p3V); response.GetParameter(115, out _squibN5V); } if (response.ParameterLength >= QUATS_MIN_LENGTH_CLKSTATUS) { response.GetParameter(119, out _ptpEnable); response.GetParameter(120, out _adcPtpClkEnable); response.GetParameter(121, out _ptpSyncStatus); response.GetParameter(122, out _adcClkSyncStatus); } if (response.ParameterLength >= QUATS_MIN_LENGTH_EXTFAULTID) { response.GetParameter(123, out _extFaultId); } for (int i = 0; i < 32; i++) { if (0 != (_extFaultId & (1 << i))) { _extendedFaultFlags.Add((QATSExtendedFault)(1 << i)); } } } } return CommandReceiveAction.StopReceiving; } public override void ResponseToString(ref List> lines) { base.ResponseToString(ref lines); lines.Add(new List() { $"Event number: {EventNumber}, Arm Mode: {ArmMode}" }); lines.Add(new List() { $"Armed: {IsArmed}, Started: {IsRecording}, Triggered: {IsTriggered}, Faulted: {IsFaulted}, Diagnostics: {IsDiagnostics}, FlashClear: {IsFlashClear}, Arming: {IsArming}, ArmState: {_armstate}" }); lines.Add(new List() { $"Samplerate: {EventSampleRate}, Current Sample: {CurrentSample}, Total Samples: {TotalSamples}, Fault Sample Number: {FaultSampleNumber}" }); lines.Add(new List() { $"Input Voltage: {InputVoltage.ToString("N3")}V, Backup Voltage: {BackupVoltage.ToString("N3")}V, Backup Percentage Remaining: {BatterySoc}%" }); lines.Add(new List() { $"System Temp: {SystemTempC}C, Actual Current Sample: {ActualCurrentSample}, Max Sample Available: {MaxSampleAvailable}" }); lines.Add(new List() { $"Tilt Ch1: {TiltSensorChannel1}, Tilt Ch2: {TiltSensorChannel2}, Tilt Ch3: {TiltSensorChannel3}" }); lines.Add(new List() { $"Squib Ch1: {SquibResistance1}, Squib Ch2: { SquibResistance2}, Squib Ch3: { SquibResistance3}, Squib Ch4: { SquibResistance4}" }); lines.Add(new List() { $"Squib P17V: {SquibPowerP17V}, Squib PV5: { SquibPowerP5V}, Squib P3p3V: { SquibPowerP3p3V}, Squib N5V: { SquibPowerN5V}" }); lines.Add(new List() { $"PTP Enabled: {PtpFunctionEnable}, PTP Clk Enable: {AdcPtpClkEnable}, PTP Clk Sync Status: {PtpClkSyncStatus}, ADC Clk Sync Status: {AdcClkSyncStatus}" }); var sb = new StringBuilder(50); sb.AppendFormat("Fault Flags: "); if (null != CurrentFaultFlags && CurrentFaultFlags.Count > 0) { var addcomma = false; for (int i = 0; i < CurrentFaultFlags.Count; i++) { if (addcomma) sb.AppendFormat(", "); addcomma = true; sb.AppendFormat("{0}", CurrentFaultFlags[i].ToString()); } } else { sb.AppendFormat("none"); } lines.Add(new List() { sb.ToString() }); sb = new StringBuilder(); sb.AppendFormat("Extended Fault Flags: "); if (null != ExtendedFaultFlags && ExtendedFaultFlags.Count > 0) { var addcomma = false; for (int i = 0; i < ExtendedFaultFlags.Count; i++) { if (addcomma) sb.AppendFormat(", "); addcomma = true; sb.AppendFormat("{0}", ExtendedFaultFlags[i].ToString()); } } else { sb.AppendFormat("none"); } lines.Add(new List() { sb.ToString() }); } } public class Disarm : ArmCommands { protected override Commands _Command => Commands.Disarm; public Disarm(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { } public Disarm(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { } } public class PrepareForDiagnostics : ArmCommands { protected override Commands _Command => Commands.PrepareForDiagnostics; public PrepareForDiagnostics(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { } public PrepareForDiagnostics(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { } } public class PrepareForDataCollection : ArmCommands { protected override Commands _Command => Commands.PrepareForDataCollection; public PrepareForDataCollection(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { } public PrepareForDataCollection(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { } } public class BeginFlashErase : ArmCommands { protected override Commands _Command => Commands.BeginFlashErase; public BeginFlashErase(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { } public BeginFlashErase(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { } } public class QueryFlashEraseStatus : ArmCommands { protected override Commands _Command => Commands.QueryFlashEraseStatus; public QueryFlashEraseStatus(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { } public QueryFlashEraseStatus(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { } private float _percentcomplete; public float PercentComplete => _percentcomplete; private byte _lasterror; public DFConstantsAndEnums.CommandStatus LastError => (DFConstantsAndEnums.CommandStatus)_lasterror; protected override CommandReceiveAction WholePackage() { const int LastErrorPosition = 0; const int PercentCompletePosition = 1; if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError) { response.GetParameter(LastErrorPosition, out _lasterror); response.GetParameter(PercentCompletePosition, out _percentcomplete); } return CommandReceiveAction.StopReceiving; } public override void ResponseToString(ref List> lines) { base.ResponseToString(ref lines); lines.Add(new List() { $"Erase status: {LastError.ToString()}, Percent complete: {PercentComplete.ToString()}" }); } } public class InitializeHardwareLines : ArmCommands { protected override Commands _Command => Commands.InitializeHardwareLines; public bool CheckTriggerForShort { get => Convert.ToBoolean(command.Parameter[0]); set => command.Parameter[0] = Convert.ToByte(value); } public bool CheckStartForShort { get => Convert.ToBoolean(command.Parameter[1]); set => command.Parameter[1] = Convert.ToByte(value); } public InitializeHardwareLines(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { command.Parameter = new byte[] { 0x01, 0x01 }; LogCommands = false; } public InitializeHardwareLines(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec) { command.Parameter = new byte[] { 0x01, 0x01 }; LogCommands = false; } public bool StartRecordShorted { get; private set; } = false; public bool TriggerInputShorted { get; private set; } = false; protected override CommandReceiveAction WholePackage() { switch (response.Status) { case DFConstantsAndEnums.CommandStatus.StatusNoError: break; case DFConstantsAndEnums.CommandStatus.StatusArmShortedStartRecordInput: StartRecordShorted = true; break; case DFConstantsAndEnums.CommandStatus.StatusArmShortedTriggerInput: TriggerInputShorted = true; break; case DFConstantsAndEnums.CommandStatus.StatusArmShortedStartAndTrigger: StartRecordShorted = true; TriggerInputShorted = true; break; default: APILogger.Log("Unexpected return from InitializeHardwareLines ", response.Status.ToString()); break; } return CommandReceiveAction.StopReceiving; } public override void ResponseToString(ref List> lines) { base.ResponseToString(ref lines); lines.Add(new List(new[] { $"StartRecord: {StartRecordShorted}, Trigger: {TriggerInputShorted}" })); } public static void Log(Exception exception, InitializeHardwareLines ihl) { var bShortStart = exception.Message.Contains(DFConstantsAndEnums.CommandStatus.StatusArmShortedStartRecordInput.ToString()); var bShortTrig = exception.Message.Contains(DFConstantsAndEnums.CommandStatus.StatusArmShortedTriggerInput.ToString()); if (exception.Message.Contains(DFConstantsAndEnums.CommandStatus.StatusArmShortedStartAndTrigger.ToString())) { bShortStart = true; bShortTrig = true; } APILogger.Log($"InitializeHardwareLines: Start shorted: {bShortStart} Trigger shorted: {bShortTrig}"); } } }