Files
DP44/DataPRO/IService/.svn/pristine/cd/cdb0f5025dae40ba0310f2e597b67b3fcfba3fda.svn-base

1655 lines
76 KiB
Plaintext
Raw Normal View History

2026-04-17 14:55:32 -04:00
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Threading;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Interface.Connection;
using DTS.Common.Interface.TestSetups;
using DTS.Common.Utilities;
using DTS.Common.Utilities.Logging;
using DTS.Common.Utils;
using DTS.DASLib.Command;
using DTS.DASLib.Command.SLICE;
using DTS.DASLib.Service.Interfaces;
using DTS.Common.ICommunication;
using DTS.Common.Interface.DASFactory.Download;
using DTS.DASLib.Command.SLICE.DownloadCommands;
using DTS.Common.Interface.StatusAndProgressBar;
using DTS.Common.Constant.DASSpecific;
using DTS.Common.Enums;
using DTS.Common;
using DTS.Common.Interface.DASFactory.Config;
namespace DTS.DASLib.Service
{
public class SLICE6AIR<T> : SLICE6_Base<T>, ITestDASOrder, IUARTDownload, IUARTDownloadActions, IAlignUDPToPPSAware
where T : IConnection, new()
{
public bool AlignUDPToPPS { get; set; }
public override bool SupportsADCSamplesPerPacket => true;
public override bool SupportsRemoveLeapSeconds => true;
protected override bool AdjustInputRange(AnalogInputDASChannel analog)
{
return analog.IEPEChannel;
}
protected override bool SupportsDiagnosticsMode => true;
public override void SetIsStreamingSupported(bool supported)
{
IsStreamingSupported = true;
}
protected override void FirmwareVersionUpdated()
{
base.FirmwareVersionUpdated();
if (DFConstantsAndEnums.IsSLICE6ERFirmware(FirmwareVersion))
{
IsEthernetRecorder = true;
}
}
private bool _IsEthernetRecorder = false;
public bool IsEthernetRecorder
{
get => _IsEthernetRecorder;
set
{
_IsEthernetRecorder = value;
if (value)
{
SetEthernetRecorderProtocolMins();
}
}
}
private void SetEthernetRecorderProtocolMins()
{
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryTiltSensorData] = byte.MaxValue;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InSliceTiltSensorADCPre] = byte.MaxValue;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RecordOnBoot] = byte.MaxValue;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.UDPAddressList] = SLICE6AIR.MULTIPLE_UDP_ADDRESSES_S6A_ETHERNETRECORDER;
}
protected override DASModule MakeConfigModuleFromInfoModule(InfoResult.Module infoModule)
{
//per LP we can make this simpler, S6A always supports 1/2,Full,IEPE
var configModule = new DASModule(infoModule.ModuleArrayIndex, this);
configModule.Channels = new DASChannel[infoModule.NumberOfChannels];
for (var i = 0; i < infoModule.NumberOfChannels; i++)
{
if (DFConstantsAndEnums.ModuleType.UART == configModule.ModuleType())
{
var uartChannel = new UARTInputDASChannel(configModule, i);
configModule.Channels[i] = uartChannel;
}
else if (DFConstantsAndEnums.ModuleType.StreamOut == configModule.ModuleType())
{
var streamOutChannel = new StreamOutputDASChannel(configModule, i);
configModule.Channels[i] = streamOutChannel;
}
else if (DFConstantsAndEnums.ModuleType.StreamIn == configModule.ModuleType())
{
var streamInChannel = new StreamInputDASChannel(configModule, i);
configModule.Channels[i] = streamInChannel;
}
else
{
var channel = new AnalogInputDASChannel(configModule, i);
channel.SupportedBridges = new SensorConstants.BridgeType[]
{
SensorConstants.BridgeType.FullBridge,
SensorConstants.BridgeType.HalfBridge, SensorConstants.BridgeType.IEPE
};
configModule.Channels[i] = channel;
}
}
return configModule;
}
private const byte DEVICE_STREAMING_ONLY = 1;
protected override void AsyncAutoDetect(object o)
{
if (!(o is AutoDetectServiceAsyncInfo info))
{
return;
}
if (GetIsStreaming())
{
//if we are streaming avoid getting this information
info.Success();
return;
}
if (null == DASInfo || null == DASInfo.Modules || 0 == DASInfo.Modules.Length
|| null == ConfigData || 0 == ConfigData.Modules.Length)
{
info.Error($"no configuration on unit {SerialNumber}");
return;
}
if (DASInfo.Modules[0].IsProgrammable)
{
var channels = new List<SetStackChannelTypeConfiguration.ChannelTypes>();
foreach (var module in ConfigData.Modules)
{
foreach (var channel in module.Channels)
{
channels.Add(SetStackChannelTypeConfiguration.ChannelTypes.AUTO_DETECT);
}
}
var cmd = new SetStackChannelTypeConfiguration(this);
cmd.SetValue(channels.ToArray());
if (info.QueryConfiguration)
{
var query = new QueryStackSensorIDs(this);
query.Exec();
var idx = 0;
foreach (var m in ConfigData.Modules)
{
foreach (var c in m.Channels)
{
if (c is AnalogInputDASChannel)
{
switch (Convert.ToInt32(query.Types[idx]))
{
case (int)SetStackChannelTypeConfiguration.ChannelTypes.FORCE_IEPE:
(c as AnalogInputDASChannel).IEPEChannel = true;
break;
case (int)SetStackChannelTypeConfiguration.ChannelTypes.FORCE_IEPE_LOW:
(c as AnalogInputDASChannel).IEPEChannel = true;
break;
default:
(c as AnalogInputDASChannel).IEPEChannel = false;
break;
}
var id = new EID(HexEncoding.ToString(query.IDs[idx]));
if (id.IsValid() && !RunTestVariables.BypassEIDRead)
{
c.IDs = new EID[] { id };
}
}
idx++;
}
}
}
}
try
{
// FB15353 Is this device hardware configured for streaming only?
var qsaDeviceStreamingOnly = new QuerySystemAttributeSLICE6AIR(this, QuerySystemAttribute.Default_IO_Timeout);
qsaDeviceStreamingOnly.Key = AttributeTypes.SystemAttributesSLICE6AIR.S6A_DeviceStreamingOnly;
qsaDeviceStreamingOnly.SyncExecute();
//we made it, set results
DASInfo.DeviceStreamingOnly = (DEVICE_STREAMING_ONLY == (byte)qsaDeviceStreamingOnly.Value);
}
catch (Exception ex)
{
APILogger.Log("Problem getting Device Streaming only system attribute", ex);
}
info.Success();
}
public override double[] GetNominalRanges(SensorConstants.BridgeType bridgeType)
{
//FB15462 separate S6 gain limits from S6A
switch (bridgeType)
{
case SensorConstants.BridgeType.IEPE:
return WinUSBSlice.StaticDASS6AEIEPEInfo.NominalRanges;
default:
return WinUSBSlice.StaticDASBridgeInfo.NominalRanges;
}
}
#region protocol settings/overrides
private readonly Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte> SLICE6AIR_MinimumProtocols =
new Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte>();
protected override bool SupportsIEPECalSignal =>
IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.IEPE);
private const int MIN_HW_REVISION_ETHERNET_RECORDER = 10;
protected override void QueryHardwareRevisionPost()
{
if (_hardwareRevision >= MIN_HW_REVISION_ETHERNET_RECORDER)
{
IsEthernetRecorder = true;
}
}
protected override void VerifyConfig(bool DoStrictCheck, ErrorCallback failedChallengeFunc)
{
if (IsEthernetRecorder)
{
//no verify needed
}
else { base.VerifyConfig(DoStrictCheck, failedChallengeFunc); }
}
public override void InitMinProto()
{
// SLICE 6 AIR Protocol Limitations
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleAndHybridEvents] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleEvents] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArm] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmRepeatEnable] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetDefaultMIF] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.FileData] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackSensors] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseSystemTime] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.TestCommunication] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackLowPowerMode] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetRealtimeSampleRate] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SLICE2_OneWireID] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.HardwareRevision] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.HardwareConfiguration] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventFaultFlags] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventArmAttempts] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryActualSampleRateImmediate] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.VoltageSysAttributes] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.DiagnosticsMode] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.LevelTrigger] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AttributeStoreBlocks] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryArmAndTriggerStatus_VoltageReadings] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MaxEvents] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmDiagnosticDelay] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackChannelAutoArmDiagLevel] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.FlashClear] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleSamplesRealtime] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseCalibrationDate] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.IgnoreShortedStartEvent] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ResetAttributeStore] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.DiangosShuntDAC] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.VoltageInsertion] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.PTPTimestamp] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StartRecDelayInSecond] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryTiltSensorData] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InSliceTiltSensorADCPre] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StartRealtimeStream] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.UDPRealtimeStream] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ProgramStackChannels] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.IEPE] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackChannelTypeConfiguration] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackSensors] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryClockSyncStatus] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetClockSyncConfig] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryUARTDownload] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.GetUARTSettings] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetUARTSettings] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetDSPFilterSettings] = SLICE6AIR.SET_DSP_FILTER_SETTINGS;
//18090 Implement chapter 10 streaming while recording(in DTS format)
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RecordAndStreamSubSample] = SLICE6AIR.RECORD_AND_STREAM_SUBSAMPLE;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackChannelBridgeACCouplerEnable] = SLICE6AIR.AC_COUPLER_ENABLE;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryMSP430Firmware] = SLICE6AIR.MIN_PROTOCOL_VER;
//31747 Add-support-for-GPS-Time-leap-seconds
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RemoveLeapSeconds] = SLICE6AIR.REMOVE_LEAP_SECONDS_VER;
//31754 expose-number-of-ADC-samples-in-UDP-packet
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ADCSamplesPerPacket] = SLICE6AIR.ADC_SAMPLES_PER_PACKET_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.PTPDomainID] = SLICE6AIR.MIN_PROTOCOL_VER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ActiveRAM] = SLICE6AIR.MIN_PROTOCOL_VER;
if (IsEthernetRecorder)
{
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RecordOnBoot] = SLICE6AIR.RECORD_ON_BOOT_PROTOCOL_S6A_ETHERNETRECORDER;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmRecordDelay] = SLICE6AIR.AUTOARM_RECORD_DELAY_PROTOCOL_S6A_ETHERNETRECORDER;
}
else
{
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RecordOnBoot] = SLICE6AIR.RECORD_ON_BOOT_PROTOCOL;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmRecordDelay] = SLICE6AIR.AUTOARM_RECORD_DELAY_PROTOCOL;
}
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmRecordDelay] = SLICE6AIR.AUTOARM_RECORD_DELAY_PROTOCOL;
SLICE6AIR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.UDPAlignOnPPS] = SLICE6AIR.UDPALIGNONPPS_PROTOCOL;
MinimumProtocols = SLICE6AIR_MinimumProtocols;
}
#endregion
private void AsyncPrepareForArmNowOBRDDR(ArmPacket info)
{
try
{
var recordingMode = GetOBRDDREquivalentMode(ConfigData.Modules[0].RecordingMode, info.MaxNumberEvents);
var saa = new SetArmAttribute(this);
saa.SetValue(AttributeTypes.ArmAndEventAttributes.SampleRate, ConfigData.Modules[0].SampleRateHz, true);
saa.SyncExecute();
SetArmMode(recordingMode);
saa = new SetArmAttribute(this);
var postTriggerSamples = Convert.ToUInt64(ConfigData.Modules[0].PostTriggerSeconds *
ConfigData.Modules[0].SampleRateHz);
saa.SetValue(AttributeTypes.ArmAndEventAttributes.PostTriggerSamplesRequested, postTriggerSamples, true);
saa.SyncExecute();
saa = new SetArmAttribute(this);
var preTriggerSamples = 0UL;
if (ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.CircularBuffer ||
ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.CircularBufferPlusUART ||
ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.RAMActive ||
ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.MultipleEventRAMActive)
{
preTriggerSamples =
Convert.ToUInt64(Math.Abs(ConfigData.Modules[0].PreTriggerSeconds *
ConfigData.Modules[0].SampleRateHz));
}
saa.SetValue(AttributeTypes.ArmAndEventAttributes.PreTriggerSamplesRequested, preTriggerSamples, true);
saa.SyncExecute();
SetMaxEvents(info.MaxNumberEvents);
var ssa = new SetSystemAttributeSLICE6AIR(this);
SetValueBasedOnProtocolVersion(ref ssa);
ssa.SyncExecute();
//var ssaV = new SetSystemAttributeSLICE6DB(this);
////input min, input max, battery min, battery max
//var requirements = new[] { InputLowVoltage, InputHighVoltage, BatteryLowVoltage, BatteryHighVoltage };
//ssaV.SetValue(AttributeTypes.SystemAttributesSLICE6DB.VoltageRequirements, requirements, true);
//ssaV.SyncExecute();
info.Success();
}
catch (Exception ex)
{
APILogger.Log(ex);
info.Error(ex.Message);
}
}
public override void Download(ServiceCallback callback, object userData)
{
if (IsEthernetRecorder)
{
var info = new SliceServiceAsyncInfo(callback, userData);
LaunchAsyncWorker("Slice6A.DownloadOBRDDR", AsyncDownloadOBRDDDR, info);
}
else
{
base.Download(callback, userData);
}
}
/// <summary>
/// returns true if the DAS supports DiagnosticsFactoryExcitation attribute,
/// false otherwise
/// <inheritdoc cref="Slice{T}"/>
/// </summary>
protected override bool SupportsDiagnosticsFactoryExcitation
{
get
{
if (IsTSRAIR()) { return false; }
return base.SupportsDiagnosticsFactoryExcitation;
}
}
public override bool IsSlice6Air()
{
return true;
}
public override bool IsScheduleEventCountSupported()
{
return false;
}
private void AsyncDownloadOBRDDDR(object o)
{
var info = (SliceServiceAsyncInfo)o;
try
{
var queryEthernetEventInfo = new QueryEthernetEventInfo(this);
queryEthernetEventInfo.EventID = WhatToDownload.EventNumber;
queryEthernetEventInfo.SyncExecute();
if (0 == queryEthernetEventInfo.TotalByteCount)
{
var msg = $"No Ethernet Recorder data to download: {SerialNumber}";
APILogger.Log(msg);
info.Success();
return;
}
var bytesToRead = queryEthernetEventInfo.TotalByteCount;//34844UL
var curBytesRead = 0UL;
while (curBytesRead < bytesToRead)
{
var queryEthernetEventData = new QueryEthernetEventData(this);
queryEthernetEventData.EventID = queryEthernetEventInfo.EventID;
var requestSize = (bytesToRead - curBytesRead) < int.MaxValue ? (int)(bytesToRead - curBytesRead) : int.MaxValue;
queryEthernetEventData.RequestByteCount = (uint)requestSize;
queryEthernetEventData.StartDataOffsetBytes = curBytesRead;
queryEthernetEventData.SyncExecute();
var data = new byte[queryEthernetEventData.Data.Length];
Array.Copy(queryEthernetEventData.Data, 0, data, 0, queryEthernetEventData.Data.Length);
curBytesRead += (ulong)queryEthernetEventData.Data.Length;
info.NewData(data);
info.Progress(Convert.ToInt32(100D * curBytesRead / bytesToRead));
}
}
catch (Exception ex)
{
APILogger.Log(ex);
info.Error(ex.Message);
return;
}
APILogger.Log($"Data successfully downloaded from {SerialNumber}");
info.Progress(100);
var config = GetConfigAttributes(this);
config.SetEventDownloaded(WhatToDownload.EventNumber, 1);
info.Success();
}
protected override void AsyncPrepareForArmNow(object asyncInfo)
{
if (!IsEthernetRecorder) { base.AsyncPrepareForArmNow(asyncInfo); }
else
{
if (!(asyncInfo is ArmPacket info)) { return; }
AsyncPrepareForArmNowOBRDDR(info);
}
}
/// <summary>
/// returns whether the unit supports 2V or not
/// </summary>
/// <returns></returns>
protected override bool GetSupports2Volt()
{
return false;
}
/// <summary>
/// returns true if the device is known to be streaming
/// does not query device, just returns a flag if it has been set
/// </summary>
public override bool GetIsStreaming()
{
if (null == DASArmStatus) { return false; }
//18852 Cannot use Stop streaming / (Dis)Auto Arm button if one or more DAS is idle
//can't rely on just having received invalid mode, QATS will still have a status of realtime
//when streaming, so we'll use either for now.
return DASArmStatus.ReceivedInvalidModeDuringSetup || DASArmStatus.IsInRealtime;
}
protected override void PerformBridgeResistanceMeasurement(Common.Interface.DASFactory.Diagnostics.IDiagnosticActions[] ChannelActions, SliceServiceAsyncInfo info, ref Common.Interface.DASFactory.Diagnostics.IDiagnosticResult[] results)
{
//18927 Bridge resistance inaccurate due to channel config setting prior to measurement
try
{
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.ProgramStackChannels))
{
ReconfigureAccordingToConfig();
}
}
catch (Exception ex) { APILogger.Log("Failed to force stack channel types", ex); }
base.PerformBridgeResistanceMeasurement(ChannelActions, info, ref results);
}
#region configure overrides
/// <summary>
/// adjusts the requested input range to avoid certain gains if needed
/// we are doing this for
/// 15462 Limit SLICE 6 AIR gains as they are not functional with IEPE accel
/// we manipulate the input range requested so we fall
/// within acceptable gains
/// </summary>
/// <param name="originalRange"></param>
/// <returns></returns>
protected override double AdjustInputRangeIfNeeded(double originalRange, bool bModified)
{
var gains = Enum.GetValues(typeof(GainCodesSLICE6IEPE)).Cast<GainCodesSLICE6IEPE>().ToList();
gains.Sort(new GainSorterSLICE6IEPE());
gains.Reverse();
var lastAcceptableValue = double.NaN;
//assume gains are in order from 1 to 1600, so find the first gain which is too restrictive and bounce back from that
//so for instance, if someone selected a range of 700mV, we would start with G1, pass, go to G2, pass, go to G4, fail, so we would use
//G2. Also note, while we know the min/max theoretical value foreach gain, when we request a range from the firmware we don't use that value
//we use somewhere inbetween (the FirmwareInputRangemV) to increase the chances we get the gain we want...
//note there are gains greater than 1600, but they are currently explicitly disabled by issue 10080
foreach (var gain in gains)
{
if (GainDisabledAttribute.IsGainDisabled(gain))
{
continue;
}
var maxValue = MaxInputRangeAttribute.GetMaxInputRangemV(gain);
if (originalRange < maxValue)
{
lastAcceptableValue = FirmwareInputRangeAttribute.GetFirmwareInputRangemV(gain);
}
else
{
break;
}
}
return !double.IsNaN(lastAcceptableValue) ? lastAcceptableValue : originalRange;
}
/// <summary>
/// queries download information
/// </summary>
protected override void AsyncQueryDownload(object asyncInfo)
{
if (IsEthernetRecorder)
{
AsyncQueryDownloadDDR(asyncInfo);
}
else { base.AsyncQueryDownload(asyncInfo); }
}
/// <summary>
/// handles quering download information but specifically for OBR-DDR
/// most of it is copied from the base, but the DDR doesn't have the same
/// amount of information available, and has some alternate info available
/// </summary>
private void AsyncQueryDownloadDDR(object asyncInfo)
{
var info = asyncInfo as QueryDownloadAsyncInfo;
// since we don't know exact how many XML attributes, modules or channels that's in the
// configuration, we guess on the high end.
// (44 per stored config + 4 + 3 per module + 3 per channel) * number of events
// equals 44 + 4 + 30 + 90 = 168 per event
const int StepsPerEvent = 168;
try
{
if (info.EventIndex < 0) { RetrieveDASBootCount(); }
var EventCount = new QueryTotalEventCount(this);
EventCount.SyncExecute();
var config = GetConfigAttributes(this);
var progress = new QueryDownloadProgress(info, StepsPerEvent * EventCount.Count, 1);
// we'll also freshen up the cached event GUIDs
// NOT IF WE ARE QUERYING A SPECIFIC GUID
var eventGuids = new Guid[EventCount.Count];
var faultFlags = new ushort[EventCount.Count];
var faultFlagsEx = new ushort[EventCount.Count];
var armAttempts = new byte[EventCount.Count];
//each index in outer array belongs to event index, there are 4 extended fault ids for each event
var extendedFaultIds = new List<uint[]>();
var dlReport = new DownloadReport();
if (0 > info.EventIndex)
{
dlReport.Events = new DownloadReport.EventInfo[EventCount.Count];
var queryAutoArmError = new QuerySystemAttribute(this) { Key = AttributeTypes.SystemAttributes.AutoArmError };
try
{
queryAutoArmError.SyncExecute();
AutoArmStatus = (DFConstantsAndEnums.CommandStatus)(Convert.ToInt32(queryAutoArmError.Value));
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
for (var eventIdx = 0; eventIdx < EventCount.Count; eventIdx++)
{
if (info.EventIndex >= 0 && eventIdx != info.EventIndex) { continue; }
extendedFaultIds.Add(GetExtendedFaultFlags(eventIdx));
// Retrieved the stored configuration
var storedConfigStr = config.RetrieveEventXMLConfig(eventIdx, progress, this); // I/O * n
var triggerSampleNumber = 0UL;
try
{
triggerSampleNumber = config.GetEventTriggerSampleNumber(eventIdx); // I/O
}
catch (Exception ex)
{
APILogger.Log(ex);
}
// convert it from XML to object
var storedConfig = ConfigurationData.DeserializeFromString(storedConfigStr);
// the object to store it all in
var eventInfo = new DownloadReport.EventInfo();
// get the event level values
try
{
eventInfo.Description = config.GetEventDescription(eventIdx); // I/O
if (null != ConfigData) { eventInfo.Description = ConfigData.Description; }
}
catch (Exception) { }
progress.Step();
try
{
eventInfo.TestID = config.GetEventID(eventIdx, this).TrimEnd(new char[] { '\0' }); ; // I/O
}
catch (Exception ex)
{
eventInfo.TestID = string.Empty;
APILogger.Log(ex);
}
progress.Step();
eventInfo.EventNumber = eventIdx;
progress.Step();
try
{
eventInfo.TestGUID = GetEventGuid(eventIdx);
}
catch (Exception) { eventInfo.TestGUID = Guid.NewGuid(); }
try
{
eventInfo.FaultFlags = config.GetEventFaultFlags(eventIdx);
eventInfo.FaultFlagsEx = config.GetEventFaultFlagsEx(eventIdx);
}
catch (Exception ex)
{
APILogger.Log("could not get fault flags", ex);
}
try
{
eventInfo.ArmAttempts = config.GetEventArmAttempts(eventIdx);
}
catch (Exception ex)
{
APILogger.Log("could not get arm attempts", ex);
}
eventGuids[eventIdx] = eventInfo.TestGUID;
faultFlags[eventIdx] = eventInfo.FaultFlags;
faultFlagsEx[eventIdx] = eventInfo.FaultFlagsEx;
armAttempts[eventIdx] = eventInfo.ArmAttempts;
try
{
var q = new QueryEthernetEventInfo(this);
q.EventID = Convert.ToUInt16(eventIdx);
q.SyncExecute();
if (0 == q.TotalByteCount)
{
faultFlags[eventIdx] |= (ushort)DFConstantsAndEnums.FaultFlags.NO_DATA;
eventInfo.FaultFlags |= (ushort)DFConstantsAndEnums.FaultFlags.NO_DATA;
}
}
catch (Exception ex)
{
APILogger.Log("could not get EventTotalByteCount", ex);
}
eventInfo.HasBeenDownloaded = config.EventHasBeenDownloaded(eventIdx, out uint flag); // I/O
progress.Step();
// take the module from the stored config
var module = (DASModule)storedConfig.Modules[0];
//module.SampleRateHz = Convert.ToUInt32(actualSampleRate);
//module.EmbeddedSampleRateHz = stackActualSampleRate;
/// <DesignNote topic="Level Trigger Configuration" author="PKXH">
/// Amongst other things, the level trigger offset correction, if it exists, is getting applied
/// to the module trigger sample numbers below. There shouldn't be any danger of this value being
/// erroneously applied to outside "tweaking" since the only outside tweak should only ever happen
/// if there was no trigger. Still I'm a little concerned that this value will still be invisibly
/// applied to user-overridden trigger sample numbers. We could conceivably guard against this
/// situation with an "original trigger sample number" concept, which we could then check against
/// and not re-apply things like level trigger offset correction if the current value doesn't
/// match it, implying it has been manually overridden.
/// </DesignNote>
// now update the module with dynamic data
module.OwningDAS = this;
//module.NumberOfSamples = numberOfSamples;
progress.Step();
module.TriggerSampleNumbers = new ulong[1]; // only one so far
//var phaseShift = GetPhaseShiftSamples(Convert.ToUInt32(1 + module.ModuleArrayIndex), Convert.ToDouble(actualSampleRate), Convert.ToUInt32(aafilter), triggerSampleNumber);
module.TriggerSampleNumbers[0] = triggerSampleNumber;
eventInfo.WasTriggered = module.TriggerSampleNumbers[0] > 0;
progress.Step();
eventInfo.Modules = new DASModule[1];
eventInfo.Modules[0] = module;
if (0 > info.EventIndex)
{
// store it in the object
dlReport.Events[eventIdx] = eventInfo;
}
else { EventInfo.Events[eventIdx] = eventInfo; }
}
// now assigned the data to the public property
if (0 > info.EventIndex)
{
SetEventInfo(dlReport);
}
SetEventFaultFlags(faultFlags);
((IDownload)this)?.SetExtendedFaultFlags(extendedFaultIds.ToArray());
SetEventGuids(eventGuids);
SetEventArmAttemps(armAttempts);
info.Success();
}
catch (CanceledException)
{
info.Cancel();
}
catch (Exception ex)
{
info.Error(ex.Message, ex);
}
}
/// <summary>
/// the minimum version that supports TMATS interval attribute is 33 per LP
/// http://manuscript.dts.local/f/cases/30460/S6-Air-attribute-145-interval-is-not-being-set-by-Datapro-because-of-protocol-version-41-ON-G0N5-FW
/// </summary>
protected override int MIN_PROTOCOL_TMATS_INTERVAL => 33;
void SetValueBasedOnProtocolVersion(ref SetSystemAttributeSLICE6AIR ssa)
{
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.UDPAddressList))
{
//43618 If new firmware is running, set the entire list of UDP addresses.
ssa.SetValue(AttributeTypes.SystemAttributesSLICE6AIR.EthRecordingMcAddrList, ConfigData.UDPReceiveAddress, true);
}
else
{
//43618 If old firmware is running, only set the first UDP address in the list, and notify the user.
var firstAddress = ConfigData.UDPReceiveAddress;
var indexOfFirstComma = ConfigData.UDPReceiveAddress.IndexOf(',');
if (indexOfFirstComma != -1)
{
firstAddress = ConfigData.UDPReceiveAddress.Substring(0, indexOfFirstComma);
}
ssa.SetValue(AttributeTypes.SystemAttributesSLICE6AIR.EthRecordingMcAddrList, firstAddress, true);
}
}
/// <summary>
/// we can probably simplify and take common items (slice6+slice1) out of this function, but for now
/// it's mostly a copy of SLICE1.AsyncConfigure
/// </summary>
/// <param name="configAsyncInfo"></param>
protected override void AsyncConfigure(object configAsyncInfo)
{
var info = configAsyncInfo as SliceConfigServiceAsyncInfo;
SetUDPAlignOnPPS();
IncrementNumberOfTimesWritten();
if (IsEthernetRecorder)
{
var ssa = new SetSystemAttributeSLICE6AIR(this);
SetValueBasedOnProtocolVersion(ref ssa);
ssa.SyncExecute();
}
else
{
SetRemoveSeconds();
if ((info.StreamADCPerPacket != null) && info.StreamADCPerPacket.ContainsKey(this))
{
SetADCSamplesPerPacket(info.StreamADCPerPacket[this]);
}
}
//12638 DAS does not record data in recorder mode during calibration ~ 40% of time.
//for SLICE6 we call reseteventlist here, prior to configuring and NOT before arming
ResetEventListPriorToConfigure();
int progressValue = 0;
bool bReleased = true;
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.ProgramStackChannels))
{
ReconfigureAccordingToConfig();
}
PresetSampleRate();
SetVoltageRequirements();
SetPolarity();
SetArmDisableShortCheck();
try
{
Lock();
bReleased = false;
// loop thru the modules (slices) and configure the non-UART channels
var numChannels = DASInfo.Modules.Sum(mod => mod.NumberOfChannels);
var numUartChannels = DASInfo.Modules.Sum(mod => DFConstantsAndEnums.ModuleType.UART == mod.TypeOfModule ? mod.NumberOfChannels : 0);
var numStreamingChannels = DASInfo.Modules.Sum(mod => DFConstantsAndEnums.ModuleType.StreamOut == mod.TypeOfModule ? mod.NumberOfChannels : 0);
var rangeArray = new float[numChannels];
//var IsHalfBridgeArray = new bool[numChannels];
var bridgeModeArray = new byte[numChannels];
var BridgeResistanceArray = new ushort[numChannels];
var IsACCoupledArray = new bool[numChannels];
//18294 Implement Bridge AC / DC coupling(fw update dependent)
var bridgeACCouplingArray = new bool[numChannels];
// level trigger values
var enableLowerLevelTriggerThreshold = new bool[numChannels];
var enableUpperLevelTriggerThreshold = new bool[numChannels];
var lowerLevelTriggerThreshold = new float[numChannels];
var upperLevelTriggerThreshold = new float[numChannels];
var qualificationSamples = new int[numChannels];
var diagnosticChannels = new List<byte>();
var bModified = false;
CommonConfigureWork(diagnosticChannels, qualificationSamples, ref bReleased,
info, bridgeModeArray, IsACCoupledArray, BridgeResistanceArray,
ref bModified, rangeArray, enableUpperLevelTriggerThreshold, upperLevelTriggerThreshold,
enableLowerLevelTriggerThreshold, lowerLevelTriggerThreshold, bridgeACCouplingArray);
if (bReleased) { return; }
// report progress
progressValue = 5;
info.Progress(progressValue);
StoreConfigAttributes(info, rangeArray, ref bReleased, ref progressValue,
bridgeModeArray, IsACCoupledArray, BridgeResistanceArray, enableLowerLevelTriggerThreshold,
lowerLevelTriggerThreshold, enableUpperLevelTriggerThreshold, upperLevelTriggerThreshold,
qualificationSamples, numChannels, out var config, bridgeACCouplingArray, numUartChannels,
numStreamingChannels);
progressValue = 20;
info.Progress(progressValue);
RemainingConfigWork(ref progressValue, info, diagnosticChannels, config, ref bReleased,
null, null, null);
}
catch (CanceledException)
{
if (!bReleased)
{
bReleased = true;
Release();
}
info.Cancel();
}
catch (Exception ex)
{
if (!bReleased)
{
bReleased = true;
Release();
}
info.Error(ex.Message, ex);
}
finally
{
if (!bReleased)
{
bReleased = true;
Release();
}
}
info.Progress(100);
info.Success();
}
protected override ConfigAttributes GetConfigAttributes(ICommunication com)
{
return new SLICE6AIRConfigAttributes(com);
}
/// <summary>
/// SLICE6 config attributes, mostly inherits from SLICE.ConfigAttributes with some functionality removed
/// </summary>
protected class SLICE6AIRConfigAttributes : ConfigAttributes
{
/// <summary>
/// I'm not aware of a purgeStaleData function in SLICE6/6AIR yet
/// this may be unnecessary if the firmware is intelligent enough, and maybe this is legacy
/// </summary>
/// <param name="das"></param>
public override void PurgeStaleData(IDASCommunication das)
{
}
public SLICE6AIRConfigAttributes(ICommunication _com) : base(_com)
{
}
#region CONFIG_XML
private readonly object _storeXMLConfigLock = new object();
/// <summary>
/// SLICE6 stores the xml in flash using SetFileData. We compress the XML string, write the header,
/// then write data 400 bytes at a time. For the header, we first write XML_STORE_MAGIC_BYTES followed
/// by the length of the compressed XML in bytes.
/// </summary>
/// <param name="data"></param>
/// <param name="info"></param>
/// <param name="ProgressSteps"></param>
public override void StoreXMLConfig(string data, FileStore fileStore)
{
lock (_storeXMLConfigLock)
{
if (string.IsNullOrEmpty(data))
{
return;
}
// since this might contain multi byte characters, we need to convert it to a byte array first
var ByteArrayData = GetCompressedBytes(GetBytes(fileStore, data));
var fileid = (ushort)fileStore; //EventConfig ? Convert.ToUInt16(1) : Convert.ToUInt16(0);
//Store Header - magic bytes and data length
//Store Magic bytes
var sfd = new SetFileData(com, 600000);
sfd.StartByteCount = 0;
sfd.FileID = fileid;
sfd.Data = Constants.XML_STORE_MAGIC_BYTES;
sfd.SyncExecute();
//Store Header - data length
sfd.StartByteCount = (Constants.XML_HEADER_LENGTH / 2);
sfd.FileID = fileid;
sfd.Data = BitConverter.GetBytes((uint)ByteArrayData.Length);
sfd.SyncExecute();
//purposely corrupt for testing purposes
//if (EventConfig)
//{
// System.Random r = new Random(DateTime.Now.Second);
// for (int i = 0; i < 100; i++)
// {
// int position = r.Next(0, ByteArrayData.Length - 1);
// ByteArrayData[position] = Convert.ToByte(r.Next(0, 255));
// }
//}
//Store Data
for (uint i = 0; i < ByteArrayData.Length; i += (uint)sfd.MaximumFileStreamBytes)
{
long array_size = sfd.MaximumFileStreamBytes;
if ((i + sfd.MaximumFileStreamBytes) > ByteArrayData.Length)
{
array_size = ByteArrayData.Length - i;
}
var dataToSend = new byte[array_size];
Array.Copy(ByteArrayData, i, dataToSend, 0, array_size);
sfd.Data = dataToSend;
sfd.FileID = fileid;
sfd.StartByteCount = i + Constants.XML_HEADER_LENGTH;
sfd.SyncExecute();
}
if ((FileStore.Diagnostic == fileStore) || (FileStore.Event == fileStore))
{
StoreXmlConfigPC(data);
}
}
}
/// <summary>
/// We retrieve the xml from SLICE 2 flash using QueryFileData. We read the header, then read data 400
/// bytes at a time. For the header, we first read XML_STORE_MAGIC_BYTES followed by the length of the
/// compressed XML in bytes. We then unzip the data and return the XML string.
/// </summary>
/// <returns></returns>
public override string RetrieveXMLConfig(FileStore fileStore, IDASCommunication das)
{
lock (_storeXMLConfigLock)
{
var WholeStr = "";
try
{
var allBytes = new List<byte>();
allBytes.Clear();
//Get Header - magic bytes and data length
//Get Magic bytes
var qfd = new QueryFileData(com, 600000);
var fileid = (ushort)fileStore;
qfd.FileID = fileid;
qfd.StartByteCount = 0;
qfd.EndByteCount = (Constants.XML_HEADER_LENGTH / 2) - 1;
if (das.GetIsStreaming())
{
//this is a big assumption here, when das is streaming we can't query it from the unit
//but we might be able to from the pc ...
//15949 S6A when streaming does a whole bunch of unnecessary queries
if (FileStore.UserAttributes != fileStore)
{
//event config falls back to regular config, regular config falls back to pc file
WholeStr = RetrieveXmlConfigPC();
}
}
else
{
qfd.SyncExecute();
if (qfd.Data.Length < 4)
{
return "";
}
if (qfd.Data[0] == 0xFF && qfd.Data[1] == 0xFF && qfd.Data[2] == 0xFF &&
qfd.Data[3] == 0xFF)
{
return "";
}
if (BitConverter.ToUInt32(qfd.Data, 0) != BitConverter.ToUInt32(Constants.XML_STORE_MAGIC_BYTES, 0))
{
throw new InvalidDataException("Magic bytes not found");
}
//Get data length
qfd.FileID = fileid;
qfd.StartByteCount = (Constants.XML_HEADER_LENGTH / 2); //account for magic bytes
qfd.EndByteCount = Constants.XML_HEADER_LENGTH - 1;
qfd.SyncExecute();
var ByteArrayDataLength = BitConverter.ToUInt32(qfd.Data, 0);
if (Math.Pow(2, 21) < ByteArrayDataLength)
{
throw new InvalidDataException("data length is greater than store size");
}
//Get Data
for (uint i = 0; i < ByteArrayDataLength; i += (uint)qfd.MaximumFileStreamBytes)
{
var array_size = (uint)qfd.MaximumFileStreamBytes;
if ((i + qfd.MaximumFileStreamBytes) > ByteArrayDataLength)
{
array_size = ByteArrayDataLength - i;
}
qfd.StartByteCount = Constants.XML_HEADER_LENGTH + i;
qfd.EndByteCount = Constants.XML_HEADER_LENGTH - 1 + (i + array_size);
qfd.FileID = fileid;
qfd.SyncExecute();
allBytes.InsertRange((int)i, qfd.Data);
}
if (allBytes.Count < 1)
{
// "Slice.RetrieveAttributes: Attributes are empty"
throw new Exception("Attributes are empty");
}
// Decopress data
WholeStr = GetDecompressedString(allBytes.ToArray(), fileStore);
}
}
catch (Exception ex)
{
APILogger.Log("failed to retrieve xml config - EventConfig: ", fileStore.ToString(), " error: ",
ex);
//if (!EventConfig)
if (FileStore.UserAttributes != fileStore)
{
//event config falls back to regular config, regular config falls back to pc file
WholeStr = RetrieveXmlConfigPC();
}
}
try
{
APILogger.ConfLog(com.SerialNumber, "XML Config\n", Utils.PrettyPrint(WholeStr));
}
catch (Exception)
{
}
return WholeStr;
}
}
private void StoreXmlConfigPC(string data)
{
try
{
const string dasConfigs = "DASConfigs";
var fileName =
Path.Combine(
Path.Combine(
Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location),
dasConfigs), string.Format("{0}.xml", com.SerialNumber));
if (File.Exists(fileName))
{
File.Delete(fileName);
}
using (var file = File.CreateText(fileName))
{
file.Write(data);
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
#endregion
/// <summary>
/// Retrieve the XML string that was split and stored in the Arm attributes
/// note that SLICE2 is apparently not going to store separate event configs,
/// so we just grab the same one off the pc again
/// [this is a bad idea as the event could be from earlier and the system config could have been
/// changed after the use ran the test, and then reconfigured but wants to download the old test]
/// </summary>
/// <param name="eventNum">The event number to get it from</param>
/// <param name="progress"></param>
/// <returns>The combined XML string</returns>
public override string RetrieveEventXMLConfig(int eventNum, QueryDownloadProgress progress,
IDASCommunication das)
{
lock (_storeXMLConfigLock)
{
var s = string.Empty;
try
{
s = RetrieveXMLConfig(FileStore.Event, das);
}
catch (Exception ex)
{
APILogger.Log("failed to retrieve event xml config for event ", eventNum, ex);
}
//fall back to whatever is on the live config
if (string.IsNullOrEmpty(s))
{
APILogger.Log("failed to retrieve event xml config (it was empty) for event ", eventNum);
s = RetrieveXMLConfig(FileStore.Diagnostic, das);
}
return s;
}
}
}
#endregion
protected override void SetArmAttribute(AttributeTypes.ArmAndEventAttributes key, DFConstantsAndEnums.RecordingMode value)
{
var mode = value;
if (IsEthernetRecorder)
{
mode = GetOBRDDREquivalentMode(value, 1);
}
base.SetArmAttribute(key, mode);
}
#region IClockSyncActions
protected override void AsyncGetClockSyncStatus(object asyncInfo)
{
//S6A has a command for both profile and status fetch
if (!(asyncInfo is GetClockSyncStatusPacket packet)) { return; }
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.QueryClockSyncStatus))
{
packet.Info.Error("Get clock sync status not supported");
return;
}
var info = packet.Info;
var bLocked = false;
try
{
Lock();
bLocked = true;
var status = new QueryClockSyncStatus(this);
status.SyncExecute();
DASClockSyncProfile = status.ClockSyncProfile;
DASClockSyncStatus = status.InputSyncStatus;
DoRTCInUTCCheck();
bLocked = false;
Release();
info.Success();
}
catch (CanceledException)
{
if (bLocked) { bLocked = false; Release(); }
info.Cancel();
}
catch (CommandException ce)
{
if (bLocked) { Release(); bLocked = false; }
straightFailures++;
if (straightFailures > PERMITTED_FAILURES)
{
APILogger.Log("GetClockSyncStatus error - has failed ", straightFailures, " times, giving up", ce);
info.Error(ce.Message, ce);
}
else
{
if (info.userData is ServiceBase.CallbackData cbData)
{
cbData.Target.DASClockSyncStatus = null;
}
info.Success();
APILogger.Log("GetClockSyncStatus error", ce);
}
}
catch (Exception ex)
{
if (bLocked) { bLocked = false; Release(); }
info.Error(ex.Message, ex);
}
finally { if (bLocked) { Release(); } }
}
#endregion
public bool DownloadEthernetData { get; set; } = false;
#region IUARTDownload
public uint BaudRate { get; private set; }
public uint DataBits { get; private set; }
public StopBits StopBits { get; private set; }
public Parity Parity { get; private set; }
public Handshake FlowControl { get; private set; }
public UartDataFormat DataFormat { get; private set; }
public IUARTDownloadRequest WhatUARTToDownload { get; set; }
public void SetWhatUARTToDownload(IUARTDownloadRequest request, bool bSetInDb = true)
{
UARTDownloadRequest.SetWhatToDownload(this, request, bSetInDb);
}
#endregion
#region IUARTDownloadActions
public void UARTDownload(ServiceCallback callback, object userData)
{
var state = new SliceUARTDownloadState(callback, userData, WhatUARTToDownload);
if (null == WhatUARTToDownload)
{
APILogger.Log("UART download - what to download is null");
state.Success();
return;
}
APILogger.Log("Starting UART Download ", WhatUARTToDownload.StartTimestamp,
WhatUARTToDownload.EndTimestamp);
ulong totalDownloaded = 0, needed = WhatUARTToDownload.TotalByteCount;
try
{
while (totalDownloaded < needed)
{
var getData = new QueryUARTEventData(this)
{
EventNumber = WhatUARTToDownload.EventNumber,
LogCommands = false,
RequestOffsetByteCount = totalDownloaded,
RequestByteCount = needed - totalDownloaded < uint.MaxValue
? (uint)(needed - totalDownloaded)
: uint.MaxValue
};
getData.SyncExecute();
if (null == getData.PayloadData)
{
Thread.Sleep(10);
continue;
}
state.NewData(new ServiceCallbackData.UARTNewData { DataOffset = getData.RequestOffsetByteCount, UARTData = getData.PayloadData });
var ratio = 100D * totalDownloaded / needed;
if (ratio < 0)
{
ratio = 0;
}
else if (ratio > 100)
{
ratio = 100D;
}
state.Progress(Convert.ToInt32(ratio));
totalDownloaded += getData.PayloadByteCount;
}
state.Success();
}
catch (CanceledException)
{
state.Cancel();
}
catch (Exception e)
{
APILogger.LogException(e);
state.Error(e.Message, e);
}
}
/// <summary>
/// Retrieve UART info about available events to download
/// </summary>
/// <param name="callback">The function to call with information</param>
/// <param name="userData">Whatever you want to pass along</param>
void IUARTDownloadActions.QueryUARTDownload(ServiceCallback callback, object userData, int eventIndex, TDASServiceSetupInfo setupInfo)
{
var info = new QueryDownloadAsyncInfo(callback, userData, eventIndex);
LaunchAsyncWorker("Slice.QueryUARTDownload", AsyncQueryUARTDownload, info);
}
protected virtual void AsyncQueryUARTDownload(object asyncInfo)
{
if (!(asyncInfo is QueryDownloadAsyncInfo info)) { return; }
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.QueryUARTDownload))
{
info.Error("Query UART download is not supported");
return;
}
var bLocked = false;
try
{
Lock();
bLocked = true;
var status = new QueryUARTEventInfo(this) { EventNumber = (ushort)info.EventIndex };
status.SyncExecute();
bLocked = false;
Release();
info.Success();
}
catch (CanceledException)
{
if (bLocked) { bLocked = false; Release(); }
info.Cancel();
}
catch (CommandException ce)
{
if (bLocked) { Release(); bLocked = false; }
straightFailures++;
if (straightFailures > PERMITTED_FAILURES)
{
APILogger.Log("QueryUARTDownload error - has failed ", straightFailures, " times, giving up", ce);
info.Error(ce.Message, ce);
}
else
{
if (info.userData is ServiceBase.CallbackData cbData)
{
//cbData.Target.DASClockSyncStatus = null;
}
info.Success();
APILogger.Log("QueryUARTDownload error", ce);
}
}
catch (Exception ex)
{
if (bLocked) { bLocked = false; Release(); }
info.Error(ex.Message, ex);
}
finally { if (bLocked) { Release(); } }
}
void IUARTDownloadActions.GetUARTSettings(ServiceCallback callback, object userData)
{
var info = new SliceServiceAsyncInfo(callback, userData);
LaunchAsyncWorker("Slice.GetUARTSettings", AsyncGetUARTSettings, info);
}
protected virtual void AsyncGetUARTSettings(object asyncInfo)
{
if (!(asyncInfo is SliceServiceAsyncInfo info)) { return; }
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.GetUARTSettings))
{
info.Error("Get UART settings is not supported");
return;
}
var bLocked = false;
try
{
Lock();
bLocked = true;
try
{
var qsaUARTSettings = new QuerySystemAttributeSLICE6AIR(this, QuerySystemAttribute.Default_IO_Timeout);
qsaUARTSettings.Key = AttributeTypes.SystemAttributesSLICE6AIR.S6A_GpsCanUARTSettings;
qsaUARTSettings.SyncExecute();
//we made it, set results
var uartSettings = (uint[])qsaUARTSettings.Value;
BaudRate = uartSettings[0];
DataBits = uartSettings[1];
StopBits = (StopBits)uartSettings[2];
Parity = (Parity)uartSettings[3];
FlowControl = (Handshake)uartSettings[4];
}
catch (Exception ex)
{
APILogger.Log("Problem getting UART settings", ex);
}
bLocked = false;
Release();
info.Success();
}
catch (CanceledException)
{
if (bLocked)
{
bLocked = false;
Release();
}
info.Cancel();
}
catch (CommandException ce)
{
if (bLocked)
{
Release();
bLocked = false;
}
straightFailures++;
if (straightFailures > PERMITTED_FAILURES)
{
APILogger.Log("GetUARTSettings error - has failed ", straightFailures, " times, giving up", ce);
info.Error(ce.Message, ce);
}
else
{
info.Success();
APILogger.Log("GetUARTSettings error", ce);
}
}
catch (Exception ex)
{
if (bLocked)
{
bLocked = false;
Release();
}
info.Error(ex.Message, ex);
}
finally
{
if (bLocked)
{
Release();
}
}
}
void IUARTDownloadActions.SetUARTSettings(ServiceCallback callback, object userData, uint baudRate, uint dataBits, uint stopBits, uint parity, uint flowControl)
{
var info = new SetUARTSettingsAsyncInfo(callback, userData, baudRate, dataBits, stopBits, parity, flowControl);
LaunchAsyncWorker("Slice.SetUARTSettings", AsyncSetUARTSettings, info);
}
protected virtual void AsyncSetUARTSettings(object asyncInfo)
{
if (!(asyncInfo is SetUARTSettingsAsyncInfo info)) { return; }
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.SetUARTSettings))
{
info.Error("Set UART settings is not supported");
return;
}
var bLocked = false;
try
{
Lock();
bLocked = true;
var value = new uint[] { info.BaudRate, info.DataBits, info.StopBits, info.Parity, info.FlowControl };
try
{
var ssaUARTSettings =
new SetSystemAttributeSLICE6AIR(this, SetSystemAttribute.Default_IO_Timeout);
ssaUARTSettings.SetValue(AttributeTypes.SystemAttributesSLICE6AIR.S6A_GpsCanUARTSettings,
value, true);
ssaUARTSettings.SyncExecute();
}
catch (Exception ex)
{
APILogger.Log("Problem setting UART settings", ex);
}
bLocked = false;
Release();
info.Success();
}
catch (CanceledException)
{
if (bLocked)
{
bLocked = false;
Release();
}
info.Cancel();
}
catch (CommandException ce)
{
if (bLocked)
{
Release();
bLocked = false;
}
straightFailures++;
if (straightFailures > PERMITTED_FAILURES)
{
APILogger.Log("SetUARTSettings error - has failed ", straightFailures, " times, giving up", ce);
info.Error(ce.Message, ce);
}
else
{
info.Success();
APILogger.Log("SetUARTSettings error", ce);
}
}
catch (Exception ex)
{
if (bLocked)
{
bLocked = false;
Release();
}
info.Error(ex.Message, ex);
}
finally
{
if (bLocked)
{
Release();
}
}
}
#endregion
private DFConstantsAndEnums.RecordingMode GetOBRDDREquivalentMode(DFConstantsAndEnums.RecordingMode input,
int numEvents)
{
switch (input)
{
case DFConstantsAndEnums.RecordingMode.InvalidArmMode:
case DFConstantsAndEnums.RecordingMode.ImmediateMode:
case DFConstantsAndEnums.RecordingMode.HighPowerRecorderMode:
case DFConstantsAndEnums.RecordingMode.LowPowerRecorderMode:
case DFConstantsAndEnums.RecordingMode.ContinuousRecorderMode:
case DFConstantsAndEnums.RecordingMode.AutoActiveMode:
case DFConstantsAndEnums.RecordingMode.AerospaceWithMotion:
case DFConstantsAndEnums.RecordingMode.S6A_DeviceStreamingOnly:
APILogger.Log($"Invalid recording mode for OBR-DDR {input}");
return input;
case DFConstantsAndEnums.RecordingMode.AutoCircularBufferMode:
return DFConstantsAndEnums.RecordingMode.MultiEthernetUDPRecordingCircularMode;
case DFConstantsAndEnums.RecordingMode.AutoRecorderMode:
return DFConstantsAndEnums.RecordingMode.MultiEthernetUDPRecordingRecorderMode;
case DFConstantsAndEnums.RecordingMode.CircularBuffer:
case DFConstantsAndEnums.RecordingMode.a16_CircularBufferAndStreamSubSampleMode:
case DFConstantsAndEnums.RecordingMode.CircularBufferPlusUART:
case DFConstantsAndEnums.RecordingMode.MultipleEventRAMActive:
case DFConstantsAndEnums.RecordingMode.RAMActive:
return numEvents > 1
? DFConstantsAndEnums.RecordingMode.MultiEthernetUDPRecordingCircularMode
: DFConstantsAndEnums.RecordingMode.EthernetUDPRecordingCircularMode;
case DFConstantsAndEnums.RecordingMode.RecorderMode:
case DFConstantsAndEnums.RecordingMode.a14_NormalRecorderAndStreamSubSampleMode:
case DFConstantsAndEnums.RecordingMode.RecorderModePlusUART:
return numEvents > 1
? DFConstantsAndEnums.RecordingMode.MultiEthernetUDPRecordingRecorderMode
: DFConstantsAndEnums.RecordingMode.EthernetUDPRecordingRecorderMode;
case DFConstantsAndEnums.RecordingMode.HybridRecorderMode:
return numEvents > 1
? DFConstantsAndEnums.RecordingMode.MultiEthernetHybridRecorderMode
: DFConstantsAndEnums.RecordingMode.EthernetHybridRecorderMode;
case DFConstantsAndEnums.RecordingMode.MultiHybridRecorderMode:
return DFConstantsAndEnums.RecordingMode.MultiEthernetHybridRecorderMode;
default:
APILogger.Log($"possible invalid recording mode for OBR-DDR {input}");
return input;
}
}
// http://manuscript.dts.local/f/cases/16493/How-to-bypass-adjustable-HW-filter-for-Data-Collection-on-S6A
// Loc, 11:44 AM S6A should have limit to 50K only.Anything< 50K will be with SCF. 50K and higher will be in by-pass mode.
private uint _maxAAFilterRateHz = 0U;
protected override uint MaxAAFilterRateHz
{
get
{
if (_maxAAFilterRateHz == 0)
{
// FW added bandwidth to the MIF for S6A, lets use that.
var qsa = new QuerySystemAttribute_BridgeSlice6(this)
{
Key = AttributeTypes.SystemAttributes_BridgeSlice6.Hardware_Analog_Bandwidth,
DeviceID = 0x01 //per Loc we can always use 1 with slice6
};
try
{
qsa.SyncExecute();
_maxAAFilterRateHz = (uint)((float)qsa.Value * 1000F);
}
catch
{
// Something went wrong. Set to default
// This is the max SCF for the current S6A device family as of 9/28/2020
_maxAAFilterRateHz = SLICE6AIR.MaxAAFilterRateHz;
}
}
return _maxAAFilterRateHz;
}
}
protected override uint MaxSampleRateHz => IsEthernetRecorder ? SLICE6AIR.MaxSampleRateHz_OBRDDR : SLICE6AIR.MaxSampleRateHz;
}
}