diff --git a/TBF/Rig/TestMethods/iPerlCommunication/common/OptoTelegramRaw.cs b/TBF/Rig/TestMethods/iPerlCommunication/common/OptoTelegramRaw.cs index 119931a71..debde9c6b 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/common/OptoTelegramRaw.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/common/OptoTelegramRaw.cs @@ -40,11 +40,11 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.common public Int32 EmfRaw; /// Signed EMF from iPerl opto data public Int16 MagneticFieldRaw; public Int16 FlowRaw; - public UInt32 VolumeRaw; - public Int64 VolumeRawExt; + public double VolumeRaw; + public double VolumeRawExt; public Int16 Impedance; - public UInt32 Timestamp; - public Int64 TimestampExt; + public double Timestamp; + public double TimestampExt; public byte CheckSum; /// @@ -106,146 +106,148 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.common /// /// A complete byte array data /// true = telegram OK, false = telegram NOK - public bool UpdateFromString(string telegram, int counter, float refFlow, ref Int64 volumeRawExtLast, ref Int64 timestampExtLast, bool isLog = false) - { - DateTime = DateTime.Now; - Counter = counter; - RefFlow = refFlow; + // public bool UpdateFromString(string telegram, int counter, float refFlow, ref Int64 volumeRawExtLast, ref Int64 timestampExtLast, bool isLog = false) + // { + // DateTime = DateTime.Now; + // Counter = counter; + // RefFlow = refFlow; + // + // if ((telegram == null) || (telegram.Length < Length) || + // (telegram[6] != '\t') || (telegram[11] != '\t') || (telegram[16] != '\t') || + // (telegram[23] != '\t') || (telegram[28] != '\t') || (telegram[37] != '\t') || + // (!isLog && (telegram[40] != '\r' || telegram[41] != '\n'))) + // { + // Flags = OptoTelegramFlags.InvalidTelegram; + // return false; + // } + // + // UInt32 uEmfRaw; + // bool f1 = UInt32.TryParse(telegram.Substring(0, 6), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out uEmfRaw); + // EmfRaw = (uEmfRaw > 0x7FFFFF) ? ((int)uEmfRaw - 0x1000000) : (int)uEmfRaw; + // + // bool f2 = Int16.TryParse(telegram.Substring(7, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out MagneticFieldRaw); + // bool f3 = Int16.TryParse(telegram.Substring(12, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out FlowRaw); + // bool f4 = UInt32.TryParse(telegram.Substring(17, 6), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out VolumeRaw); + // bool f5 = Int16.TryParse(telegram.Substring(24, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out Impedance); + // bool f6 = UInt32.TryParse(telegram.Substring(29, 8), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out Timestamp); + // bool f7 = byte.TryParse(telegram.Substring(38, 2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out CheckSum); + // + // byte calculatedCheckSum = 0; + // for (int i = 0; i < Length - 4; i++) + // { + // calculatedCheckSum += (byte)telegram[i]; + // } + // + // bool allOk = f1 && f2 && f3 && f4 && f5 && f6 && f7 && (calculatedCheckSum == CheckSum); + // + // if (allOk) + // { + // /// + // /// Cope with 'VolumeRaw' overflow + // /// + // Int64 uncorrected = (Int64)(((UInt64)volumeRawExtLast & 0xFFFFFFFFFF000000UL) | VolumeRaw); + // if (Math.Abs(uncorrected - volumeRawExtLast) <= 0x800000L) + // { + // VolumeRawExt = volumeRawExtLast = uncorrected; + // } + // else if (Math.Abs(uncorrected + 0x1000000L - volumeRawExtLast) <= 0x800000L) + // { + // VolumeRawExt = volumeRawExtLast = uncorrected + 0x1000000L; + // } + // else if (Math.Abs(uncorrected - 0x1000000L - volumeRawExtLast) <= 0x800000L) + // { + // VolumeRawExt = volumeRawExtLast = uncorrected - 0x1000000L; + // } + // else + // { + // VolumeRawExt = volumeRawExtLast = uncorrected; + // } + // + // /// + // /// Cope with 'Timestamp' overflow + // /// + // uncorrected = (Int64)(((UInt64)timestampExtLast & 0xFFFFFFFF00000000UL) | Timestamp); + // if (Math.Abs(uncorrected - timestampExtLast) <= 0x80000000L) + // { + // TimestampExt = timestampExtLast = uncorrected; + // } + // else if (Math.Abs(uncorrected + 0x100000000L - timestampExtLast) <= 0x80000000L) + // { + // TimestampExt = timestampExtLast = uncorrected + 0x100000000L; + // } + // else if (Math.Abs(uncorrected - 0x100000000L - timestampExtLast) <= 0x80000000L) + // { + // TimestampExt = timestampExtLast = uncorrected - 0x100000000L; + // } + // else + // { + // TimestampExt = timestampExtLast = uncorrected; + // } + // } + // + // Flags = allOk ? OptoTelegramFlags.OK : OptoTelegramFlags.InvalidTelegram; + // + // return allOk; + // } - if ((telegram == null) || (telegram.Length < Length) || - (telegram[6] != '\t') || (telegram[11] != '\t') || (telegram[16] != '\t') || - (telegram[23] != '\t') || (telegram[28] != '\t') || (telegram[37] != '\t') || - (!isLog && (telegram[40] != '\r' || telegram[41] != '\n'))) - { - Flags = OptoTelegramFlags.InvalidTelegram; - return false; - } + // -------- TIMESTAMP (seconds) -------- + const double TS_TICKS_PER_SEC = 4096.0; + const double TS_RANGE = (1UL << 32) / TS_TICKS_PER_SEC; + //const double TS_HALF = TS_RANGE / 2.0; - UInt32 uEmfRaw; - bool f1 = UInt32.TryParse(telegram.Substring(0, 6), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out uEmfRaw); - EmfRaw = (uEmfRaw > 0x7FFFFF) ? ((int)uEmfRaw - 0x1000000) : (int)uEmfRaw; - - bool f2 = Int16.TryParse(telegram.Substring(7, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out MagneticFieldRaw); - bool f3 = Int16.TryParse(telegram.Substring(12, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out FlowRaw); - bool f4 = UInt32.TryParse(telegram.Substring(17, 6), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out VolumeRaw); - bool f5 = Int16.TryParse(telegram.Substring(24, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out Impedance); - bool f6 = UInt32.TryParse(telegram.Substring(29, 8), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out Timestamp); - bool f7 = byte.TryParse(telegram.Substring(38, 2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out CheckSum); - - byte calculatedCheckSum = 0; - for (int i = 0; i < Length - 4; i++) - { - calculatedCheckSum += (byte)telegram[i]; - } - - bool allOk = f1 && f2 && f3 && f4 && f5 && f6 && f7 && (calculatedCheckSum == CheckSum); - - if (allOk) - { - /// - /// Cope with 'VolumeRaw' overflow - /// - Int64 uncorrected = (Int64)(((UInt64)volumeRawExtLast & 0xFFFFFFFFFF000000UL) | VolumeRaw); - if (Math.Abs(uncorrected - volumeRawExtLast) <= 0x800000L) - { - VolumeRawExt = volumeRawExtLast = uncorrected; - } - else if (Math.Abs(uncorrected + 0x1000000L - volumeRawExtLast) <= 0x800000L) - { - VolumeRawExt = volumeRawExtLast = uncorrected + 0x1000000L; - } - else if (Math.Abs(uncorrected - 0x1000000L - volumeRawExtLast) <= 0x800000L) - { - VolumeRawExt = volumeRawExtLast = uncorrected - 0x1000000L; - } - else - { - VolumeRawExt = volumeRawExtLast = uncorrected; - } - - /// - /// Cope with 'Timestamp' overflow - /// - uncorrected = (Int64)(((UInt64)timestampExtLast & 0xFFFFFFFF00000000UL) | Timestamp); - if (Math.Abs(uncorrected - timestampExtLast) <= 0x80000000L) - { - TimestampExt = timestampExtLast = uncorrected; - } - else if (Math.Abs(uncorrected + 0x100000000L - timestampExtLast) <= 0x80000000L) - { - TimestampExt = timestampExtLast = uncorrected + 0x100000000L; - } - else if (Math.Abs(uncorrected - 0x100000000L - timestampExtLast) <= 0x80000000L) - { - TimestampExt = timestampExtLast = uncorrected - 0x100000000L; - } - else - { - TimestampExt = timestampExtLast = uncorrected; - } - } - - Flags = allOk ? OptoTelegramFlags.OK : OptoTelegramFlags.InvalidTelegram; - - return allOk; - } + // -------- VOLUME (liters) -------- + const double GAL_TO_LITER = 3.785411784; + const double VOL_LITERS_PER_TICK = + (4.0 / 1000.0) / GAL_TO_LITER / 2.0; + const double VOL_RANGE = (1 << 24) * VOL_LITERS_PER_TICK; + //const double VOL_HALF = VOL_RANGE / 2.0; + //New IPERL ASIC - public void UpdateFromSmart(DiagnosticLedState4Data data, int counter, float refFlow, - ref Int64 volumeRawExtLast, ref Int64 timestampExtLast) - { - DateTime = DateTime.Now; - Counter = counter; - RefFlow = refFlow; - - FlowRaw = data.RawFlow; - VolumeRaw = data.RawVolume; - Timestamp = data.AsicTimestamp; - - - /// - /// Cope with 'VolumeRaw' overflow - /// - Int64 uncorrected = (Int64)(((UInt64)volumeRawExtLast & 0xFFFFFFFFFF000000UL) | VolumeRaw); - if (Math.Abs(uncorrected - volumeRawExtLast) <= 0x800000L) - { - VolumeRawExt = volumeRawExtLast = uncorrected; - } - else if (Math.Abs(uncorrected + 0x1000000L - volumeRawExtLast) <= 0x800000L) - { - VolumeRawExt = volumeRawExtLast = uncorrected + 0x1000000L; - } - else if (Math.Abs(uncorrected - 0x1000000L - volumeRawExtLast) <= 0x800000L) - { - VolumeRawExt = volumeRawExtLast = uncorrected - 0x1000000L; - } - else - { - VolumeRawExt = volumeRawExtLast = uncorrected; - } + public void UpdateFromSmart( + DiagnosticLedState4Data data, + int counter, + float refFlow, + ref double volumeRawExtLast, + ref double timestampExtLast) + { + DateTime = DateTime.Now; + Counter = counter; + RefFlow = refFlow; - /// - /// Cope with 'Timestamp' overflow - /// - uncorrected = (Int64)(((UInt64)timestampExtLast & 0xFFFFFFFF00000000UL) | Timestamp); - if (Math.Abs(uncorrected - timestampExtLast) <= 0x80000000L) - { - TimestampExt = timestampExtLast = uncorrected; - } - else if (Math.Abs(uncorrected + 0x100000000L - timestampExtLast) <= 0x80000000L) - { - TimestampExt = timestampExtLast = uncorrected + 0x100000000L; - } - else if (Math.Abs(uncorrected - 0x100000000L - timestampExtLast) <= 0x80000000L) - { - TimestampExt = timestampExtLast = uncorrected - 0x100000000L; - } - else - { - TimestampExt = timestampExtLast = uncorrected; - } - } + FlowRaw = data.RawFlow; + VolumeRaw = data.RawVolume; + Timestamp = data.AsicTimestamp; + // ---------- VOLUME UNWRAP ---------- + double uncorrected = VolumeRaw; + + if (double.IsNaN(volumeRawExtLast)) + { + VolumeRawExt = volumeRawExtLast = uncorrected; + } + else + { + double k = Math.Round((volumeRawExtLast - uncorrected) / VOL_RANGE); + VolumeRawExt = volumeRawExtLast = uncorrected + k * VOL_RANGE; + } + + // ---------- TIMESTAMP UNWRAP ---------- + uncorrected = Timestamp; + + if (double.IsNaN(timestampExtLast)) + { + TimestampExt = timestampExtLast = uncorrected; + } + else + { + double k = Math.Round((timestampExtLast - uncorrected) / TS_RANGE); + TimestampExt = timestampExtLast = uncorrected + k * TS_RANGE; + } + } + + + /// /// Alternative to UpdateFromString(...) when data are flushed /// diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedData.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedData.cs index 1ca1709db..edc2c561e 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedData.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedData.cs @@ -39,7 +39,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed. /// public abstract class DiagnosticLedData { - + const double GalToLiterConversion = 3.785411784D; public abstract int GetByteCount(); /// @@ -66,10 +66,35 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed. public short RawFlow { get; protected set; } /// - /// Unsigned 24-bit raw volume accumulation in units of ¼ milliliter per bit. + /// Unsigned 24-bit raw volume accumulation in units of ¼ milliliter per bit. it is in Gal * 2 /// - public uint RawVolume { get; protected set; } - + public uint RawVolume1to4 { get; protected set; } // in 1/4 ml Gal * 2 + + /// + /// Raw volume in liters + /// + public double RawVolume // in liter + { + get + { + double volume = (RawVolume1to4 * 0.00025) ; // convert to liters + return volume; + } + } + + /// + /// Raw volume in Gal + /// + public double RawVolumeInGal // in Gal + { + get + { + double volume = (RawVolume1to4 * 4.0) / 1000.0F; // convert to Gal + //volume = (volume / GalToLiterConversion) / 2; // convert to liter + return volume; + } + } + /// /// Unsigned 16-bit millivolt delta measured on the field drive capacitor. /// diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState1Data.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState1Data.cs index 6d9edeee0..651a7637b 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState1Data.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState1Data.cs @@ -33,7 +33,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed. Adc24 = DiagnosticHex.ParseInt24(f[0]); FieldStrength = DiagnosticHex.ParseUInt16(f[1]); RawFlow = DiagnosticHex.ParseInt16(f[2]); - RawVolume = DiagnosticHex.ParseUInt24(f[3]); + RawVolume1to4 = DiagnosticHex.ParseUInt24(f[3]); CapacitorMv = DiagnosticHex.ParseUInt16(f[4]); } diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState2Data.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState2Data.cs index cda442695..f5364d6ae 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState2Data.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState2Data.cs @@ -59,7 +59,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed. Adc24 = DiagnosticHex.ParseInt24(fields[0]); FieldStrength = DiagnosticHex.ParseUInt16(fields[1]); RawFlow = DiagnosticHex.ParseInt16(fields[2]); - RawVolume = DiagnosticHex.ParseUInt24(fields[3]); + RawVolume1to4 = DiagnosticHex.ParseUInt24(fields[3]); CapacitorMv = DiagnosticHex.ParseUInt16(fields[4]); // ---- State #2 specific ---- diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState3Data.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState3Data.cs index 09a9f22bf..fb000f1dd 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState3Data.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState3Data.cs @@ -59,7 +59,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed. Adc24 = DiagnosticHex.ParseInt24(fields[0]); FieldStrength = DiagnosticHex.ParseUInt16(fields[1]); RawFlow = DiagnosticHex.ParseInt16(fields[2]); - RawVolume = DiagnosticHex.ParseUInt24(fields[3]); + RawVolume1to4 = DiagnosticHex.ParseUInt24(fields[3]); CapacitorMv = DiagnosticHex.ParseUInt16(fields[4]); // ---- State #3 specific fields ---- diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState4Data.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState4Data.cs index 76af9df4c..bb0df1c27 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState4Data.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState4Data.cs @@ -13,7 +13,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed. /// 0 – xxxxxxsigned 24-bit ADC value /// 1 – aaaaunsigned 16-bit Field strength /// 2 – yyyysigned 16-bit Raw flow rate (1/4 ml per bit) - /// 3 – vvvvvvunsigned 24-bit Raw volume accumulation + /// 3 – vvvvvvunsigned 24 bit raw volume accumulation in ¼ ml per bit /// 4 – ccccunsigned 16-bit Capacitor mV delta /// 5 – ttttunsigned 16-bit Field calibration /// 6 – bbbbbbbbunsigned 32-bit ASIC timestamp @@ -30,7 +30,19 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed. public sealed class DiagnosticLedState4Data : DiagnosticLedData { public ushort FieldCalibration { get; } - public uint AsicTimestamp { get; } + + /// + /// ASIC timestamp in seconds + /// + public double AsicTimestamp + { + get { return AsicTimestampTicks / 8192; } //4096.0; } + } + + /// + /// ASIC timestamp in units of 1 / 4096 seconds. + /// + public uint AsicTimestampTicks { get; } public byte FieldDriveTimeUs { get; } public int MeanFlowRate { get; } @@ -50,12 +62,13 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed. Adc24 = DiagnosticHex.ParseInt24(fields[0]); FieldStrength = DiagnosticHex.ParseUInt16(fields[1]); RawFlow = DiagnosticHex.ParseInt16(fields[2]); - RawVolume = DiagnosticHex.ParseUInt24(fields[3]); + RawVolume1to4 = DiagnosticHex.ParseUInt24(fields[3]); //1/4 ml Gal double CapacitorMv = DiagnosticHex.ParseUInt16(fields[4]); // ---- State #4 specific ---- FieldCalibration = DiagnosticHex.ParseUInt16(fields[5]); - AsicTimestamp = DiagnosticHex.ParseUInt32(fields[6]); + + AsicTimestampTicks = DiagnosticHex.ParseUInt32(fields[6]); FieldDriveTimeUs = DiagnosticHex.ParseByte(fields[7]); MeanFlowRate = unchecked((int)DiagnosticHex.ParseUInt32(fields[8])); @@ -71,7 +84,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed. public override string ToString() { - return $"DiagnosticLedState4Data: Adc24={Adc24}, FieldStrength={FieldStrength}, RawFlow={RawFlow}, RawVolume={RawVolume}, CapacitorMv={CapacitorMv}, FieldCalibration={FieldCalibration}, AsicTimestamp={AsicTimestamp}, FieldDriveTimeUs={FieldDriveTimeUs}, MeanFlowRate={MeanFlowRate}, Field1Measurement={Field1Measurement}, Field2Measurement={Field2Measurement}, IntegratorCalibrationPositive={IntegratorCalibrationPositive}, IntegratorCalibrationNegative={IntegratorCalibrationNegative}, AsicState={AsicState}"; + return $"DiagnosticLedState4Data: Adc24={Adc24}, FieldStrength={FieldStrength}, RawFlow={RawFlow}, RawVolume={RawVolume}, RawVolume1to4 = {RawVolume1to4}, RawVolumeGal={RawVolumeInGal}, CapacitorMv={CapacitorMv}, FieldCalibration={FieldCalibration}, AsicTimestamp={AsicTimestamp}, FieldDriveTimeUs={FieldDriveTimeUs}, MeanFlowRate={MeanFlowRate}, Field1Measurement={Field1Measurement}, Field2Measurement={Field2Measurement}, IntegratorCalibrationPositive={IntegratorCalibrationPositive}, IntegratorCalibrationNegative={IntegratorCalibrationNegative}, AsicState={AsicState}, RawLine={RawLine}"; } /// diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState5Data.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState5Data.cs index c541fa74a..a18b926d3 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState5Data.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState5Data.cs @@ -69,7 +69,7 @@ public sealed class DiagnosticLedState5Data : DiagnosticLedData Adc24 = DiagnosticHex.ParseInt24(fields[0]); FieldStrength = DiagnosticHex.ParseUInt16(fields[1]); RawFlow = DiagnosticHex.ParseInt16(fields[2]); - RawVolume = DiagnosticHex.ParseUInt24(fields[3]); + RawVolume1to4 = DiagnosticHex.ParseUInt24(fields[3]); CapacitorMv = DiagnosticHex.ParseUInt16(fields[4]); // ---- State #5 specific ---- diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState6Data.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState6Data.cs index d74df8ed8..5303a3417 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState6Data.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState6Data.cs @@ -69,7 +69,7 @@ public sealed class DiagnosticLedState6Data : DiagnosticLedData Adc24 = DiagnosticHex.ParseInt24(fields[0]); FieldStrength = DiagnosticHex.ParseUInt16(fields[1]); RawFlow = DiagnosticHex.ParseInt16(fields[2]); - RawVolume = DiagnosticHex.ParseUInt24(fields[3]); + RawVolume1to4 = DiagnosticHex.ParseUInt24(fields[3]); CapacitorMv = DiagnosticHex.ParseUInt16(fields[4]); // ---- State #6 specific ---- diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState7Data.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState7Data.cs index 7e203e254..37341581a 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState7Data.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/parserer/DiagnosticLedState7Data.cs @@ -98,7 +98,7 @@ public sealed class DiagnosticLedState7Data : DiagnosticLedData Adc24 = DiagnosticHex.ParseInt24(fields[0]); FieldStrength = DiagnosticHex.ParseUInt16(fields[1]); RawFlow = DiagnosticHex.ParseInt16(fields[2]); - RawVolume = DiagnosticHex.ParseUInt24(fields[3]); + RawVolume1to4 = DiagnosticHex.ParseUInt24(fields[3]); CapacitorMv = DiagnosticHex.ParseUInt16(fields[4]); // ---- State #6 fields ---- diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/utils/DiagnostigLedDataByUnit.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/utils/DiagnostigLedDataByUnit.cs new file mode 100644 index 000000000..960594c52 --- /dev/null +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/diagnosticLed/utils/DiagnostigLedDataByUnit.cs @@ -0,0 +1,49 @@ +using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed.parserer; +using TBF.Rig.TestMethods.iPerlCommunication.iPerlHead; + +namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed.utils +{ + public class DiagnostigLedDataByUnit + { + private readonly Common.Unit _unitFlow; + private readonly Common.Unit _unitVolume; + private readonly DiagnosticLedState4Data _data; + + public DiagnostigLedDataByUnit(Common.Unit unitFlow, Common.Unit unitVolume, DiagnosticLedState4Data data) + { + this._unitFlow = unitFlow; + this._unitVolume = unitVolume; + this._data = data; + } + + public Common.Unit Unit => _unitVolume; + public DiagnosticLedState4Data Data => _data; + + public double RawFlow { + get { return UnitVolume(_unitFlow, _data.RawFlow); } + } + + public double RawVolume + { + get { return Common.Units.ConvertFrom(_unitVolume, _data.RawVolume); } + } + + public double AsicTimestamp + { + get { return _data.AsicTimestamp; } + } + + public static double UnitVolume(Common.Unit unit, double volume) + { + return Common.Units.ConvertFrom(unit, volume); /// 1 liter + } + + public static uint DeltaTicks(uint oldTicks, uint newTicks) + { + return newTicks >= oldTicks + ? newTicks - oldTicks + : uint.MaxValue - oldTicks + newTicks + 1; + } + + } +} \ No newline at end of file diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/hexLogger/HexFormatter.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/hexLogger/HexFormatter.cs index 8a9121671..e87448abe 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/hexLogger/HexFormatter.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/C4/hexLogger/HexFormatter.cs @@ -8,6 +8,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.hexLogger public static class HexFormatter { /// + /// Byte to hex string. /// Formats a single byte as 0xNN. /// Example: 0x0D /// @@ -17,7 +18,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.hexLogger } /// - /// int to byte securely + /// int to byte - securely /// /// /// diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/OpthoHeadService.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/OpthoHeadService.cs index 55859155f..08372dd45 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/communication/OpthoHeadService.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/OpthoHeadService.cs @@ -4,7 +4,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication { public class OpthoHeadService { - protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData"); + } } \ No newline at end of file diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/OptoHeadTest.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/OptoHeadTest.cs index ae462c04d..aa315e93d 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/communication/OptoHeadTest.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/OptoHeadTest.cs @@ -10,9 +10,11 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication { public class OptoHeadTest : IDisposable { - protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData"); + //protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData"); + private static readonly ILog log = LogManager.GetLogger(typeof(OptoHeadTest)); - private static SerialDriver serialDriver; + private IperlHead iperlHead; + private SerialDriver serialDriver; public static SerialDriver BuildConnection(IperlHead iHead) { @@ -27,29 +29,36 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication } + public OptoHeadTest(IperlHead iperlHead) + { + this.iperlHead = iperlHead; + } + private void CloseConnection() { if (serialDriver != null) serialDriver.CloseConnection(); + serialDriver = null; } - public static string ReadRequest_PCB(ref IperlHead iHead) + public string ReadRequest_PCB() { - if (iHead.DebugLevel == DebugMode.Simulate) + if (iperlHead.DebugLevel == DebugMode.Simulate) { return "-OK Simulated response-"; } try { - if (iHead != null) + if (iperlHead != null) { if (serialDriver == null) - serialDriver = BuildConnection(iHead); + serialDriver = BuildConnection(iperlHead); RadioService headService = new RadioService(serialDriver); - string serialNo = headService.ReadRequest_PCB(ref iHead); + string serialNo = headService.ReadRequest_PCB(ref iperlHead); + log.Info($"PCB Number: {serialNo} on COM{iperlHead.RfidComPortNr} serialDriver: {serialDriver}"); return serialNo; } } @@ -66,12 +75,13 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication /// /// /// - public static bool SetTestMode(ref IperlHead iHead) + public bool SetTestMode() { - bool activityModeActive = SetActivityMode_Active(iHead); - bool optActiveMode = SetOptTestMode(ref iHead); - + log.Debug("SetTestMode called for iHead: " + iperlHead.ToString()); + bool activityModeActive = SetActivityMode_Active(); + bool optActiveMode = SetOptTestMode(); + log.Debug("SetTestMode result: optoMod-> " + optActiveMode + " meterModeActive ->" + activityModeActive); return (optActiveMode && activityModeActive); } @@ -80,10 +90,11 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication /// /// /// - public static bool SetActiveMode(ref IperlHead iHead) + public bool SetActiveMode() { - bool optActiveMode = SetOptActiveMode(iHead); - bool activityModeIdle = SetActivityMode_Idle(iHead); + log.Debug("SetActiveMode called for iHead: " + iperlHead.ToString()); + bool optActiveMode = SetOptActiveMode(iperlHead); + bool activityModeIdle = SetActivityMode_Idle(); return (optActiveMode && activityModeIdle); } @@ -94,9 +105,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication /// /// /// - public static string SetTestMode(ref IperlHead iHead, ref bool isTestModeSuccessful) + public string SetTestMode(ref bool isTestModeSuccessful) { - if (iHead.DebugLevel == DebugMode.Simulate) + if (iperlHead.DebugLevel == DebugMode.Simulate) { isTestModeSuccessful = true; return "-OK Simulated response-"; @@ -104,10 +115,12 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication try { - isTestModeSuccessful = SetTestMode(ref iHead); - return isTestModeSuccessful ? "Set Test Mode - OK" : "Set Test Mode - FAILED"; + bool testMode = SetTestMode(); + isTestModeSuccessful = testMode; + return testMode ? "Set Test Mode - OK" : "Set Test Mode - FAILED"; }catch (Exception ex) { + log.Error("SetTestMode() - Exception:" + ex.StackTrace); return "Set Test Mode - Exception"; } } @@ -120,18 +133,19 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication /// /// /// - private static bool SetOptTestMode(ref IperlHead iHead) + private bool SetOptTestMode() { try { - if (iHead != null) + if (iperlHead != null) { if (serialDriver == null) - serialDriver = BuildConnection(iHead); + serialDriver = BuildConnection(iperlHead); RadioService headService = new RadioService(serialDriver); - var optTestMode = headService.SetOptTestMode(iHead); - iHead.ConfigStruct.OpthoStatusMode = optTestMode ? DiagnosticLedState.State4 : DiagnosticLedState.StatusUnknown; + bool optTestMode = headService.SetOptTestMode(iperlHead); + if (iperlHead.ConfigStruct != null) + iperlHead.ConfigStruct.OpthoStatusMode = optTestMode ? DiagnosticLedState.State4 : DiagnosticLedState.StatusUnknown; return optTestMode; } } @@ -148,9 +162,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication /// /// /// - public static string SetActiveMode(ref IperlHead iHead, ref bool isTestModeSuccessful) + public string SetActiveMode(ref bool isTestModeSuccessful) { - if (iHead.DebugLevel == DebugMode.Simulate) + if (iperlHead.DebugLevel == DebugMode.Simulate) { isTestModeSuccessful = true; return "-OK Simulated response-"; @@ -158,8 +172,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication try { - isTestModeSuccessful = SetActiveMode(ref iHead); - return isTestModeSuccessful ? "Set Active Mode - OK" : "Set Active Mode - FAILED"; + bool activeMode = SetActiveMode(); + isTestModeSuccessful = activeMode; + return activeMode ? "Set Active Mode - OK" : "Set Active Mode - FAILED"; } catch (Exception ex) { @@ -172,7 +187,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication /// /// /// - private static bool SetOptActiveMode(IperlHead iHead) + private bool SetOptActiveMode(IperlHead iHead) { try { @@ -180,7 +195,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication { if (serialDriver == null) serialDriver = BuildConnection(iHead); - + RadioService headService = new RadioService(serialDriver); return headService.SetOptActiveMode(iHead); } @@ -199,17 +214,18 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication /// /// /// - private static bool SetActivityMode_Active(IperlHead iHead) + private bool SetActivityMode_Active() { try { - if (iHead != null) + if (iperlHead != null) { if (serialDriver == null) - serialDriver = BuildConnection(iHead); + serialDriver = BuildConnection(iperlHead); + log.Debug("SetActivityMode_Active called for iHead: " + iperlHead.ToString() + " serialDriver: " + serialDriver); RadioService headService = new RadioService(serialDriver); - return headService.SetActivityMode_Active(iHead); + return headService.SetActivityMode_Active(iperlHead); } } catch (Exception ex) @@ -226,17 +242,19 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication /// /// /// - private static bool SetActivityMode_Idle(IperlHead iHead) + private bool SetActivityMode_Idle() { try { - if (iHead != null) + if (iperlHead != null) { if (serialDriver == null) - serialDriver = BuildConnection(iHead); + serialDriver = BuildConnection(iperlHead); + + log.Debug("SetActivityMode_Idle called for iHead: " + iperlHead.ToString() + " serialDriver: " + serialDriver); RadioService headService = new RadioService(serialDriver); - return headService.SetActivityMode_Idle(iHead); + return headService.SetActivityMode_Idle(iperlHead); } } catch (Exception ex) @@ -260,9 +278,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication /// /// /// - public static bool ReadConfiguration(ref IperlHead iHead, DiagnosticLedState ledState ) + public bool ReadConfiguration(DiagnosticLedState ledState ) { - if (iHead.DebugLevel == DebugMode.Simulate) + if (iperlHead.DebugLevel == DebugMode.Simulate) { return true; } @@ -270,26 +288,28 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication try { - if (iHead != null) + if (iperlHead != null) { - iHead.ConfigStruct = new ConfigStruct(); + iperlHead.ConfigStruct = new ConfigStruct(); if (serialDriver == null) - serialDriver = BuildConnection(iHead); + serialDriver = BuildConnection(iperlHead); RadioService headService = new RadioService(serialDriver); - iHead.ConfigStruct.PCBNumberString = headService.ReadRequest_PCB(ref iHead); - iHead.ConfigStruct.StatusMode = headService.GetActivityStatusMode(iHead); + iperlHead.ConfigStruct.PCBNumberString = headService.ReadRequest_PCB(ref iperlHead); + iperlHead.ConfigStruct.StatusMode = headService.GetActivityStatusMode(iperlHead); + iperlHead.ConfigStruct.Unit = headService.GetUnit(iperlHead); + if (ledState != DiagnosticLedState.StatusUnknown) // do set { - iHead.ConfigStruct.OpthoStatusMode = headService.SetOptoStatusMode(iHead, ledState); + iperlHead.ConfigStruct.OpthoStatusMode = headService.SetOptoStatusMode(iperlHead, ledState); } else { - iHead.ConfigStruct.OpthoStatusMode = DiagnosticLedState.StatusUnknown; + iperlHead.ConfigStruct.OpthoStatusMode = DiagnosticLedState.StatusUnknown; } - iHead.ConfigStruct.Version = headService.GetVersion(iHead); + iperlHead.ConfigStruct.Version = headService.GetVersion(iperlHead); return true; } diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/RadioService.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/RadioService.cs index b1e3affe2..b08b971b8 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/communication/RadioService.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/RadioService.cs @@ -1,3 +1,4 @@ +using log4net; using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed; using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol; using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons; @@ -8,6 +9,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication { public class RadioService { + private static readonly ILog log = LogManager.GetLogger(typeof(RadioService)); static string okResponse = "Command complete, no errors"; static string errorResponse = "Unable to execute"; @@ -16,6 +18,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication public RadioService(SerialDriver serialDriver) { this.serialDriver = serialDriver; + log.Debug("RadioService created with serialDriver= " + serialDriver + ""); } public string ReadRequest_PCB(ref IperlHead iHead) @@ -97,6 +100,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication var parser = new IperlHatFrameParser(); IperlHatResponse decoded = parser.Parse(rawData); + log.Debug("SetOptoStatusMode isOK: " + decoded.IsOk); // if is response ok - it set it correctly if (!decoded.IsOk) return DiagnosticLedState.StatusUnknown; @@ -135,6 +139,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication // parse rawData var parser = new IperlHatFrameParser(); IperlHatResponse decoded = parser.Parse(rawData); + log.Debug("GetVersion isOK: " + decoded.IsOk); if (decoded.IsOk) { return decoded.GetAsciiPayload(); @@ -158,7 +163,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication .AddSubCommand(ProtocolStatuses.Active) // Active .BuildBytes(); - byte[] rawData = serialDriver.SendAndWait(request, 2000); + byte[] rawData = serialDriver.SendAndWait(request, 5000); if (rawData == null) return false; @@ -166,6 +171,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication // parse rawData var parser = new IperlHatFrameParser(); IperlHatResponse decoded = parser.Parse(rawData); + log.Debug("SetActivityMode_Active isOK: " + decoded.IsOk); return decoded.IsOk; } @@ -191,6 +197,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication // parse rawData var parser = new IperlHatFrameParser(); IperlHatResponse decoded = parser.Parse(rawData); + log.Debug("SetActivityMode_Idle isOK: " + decoded.IsOk); return decoded.IsOk; } @@ -202,11 +209,13 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication } //Set LED to state 4 - byte[] request = new IperlHatFrameBuilder() - .AddDiagnosticLedState(DiagnosticLedState.State4) + var request = new IperlHatFrameBuilder() + .RequestResponse(true) + .AddDeviceCommand(ProtocolDeviceSubCommand.SetDiagnosticLEDState) + .AddPayload(DiagnosticLedState.State4) .BuildBytes(); - byte[] rawData = serialDriver.SendAndWait(request, 1000); + byte[] rawData = serialDriver.SendAndWait(request, 5000); if (rawData == null) return false; @@ -214,7 +223,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication // parse rawData var parser = new IperlHatFrameParser(); IperlHatResponse decoded = parser.Parse(rawData); - return decoded.IsOk; + bool isOk = decoded.IsOk; + log.Debug("SetOptTestMode isOK: " + isOk); + return isOk; } @@ -231,11 +242,13 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication } //Set LED to state 1 - byte[] request = new IperlHatFrameBuilder() - .AddDiagnosticLedState(DiagnosticLedState.StateOFF) + var request = new IperlHatFrameBuilder() + .RequestResponse(true) + .AddDeviceCommand(ProtocolDeviceSubCommand.SetDiagnosticLEDState) + .AddPayload(DiagnosticLedState.StateOFF) .BuildBytes(); - byte[] rawData = serialDriver.SendAndWait(request, 2000); + byte[] rawData = serialDriver.SendAndWait(request, 5000); if (rawData == null) return false; @@ -243,7 +256,41 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication // parse rawData var parser = new IperlHatFrameParser(); IperlHatResponse decoded = parser.Parse(rawData); + log.Debug("SetOptActiveMode isOK: " + decoded.IsOk); return decoded.IsOk; } + + public string GetUnit(IperlHead iperlHead) + { + if (!serialDriver.IsOpen()) + { + serialDriver.Open(); + } + + var request = new IperlHatFrameBuilder() + .RequestResponse(true) + .AddCommand(ProtocolCommand.ViewFactoryId) + .BuildBytes(); + + + byte[] rawData = serialDriver.SendAndWait(request, 10000); + if (rawData == null) + return null; + + // parse rawData + var parser = new IperlHatFrameParser(); + IperlHatResponse decoded = parser.Parse(rawData); + if (decoded.IsOk) + { + string asciiPayload = decoded.GetAsciiPayload(); + if (iperlHead.ConfigStruct != null) // store mechanism + { + iperlHead.ConfigStruct.Unit = asciiPayload; + } + return asciiPayload; + } + + return null; + } } } \ No newline at end of file diff --git a/TBF/Rig/TestMethods/iPerlCommunication/communication/Utils/SerialDriver.cs b/TBF/Rig/TestMethods/iPerlCommunication/communication/Utils/SerialDriver.cs index fa29f3ea1..2dbf4b93a 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/communication/Utils/SerialDriver.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/communication/Utils/SerialDriver.cs @@ -4,11 +4,13 @@ using System.Diagnostics; using System.IO.Ports; using System.Threading; using FluentNHibernate.Conventions; +using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.hexLogger; namespace TBF.Rig.TestMethods.iPerlCommunication.communication.Utils { public class SerialDriver : IDisposable { + readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(SerialDriver)); public string ErrorMessage { get; private set; } private List SerialPortReadBuffer = new List(); @@ -110,6 +112,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.Utils ErrorMessage = $"COM error: Can't open {comPort}."; return false; } + + log.Debug("SerialDriver opened successfully for port: " + comPort); } return true; } @@ -172,6 +176,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.Utils _serialPort.DiscardInBuffer(); _binMessages.Clear(); _responseReceived.Reset(); + SerialPortReadBuffer.Clear(); _isReading = true; } @@ -188,7 +193,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.Utils try { - Thread.Sleep(5); + //Thread.Sleep(5); if (!SerialPortReadBuffer.IsEmpty()) { @@ -204,13 +209,13 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.Utils byte readByte = (byte)_serialPort.ReadByte(); //I have START - if (readByte == TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Start) + if (readByte == C4.IperlHatProtocol.IperlHatProtocolConstants.Start) { iWordCounter++; isStart = true; } // I have QUESTION - if (readByte == TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question) + if (readByte == C4.IperlHatProtocol.IperlHatProtocolConstants.Question) { iWordCounter++; isQuestion = true; @@ -231,12 +236,16 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.Utils } //If we have enough bytes - if (isStart && iLength > 0 && SerialPortReadBuffer.Count >= iLength) + if (isStart && iLength > 0 + && (SerialPortReadBuffer.Count >= iLength || + readByte == C4.IperlHatProtocol.IperlHatProtocolConstants.End + ) + ) { break; } //if we read END - if (isQuestion && readByte == TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.End) + if (isQuestion && readByte == C4.IperlHatProtocol.IperlHatProtocolConstants.End) { break; } @@ -264,11 +273,18 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.Utils if (!IsOpen()) throw new InvalidOperationException("Serial port not open"); + log.Debug("SendAndWait() - TX: " + HexFormatter.ToHex(data)); PrepareReading(); _serialPort.Write(data, 0, data.Length); if (!_responseReceived.WaitOne(timeoutMs)) { + log.Error("SendAndWait() - Response timeout! Details: " + + " SerialPortReadBuffer: " + HexFormatter.ToHex(SerialPortReadBuffer.ToArray()) + + " _binMessages" + HexFormatter.ToHex(_binMessages.ToArray()) + + "_responseReceived: " + _responseReceived.WaitOne(0) + ); + ErrorMessage = "COM error: response timeout"; return null; } @@ -283,5 +299,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.Utils { CloseConnection(); } + + public override string ToString() + { + return "SerialDriver: " + _serialPort.PortName + " (opened status:" + _serialPort.IsOpen +")"; + } } } diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs index 4fa754c8e..f032623ed 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs @@ -838,14 +838,27 @@ namespace TBF.Rig.TestMethods.iPerlCommunication /// Read configuration - if (OptoHeadTest.ReadConfiguration(ref ihead, DiagnosticLedState.StatusUnknown)) + if (ihead.OptoHeadTest.ReadConfiguration(DiagnosticLedState.State4)) { error = CommErr.None; - ihead.ConfigStruct = new ConfigStruct(); //.FromByteArray(config); - resultStr = ihead.ConfigStruct.ToString(1); + //read, set and create ConfigStruct is set directly in method ReadConfiguration + //ihead.ConfigStruct = new ConfigStruct(); //.FromByteArray(config); + if (ihead.ConfigStruct != null) + { + resultStr = ihead.ConfigStruct.ToString(1); + } + else + { + resultStr = "Data not available"; + } + } + else + { + resultStr = "Failed to read configuration"; } - return error + Math.Max(0, Math.Min(readRetVal, 4)); + //return error + Math.Max(0, Math.Min(readRetVal, 4)); + return error; } @@ -861,6 +874,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication /// true on success static CommErr SetTestMode(int threadId, IperlHead ihead, ref string resultStr) { + log.Debug("SetTestMode threadId=" + threadId + ", ihead=" + ihead.ToString()); if (ihead.ConfigStruct == null) { log.Debug("ConfigStruct is null - created new in SetTestMode()"); @@ -874,7 +888,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication /// //string testModeConfigStr = multiTestParams[currentActivityStep].Activity.Substring(SetTestModeStr.Length + 1); - if (OptoHeadTest.SetTestMode(ref ihead)) + if (ihead.OptoHeadTest.SetTestMode()) { log.Debug("test mode activated now"); testModeConfig = ihead.ConfigStruct.OpthoStatusMode; @@ -899,7 +913,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication error = CommErr.Verify; //TODO BUMI use read config - if (OptoHeadTest.ReadConfiguration(ref ihead, DiagnosticLedState.State4)) + if (ihead.OptoHeadTest.ReadConfiguration(DiagnosticLedState.State4)) { if ((ihead.ConfigStruct.MeterState == ProtocolStatuses.Active) && (ihead.ConfigStruct.TestModeConfig == testModeConfig)) @@ -924,11 +938,12 @@ namespace TBF.Rig.TestMethods.iPerlCommunication /// true on success static CommErr SetActiveMode(int threadId, IperlHead ihead, ref string resultStr) { + log.Debug("SetActiveMode threadId=" + threadId); CommErr error = CommErr.CmdActive; /// Switch to active mode - if (OptoHeadTest.SetActiveMode(ref ihead)) + if (ihead.OptoHeadTest.SetActiveMode()) { error = CommErr.None; } @@ -2651,7 +2666,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication switch (tag) { case "ReadPCB": - txt = OptoHeadTest.ReadRequest_PCB(ref iHead); + txt = iHead.OptoHeadTest.ReadRequest_PCB(); break; case "WriteRequestPort_u8_Customer_Text": txt = "Not Supported NOW!";//OpticalHeadTest.WriteRequestPort_u8_Customer_Text(iHead); @@ -2660,10 +2675,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication txt = "Not Supported NOW!";//OpticalHeadTest.OpenSealing(iHead); break; case "StartTestMode": - txt = OptoHeadTest.SetTestMode(ref iHead, ref success); + txt = iHead.OptoHeadTest.SetTestMode(ref success); break; case "TurnOffTestMode": - txt = OptoHeadTest.SetActiveMode(ref iHead, ref success); + txt = iHead.OptoHeadTest.SetActiveMode(ref success); break; case "TurnOffRadio": txt = "Not Supported NOW!";//OpticalHeadTest.TurnOffRadio(iHead); diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/ConfigStruct.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/ConfigStruct.cs index 5ae3ad7b9..eb989fccb 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/ConfigStruct.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/ConfigStruct.cs @@ -17,8 +17,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead public string PCBNumberString; // dynamic public ProtocolStatuses StatusMode; // byte public DiagnosticLedState OpthoStatusMode;// byte + public string Unit; //dynamic public string Version; // dynamic - public ConfigStruct() { @@ -80,20 +80,25 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead public override string ToString() { return string.Format( - "Config: V{0} PCB#={1} StatusMode={2}", - Version, + "Config: PCB#={0} StatusMode={1} Unit={2} V{3}", + GetPcbNrString(), - StatusMode + StatusMode, + Unit, + Version ); } public string ToString(int sel) { - return string.Format("{0} PCB#={1} StatusMode={2}", - Version, - GetPcbNrString(), - StatusMode - ); + return string.Format( + "Config: PCB#={0} StatusMode={1} Unit={2} V{3}", + + GetPcbNrString(), + StatusMode, + Unit, + Version + ); } public virtual void WriteBinary(BinaryWriter writer) @@ -115,16 +120,27 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead // 2) write string bytes writer.Write(PCBNumberStringBytes); + // Convert string to bytes (UTF8 is standard) + byte[] unitBytes = Encoding.UTF8.GetBytes(Unit); + // 1) write length + writer.Write(unitBytes.Length); + // 2) write string bytes + writer.Write(unitBytes); + //writer.Write(Version); + } public virtual void ReadBinary(BinaryReader reader) { + int ReadBytesCount = 0; // ---- Test Data type ---- var readByte = reader.ReadByte(); if (readByte != 0x11) return; // not correct version + ReadBytesCount++; // ---- Version ---- // 1) read length int length = reader.ReadInt32(); + ReadBytesCount += 4 + length; // 2) read string bytes byte[] versionBytes = reader.ReadBytes(length); // 3) convert back to string @@ -132,11 +148,19 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead // ---- PCB Number ---- // 1) read length int lengthPCB = reader.ReadInt32(); + ReadBytesCount += 4 + lengthPCB; // 2) read string bytes byte[] bytesPCB = reader.ReadBytes(lengthPCB); // 3) convert back to string PCBNumberString = Encoding.UTF8.GetString(bytesPCB); - + // ---- Unit ---- + // 1) read length + int lengthUnit = reader.ReadInt32(); + ReadBytesCount += 4 + lengthUnit; + // 2) read string bytes + byte[] bytesUnit = reader.ReadBytes(lengthUnit); + // 3) convert back to string + Unit = Encoding.UTF8.GetString(bytesUnit); } } diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/FlowDirectionDetection.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/FlowDirectionDetection.cs index 37745792e..2e23e3f6d 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/FlowDirectionDetection.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/FlowDirectionDetection.cs @@ -11,40 +11,35 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead { private static readonly ILog log = LogManager.GetLogger(typeof(IperlHead)); - const int FIFO_SIZE = 64; /// 8 sec. @ 8Hz - const double MAX_OPTO_DROPOUT = 4.5; /// sec. - + const int FIFO_SIZE = 64; // 8 sec @ 8Hz + const double MAX_OPTO_DROPOUT = 4.5; // sec - Int64[] volumeRawFifo; /// Volume FIFO buffer - Int64[] timestampFifo; /// Timestamp FIFO buffer + private readonly double[] volumeRawFifo; + private readonly double[] timestampFifo; // centered timestamps - int fifoCount; /// Number of valid FIFO items - int fifoIx; /// Index of the next FIFO item - DateTime lastFifoWriteTime; /// Time of the last write to FIFO + private int fifoCount; + private int fifoIx; + private DateTime lastFifoWriteTime; - /// - /// Sums for linear regression calculation - /// - decimal sumXX; - decimal sumX; - decimal sumXY; - decimal sumY; - decimal N; + // regression sums (double is ideal here) + private double sumXX; + private double sumX; + private double sumXY; + private double sumY; - double minSlope; /// max. slope of the regressed line, always positive or 0 - double maxSlope; /// min. slope of the regressed line, always negative or 0 + private double minSlope; + private double maxSlope; + + // timestamp centering for numerical stability + private double firstTimestamp = double.NaN; public FlowDirectionDetection() { - volumeRawFifo = new Int64[FIFO_SIZE]; - timestampFifo = new Int64[FIFO_SIZE]; + volumeRawFifo = new double[FIFO_SIZE]; + timestampFifo = new double[FIFO_SIZE]; ClearFifo(); } - - /// - /// Clear FIFO data - /// public void ClearFifo() { fifoCount = 0; @@ -55,94 +50,93 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead sumX = 0; sumXY = 0; sumY = 0; - N = 0; minSlope = 0; maxSlope = 0; + firstTimestamp = double.NaN; } - /// - /// Write data to FIFO + /// Add sample to rolling FIFO and update regression sums /// - /// Volume - /// Time stamp - public void WriteToFifo(Int64 volumeRaw, Int64 timestamp) + public void WriteToFifo(double volumeRaw, double timestamp) { - /// - /// Update sums for linear regression calculation - /// + // establish time origin (CRITICAL for double precision) + if (double.IsNaN(firstTimestamp)) + firstTimestamp = timestamp; + + double x = timestamp - firstTimestamp; // centered time + double y = volumeRaw; + + // remove oldest sample if buffer full if (fifoCount == FIFO_SIZE) { - /// Buffer is already full, the oldest item will be re-written - sumXX -= timestampFifo[fifoIx] * timestampFifo[fifoIx]; - sumX -= timestampFifo[fifoIx]; - sumXY -= timestampFifo[fifoIx] * volumeRawFifo[fifoIx]; - sumY -= volumeRawFifo[fifoIx]; - N--; - } - sumXX += timestamp * timestamp; - sumX += timestamp; - sumXY += timestamp * volumeRaw; - sumY += volumeRaw; - N++; + double oldX = timestampFifo[fifoIx]; + double oldY = volumeRawFifo[fifoIx]; + + sumXX -= oldX * oldX; + sumX -= oldX; + sumXY -= oldX * oldY; + sumY -= oldY; + } + else + { + fifoCount++; + } + + // add new sample + sumXX += x * x; + sumX += x; + sumXY += x * y; + sumY += y; + + // store sample + timestampFifo[fifoIx] = x; + volumeRawFifo[fifoIx] = y; - /// - /// Save new values to FIFO - /// - volumeRawFifo[fifoIx] = volumeRaw; - timestampFifo[fifoIx] = timestamp; fifoIx = (fifoIx + 1) % FIFO_SIZE; - fifoCount = Math.Min(fifoCount + 1, FIFO_SIZE); lastFifoWriteTime = DateTime.Now; } - - /// - /// Determine whether there are enough recent FIFO data - /// - /// true when data valid public bool AreFifoDataValid() { - return (DateTime.Now.Subtract(lastFifoWriteTime).TotalSeconds <= MAX_OPTO_DROPOUT) && (fifoCount == FIFO_SIZE); + return (DateTime.Now.Subtract(lastFifoWriteTime).TotalSeconds <= MAX_OPTO_DROPOUT) + && (fifoCount == FIFO_SIZE); } - - /// - /// Verify whether the flow direction is correct - /// - /// OptoHeadState.OptoAndDirOK, OptoHeadState.OptoNok or OptoHeadState.DirNok public OptoHeadState CheckFlowDirection(Counting counting, string iPerlHeadName) { - if (!AreFifoDataValid()) return OptoHeadState.OptoNok; + if (!AreFifoDataValid()) + return OptoHeadState.OptoNok; try { - decimal numer = N * sumXY - sumX * sumY; - decimal denom = N * sumXX - sumX * sumX; + double N = fifoCount; - if (denom == 0) return OptoHeadState.DirNok; + double numer = N * sumXY - sumX * sumY; + double denom = N * sumXX - sumX * sumX; + + if (Math.Abs(denom) < 1e-12) + return OptoHeadState.DirNok; + + double slope = numer / denom; - /// Calculate the slope of the regressed line, determine min. and max. - double slope = (double)(numer / denom); if (slope > maxSlope) maxSlope = slope; if (slope < minSlope) minSlope = slope; - if ( counting == Counting.Arbitrary || + if (counting == Counting.Arbitrary || (counting == Counting.Positive && maxSlope > Math.Abs(2 * minSlope)) || (counting == Counting.Negative && minSlope < -Math.Abs(2 * maxSlope))) { return OptoHeadState.OptoAndDirOK; } - else - { - return OptoHeadState.DirNok; - } + + return OptoHeadState.DirNok; } - catch (Exception) + catch (Exception ex) { - log.ErrorFormat("{0} : CheckFlowDirection() failed", iPerlHeadName); - return OptoHeadState.DirNok; /// ??? + log.ErrorFormat("{0} : CheckFlowDirection() failed: {1}", iPerlHeadName, ex); + return OptoHeadState.DirNok; } } } diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs index 5d2fef6ac..fd8547947 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs @@ -13,10 +13,13 @@ using Sensus.iPerl.NfcHandler; using NHibernate; using System.Linq; using System.Text; -using System.Xml.Linq; // This line is correct and does not need to be changed. +using System.Xml.Linq; +using TBF.Rig.TestMethods.iPerlCommunication.communication; // This line is correct and does not need to be changed. using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed; using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed.parserer; +using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed.utils; using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.hexLogger; +using TBF.Rig.TestMethods.iPerlCommunication.communication.Utils; using OptoTelegramFlags = TBF.Rig.TestMethods.iPerlCommunication.common.OptoTelegramFlags; using OptoTelegramRaw = TBF.Rig.TestMethods.iPerlCommunication.common.OptoTelegramRaw; @@ -28,6 +31,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead public class IperlHead : ComponentBase, IDevice,IRegReaderDatastream, ISessionDataMngmnt, IOperation { private static readonly ILog log = LogManager.GetLogger(typeof(IperlHead)); + private static readonly ILog logStream = LogManager.GetLogger("StreamData"); public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); } #if TURA_SPECIAL @@ -41,6 +45,19 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead public const int StartEndFilterSamplesCount2 = 20; /// StartEndFilterSamplesCount = 2 * StartEndFilterSamplesCount2 + 1 public const int FeatureVectorSize = 9; + private OptoHeadTest _optoHeadTest; + + public OptoHeadTest OptoHeadTest + { + get + { + if (_optoHeadTest == null) + _optoHeadTest = new OptoHeadTest(this); + return _optoHeadTest; + } + set { _optoHeadTest = value; } + } + readonly IperlHeadCfg iperlHeadCfg; @@ -103,8 +120,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// /// Passed to OptoTelegramRaw.UpdateFromString(...) /// - Int64 volumeRawExtLast; - Int64 timestampExtLast; + double volumeRawExtLast; + double timestampExtLast; FlowDirectionDetection flowDirectionDetection; @@ -360,7 +377,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// /// Timestamp from the opto telegram /// - private Int64 lastTimestamp; + private double lastTimestamp; private double timestampSec; private double timestampSec0; @@ -383,7 +400,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// /// Volume of water from the opto telegram /// - private Int64 lastVolumeRaw; /// Last read raw volume + private double lastVolumeRaw; /// Last read raw volume private double volumeLtr; private double volumeLtr0; @@ -589,10 +606,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead { ResultCode = 0; - volumeLtr = 0; - volumeLtr0 = 0; - timestampSec = 0; - timestampSec0 = 0; + volumeLtr = Double.NaN; + volumeLtr0 = Double.NaN; + timestampSec = Double.NaN; + timestampSec0 = Double.NaN; extraDataPath = null; @@ -858,6 +875,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead endWMState = volumeLtr; wmVolume = Math.Abs(endWMState - beginWMState); wmPulses = (int)(wmVolume * (double)PulsesPerLtr + 0.5); + log.Debug("wmPulses = " + wmPulses + "wmVolume = " + wmVolume + "PulsesPerLtr = " + PulsesPerLtr + ""); wmRefPulses = StateMachine.ControlBoardMain.RefPulses; wmTestTime = timestampSec - timestampSec0; } @@ -980,8 +998,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead { string line = optoSerialPort.ReadLine(); // string byte[] bytes = optoSerialPort.Encoding.GetBytes(line); - - Console.WriteLine("RX ← " + HexFormatter.ToSerialHex(bytes)); + + log.Debug("ComPort: "+ OptoComPortNr +" OPTHO RX ← " + HexFormatter.ToSerialHex(bytes)); try { @@ -989,6 +1007,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead if (optoState == DataStreamState.ProcessAndSave) { DiagnosticLedState4Data data = (DiagnosticLedState4Data)parser.ParseLine(line, false); + //DiagnostigLedDataByUnit unitData = new DiagnostigLedDataByUnit(Common.Unit.m3, Common.Unit.m3, data); int bufferIx = BufferIdx(optoDataCount); if (synchronized) @@ -999,11 +1018,17 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead if (data != null) { - + //TODO BUMI UNITS + // apply units + log.Debug($"OPTHO {OptoComPortNr} Parsed optho data:" + data.ToString()); + logStream.Debug($"ID: {OptoComPortNr} " + data.ToString()); + optoData[bufferIx].UpdateFromSmart(data, optoDataCount, Convert.ToSingle(Sequences.ProcessData.RefFlow.Val), ref volumeRawExtLast, ref timestampExtLast); + log.Debug("OPTHO UpdateFromSmart() volumeRawExtLast:" + volumeRawExtLast + " timestampExtLast:" + timestampExtLast); + /// CR+LF was found && (pos >= OptoTelegramRaw.Length - 2) && the telegram is OK flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast); OptoTelegramReceived(optoDataCount, true, volumeRawExtLast, @@ -1056,31 +1081,31 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead } - void OptoTelegramReceived(int currentIx, bool async, Int64 volumeRawExt, Int64 timestampRawExt) + void OptoTelegramReceived(int currentIx, bool async, double volumeRawExt, double timestampRawExt) { currentTelegramIx = currentIx; lastVolumeRaw = volumeRawExt; lastTimestamp = timestampRawExt; - if (volumeLtr == 0 && volumeLtr0 == 0) + if (Double.IsNaN(volumeLtr) && Double.IsNaN(volumeLtr0)) { - volumeLtr = (double)lastVolumeRaw * ScalingFactor() / 16000.0; + volumeLtr = lastVolumeRaw; volumeLtr0 = volumeLtr; } else { - volumeLtr = (double)lastVolumeRaw * ScalingFactor() / 16000.0; + volumeLtr = lastVolumeRaw; } - if (timestampSec == 0 && timestampSec0 == 0) + if (Double.IsNaN(timestampSec)&& Double.IsNaN(timestampSec0)) { - timestampSec = (double)lastTimestamp / 8192.0; + timestampSec = lastTimestamp; timestampSec0 = timestampSec; } else { - timestampSec = (double)lastTimestamp / 8192.0; + timestampSec = lastTimestamp; } } @@ -1185,25 +1210,50 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// Filtered volume double VolumeFromSamples(OptoTelegramRaw[] optoData, int optoDataCount, int unwrappedIx, double scalingFactor, int samplesCount2 = 0) { - if (samplesCount2 < 0) samplesCount2 = 0; - if ((unwrappedIx - samplesCount2) < 0 || (unwrappedIx + samplesCount2) >= optoDataCount) return 0; - - Int64 sum = 0; - for (int i = unwrappedIx - samplesCount2; i <= unwrappedIx + samplesCount2; i++) + log.Debug("-- Get VolumeFromSamples() --"); + if (unwrappedIx >= optoDataCount) { - int wrappedIx = BufferIdx(i); - - if (optoData[wrappedIx].Flags != OptoTelegramFlags.OK && - optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestStart && - optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestEnd) - { - return 0; - } - - sum += optoData[wrappedIx].VolumeRawExt; + log.Debug( + $"-- FAILED VolumeFromSamples() - unwrappedIx {unwrappedIx} >= optoDataCount{optoDataCount}--"); + return 0; } + + int wrappedIx = BufferIdx(unwrappedIx); - return 0.0000625 * scalingFactor * sum / (double)(2 * samplesCount2 + 1); + if (optoData[wrappedIx].Flags != OptoTelegramFlags.OK && + optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestStart && + optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestEnd) + { + log.Debug($"-- Get VolumeFromSamples() - Quit because:{optoData[wrappedIx].Flags}--"); + return 0; + } + log.Debug($"Valid data VolumeRawExt: {optoData[wrappedIx].VolumeRawExt}"); + return optoData[wrappedIx].VolumeRawExt; + + + + // + // if (samplesCount2 < 0) samplesCount2 = 0; + // if ((unwrappedIx - samplesCount2) < 0 || (unwrappedIx + samplesCount2) >= optoDataCount) return 0; + // + // + // Int64 sum = 0; + // for (int i = unwrappedIx - samplesCount2; i <= unwrappedIx + samplesCount2; i++) + // { + // int wrappedIx = BufferIdx(i); + // + // if (optoData[wrappedIx].Flags != OptoTelegramFlags.OK && + // optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestStart && + // optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestEnd) + // { + // return 0; + // } + // + // sum += optoData[wrappedIx].VolumeRawExt; + // } + // + // return 0.0000625 * scalingFactor * sum / (double)(2 * samplesCount2 + 1); + } /// @@ -1214,25 +1264,45 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// Filtered time double TimeFromSamples(OptoTelegramRaw[] optoData, int optoDataCount, int unwrappedIx, int samplesCount2 = 0) { - if (samplesCount2 < 0) samplesCount2 = 0; - if ((unwrappedIx - samplesCount2) < 0 || (unwrappedIx + samplesCount2) >= optoDataCount) return 0; - - Int64 sum = 0; - for (int i = unwrappedIx - samplesCount2; i <= unwrappedIx + samplesCount2; i++) + log.Debug("-- Get TimeFromSamples() --"); + if (unwrappedIx >= optoDataCount) { - int wrappedIx = BufferIdx(i); - - if (optoData[wrappedIx].Flags != OptoTelegramFlags.OK && - optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestStart && - optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestEnd) - { - return 0; - } - - sum += optoData[wrappedIx].TimestampExt; + log.Debug( + $"-- FAILED TimeFromSamples() - unwrappedIx {unwrappedIx} >= optoDataCount{optoDataCount}--"); + return 0; } + + int wrappedIx = BufferIdx(unwrappedIx); - return sum / (double)(8192 * (2 * samplesCount2 + 1)); + if (optoData[wrappedIx].Flags != OptoTelegramFlags.OK && + optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestStart && + optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestEnd) + { + log.Debug($"-- Get TimeFromSamples() - Quit because:{optoData[wrappedIx].Flags}--"); + return 0; + } + log.Debug($"Valid data TimestampExt: {optoData[wrappedIx].TimestampExt}"); + return optoData[wrappedIx].TimestampExt; + + // if (samplesCount2 < 0) samplesCount2 = 0; + // if ((unwrappedIx - samplesCount2) < 0 || (unwrappedIx + samplesCount2) >= optoDataCount) return 0; + // + // Int64 sum = 0; + // for (int i = unwrappedIx - samplesCount2; i <= unwrappedIx + samplesCount2; i++) + // { + // int wrappedIx = BufferIdx(i); + // + // if (optoData[wrappedIx].Flags != OptoTelegramFlags.OK && + // optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestStart && + // optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestEnd) + // { + // return 0; + // } + // + // sum += optoData[wrappedIx].TimestampExt; + // } + // + // return sum / (double)(8192 * (2 * samplesCount2 + 1)); } /// @@ -1451,5 +1521,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead { return this; } + + } } diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHeadTestCtrl.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHeadTestCtrl.cs index 4b4e30c9c..cac54258e 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHeadTestCtrl.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHeadTestCtrl.cs @@ -83,10 +83,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead switch (rfidCommandComboBox.SelectedValue) { case "ReadPCB": - rfidListItem.Text = $"PCB: {OptoHeadTest.ReadRequest_PCB(ref iPerlHead)}"; + rfidListItem.Text = $"PCB: {iPerlHead.OptoHeadTest.ReadRequest_PCB()}"; break; case "SetTestMode": - rfidListItem.Text = OptoHeadTest.SetTestMode(ref iPerlHead, ref isTestModeSuccessful); + rfidListItem.Text = iPerlHead.OptoHeadTest.SetTestMode(ref isTestModeSuccessful); optoListBox.Items.Clear(); stopWorkerThread = false; optoThread = new Thread(OptoWorker); @@ -98,7 +98,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead break; case "SetActiveMode": - rfidListItem.Text = OptoHeadTest.SetActiveMode(ref iPerlHead, ref isTestModeSuccessful); + rfidListItem.Text = iPerlHead.OptoHeadTest.SetActiveMode(ref isTestModeSuccessful); stopWorkerThread = true; iPerlHead.StopDataStreamProcessing(); // close opto port break;