1351 lines
62 KiB
C#
1351 lines
62 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using DTS.DASLib.Command.SLICE;
|
|
using DTS.Common.DAS.Concepts;
|
|
using System.IO.Compression;
|
|
using System.IO;
|
|
using System.Xml;
|
|
using DTS.Common.Constant;
|
|
using DTS.Common.DASResource;
|
|
using DTS.Common.Interface.DASFactory;
|
|
using DTS.Common.Utilities.Logging;
|
|
using DTS.Common.Interface.Connection;
|
|
using DTS.Common.Enums.DASFactory;
|
|
using DTS.Common.ICommunication;
|
|
using DTS.Common;
|
|
|
|
namespace DTS.DASLib.Service
|
|
{
|
|
public partial class Slice<T> : Communication<T>,
|
|
IDASCommunication,
|
|
IConfigurationActions,
|
|
IDiagnosticsActions,
|
|
ITriggerCheckActions,
|
|
IRealTimeActions,
|
|
IArmActions,
|
|
IDownloadActions where T : IConnection, new()
|
|
{
|
|
|
|
protected virtual ConfigAttributes GetConfigAttributes(DTS.Common.Interface.DASFactory.ICommunication com)
|
|
{
|
|
return new ConfigAttributes(com);
|
|
}
|
|
protected class ConfigAttributes
|
|
{
|
|
protected ICommunication com { get; set; }
|
|
|
|
public ConfigAttributes(DTS.Common.Interface.DASFactory.ICommunication _com)
|
|
{
|
|
com = _com;
|
|
}
|
|
|
|
public virtual void PurgeStaleData(IDASCommunication das)
|
|
{
|
|
var cmd = new SetArmAttributesToDefaults(com);
|
|
cmd.SyncExecute();
|
|
|
|
// get bridge stuff
|
|
var dacValues = new ushort[das.ConfigData.NumberOfChannels()];
|
|
foreach (var module in das.DASInfo.Modules)
|
|
{
|
|
if (module.TypeOfModule == DFConstantsAndEnums.ModuleType.SLICEIEPE)
|
|
{
|
|
//call something else
|
|
//var odQuery = new QuerySystemAttribute_Bridge(com);
|
|
var odQuery = new QuerySystemAttribute_IEPE(com);
|
|
odQuery.DeviceID = (byte)(module.ModuleArrayIndex + 1);
|
|
|
|
odQuery.Key = AttributeTypes.SystemAttributes_IEPE.IA_OffsetDACA_Midscale;// OffsetDACA_Midscale;
|
|
odQuery.SyncExecute();
|
|
dacValues[module.ModuleArrayIndex * 3 + 0] = (ushort)odQuery.Value;
|
|
|
|
odQuery.Key = AttributeTypes.SystemAttributes_IEPE.IA_OffsetDACB_Midscale;
|
|
odQuery.SyncExecute();
|
|
dacValues[module.ModuleArrayIndex * 3 + 1] = (ushort)odQuery.Value;
|
|
|
|
odQuery.Key = AttributeTypes.SystemAttributes_IEPE.IA_OffsetDACC_Midscale;
|
|
odQuery.SyncExecute();
|
|
dacValues[module.ModuleArrayIndex * 3 + 2] = (ushort)odQuery.Value;
|
|
}
|
|
else
|
|
{
|
|
var odQuery = new QuerySystemAttribute_Bridge(com);
|
|
odQuery.DeviceID = (byte)(module.ModuleArrayIndex + 1);
|
|
|
|
odQuery.Key = AttributeTypes.SystemAttributes_Bridge.OffsetDACA_Midscale;
|
|
odQuery.SyncExecute();
|
|
dacValues[module.ModuleArrayIndex * 3 + 0] = (ushort)odQuery.Value;
|
|
|
|
odQuery.Key = AttributeTypes.SystemAttributes_Bridge.OffsetDACB_Midscale;
|
|
odQuery.SyncExecute();
|
|
dacValues[module.ModuleArrayIndex * 3 + 1] = (ushort)odQuery.Value;
|
|
|
|
odQuery.Key = AttributeTypes.SystemAttributes_Bridge.OffsetDACC_Midscale;
|
|
odQuery.SyncExecute();
|
|
dacValues[module.ModuleArrayIndex * 3 + 2] = (ushort)odQuery.Value;
|
|
}
|
|
}
|
|
|
|
// set base stuff
|
|
var odSet = new SetArmAttribute(com);
|
|
odSet.SetValue(AttributeTypes.ArmAndEventAttributes.StackChannelOffsetDACSettings, dacValues, true);
|
|
odSet.SyncExecute();
|
|
}
|
|
|
|
#region Arm attribute helpers
|
|
|
|
private void SetArmAttribute(AttributeTypes.ArmAndEventAttributes key, object value, bool ShouldOverwrite)
|
|
{
|
|
var set = new SetArmAttribute(com);
|
|
set.SetValue(key, value, ShouldOverwrite);
|
|
set.SyncExecute();
|
|
}
|
|
|
|
public void SetArmAttribute(AttributeTypes.ArmAndEventAttributes key, DFConstantsAndEnums.RecordingMode value)
|
|
{
|
|
if (com is EthernetSlice6Air s6A)
|
|
{
|
|
s6A.SetArmAttribute(key, value);
|
|
}
|
|
else { SetArmAttribute(key, (byte)value, true); }
|
|
}
|
|
|
|
public void SetArmAttribute(AttributeTypes.ArmAndEventAttributes key, UInt32 value)
|
|
{
|
|
SetArmAttribute(key, value, true);
|
|
}
|
|
|
|
public void SetArmAttribute(AttributeTypes.ArmAndEventAttributes key, float value)
|
|
{
|
|
SetArmAttribute(key, value, true);
|
|
}
|
|
|
|
public void SetArmAttribute(AttributeTypes.ArmAndEventAttributes key, string value)
|
|
{
|
|
var set = new SetArmAttribute(com);
|
|
var ByteArrayData = Encoding.UTF8.GetBytes(value);
|
|
set.SetValue(key, ByteArrayData, true);
|
|
set.SyncExecute();
|
|
}
|
|
|
|
public void SetArmAttribute(AttributeTypes.ArmAndEventAttributes key, ulong value)
|
|
{
|
|
SetArmAttribute(key, value, true);
|
|
}
|
|
|
|
public void GetArmAttribute(AttributeTypes.ArmAndEventAttributes key, out DFConstantsAndEnums.RecordingMode value)
|
|
{
|
|
var query = new QueryArmAttribute(com);
|
|
query.Key = key;
|
|
query.SyncExecute();
|
|
if (query.DataType != AttributeTypes.AttributeDataTypes.UInt8)
|
|
throw new Exception("ConfigurationService.GetArmAttribute.RecordingMode: Found type " + query.DataType);
|
|
value = (DFConstantsAndEnums.RecordingMode)query.Value;
|
|
}
|
|
|
|
public void GetArmAttribute(AttributeTypes.ArmAndEventAttributes key, out uint value)
|
|
{
|
|
var query = new QueryArmAttribute(com);
|
|
query.Key = key;
|
|
query.SyncExecute();
|
|
if (query.DataType != AttributeTypes.AttributeDataTypes.UInt32)
|
|
throw new Exception("ConfigurationService.GetArmAttribute.UInt32: Found type " + query.DataType);
|
|
value = (uint)query.Value;
|
|
}
|
|
|
|
public void GetArmAttribute(AttributeTypes.ArmAndEventAttributes key, out uint[] value)
|
|
{
|
|
var query = new QueryArmAttribute(com);
|
|
query.Key = key;
|
|
query.SyncExecute();
|
|
if (query.DataType != AttributeTypes.AttributeDataTypes.UInt32Star)
|
|
throw new Exception("ConfigurationService.GetArmAttribute.UInt32Star: Found type " + query.DataType);
|
|
value = (uint[])query.Value;
|
|
}
|
|
|
|
public void GetArmAttribute(AttributeTypes.ArmAndEventAttributes key, out float value)
|
|
{
|
|
var query = new QueryArmAttribute(com);
|
|
query.Key = key;
|
|
query.SyncExecute();
|
|
if (query.DataType != AttributeTypes.AttributeDataTypes.Float32)
|
|
throw new Exception("ConfigurationService.GetArmAttribute.float: Found type " + query.DataType);
|
|
value = (float)query.Value;
|
|
}
|
|
|
|
public void GetArmAttribute(AttributeTypes.ArmAndEventAttributes key, out string value)
|
|
{
|
|
var query = new QueryArmAttribute(com);
|
|
query.Key = key;
|
|
query.SyncExecute();
|
|
if (query.DataType != AttributeTypes.AttributeDataTypes.Unicode)
|
|
{
|
|
throw new Exception("ConfigurationService.GetArmAttribute.string: Found type " + query.DataType);
|
|
}
|
|
var values = query.Value as byte[];
|
|
value = Encoding.UTF8.GetString(values);
|
|
}
|
|
|
|
public void GetArmAttribute(AttributeTypes.ArmAndEventAttributes key, out ulong value)
|
|
{
|
|
var query = new QueryArmAttribute(com);
|
|
query.Key = key;
|
|
query.SyncExecute();
|
|
if (query.DataType != AttributeTypes.AttributeDataTypes.UInt64)
|
|
throw new Exception("ConfigurationService.GetArmAttribute.UInt64: Found type " + query.DataType);
|
|
value = (ulong)query.Value;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region XML attributes
|
|
protected byte[] GetBytes(FileStore fileStore, string data)
|
|
{
|
|
var d = fileStore == FileStore.TestSetup ? Encoding.Unicode.GetBytes(data) : Encoding.UTF8.GetBytes(data);
|
|
return d;
|
|
}
|
|
private string GetString(FileStore fileStore, byte[] data)
|
|
{
|
|
var WholeStr = fileStore == FileStore.TestSetup ? Encoding.Unicode.GetString(data) : Encoding.UTF8.GetString(data);
|
|
return WholeStr;
|
|
}
|
|
protected byte[] GetCompressedBytes(byte[] data)
|
|
{
|
|
byte[] ByteArrayData = null;
|
|
using (var s = new MemoryStream())
|
|
{
|
|
using (var gs = new GZipStream(s, CompressionMode.Compress, false))
|
|
{
|
|
gs.Write(data, 0, data.Length);
|
|
gs.Flush();
|
|
gs.Close();
|
|
ByteArrayData = s.GetBuffer();
|
|
}
|
|
}
|
|
return ByteArrayData;
|
|
}
|
|
public virtual void StoreXMLConfig(string data, FileStore fileStore)
|
|
{
|
|
if (string.IsNullOrEmpty(data))
|
|
{
|
|
return;
|
|
}
|
|
// since this might contain multi byte characters, we need to convert it to a byte array first
|
|
|
|
byte[] ByteArrayData = GetCompressedBytes(GetBytes(fileStore, data));
|
|
|
|
// calc how many we need
|
|
var NumBlocks = ByteArrayData.Length / Slice.Service.Attribute.MaxSingleAttributeSize;
|
|
if ((ByteArrayData.Length % Slice.Service.Attribute.MaxSingleAttributeSize) != 0)
|
|
{
|
|
NumBlocks++;
|
|
}
|
|
|
|
// write the blocks
|
|
// for progress, assume that we'll have about 40 blocks to write
|
|
var blockWeight = 40.0 / NumBlocks;
|
|
for (int BlockIdx = 0; BlockIdx < NumBlocks; BlockIdx++)
|
|
{
|
|
// contruct the current block
|
|
int blockLength = ByteArrayData.Length - (BlockIdx * Slice.Service.Attribute.MaxSingleAttributeSize);
|
|
if (blockLength > Slice.Service.Attribute.MaxSingleAttributeSize)
|
|
{
|
|
blockLength = Slice.Service.Attribute.MaxSingleAttributeSize;
|
|
}
|
|
var block = new byte[blockLength];
|
|
Array.Copy(ByteArrayData, BlockIdx * Slice.Service.Attribute.MaxSingleAttributeSize, block, 0, blockLength);
|
|
|
|
// write it to firmware
|
|
var AttrSet = new SetArmAttribute(com);
|
|
var attrNum = (AttributeTypes.ArmAndEventAttributes)(Slice.Service.Attribute.BulkAttributeStartNumber + BlockIdx);
|
|
AttrSet.SetValue(attrNum, block, AttributeTypes.AttributeDataTypes.Unicode, true);
|
|
AttrSet.SyncExecute();
|
|
}
|
|
|
|
// write our speacial header attribute
|
|
var InvariantCulture = new System.Globalization.CultureInfo("");
|
|
var BlockList = new StringBuilder(Slice.Service.Attribute.BulkAttributeStartNumber.ToString(InvariantCulture),
|
|
Slice.Service.Attribute.MaxSingleAttributeSize);
|
|
for (var BlockIdx = 1; BlockIdx < NumBlocks; BlockIdx++)
|
|
{
|
|
BlockList.Append("," + (Slice.Service.Attribute.BulkAttributeStartNumber + BlockIdx).ToString(InvariantCulture));
|
|
}
|
|
var HeaderAttrSet = new SetArmAttribute(com);
|
|
// this attribute only contains digits and commas so it's OK to keep it as Ascii
|
|
HeaderAttrSet.SetValue(AttributeTypes.ArmAndEventAttributes.StoredConfigIndex,
|
|
BlockList.ToString(), AttributeTypes.AttributeDataTypes.Ascii, true);
|
|
HeaderAttrSet.SyncExecute();
|
|
|
|
if ((FileStore.Diagnostic == fileStore) || (FileStore.Event == fileStore)) { StoreXmlConfigPC(data, "DASConfigs", com.SerialNumber); }
|
|
}
|
|
|
|
public void StoreXmlConfigPC(string data, string folder, string fn)
|
|
{
|
|
try
|
|
{
|
|
var folderName = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), folder);
|
|
var fileName = Path.Combine(folderName, fn);
|
|
if (!fileName.ToLower().EndsWith(".xml")) { fileName = $"{fileName}.xml"; }
|
|
if (folder.Equals(Constants.DAS_CONFIGS))
|
|
{
|
|
if (File.Exists(fileName)) { File.Delete(fileName); }
|
|
using (var file = File.CreateText(fileName))
|
|
{
|
|
file.Write(data);
|
|
APILogger.Log($"DASConfig file written: {fileName}");
|
|
}
|
|
}
|
|
else if (folder.Equals(Constants.DAS_TEST_SETUPS))
|
|
{
|
|
//If it already exists, don't delete and then re-write, just use it.
|
|
if (!File.Exists(fileName))
|
|
{
|
|
if (!Directory.Exists(folder))
|
|
{
|
|
Directory.CreateDirectory(folder);
|
|
}
|
|
using (var file = File.CreateText(fileName))
|
|
{
|
|
file.Write(data);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log(ex);
|
|
APILogger.RaiseError(DTS.Common.Strings.Strings.FailedToWritePcConfigFile);
|
|
}
|
|
}
|
|
|
|
public enum FileStore
|
|
{
|
|
Diagnostic = 0x00,
|
|
Event = 0x01,
|
|
TestSetup = 0x02,
|
|
SpeedTest = 0x03,
|
|
UserAttributes = 0x04
|
|
}
|
|
public virtual string RetrieveXMLConfig(FileStore filestore, IDASCommunication das)
|
|
{
|
|
var WholeStr = string.Empty;
|
|
try
|
|
{
|
|
// first get our special header attribute
|
|
var AttrGet = new QueryArmAttribute(com);
|
|
AttrGet.Key = AttributeTypes.ArmAndEventAttributes.StoredConfigIndex;
|
|
AttrGet.SyncExecute();
|
|
// this attribute only contains digits and commas so it's OK to keep it as Ascii (see above)
|
|
var BlockListStr = AttrGet.Value as string;
|
|
|
|
// still there?
|
|
if (string.IsNullOrEmpty(BlockListStr))
|
|
{
|
|
// "Slice.RetrieveAttributes: Header attribute as string is empty"
|
|
throw new Exception(Strings.Slice_RetrieveAttributes_Err2);
|
|
}
|
|
|
|
var InvariantCulture = new System.Globalization.CultureInfo("");
|
|
var BlockListStrArr = BlockListStr.Split(',');
|
|
var BlockList = new List<ushort>();
|
|
foreach (string NumStr in BlockListStrArr)
|
|
{
|
|
if (!ushort.TryParse(NumStr, System.Globalization.NumberStyles.Integer, InvariantCulture, out ushort Number))
|
|
{
|
|
// "Slice.RetrieveAttributes: Header attribute is invalid"
|
|
throw new System.Exception(Strings.Slice_RetrieveAttributes_Err3);
|
|
}
|
|
BlockList.Add(Number);
|
|
}
|
|
|
|
var allBytes = new List<byte>(131072);
|
|
foreach (var AttrNumber in BlockList)
|
|
{
|
|
AttrGet.LogCommands = false;
|
|
AttrGet.Key = (AttributeTypes.ArmAndEventAttributes)AttrNumber;
|
|
AttrGet.SyncExecute();
|
|
// old version stored the data as Ascii
|
|
if (AttrGet.DataType == AttributeTypes.AttributeDataTypes.Ascii)
|
|
{
|
|
allBytes.AddRange(Encoding.UTF8.GetBytes((AttrGet.Value as string)));
|
|
}
|
|
// new version uses Unicode (basically byte[])
|
|
else if (AttrGet.DataType == AttributeTypes.AttributeDataTypes.Unicode)
|
|
{
|
|
var values = AttrGet.Value as byte[];
|
|
allBytes.AddRange(values);
|
|
}
|
|
else
|
|
{
|
|
// this is really bad!
|
|
throw new Exception(string.Format("RetrieveXMLConfig: Unknown datatype {0}", AttrGet.DataType.ToString()));
|
|
}
|
|
}
|
|
if (allBytes.Count < 1)
|
|
{
|
|
// "Slice.RetrieveAttributes: Attributes are empty"
|
|
throw new Exception(Strings.Slice_RetrieveAttributes_Err4);
|
|
}
|
|
return GetDecompressedString(allBytes.ToArray(), filestore);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log($"Failed to retrieve xml config - {filestore} on {com.SerialNumber}. Error: {ex}");
|
|
if (FileStore.Event == filestore)
|
|
{
|
|
//event file store FIRST falls back to diagnostics
|
|
//which will fall back onto pc if it fails
|
|
WholeStr = RetrieveXMLConfig(FileStore.Diagnostic, das);
|
|
}
|
|
else if (FileStore.Diagnostic == filestore)
|
|
{
|
|
//diagnostics falls back to pc
|
|
WholeStr = RetrieveXmlConfigPC();
|
|
}
|
|
}
|
|
try { APILogger.ConfLog(com.SerialNumber, "XML Config\n", Common.Utils.Utils.PrettyPrint(WholeStr)); }
|
|
catch (Exception) { }
|
|
return WholeStr;
|
|
}
|
|
|
|
protected string RetrieveXmlConfigPC()
|
|
{
|
|
try
|
|
{
|
|
var fileName = Path.Combine(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), Constants.DAS_CONFIGS), string.Format("{0}.xml", com.SerialNumber));
|
|
if (File.Exists(fileName))
|
|
{
|
|
return File.ReadAllText(fileName);
|
|
}
|
|
}
|
|
catch (Exception ex) { APILogger.Log(ex); }
|
|
return "";
|
|
}
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="allBytes"></param>
|
|
/// <param name="fileStore"></param>
|
|
/// <returns></returns>
|
|
protected string GetDecompressedString(byte[] allBytes, FileStore fileStore)
|
|
{
|
|
var WholeStr = string.Empty;
|
|
var gData = new byte[8192];
|
|
var crc = new Utilities.Crc32();
|
|
var crcBefore = crc.Get(allBytes);
|
|
APILogger.Log($"RetrieveXmlConfig {com.SerialNumber} crc compressed: {crcBefore} filestore: {fileStore}");
|
|
using (var sr = new MemoryStream(allBytes))
|
|
{
|
|
using (var gs = new GZipStream(sr, CompressionMode.Decompress, false))
|
|
{
|
|
using (var ms = new MemoryStream(WholeStr.Length * 10))
|
|
{
|
|
try
|
|
{
|
|
var count = gs.Read(gData, 0, gData.Length);
|
|
while (count > 0)
|
|
{
|
|
ms.Write(gData, 0, count);
|
|
ms.Flush();
|
|
count = gs.Read(gData, 0, gData.Length);
|
|
}
|
|
gs.Close();
|
|
var allBytesAfter = ms.ToArray();
|
|
var crcAfter = crc.Get(allBytesAfter);
|
|
APILogger.Log($"RetrieveXmlConfig {com.SerialNumber} crc uncompressed: {crcAfter} crc compressed: {crcBefore} filestore: {fileStore}");
|
|
WholeStr = GetString(fileStore, allBytesAfter);
|
|
}
|
|
catch (InvalidDataException ex)
|
|
{
|
|
//well perhaps it's not zipped up then!
|
|
WholeStr = GetString(fileStore, ms.ToArray());
|
|
APILogger.Log($"RetreiveXmlConfig {com.SerialNumber} Filestore {fileStore} InvalidDataException {com.SerialNumber} ", ex, WholeStr);
|
|
APILogger.ConfigReadErrorLogWriter($"{DateTime.Now:yyyy - MM - dd HH: mm:ss.fff} {com.SerialNumber} Filestore {fileStore} crc compressed: {crcBefore} exception: {ex.Message}\n");
|
|
throw new Exception("Invalid data", ex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return WholeStr;
|
|
}
|
|
// Attractively format the XML with consistant indentation.
|
|
|
|
/// <summary>
|
|
/// Retrieve the XML string that was split and stored in the Arm attributes
|
|
/// </summary>
|
|
/// <param name="eventNum">The event number to get it from</param>
|
|
/// <param name="progress"></param>
|
|
/// <returns>The combined XML string</returns>
|
|
public virtual string RetrieveEventXMLConfig(int eventNum, QueryDownloadProgress progress, IDASCommunication das)
|
|
{
|
|
// first get our special header attribute
|
|
var AttrGet = new QueryEventAttribute(com);
|
|
AttrGet.EventNumber = (ushort)eventNum;
|
|
AttrGet.Key = AttributeTypes.ArmAndEventAttributes.StoredConfigIndex;
|
|
AttrGet.SyncExecute();
|
|
if (null != progress) { progress.Step(); }
|
|
|
|
var BlockListStr = AttrGet.Value as string;
|
|
|
|
// still there?
|
|
if (string.IsNullOrEmpty(BlockListStr))
|
|
{
|
|
// "Slice.RetrieveEventAttributes: Header attribute is empty"
|
|
throw new Exception(Strings.Slice_RetrieveEventAttributes_Err1);
|
|
}
|
|
|
|
var InvariantCulture = new System.Globalization.CultureInfo("");
|
|
var BlockListStrArr = BlockListStr.Split(',');
|
|
var BlockList = new List<ushort>();
|
|
foreach (var NumStr in BlockListStrArr)
|
|
{
|
|
if (!ushort.TryParse(NumStr, System.Globalization.NumberStyles.Integer, InvariantCulture, out ushort Number))
|
|
{
|
|
// "Slice.RetrieveEventAttributes: Header attribute is invalid"
|
|
throw new System.Exception(Strings.Slice_RetrieveEventAttributes_Err2);
|
|
}
|
|
BlockList.Add(Number);
|
|
}
|
|
var AllStrings = new StringBuilder(BlockList.Count * Slice.Service.Attribute.MaxSingleAttributeSize);
|
|
var AllBytes = new List<byte>(BlockList.Count * Slice.Service.Attribute.MaxSingleAttributeSize * 2);
|
|
foreach (var AttrNumber in BlockList)
|
|
{
|
|
AttrGet.Key = (AttributeTypes.ArmAndEventAttributes)AttrNumber;
|
|
AttrGet.LogCommands = false;
|
|
AttrGet.SyncExecute();
|
|
if (null != progress) { progress.Step(); }
|
|
// old version stored the data as Ascii
|
|
if (AttrGet.DataType == AttributeTypes.AttributeDataTypes.Ascii)
|
|
{
|
|
AllBytes.AddRange(Encoding.UTF8.GetBytes((AttrGet.Value as string)));
|
|
}
|
|
// new version uses Unicode (basically byte[])
|
|
else if (AttrGet.DataType == AttributeTypes.AttributeDataTypes.Unicode)
|
|
{
|
|
var values = AttrGet.Value as byte[];
|
|
AllBytes.AddRange(values);
|
|
}
|
|
else
|
|
{
|
|
// this is really bad!
|
|
throw new Exception(string.Format("RetrieveXMLConfig: Unknown datatype {0}", AttrGet.DataType.ToString()));
|
|
}
|
|
}
|
|
if (AllBytes.Count < 1)
|
|
{
|
|
// "Slice.RetrieveAttributes: Attributes are empty"
|
|
throw new Exception(Strings.Slice_RetrieveAttributes_Err4);
|
|
}
|
|
var WholeStr = GetDecompressedString(AllBytes.ToArray(), FileStore.Event);
|
|
|
|
try { APILogger.ConfLog(com.SerialNumber, "XML Config\n", DTS.Common.Utils.Utils.PrettyPrint(WholeStr)); }
|
|
catch (Exception) { }
|
|
return WholeStr;
|
|
}
|
|
|
|
#endregion
|
|
|
|
public void ConfigureRange(float[] ranges)
|
|
{
|
|
// this function shall just set the range attribute for channel
|
|
var set = new SetArmAttribute(com);
|
|
set.SetValue(AttributeTypes.ArmAndEventAttributes.StackChannelRangesMillivolts, ranges, true);
|
|
set.SyncExecute();
|
|
}
|
|
public virtual void ConfigureCoupling(bool[] IsACCoupledArray)
|
|
{
|
|
var set = new SetArmAttribute(com, QueryArmAttribute.Default_IO_Timeout);
|
|
set.SetValue(AttributeTypes.ArmAndEventAttributes.StackChannelACCouplerEnable, IsACCoupledArray, true);
|
|
set.SyncExecute();
|
|
}
|
|
|
|
public virtual void ConfigureBridge(byte[] bridgeModeArray)
|
|
{
|
|
var set = new SetArmAttribute(com);
|
|
set.SetValue(AttributeTypes.ArmAndEventAttributes.StackChannelBridgeCompletionEnable, bridgeModeArray, true);
|
|
set.SyncExecute();
|
|
}
|
|
|
|
public virtual void ConfigureBridgeResistance(ushort[] BridgeResistanceArray)
|
|
{
|
|
// this function shall just set the bridge resistance for the channels
|
|
var set = new SetArmAttribute(com);
|
|
set.SetValue(AttributeTypes.ArmAndEventAttributes.StackChannelBridgeResistanceOhms, BridgeResistanceArray, true);
|
|
set.SyncExecute();
|
|
}
|
|
|
|
public float[] GetScaleFactors()
|
|
{
|
|
// this function shall just get the scale factors for all channels
|
|
var query = new QueryArmAttribute(com);
|
|
query.Key = AttributeTypes.ArmAndEventAttributes.StackChannelScaleFactorsMillivoltsPerADC;
|
|
query.SyncExecute();
|
|
return query.Value as float[];
|
|
}
|
|
|
|
public float[] GetRanges()
|
|
{
|
|
|
|
//FB 25526 this function shall just get the stackc hannel ranges for all channels in milli volts
|
|
var query = new QueryArmAttribute(com);
|
|
query.Key = AttributeTypes.ArmAndEventAttributes.StackChannelRangesMillivolts;
|
|
query.SyncExecute();
|
|
return query.Value as float[];
|
|
}
|
|
|
|
public float[] GetMeasuredOffset()
|
|
{
|
|
//FB 25526 this function shall just get the stack channel measured offset for all channels in milli volts
|
|
var query = new QueryArmAttribute(com);
|
|
query.Key = AttributeTypes.ArmAndEventAttributes.StackChannelMeasuredOffsetMV;
|
|
query.SyncExecute();
|
|
return query.Value as float[];
|
|
}
|
|
|
|
public uint[] GetStackActualSampleRate()
|
|
{
|
|
// this function shall just get the scale factors for all channels
|
|
var query = new QueryArmAttribute(com);
|
|
query.Key = AttributeTypes.ArmAndEventAttributes.StackActualSampleRateHz;
|
|
query.SyncExecute();
|
|
return query.Value as uint[];
|
|
}
|
|
|
|
#region Attributes
|
|
|
|
public uint SampleRate
|
|
{
|
|
get
|
|
{
|
|
GetArmAttribute(AttributeTypes.ArmAndEventAttributes.SampleRate, out uint Value);
|
|
return Value;
|
|
}
|
|
set => SetArmAttribute(AttributeTypes.ArmAndEventAttributes.SampleRate, value);
|
|
}
|
|
|
|
public float ActualSampleRate
|
|
{
|
|
get
|
|
{
|
|
if (((IDASCommunication)com).GetIsStreaming())
|
|
{
|
|
//15949 S6A when streaming does a whole bunch of unnecessary queries
|
|
//avoid getting this attribute if streaming, it will fail
|
|
//also avoid returning a 0 for div0 safety reasons?
|
|
return 10000;
|
|
}
|
|
if (com.IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.QueryActualSampleRateImmediate))
|
|
{
|
|
try
|
|
{
|
|
GetArmAttribute(AttributeTypes.ArmAndEventAttributes.ActualSampleRateHz, out float Value);
|
|
return Value;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log("Failed to get ActualSampleRateHz, ", ex);
|
|
}
|
|
}
|
|
return Convert.ToSingle(SampleRate);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Retrieve currently running sample rates for devices with more than one on-board IC (read: TSR-AIR)
|
|
/// </summary>
|
|
/// <returns>
|
|
/// <see cref="float[]"/> Collection of current sample rates
|
|
/// </returns>
|
|
public float[] StackActualSampleRate
|
|
{
|
|
get
|
|
{
|
|
if (((IDASCommunication)com).GetIsStreaming())
|
|
{
|
|
//Adapted from 15949 for TSR-AIR: Unit is streaming and won't respond to the query, so return maxed out
|
|
var len = ((IDASCommunication)com).ConfigData.Modules.Length;
|
|
var rates = new float[len];
|
|
for (var i = 0; i < len; i++)
|
|
{
|
|
switch (((IDASCommunication)com).ConfigData.Modules[i].ModuleType())
|
|
{
|
|
case DFConstantsAndEnums.ModuleType.EmbeddedLinearAccelHighG:
|
|
rates[i] = (float)EmbeddedSensors.EmbeddedHighGLinearAccelerometerSampleRateMaximum;
|
|
break;
|
|
case DFConstantsAndEnums.ModuleType.EmbeddedLinearAccelLowG:
|
|
rates[i] = (float)EmbeddedSensors.EmbeddedLowGLinearAccelerometerSampleRateMaximum;
|
|
break;
|
|
case DFConstantsAndEnums.ModuleType.EmbeddedAngularAccel:
|
|
rates[i] = (float)EmbeddedSensors.EmbeddedAngularAccelerometerSampleRateMaximum;
|
|
break;
|
|
case DFConstantsAndEnums.ModuleType.EmbeddedAngularRate:
|
|
rates[i] = (float)EmbeddedSensors.EmbeddedAngularAccelerometerAndRateSensorSampleRateMaximum;
|
|
break;
|
|
case DFConstantsAndEnums.ModuleType.EmbeddedAtmospheric:
|
|
rates[i] = (float)EmbeddedSensors.EmbeddedAtmosphericSensorSampleRateMaximum;
|
|
break;
|
|
case DFConstantsAndEnums.ModuleType.EmbeddedClockSecondsAndMarker:
|
|
case DFConstantsAndEnums.ModuleType.EmbeddedClockNanosAndPad:
|
|
rates[i] = 0; //it's the encoded timestamp. no sample rate
|
|
break;
|
|
default:
|
|
rates[i] = 10000; //probably shouldn't get here, but default to super-sample rate
|
|
break;
|
|
}
|
|
}
|
|
return rates;
|
|
}
|
|
if (com.IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.QueryStackActualSampleRateImmediate))
|
|
{
|
|
try
|
|
{
|
|
var query = new QueryArmAttribute(com);
|
|
query.Key = AttributeTypes.ArmAndEventAttributes.StackActualSampleRateHz;
|
|
query.SyncExecute();
|
|
return query.Value as float[];
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log("Failed to get StackActualSampleRateHz, ", ex);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
public float AAFilter
|
|
{
|
|
get
|
|
{
|
|
GetArmAttribute(AttributeTypes.ArmAndEventAttributes.AAFilterFrequency, out float Value);
|
|
return Value;
|
|
}
|
|
set => SetArmAttribute(AttributeTypes.ArmAndEventAttributes.AAFilterFrequency, value);
|
|
}
|
|
|
|
public string TestID
|
|
{
|
|
get
|
|
{
|
|
GetArmAttribute(AttributeTypes.ArmAndEventAttributes.Name, out string Value);
|
|
try
|
|
{
|
|
Value = (com as IDASCommunication).ConfigData.TestID;
|
|
}
|
|
catch (Exception) { }
|
|
return Value;
|
|
}
|
|
set
|
|
{
|
|
SetArmAttribute(AttributeTypes.ArmAndEventAttributes.Name, value);
|
|
try
|
|
{
|
|
(com as IDASCommunication).ConfigData.TestID = value;
|
|
}
|
|
catch (Exception) { }
|
|
}
|
|
}
|
|
|
|
public string TestSetupUniqueId
|
|
{
|
|
get
|
|
{
|
|
return (com as IDASCommunication).ConfigData.TestSetupUniqueId;
|
|
}
|
|
set
|
|
{
|
|
try
|
|
{
|
|
(com as IDASCommunication).ConfigData.TestSetupUniqueId = value;
|
|
}
|
|
catch (Exception) { }
|
|
}
|
|
}
|
|
|
|
public string InstanceID
|
|
{
|
|
get
|
|
{
|
|
return (com as IDASCommunication).ConfigData.InstanceID;
|
|
}
|
|
set
|
|
{
|
|
try
|
|
{
|
|
(com as IDASCommunication).ConfigData.InstanceID = value;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log("Failed in ConfigAttributes.InstanceID property", ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
public string TestDescription
|
|
{
|
|
get
|
|
{
|
|
GetArmAttribute(AttributeTypes.ArmAndEventAttributes.Description, out string Value);
|
|
try
|
|
{
|
|
Value = (com as IDASCommunication).ConfigData.Description;
|
|
}
|
|
catch (Exception) { }
|
|
return Value;
|
|
}
|
|
set
|
|
{
|
|
if (string.IsNullOrEmpty(value)) { value = " "; }
|
|
SetArmAttribute(AttributeTypes.ArmAndEventAttributes.Description, value);
|
|
try
|
|
{
|
|
(com as IDASCommunication).ConfigData.Description = value;
|
|
}
|
|
catch (Exception) { }
|
|
}
|
|
}
|
|
|
|
public ulong PreTriggerSamples
|
|
{
|
|
get
|
|
{
|
|
GetArmAttribute(AttributeTypes.ArmAndEventAttributes.PreTriggerSamplesRequested, out ulong Value);
|
|
return Value;
|
|
}
|
|
set => SetArmAttribute(AttributeTypes.ArmAndEventAttributes.PreTriggerSamplesRequested, value);
|
|
}
|
|
|
|
public ulong PostTriggerSamples
|
|
{
|
|
get
|
|
{
|
|
GetArmAttribute(AttributeTypes.ArmAndEventAttributes.PostTriggerSamplesRequested, out ulong Value);
|
|
return Value;
|
|
}
|
|
set => SetArmAttribute(AttributeTypes.ArmAndEventAttributes.PostTriggerSamplesRequested, value);
|
|
}
|
|
public DateTime ScheduledStartTime
|
|
{
|
|
get
|
|
{
|
|
GetArmAttribute(AttributeTypes.ArmAndEventAttributes.ScheduleUnixTimeIntervalInSec, out UInt32[] Value);
|
|
var scheduledStartTime = new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(Value[0]);
|
|
return scheduledStartTime;
|
|
}
|
|
set
|
|
{
|
|
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0);
|
|
var span = value - epoch;
|
|
var startTimeInSeconds = Convert.ToUInt32(span.TotalSeconds);
|
|
//Get existing recording interval
|
|
var intervalInSeconds = (uint)RecordingInterval;
|
|
var scheduleUnixTimeIntervalInSec = new UInt32[2] { startTimeInSeconds, intervalInSeconds };
|
|
SetArmAttribute(AttributeTypes.ArmAndEventAttributes.ScheduleUnixTimeIntervalInSec, scheduleUnixTimeIntervalInSec, true);
|
|
}
|
|
}
|
|
public int RecordingInterval
|
|
{
|
|
get
|
|
{
|
|
GetArmAttribute(AttributeTypes.ArmAndEventAttributes.ScheduleUnixTimeIntervalInSec, out UInt32[] Value);
|
|
var recordingInterval = Value[1];
|
|
return (int)recordingInterval;
|
|
}
|
|
set
|
|
{
|
|
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0);
|
|
//Get existing start time
|
|
var span = ScheduledStartTime - epoch;
|
|
var startTimeInSeconds = Convert.ToUInt32(span.TotalSeconds);
|
|
var intervalInSeconds = Convert.ToUInt32(value * 60);
|
|
var scheduleUnixTimeIntervalInSec = new UInt32[2] { startTimeInSeconds, intervalInSeconds };
|
|
SetArmAttribute(AttributeTypes.ArmAndEventAttributes.ScheduleUnixTimeIntervalInSec, scheduleUnixTimeIntervalInSec, true);
|
|
}
|
|
}
|
|
|
|
public DFConstantsAndEnums.RecordingMode TestType
|
|
{
|
|
get
|
|
{
|
|
GetArmAttribute(AttributeTypes.ArmAndEventAttributes.ArmMode, out DFConstantsAndEnums.RecordingMode Value);
|
|
return Value;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Helper functions
|
|
|
|
public uint CalculateNumberOfModules(ConfigurationData config, uint numChannels, bool bIsTOM)
|
|
{
|
|
if (bIsTOM) { return 1; }
|
|
// this is a shortcut for now
|
|
return numChannels / 3;
|
|
}
|
|
|
|
public uint CalculateNumberOfUARTs(ConfigurationData config)
|
|
{
|
|
var sum = (uint)0;
|
|
foreach (var idasmod in config.Modules)
|
|
{
|
|
foreach (var ch in idasmod.Channels)
|
|
{
|
|
if (ch is UARTInputDASChannel)
|
|
{
|
|
sum++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return sum;
|
|
}
|
|
/// <summary>
|
|
/// Returns the number of modules which support output stream
|
|
/// </summary>
|
|
/// <param name="config">stored xml configuration</param>
|
|
/// <returns>number of modules in xml that contain output stream channels</returns>
|
|
public uint CalculateNumberOfStreamOuts(ConfigurationData config)
|
|
{
|
|
var sum = (uint)0;
|
|
foreach (var idasmod in config.Modules)
|
|
{
|
|
foreach (var ch in idasmod.Channels)
|
|
{
|
|
if (ch is StreamOutputDASChannel)
|
|
{
|
|
sum++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return sum;
|
|
}
|
|
/// <summary>
|
|
/// Returns the number of modules which support input stream
|
|
/// </summary>
|
|
/// <param name="config">stored xml configuration</param>
|
|
/// <returns>number of modules in xml that contain output stream channels</returns>
|
|
public uint CalculateNumberOfStreamIns(ConfigurationData config)
|
|
{
|
|
var sum = (uint)0;
|
|
foreach (var idasmod in config.Modules)
|
|
{
|
|
foreach (var ch in idasmod.Channels)
|
|
{
|
|
if (ch is StreamInputDASChannel)
|
|
{
|
|
sum++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return sum;
|
|
}
|
|
public ulong GetEventTotalSamples(int eventNum)
|
|
{
|
|
var samples = 0UL;
|
|
var eventSamples = new QueryEventAttribute(com);
|
|
eventSamples.EventNumber = (ushort)eventNum;
|
|
eventSamples.Key = AttributeTypes.ArmAndEventAttributes.TotalSamplesRecorded;
|
|
var bFakeNumberOfSamples = false;
|
|
try
|
|
{
|
|
eventSamples.SyncExecute();
|
|
samples = (ulong)eventSamples.Value;
|
|
if (0 == samples) { bFakeNumberOfSamples = true; }
|
|
}
|
|
catch (Exception) { bFakeNumberOfSamples = true; }
|
|
if (bFakeNumberOfSamples)
|
|
{
|
|
try
|
|
{ //
|
|
// Try to get enough info to proceed with a rump download.
|
|
//
|
|
var preSamplesRequested = new QueryEventAttribute(com);
|
|
preSamplesRequested.EventNumber = (ushort)eventNum;
|
|
preSamplesRequested.Key = AttributeTypes.ArmAndEventAttributes.PreTriggerSamplesRequested;
|
|
preSamplesRequested.SyncExecute();
|
|
|
|
var postSamplesRequested = new QueryEventAttribute(com);
|
|
postSamplesRequested.EventNumber = (ushort)eventNum;
|
|
postSamplesRequested.Key = AttributeTypes.ArmAndEventAttributes.PostTriggerSamplesRequested;
|
|
postSamplesRequested.SyncExecute();
|
|
|
|
samples = (ulong)preSamplesRequested.Value + (ulong)postSamplesRequested.Value + 1L;
|
|
|
|
var totalSamplesRecorded = new SetEventAttribute(com);
|
|
totalSamplesRecorded.EventNumber = (ushort)eventNum;
|
|
totalSamplesRecorded.SetValue(AttributeTypes.ArmAndEventAttributes.TotalSamplesRecorded, samples, true);
|
|
totalSamplesRecorded.SyncExecute();
|
|
}
|
|
|
|
catch (Exception ex)
|
|
{
|
|
throw new ApplicationException("encountered problem re-querying pre/post samples after initial total sample request failure", ex);
|
|
}
|
|
}
|
|
|
|
return samples;
|
|
}
|
|
|
|
public ulong GetEventTriggerSampleNumber(int eventNum)
|
|
{
|
|
var eventTSN = new QueryEventAttribute(com);
|
|
eventTSN.EventNumber = (ushort)eventNum;
|
|
eventTSN.Key = AttributeTypes.ArmAndEventAttributes.TriggerSampleNumber;
|
|
try { eventTSN.SyncExecute(); }
|
|
catch (Exception) { return 0UL; }
|
|
return (ulong)eventTSN.Value;
|
|
}
|
|
|
|
public void SetEventTriggerSampleNumber(int eventNum, ulong sampleNumber)
|
|
{
|
|
var eventTSN = new SetEventAttribute(com);
|
|
eventTSN.EventNumber = (ushort)eventNum;
|
|
eventTSN.SetValue(AttributeTypes.ArmAndEventAttributes.TriggerSampleNumber, sampleNumber, true);
|
|
eventTSN.SyncExecute();
|
|
}
|
|
|
|
public UInt64 GetEventStartRecordSampleNumber(int eventNum)
|
|
{
|
|
var eventSRSN = new QueryEventAttribute(com);
|
|
eventSRSN.EventNumber = (ushort)eventNum;
|
|
eventSRSN.Key = AttributeTypes.ArmAndEventAttributes.StartRecordSampleNumber;
|
|
try { eventSRSN.SyncExecute(); }
|
|
catch (Exception) { return 0UL; }
|
|
return (ulong)eventSRSN.Value;
|
|
}
|
|
|
|
public virtual uint GetEventSamplerate(int eventNum)
|
|
{
|
|
var eventSR = new QueryEventAttribute(com);
|
|
eventSR.EventNumber = (ushort)eventNum;
|
|
eventSR.Key = AttributeTypes.ArmAndEventAttributes.SampleRate;
|
|
eventSR.SyncExecute();
|
|
return (uint)eventSR.Value;
|
|
}
|
|
|
|
public uint[] GetEventStackSamplerate(int eventNum)
|
|
{
|
|
if (com.IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.QueryStackActualSampleRateImmediate))
|
|
{
|
|
var eventSASR = new QueryEventAttribute(com);
|
|
eventSASR.EventNumber = (ushort)eventNum;
|
|
eventSASR.Key = AttributeTypes.ArmAndEventAttributes.StackActualSampleRateHz;
|
|
eventSASR.SyncExecute();
|
|
return (uint[])eventSASR.Value;
|
|
}
|
|
return new uint[] { };
|
|
}
|
|
|
|
public virtual DateTime GetEventStartTime(int eventNum)
|
|
{
|
|
if (com.IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.BaseSystemTime))
|
|
{
|
|
try
|
|
{
|
|
// base system time format in BCD. There are 7-byte stream as follow:
|
|
// byte[0] = seconds: 0-59
|
|
// byte[1] = minutes: 0-59
|
|
// byte[2] = hours: 0:
|
|
// byte[3] = days.
|
|
// byte[4] = weekdays.
|
|
// byte[5] = months.
|
|
// byte[6] = years.
|
|
var query = new QueryEventAttribute(com);
|
|
query.EventNumber = (ushort)eventNum;
|
|
query.Key = AttributeTypes.ArmAndEventAttributes.EventTimeStamp;
|
|
query.SyncExecute();
|
|
if (query.Value is byte[] bytes)
|
|
{
|
|
if (7 <= bytes.Length)
|
|
{
|
|
//this is invalid data, just ignore it
|
|
if (bytes.Length >= 8 && 0 == bytes[0] && 0 == bytes[1] && 0 == bytes[2] && 0 == bytes[3] && 0 == bytes[4] && 0 == bytes[5] && 0 == bytes[6] && 1 == bytes[7])
|
|
{
|
|
return new DateTime(0);
|
|
}
|
|
//if month or day is 0 this is an invalid date, don't try to parse it
|
|
if (0 == bytes[5] && 0 == bytes[3]) { return new DateTime(0); }
|
|
|
|
//15613 - Don't validate RTC DateTime value from SLICE
|
|
var dt = new DateTime(bytes[6] + 2000, bytes[5], bytes[3], bytes[2], bytes[1], bytes[0]);
|
|
return dt;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log(ex);
|
|
}
|
|
}
|
|
|
|
return new DateTime(0);
|
|
}
|
|
|
|
public double GetEventAAFilter(int eventNum)
|
|
{
|
|
var eventFF = new QueryEventAttribute(com);
|
|
eventFF.EventNumber = (ushort)eventNum;
|
|
eventFF.Key = AttributeTypes.ArmAndEventAttributes.AAFilterFrequency;
|
|
eventFF.SyncExecute();
|
|
var aafilter = (float)eventFF.Value;
|
|
return aafilter;
|
|
}
|
|
|
|
public double GetEventExcitation(int eventNum)
|
|
{
|
|
var eventExc = new QueryEventAttribute(com);
|
|
eventExc.EventNumber = (ushort)eventNum;
|
|
throw new ApplicationException("GetEventExcitation needs to be implemented by channel ...");
|
|
}
|
|
|
|
public virtual float[] GetEventScaleFactors(int eventNum)
|
|
{
|
|
var query = new QueryEventAttribute(com);
|
|
query.EventNumber = (ushort)eventNum;
|
|
query.Key = AttributeTypes.ArmAndEventAttributes.StackChannelScaleFactorsMillivoltsPerADC;
|
|
query.SyncExecute();
|
|
return query.Value as float[];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the number of "level triggered" samples required for a level trigger to be declared by the DAS.
|
|
/// </summary>
|
|
///
|
|
/// <param name="eventNum">
|
|
/// The <see cref="int"/> event number for which we want level trigger qualification sample information.
|
|
/// </param>
|
|
///
|
|
/// <returns>
|
|
/// The <see cref="int"/> number of contiguous "level triggered" samples required for a level trigger event.
|
|
/// </returns>
|
|
///
|
|
private int[] GetLevelTriggerQualificationSamples(int eventNum)
|
|
{
|
|
try
|
|
{
|
|
if (this is WinUSBSlice6) { return null; }
|
|
if (this is WinUSBSlice6Air) { return null; }
|
|
var eventLevTrigQlfSamps = new QueryEventAttribute(com);
|
|
eventLevTrigQlfSamps.Key = AttributeTypes.ArmAndEventAttributes.LevelTriggerQualificationSamples;
|
|
eventLevTrigQlfSamps.SyncExecute();
|
|
return (int[])(eventLevTrigQlfSamps.Value);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new ApplicationException("encountered problem getting number of level trigger qualification samples from hardware for event " + eventNum.ToString(), ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get determination from hardware whether or not the associated DAS has directly experienced a level trigger event.
|
|
/// </summary>
|
|
///
|
|
/// <param name="eventNum">
|
|
/// The <see cref="int"/> event number for which we want level trigger seen information.
|
|
/// </param>
|
|
///
|
|
/// <returns>
|
|
/// <see cref="bool"/> True if the associated DAS has experienced a level trigger event; False otherwise.
|
|
/// </returns>
|
|
///
|
|
private bool[] GetLevelTriggerSeen(int eventNum)
|
|
{
|
|
try
|
|
{
|
|
var eventLevTrigSeen = new QueryEventAttribute(com);
|
|
eventLevTrigSeen.EventNumber = Convert.ToUInt16(eventNum);
|
|
eventLevTrigSeen.Key = AttributeTypes.ArmAndEventAttributes.LevelTriggerSeen;
|
|
eventLevTrigSeen.SyncExecute();
|
|
return (bool[])(eventLevTrigSeen.Value);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new ApplicationException("encountered problem getting \"level trigger seen\" condition from hardware for event " + eventNum.ToString(), ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get number of samples that the associated hardware adjusted its level trigger time value from the time it
|
|
/// actually issued a trigger fault. This adjustment is necessary because several contiguous level-triggered
|
|
/// samples are necessary before some flavors of DAS will declare an actual level trigger. Once the hardware has
|
|
/// determined that a trigger has occured, it must "backdate" the T0 to match the time of the first
|
|
/// level-triggered sample. This number only exists for hardware that has directly experienced a level trigger
|
|
/// condition.
|
|
/// </summary>
|
|
///
|
|
/// <param name="eventNum">
|
|
/// The <see cref="int"/> number of the event we want the adjustment samples for.
|
|
/// </param>
|
|
///
|
|
/// <returns>
|
|
/// The number of samples that this DAS' trigger time value has been adjusted to compensate for time required
|
|
/// by the hardware for level trigger evaluation. If the associated hardware did not directly experience the
|
|
/// level trigger, this value will be null.
|
|
/// </returns>
|
|
///
|
|
public int?[] GetEventLevelTriggerT0AdjustmentSamples(int eventNum)
|
|
{
|
|
try
|
|
{
|
|
var eventLevTrigT0AdjSamp = new QueryEventAttribute(com);
|
|
eventLevTrigT0AdjSamp.EventNumber = (ushort)eventNum;
|
|
eventLevTrigT0AdjSamp.Key = AttributeTypes.ArmAndEventAttributes.LevelTriggerT0AdjustmentSamples;
|
|
eventLevTrigT0AdjSamp.SyncExecute();
|
|
var levelTriggerAdjSamples = (int[])(eventLevTrigT0AdjSamp.Value);
|
|
|
|
var levelTriggerSeen = GetLevelTriggerSeen(eventNum);
|
|
|
|
var finalAdjustment = new int?[levelTriggerAdjSamples.Length];
|
|
|
|
for (var channel = 0; channel < finalAdjustment.Length; channel++)
|
|
{
|
|
finalAdjustment[channel] = (channel < levelTriggerSeen.Length && levelTriggerSeen[channel]) ? levelTriggerAdjSamples[channel] : (int?)null;
|
|
}
|
|
|
|
return finalAdjustment;
|
|
}
|
|
|
|
catch (Exception)
|
|
{
|
|
// CGO
|
|
// This is a hacked change for now to support 00G8 and prior firmware
|
|
// in the 1.04 release of SLICEWare. This and the other CGO commented
|
|
// block of code need more general cleanup before 1.05.
|
|
return null;
|
|
//throw new ApplicationException( "encountered problem getting event level trigger T0 adjustment samples from hardware for event " + eventNum.ToString( ), ex );
|
|
}
|
|
}
|
|
|
|
public bool[] GetEventLevelTriggerSeen(int eventNum)
|
|
{
|
|
try
|
|
{
|
|
var levelTriggerSeen = GetLevelTriggerSeen(eventNum);
|
|
return levelTriggerSeen;
|
|
}
|
|
|
|
catch (Exception)
|
|
{
|
|
return new bool[0];
|
|
}
|
|
}
|
|
public bool EventHasBeenDownloaded(int eventNum, out uint flag)
|
|
{
|
|
try
|
|
{
|
|
var eventDLFlag = new QueryEventAttribute(com);
|
|
eventDLFlag.EventNumber = (ushort)eventNum;
|
|
eventDLFlag.Key = AttributeTypes.ArmAndEventAttributes.EventHasBeenDownloaded;
|
|
eventDLFlag.SyncExecute();
|
|
flag = (uint)eventDLFlag.Value;
|
|
|
|
try
|
|
{
|
|
var eventTitle = new QueryEventAttribute(com);
|
|
eventTitle.EventNumber = (ushort)eventNum;
|
|
eventTitle.Key = AttributeTypes.ArmAndEventAttributes.Description;
|
|
eventTitle.SyncExecute();
|
|
|
|
if (null == eventTitle.Value)
|
|
{
|
|
return true;
|
|
}
|
|
var desc = Encoding.ASCII.GetString(eventTitle.Value as byte[]);
|
|
if (desc.Contains("TESTTRIG")) { flag = 1; }//just always mark testtrig data as already downloaded
|
|
}
|
|
catch (Exception) { }
|
|
|
|
return 0 != flag;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
flag = 0;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public void SetEventDownloaded(int eventNum, uint flag)
|
|
{
|
|
var eventDLFlag = new SetEventAttribute(com);
|
|
eventDLFlag.EventNumber = (ushort)eventNum;
|
|
eventDLFlag.SetValue(AttributeTypes.ArmAndEventAttributes.EventHasBeenDownloaded, flag, true);
|
|
eventDLFlag.SyncExecute();
|
|
}
|
|
|
|
public string GetEventID(int eventNum, IDASCommunication das)
|
|
{
|
|
try
|
|
{
|
|
var s = RetrieveEventXMLConfig(eventNum, null, das);
|
|
var cd = ConfigurationData.DeserializeFromString(s);
|
|
return cd?.TestID;
|
|
}
|
|
catch (Exception) { }
|
|
|
|
var eventName = new QueryEventAttribute(com);
|
|
eventName.EventNumber = (ushort)eventNum;
|
|
eventName.Key = AttributeTypes.ArmAndEventAttributes.Name;
|
|
eventName.SyncExecute();
|
|
var values = eventName.Value as byte[];
|
|
if (null == values)
|
|
{
|
|
return eventName.Value as string;
|
|
}
|
|
else
|
|
{
|
|
var value = Encoding.UTF8.GetString(values);
|
|
return value;
|
|
}
|
|
}
|
|
|
|
public ushort GetEventFaultFlagsEx(int eventNum)
|
|
{
|
|
//currently not implemented by firmware
|
|
return 0;
|
|
}
|
|
public ushort GetEventFaultFlags(int eventNum)
|
|
{
|
|
if (com.IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.EventFaultFlags))
|
|
{
|
|
var eventFaultFlags = new QueryEventAttribute(com, QueryEventAttribute.Default_IO_Timeout);
|
|
eventFaultFlags.EventNumber = (ushort)eventNum;
|
|
eventFaultFlags.Key = AttributeTypes.ArmAndEventAttributes.FaultFlags;
|
|
eventFaultFlags.SyncExecute();
|
|
return (ushort)eventFaultFlags.Value;
|
|
}
|
|
else { return 0; }
|
|
}
|
|
public byte GetEventArmAttempts(int eventNum)
|
|
{
|
|
if (com.IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.EventArmAttempts))
|
|
{
|
|
var eventArmAttempts = new QueryEventAttribute(com, QueryEventAttribute.Default_IO_Timeout);
|
|
eventArmAttempts.EventNumber = (ushort)eventNum;
|
|
eventArmAttempts.Key = AttributeTypes.ArmAndEventAttributes.EventArmAttempts;
|
|
eventArmAttempts.SyncExecute();
|
|
return (byte)eventArmAttempts.Value;
|
|
}
|
|
else { return 0; }
|
|
}
|
|
|
|
public string GetEventDescription(int eventNum)
|
|
{
|
|
var eventDescr = new QueryEventAttribute(com);
|
|
eventDescr.EventNumber = (ushort)eventNum;
|
|
eventDescr.Key = AttributeTypes.ArmAndEventAttributes.Description;
|
|
eventDescr.SyncExecute();
|
|
if (!(eventDescr.Value is byte[] values) || values.Length == 0)
|
|
{
|
|
return eventDescr.Value as string;
|
|
}
|
|
|
|
var value = Encoding.UTF8.GetString(values);
|
|
return value;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|
|
}
|