iPerl ASIC - implementation
This commit is contained in:
@@ -3,264 +3,203 @@
|
||||
///
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
|
||||
|
||||
namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
{
|
||||
public class ConfigStruct
|
||||
{
|
||||
public const int Length = 32;
|
||||
//public const int Length = 32; // dynamic
|
||||
|
||||
public Byte Version; /// 0: 1 byte
|
||||
public MeterState MeterState; /// 1: 1 byte
|
||||
public UInt32 TargetTimeVeryLowBatt; /// 2: 4 bytes in seconds
|
||||
public UInt32 TargetTimeLowBatt; /// 6: 4 bytes, in seconds
|
||||
public UInt32 TestModeTime; /// 10: 4 bytes, Max. test mode time in seconds
|
||||
public UInt16 EmptyPipeThreshold; /// 14: 2 bytes
|
||||
public byte[] PCBNumber; /// 16: 5 bytes
|
||||
public byte TestModeConfig; /// 21: 1 byte
|
||||
public UInt32 RadioAddress; /// 22: 4 bytes
|
||||
public UInt16 TempCalibration; /// 26: 2 bytes
|
||||
public UInt16 AlarmMask; /// 28: 2 bytes, Default 0xA3F7
|
||||
public UInt16 ConfigCheckSum; /// 30: 2 bytes
|
||||
//public Byte Version; // 0: 1 byte
|
||||
public string PCBNumberString; // dynamic
|
||||
public ProtocolStatuses StatusMode; // byte
|
||||
public DiagnosticLedState OpthoStatusMode;// byte
|
||||
public string Unit; //dynamic
|
||||
public string Version; // dynamic
|
||||
|
||||
|
||||
public ConfigStruct()
|
||||
{
|
||||
PCBNumber = new byte[5];
|
||||
}
|
||||
|
||||
public byte[] ToByteArray()
|
||||
//Optho test status mode
|
||||
public DiagnosticLedState TestModeConfig
|
||||
{
|
||||
byte[] result = new byte[Length];
|
||||
|
||||
result[0] = Version;
|
||||
result[1] = (byte)MeterState;
|
||||
|
||||
result[2] = (byte)(TargetTimeVeryLowBatt & 0x000000FF);
|
||||
result[3] = (byte)((TargetTimeVeryLowBatt >> 8) & 0x000000FF);
|
||||
result[4] = (byte)((TargetTimeVeryLowBatt >> 16) & 0x000000FF);
|
||||
result[5] = (byte)((TargetTimeVeryLowBatt >> 24) & 0x000000FF);
|
||||
|
||||
result[6] = (byte)(TargetTimeLowBatt & 0x000000FF);
|
||||
result[7] = (byte)((TargetTimeLowBatt >> 8) & 0x000000FF);
|
||||
result[8] = (byte)((TargetTimeLowBatt >> 16) & 0x000000FF);
|
||||
result[9] = (byte)((TargetTimeLowBatt >> 24) & 0x000000FF);
|
||||
|
||||
result[10] = (byte)(TestModeTime & 0x000000FF);
|
||||
result[11] = (byte)((TestModeTime >> 8) & 0x000000FF);
|
||||
result[12] = (byte)((TestModeTime >> 16) & 0x000000FF);
|
||||
result[13] = (byte)((TestModeTime >> 24) & 0x000000FF);
|
||||
|
||||
result[14] = (byte)(EmptyPipeThreshold & 0x00FF);
|
||||
result[15] = (byte)((EmptyPipeThreshold >> 8) & 0x00FF);
|
||||
|
||||
result[16] = PCBNumber[0];
|
||||
result[17] = PCBNumber[1];
|
||||
result[18] = PCBNumber[2];
|
||||
result[19] = PCBNumber[3];
|
||||
result[20] = PCBNumber[4];
|
||||
|
||||
result[21] = TestModeConfig;
|
||||
|
||||
result[22] = (byte)(RadioAddress & 0x000000FF);
|
||||
result[23] = (byte)((RadioAddress >> 8) & 0x000000FF);
|
||||
result[24] = (byte)((RadioAddress >> 16) & 0x000000FF);
|
||||
result[25] = (byte)((RadioAddress >> 24) & 0x000000FF);
|
||||
|
||||
result[26] = (byte)(TempCalibration & 0x00FF);
|
||||
result[27] = (byte)((TempCalibration >> 8) & 0x00FF);
|
||||
|
||||
result[28] = (byte)(AlarmMask & 0x00FF);
|
||||
result[29] = (byte)((AlarmMask >> 8) & 0x00FF);
|
||||
|
||||
result[30] = (byte)(ConfigCheckSum & 0x00FF);
|
||||
result[31] = (byte)((ConfigCheckSum >> 8) & 0x00FF);
|
||||
|
||||
return result;
|
||||
get { return OpthoStatusMode; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a configuration structure from a complete byte array
|
||||
/// </summary>
|
||||
/// <param name="data">A complete byte array data</param>
|
||||
/// <returns>ConfigStruct or null when byte array was not complete</returns>
|
||||
public static ConfigStruct FromByteArray(byte[] data)
|
||||
//Activity test status mode
|
||||
public ProtocolStatuses MeterState
|
||||
{
|
||||
if (data.Length != Length) return null;
|
||||
|
||||
ConfigStruct result = new ConfigStruct();
|
||||
|
||||
result.Version = data[0];
|
||||
result.MeterState = (MeterState)data[1];
|
||||
result.TargetTimeVeryLowBatt = (((UInt32)data[5] * 256 + data[4]) * 256 + data[3]) * 256 + data[2];
|
||||
result.TargetTimeLowBatt = (((UInt32)data[9] * 256 + data[8]) * 256 + data[7]) * 256 + data[6];
|
||||
result.TestModeTime = (((UInt32)data[13] * 256 + data[12]) * 256 + data[11]) * 256 + data[10];
|
||||
result.EmptyPipeThreshold = (UInt16)(data[15] * 256 + data[14]);
|
||||
result.PCBNumber[0] = data[16];
|
||||
result.PCBNumber[1] = data[17];
|
||||
result.PCBNumber[2] = data[18];
|
||||
result.PCBNumber[3] = data[19];
|
||||
result.PCBNumber[4] = data[20];
|
||||
result.TestModeConfig = data[21];
|
||||
result.RadioAddress = (((UInt32)data[25] * 256 + data[24]) * 256 + data[23]) * 256 + data[22];
|
||||
result.TempCalibration = (UInt16)(data[27] * 256 + data[26]);
|
||||
result.AlarmMask = (UInt16)(data[29] * 256 + data[28]);
|
||||
result.ConfigCheckSum = (UInt16)(data[31] * 256 + data[30]);
|
||||
|
||||
return result;
|
||||
get
|
||||
{
|
||||
return StatusMode;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the configuration structure from an incomplete byte array
|
||||
/// </summary>
|
||||
/// <param name="offset">Offset of byte array data in ConfigStruct</param>
|
||||
/// <param name="data">Byte array data</param>
|
||||
/// <returns>true when successful, false when data are not appropriate</returns>
|
||||
public bool Update(int offset, byte[] data)
|
||||
{
|
||||
if (offset == 0 && data.Length == 2)
|
||||
{
|
||||
/// iPerl mode of function
|
||||
Version = data[0];
|
||||
MeterState = (MeterState)data[1];
|
||||
return true;
|
||||
}
|
||||
else if (offset == 0 && data.Length == 4)
|
||||
{
|
||||
/// iPerl mode of function and extra 2 bytes
|
||||
Version = data[0];
|
||||
MeterState = (MeterState)data[1];
|
||||
return true;
|
||||
}
|
||||
else if (offset == 21 && data.Length == 1)
|
||||
{
|
||||
/// TestModeConfig value
|
||||
TestModeConfig = data[21 - offset];
|
||||
return true;
|
||||
}
|
||||
else if (offset == 0 && data.Length == Length)
|
||||
{
|
||||
/// Complete ConfigStruct
|
||||
Version = data[0];
|
||||
MeterState = (MeterState)data[1];
|
||||
TargetTimeVeryLowBatt = (((UInt32)data[5] * 256 + data[4]) * 256 + data[3]) * 256 + data[2];
|
||||
TargetTimeLowBatt = (((UInt32)data[9] * 256 + data[8]) * 256 + data[7]) * 256 + data[6];
|
||||
TestModeTime = (((UInt32)data[13] * 256 + data[12]) * 256 + data[11]) * 256 + data[10];
|
||||
EmptyPipeThreshold = (UInt16)(data[15] * 256 + data[14]);
|
||||
PCBNumber[0] = data[16];
|
||||
PCBNumber[1] = data[17];
|
||||
PCBNumber[2] = data[18];
|
||||
PCBNumber[3] = data[19];
|
||||
PCBNumber[4] = data[20];
|
||||
TestModeConfig = data[21];
|
||||
RadioAddress = (((UInt32)data[25] * 256 + data[24]) * 256 + data[23]) * 256 + data[22];
|
||||
TempCalibration = (UInt16)(data[27] * 256 + data[26]);
|
||||
AlarmMask = (UInt16)(data[29] * 256 + data[28]);
|
||||
ConfigCheckSum = (UInt16)(data[31] * 256 + data[30]);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns PCB number string (12 characters, 12 decimal digits)
|
||||
/// </summary>
|
||||
/// <returns>PCB number STRING</returns>
|
||||
public string GetPcbNrString()
|
||||
{
|
||||
return PCBNumber2String(this.PCBNumber);
|
||||
}
|
||||
public string GetPcbNrString(){
|
||||
return PCBNumberString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts PCBNumber to string (12 characters, 12 decimal digits)
|
||||
/// </summary>
|
||||
/// <param name="pcbNumber"></param>
|
||||
/// <returns>PCB number string</returns>
|
||||
public static string PCBNumber2String(byte[] pcbNumber)
|
||||
{
|
||||
if (pcbNumber.Length != 5) return string.Empty;
|
||||
|
||||
Int64 number = 0;
|
||||
for (int i = 4; i >= 0; i--)
|
||||
{
|
||||
number = 256 * number + (Int64)pcbNumber[i];
|
||||
}
|
||||
|
||||
return number.ToString();
|
||||
}
|
||||
public string GetStatusModeString()
|
||||
{
|
||||
return string.Format(
|
||||
"Config: StatusMode={0}",
|
||||
StatusMode
|
||||
);
|
||||
}
|
||||
|
||||
public string GetActiveModeString()
|
||||
{
|
||||
return string.Format(
|
||||
"Config: StatusMode={0}, OpthoStatusMode={1}",
|
||||
StatusMode,
|
||||
OpthoStatusMode
|
||||
);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("Config: V{0} State={1} VLoBattT={2}s LoBattT={3}s TestModeT={4}s EPThld={5} PCB#={6} TMCfg={7} RadioAddr={8} TempCalib={9} AlarmMask={10} CfgCheckSum={11}",
|
||||
Version,
|
||||
MeterState,
|
||||
TargetTimeVeryLowBatt,
|
||||
TargetTimeLowBatt,
|
||||
TestModeTime,
|
||||
EmptyPipeThreshold,
|
||||
GetPcbNrString(),
|
||||
TestModeConfig.ToString("X2"),
|
||||
RadioAddress,
|
||||
TempCalibration,
|
||||
AlarmMask.ToString("X4"),
|
||||
ConfigCheckSum.ToString("X4"));
|
||||
return string.Format(
|
||||
"Config: PCB#={0} StatusMode={1} Unit={2} V{3}",
|
||||
|
||||
GetPcbNrString(),
|
||||
StatusMode,
|
||||
Unit,
|
||||
Version
|
||||
);
|
||||
}
|
||||
|
||||
public string ToString(int sel)
|
||||
{
|
||||
return string.Format("{1} PCB#={6} TMCfg={7}",
|
||||
Version,
|
||||
MeterState,
|
||||
TargetTimeVeryLowBatt,
|
||||
TargetTimeLowBatt,
|
||||
TestModeTime,
|
||||
EmptyPipeThreshold,
|
||||
GetPcbNrString(),
|
||||
TestModeConfig.ToString("X2"),
|
||||
RadioAddress,
|
||||
TempCalibration,
|
||||
AlarmMask.ToString("X4"),
|
||||
ConfigCheckSum.ToString("X4"));
|
||||
return string.Format(
|
||||
"Config: PCB#={0} StatusMode={1} Unit={2} V{3}",
|
||||
|
||||
GetPcbNrString(),
|
||||
StatusMode,
|
||||
Unit,
|
||||
Version
|
||||
);
|
||||
}
|
||||
|
||||
public virtual void WriteBinary(BinaryWriter writer)
|
||||
{
|
||||
writer.Write(Version);
|
||||
writer.Write((byte)MeterState);
|
||||
writer.Write(TargetTimeVeryLowBatt);
|
||||
writer.Write(TargetTimeLowBatt);
|
||||
writer.Write(TestModeTime);
|
||||
writer.Write(EmptyPipeThreshold);
|
||||
writer.Write(PCBNumber[0]);
|
||||
writer.Write(PCBNumber[1]);
|
||||
writer.Write(PCBNumber[2]);
|
||||
writer.Write(PCBNumber[3]);
|
||||
writer.Write(PCBNumber[4]);
|
||||
writer.Write(TestModeConfig);
|
||||
writer.Write(RadioAddress);
|
||||
writer.Write(TempCalibration);
|
||||
writer.Write(AlarmMask);
|
||||
writer.Write(ConfigCheckSum);
|
||||
if (writer == null)
|
||||
throw new ArgumentNullException(nameof(writer));
|
||||
|
||||
// ---- Marker ----
|
||||
writer.Write((byte)0x11);
|
||||
|
||||
// ---- Version ----
|
||||
if (!string.IsNullOrEmpty(Version))
|
||||
{
|
||||
// Convert string to bytes (UTF8 is standard)
|
||||
byte[] versionBytes = Encoding.UTF8.GetBytes(Version);
|
||||
// 1) write length
|
||||
writer.Write(versionBytes.Length);
|
||||
// 2) write string bytes
|
||||
writer.Write(versionBytes);
|
||||
//writer.Write(Version);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(0);//Length
|
||||
}
|
||||
|
||||
// ---- StatusMode ----
|
||||
writer.Write((byte)StatusMode);
|
||||
|
||||
// ---- PCB Number ----
|
||||
if (!string.IsNullOrEmpty(PCBNumberString))
|
||||
{
|
||||
byte[] PCBNumberStringBytes = Encoding.UTF8.GetBytes(PCBNumberString);
|
||||
// 1) write length
|
||||
writer.Write(PCBNumberStringBytes.Length);
|
||||
// 2) write string bytes
|
||||
writer.Write(PCBNumberStringBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(0); //Length
|
||||
}
|
||||
|
||||
// ---- Unit ----
|
||||
if (!string.IsNullOrEmpty(Unit))
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(0); //Length
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public virtual void ReadBinary(BinaryReader reader)
|
||||
{
|
||||
Version = reader.ReadByte();
|
||||
MeterState = (MeterState)reader.ReadByte();
|
||||
TargetTimeVeryLowBatt = reader.ReadUInt32();
|
||||
TargetTimeLowBatt = reader.ReadUInt32();
|
||||
TestModeTime = reader.ReadUInt32();
|
||||
EmptyPipeThreshold = reader.ReadUInt16();
|
||||
PCBNumber[0] = reader.ReadByte();
|
||||
PCBNumber[1] = reader.ReadByte();
|
||||
PCBNumber[2] = reader.ReadByte();
|
||||
PCBNumber[3] = reader.ReadByte();
|
||||
PCBNumber[4] = reader.ReadByte();
|
||||
TestModeConfig = reader.ReadByte();
|
||||
RadioAddress = reader.ReadUInt32();
|
||||
TempCalibration = reader.ReadUInt16();
|
||||
AlarmMask = reader.ReadUInt16();
|
||||
ConfigCheckSum = reader.ReadUInt16();
|
||||
if (reader == null)
|
||||
throw new ArgumentNullException(nameof(reader));
|
||||
|
||||
// ---- Marker ----
|
||||
byte marker = reader.ReadByte();
|
||||
if (marker != 0x11)
|
||||
throw new InvalidDataException($"Invalid config marker: 0x{marker:X2}");
|
||||
|
||||
// ---- Version ----
|
||||
int versionLength = reader.ReadInt32();
|
||||
if (versionLength < 0)
|
||||
throw new InvalidDataException("Invalid Version length.");
|
||||
|
||||
byte[] versionBytes = reader.ReadBytes(versionLength);
|
||||
if (versionBytes.Length != versionLength)
|
||||
throw new EndOfStreamException("Unexpected end of stream while reading Version.");
|
||||
|
||||
Version = versionLength > 0
|
||||
? Encoding.UTF8.GetString(versionBytes)
|
||||
: string.Empty;
|
||||
|
||||
// ---- StatusMode ----
|
||||
StatusMode = (ProtocolStatuses)reader.ReadByte();
|
||||
|
||||
// ---- PCB Number ----
|
||||
int pcbLength = reader.ReadInt32();
|
||||
if (pcbLength < 0)
|
||||
throw new InvalidDataException("Invalid PCB number length.");
|
||||
|
||||
byte[] pcbBytes = reader.ReadBytes(pcbLength);
|
||||
if (pcbBytes.Length != pcbLength)
|
||||
throw new EndOfStreamException("Unexpected end of stream while reading PCB number.");
|
||||
|
||||
PCBNumberString = pcbLength > 0
|
||||
? Encoding.UTF8.GetString(pcbBytes)
|
||||
: string.Empty;
|
||||
|
||||
// ---- Unit ----
|
||||
int unitLength = reader.ReadInt32();
|
||||
if (unitLength < 0)
|
||||
throw new InvalidDataException("Invalid Unit length.");
|
||||
|
||||
byte[] unitBytes = reader.ReadBytes(unitLength);
|
||||
if (unitBytes.Length != unitLength)
|
||||
throw new EndOfStreamException("Unexpected end of stream while reading Unit.");
|
||||
|
||||
Unit = unitLength > 0
|
||||
? Encoding.UTF8.GetString(unitBytes)
|
||||
: string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clear FIFO data
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Write data to FIFO
|
||||
/// Add sample to rolling FIFO and update regression sums
|
||||
/// </summary>
|
||||
/// <param name="volumeRaw">Volume</param>
|
||||
/// <param name="timestamp">Time stamp</param>
|
||||
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--;
|
||||
double oldX = timestampFifo[fifoIx];
|
||||
double oldY = volumeRawFifo[fifoIx];
|
||||
|
||||
sumXX -= oldX * oldX;
|
||||
sumX -= oldX;
|
||||
sumXY -= oldX * oldY;
|
||||
sumY -= oldY;
|
||||
}
|
||||
sumXX += timestamp * timestamp;
|
||||
sumX += timestamp;
|
||||
sumXY += timestamp * volumeRaw;
|
||||
sumY += volumeRaw;
|
||||
N++;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether there are enough recent FIFO data
|
||||
/// </summary>
|
||||
/// <returns>true when data valid</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verify whether the flow direction is correct
|
||||
/// </summary>
|
||||
/// <returns>OptoHeadState.OptoAndDirOK, OptoHeadState.OptoNok or OptoHeadState.DirNok</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,28 +6,36 @@ using System.IO;
|
||||
using System.IO.Ports;
|
||||
using log4net;
|
||||
using Common;
|
||||
using Common.Iperl;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Rig.GenericDevices;
|
||||
using Sensus.iPerl.NfcHandler;
|
||||
using NHibernate;
|
||||
using Renci.SshNet;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq; // This line is correct and does not need to be changed.
|
||||
using System.Windows;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
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;
|
||||
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
|
||||
|
||||
|
||||
|
||||
namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
{
|
||||
/// <summary>
|
||||
/// This component = instance of this class is a placeholder for a combined main watermeter
|
||||
/// </summary>
|
||||
public class IperlHead : ComponentBase, IDevice,IRegReaderDatastream, ISessionDataMngmnt, IOperation, ISmartReader
|
||||
public class IperlHead : ComponentBase, IDevice,IRegReaderDatastream, ISessionDataMngmnt, IOperation, IRegReaderSmart
|
||||
{
|
||||
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
|
||||
@@ -38,63 +46,49 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
public const string OptoDataDirectory = "C:\\TBF\\ProcessData";
|
||||
public const int StartOptoDataCount = OptoDataBufferSize / 2;
|
||||
public const int EndOptoDataCount = OptoDataBufferSize - StartOptoDataCount;
|
||||
public const int StartEndFilterSamplesCount2 = 20; /// StartEndFilterSamplesCount = 2 * StartEndFilterSamplesCount2 + 1
|
||||
public const int StartEndFilterSamplesCount2 = 2; //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;
|
||||
|
||||
|
||||
public int RfidComPortNr { get { return iperlHeadCfg.RfidComPortNr; } }
|
||||
public bool CommFailed { get; set; }
|
||||
public bool Disabled { get; set; }
|
||||
public int OptoComPortNr { get { return iperlHeadCfg.OptoComPortNr; } }
|
||||
public int MuxBoardNrOrGroup14 { get { return iperlHeadCfg.MuxBoardNr; } }
|
||||
public int Group { get { return iperlHeadCfg.Group; } }
|
||||
public iPerlHead.MeterType MeterType { get { return iperlHeadCfg.MeterType; } }
|
||||
public string CommInterface { get { return iperlHeadCfg.CommunicationInterface.ToDescription(); } }
|
||||
public CommunicationInterface CommInterface { get { return iperlHeadCfg.CommunicationInterface; } }
|
||||
|
||||
|
||||
static int? ExtractPreferredNumber(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
return null;
|
||||
|
||||
// Match all sequences of digits
|
||||
var matches = Regex.Matches(input, @"\d+");
|
||||
if (matches.Count == 0)
|
||||
return null;
|
||||
|
||||
// Prefer the last one if there are multiple
|
||||
string selected = matches[matches.Count - 1].Value; // last element
|
||||
return int.Parse(selected);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// this is a hack to get the position from the name
|
||||
/// name must consist only with digit describing order of the meter
|
||||
/// </summary>
|
||||
public int Position
|
||||
{
|
||||
get
|
||||
{
|
||||
//BUMI this is a hack to get the position from the name
|
||||
// but it is not working for all cases !!!!!
|
||||
// - what stupid prediction (what index should be used?? see: 'S4iPerl1' or ...)
|
||||
|
||||
int? extractPreferredNumber = ExtractPreferredNumber(Name);
|
||||
if (extractPreferredNumber.HasValue)
|
||||
return extractPreferredNumber.Value;
|
||||
return 0;
|
||||
int firstDigitPos = Name.IndexOfAny(new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' });
|
||||
int position;
|
||||
return (firstDigitPos < 0) ? 0 : (int.TryParse(Name.Substring(firstDigitPos), out position) ? position : 0);
|
||||
}
|
||||
}
|
||||
public RegisterReaderType RegisterReaderType { get { return RegisterReaderType.DataStream; } }
|
||||
public double PulsesPerLtr {
|
||||
get { return 1000.0; }
|
||||
set {PulsesPerLtr = value; }
|
||||
get { return 1000.0; }
|
||||
set { }
|
||||
}
|
||||
public double LtrsPerPulse { get { return 1 / PulsesPerLtr; } }
|
||||
public string QuantityUnits { get; set; }
|
||||
|
||||
public double CalibTarget { get { return iperlHeadCfg.ProcParams.CalibTarget; } }
|
||||
public ushort FactorLimitLo { get { return (ushort)iperlHeadCfg.ProcParams.FactorLimitLo; } }
|
||||
public ushort FactorLimitHi { get { return (ushort)iperlHeadCfg.ProcParams.FactorLimitHi; } }
|
||||
@@ -118,7 +112,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
simulatedPcbNr = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool Disabled;
|
||||
public bool CommFailed;
|
||||
public int ResultCode;
|
||||
|
||||
|
||||
@@ -132,8 +128,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
/// <summary>
|
||||
/// Passed to OptoTelegramRaw.UpdateFromString(...)
|
||||
/// </summary>
|
||||
Int64 volumeRawExtLast;
|
||||
Int64 timestampExtLast;
|
||||
double volumeRawExtLast;
|
||||
double timestampExtLast;
|
||||
|
||||
FlowDirectionDetection flowDirectionDetection;
|
||||
|
||||
@@ -190,13 +186,23 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
///
|
||||
public int WMPulses { get { return wmPulses; } }
|
||||
public int WMRefPulses { get { return wmRefPulses; } }
|
||||
public double BeginWMState { get { return beginWMState; } set { beginWMState = value; }}
|
||||
public double EndWMState { get { return endWMState; } set { endWMState = value;} }
|
||||
public double WMVolume { get { return wmVolume; } }
|
||||
public double WMTestTime { get { return wmTestTime; } }
|
||||
public double BeginWMState { get { return ResolveNaNDouble(beginWMState); } }
|
||||
public double EndWMState { get { return ResolveNaNDouble(endWMState); } }
|
||||
public double WMVolume { get { return ResolveNaNDouble(wmVolume); } }
|
||||
public double WMTestTime { get { return ResolveNaNDouble(wmTestTime); } }
|
||||
|
||||
string simulatedPcbNr = null;
|
||||
|
||||
double ResolveNaNDouble(double d)
|
||||
{
|
||||
if (Double.IsNaN(d))
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
else
|
||||
return d;
|
||||
}
|
||||
|
||||
int wmPulses;
|
||||
int wmRefPulses;
|
||||
double beginWMState;
|
||||
@@ -269,7 +275,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
const double C = B * 60.0; /// Raw units per hour, 480
|
||||
double D = C / A; /// ml correction per hour
|
||||
double F = D / (nominalTestFlowLph * 10.0); /// Error corrected with 8 Raw Units per minute [%]
|
||||
double G = F / B; /// Error corrected with 1 Raw Unit per minute [%]
|
||||
double G = F / B; /// Error corrected with 1 Raw Units per minute [%]
|
||||
|
||||
/// Do not change the factor for an invalid measurement (q2adjResult.VolumeMeter == 0)
|
||||
double q2CorrectionFactor = (Math.Abs(currentQ2Result.VolumeMeter) <= float.Epsilon) ? Convert.ToDouble(currentFactor) :
|
||||
@@ -389,7 +395,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
///
|
||||
/// Timestamp from the opto telegram
|
||||
///
|
||||
private Int64 lastTimestamp;
|
||||
private double lastTimestamp;
|
||||
private double timestampSec;
|
||||
private double timestampSec0;
|
||||
|
||||
@@ -412,14 +418,14 @@ 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;
|
||||
|
||||
/// Test start volume for metrology in liters
|
||||
public double VolumeLtrStart
|
||||
{
|
||||
get { return NoSamples ? 0 : VolumeFromSamples(optoData, optoDataCount, TestStartTelegramIx, ScalingFactor(), StartEndFilterSamplesCount2); }
|
||||
get { return NoSamples ? 0 : VolumeFromSamples(optoData, optoDataCount, TestStartTelegramIx, ScalingFactor(), 0); }
|
||||
}
|
||||
/// Test end volume for metrology in liters
|
||||
public double VolumeLtrEnd
|
||||
@@ -473,7 +479,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
/// Check whether head is connected, working
|
||||
try
|
||||
{
|
||||
OpenOptoSerialPort($"COM{iperlHeadCfg.OptoComPortNr}", 9600, Parity.None, 8, StopBits.One, Handshake.None);
|
||||
OpenOptoSerialPort($"COM{iperlHeadCfg.OptoComPortNr}", 38400, Parity.None, 8, StopBits.One, Handshake.None);
|
||||
CloseOptoSerialPort();
|
||||
log.FatalFormat($"{Name} initialized: {this}");
|
||||
}
|
||||
@@ -618,10 +624,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;
|
||||
|
||||
@@ -887,34 +893,63 @@ 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;
|
||||
}
|
||||
|
||||
private void OpenOptoSerialPort(string comPort, int baudRate, Parity parity, int dataBits, StopBits stopBit, Handshake handshake)
|
||||
private void OpenOptoSerialPort(
|
||||
string comPort,
|
||||
int baudRate,
|
||||
Parity parity,
|
||||
int dataBits,
|
||||
StopBits stopBit,
|
||||
Handshake handshake,
|
||||
int openTimeoutMs = 3000)
|
||||
{
|
||||
if (DebugLevel == DebugMode.FailureDuringOperation) DebugLevel = DebugMode.Normal;
|
||||
if (DebugLevel == DebugMode.Normal)
|
||||
{
|
||||
/// Open serial port: 9600 Bd, 8 data bits, 1 stop bit, no parity
|
||||
try
|
||||
{
|
||||
CloseOptoSerialPort();
|
||||
optoSerialPort = new SerialPort(comPort, baudRate, parity, dataBits, stopBit);
|
||||
optoSerialPort.Handshake = handshake;
|
||||
optoSerialPort.Open();
|
||||
log.FatalFormat($"{Name} OptoPort opened: {this}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.FatalFormat($"{Name} OptoPort - error opening port: {this}" + Environment.NewLine + ex.Message);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (DebugLevel != DebugMode.Normal)
|
||||
{
|
||||
optoSerialPort = null;
|
||||
log.FatalFormat($"{Name} OproPort simulated: {this}");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
CloseOptoSerialPort();
|
||||
|
||||
var port = new SerialPort(comPort, baudRate, parity, dataBits, stopBit)
|
||||
{
|
||||
Handshake = handshake,
|
||||
NewLine = "\r\n",
|
||||
Encoding = Encoding.ASCII
|
||||
};
|
||||
|
||||
port.ReadTimeout = 5000;
|
||||
port.WriteTimeout = 5000;
|
||||
port.DtrEnable = true;
|
||||
port.RtsEnable = true;
|
||||
|
||||
// Run Open() on separate task
|
||||
var openTask = Task.Run(() => port.Open());
|
||||
|
||||
if (!openTask.Wait(openTimeoutMs))
|
||||
{
|
||||
port.Dispose();
|
||||
throw new TimeoutException(
|
||||
$"Opening serial port {comPort} timed out after {openTimeoutMs} ms.");
|
||||
}
|
||||
|
||||
optoSerialPort = port;
|
||||
|
||||
log.FatalFormat($"{Name} OptoPort opened: {this}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.FatalFormat($"{Name} OptoPort - error opening port: {this}"
|
||||
+ Environment.NewLine + ex.Message);
|
||||
throw; // NEVER use "throw ex;" (destroys stack trace)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -937,7 +972,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenOptoSerialPort($"COM{iperlHeadCfg.OptoComPortNr}", 9600, Parity.None, 8, StopBits.One, Handshake.None);
|
||||
OpenOptoSerialPort($"COM{iperlHeadCfg.OptoComPortNr}", 38400, Parity.None, 8, StopBits.One, Handshake.None);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -961,18 +996,6 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
dataStreamState = DataStreamState.ProcessAndSave;
|
||||
}
|
||||
|
||||
public void SetCommunicationInterface(string commInterface)
|
||||
{
|
||||
CommunicationInterface com = (CommunicationInterface)Enum.Parse(typeof(CommunicationInterface), commInterface);
|
||||
SetCommunicationInterface(com);
|
||||
}
|
||||
|
||||
public void SetCommunicationInterface(RegisterReaders.CommonRR.CommunicationInterface commInterface)
|
||||
{
|
||||
CommunicationInterface com = (CommunicationInterface)Enum.Parse(typeof(CommunicationInterface), commInterface.ToDescription());
|
||||
SetCommunicationInterface(com);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true when processing and saving datastream data is in progress
|
||||
/// </summary>
|
||||
@@ -981,11 +1004,6 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
return dataStreamState == DataStreamState.ProcessAndSave;
|
||||
}
|
||||
|
||||
void ISmartReader.SetRfidInterface()
|
||||
{
|
||||
SetRfidInterface();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop processing and saving datastream data
|
||||
/// </summary>
|
||||
@@ -1001,121 +1019,95 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
bool synchronized;
|
||||
bool synchronized2;
|
||||
string partOfTelegram;
|
||||
private RegisterReaders.CommonRR.CommunicationInterface _commInterface;
|
||||
private string _commInterface1;
|
||||
|
||||
DiagnosticLedParser parser = new DiagnosticLedParser(DiagnosticLedState.State4);
|
||||
|
||||
/// <summary>
|
||||
/// Reads opto-datastream via serial port. Invoked from RunDeviceBefore()
|
||||
///
|
||||
/// Telegram description:
|
||||
/// AAAAAA[tab]BBBB[tab]CCCC[tab]DDDDDD[tab]EEEE[tab]FFFFFFFF[tab]GG[cr][lf] (42 bytes)
|
||||
/// Example:
|
||||
/// FFFFFE 51EA 0000 65324E 0087 F6319DFF 86
|
||||
/// FFDD3A 51F9 0000 65324E 0088 F631A60B 45
|
||||
/// ...
|
||||
/// </summary>
|
||||
/// <param name="optoState">OptoState.Read or OptoState.Flush</param>
|
||||
void ReadOptoData(DataStreamState optoState)
|
||||
{
|
||||
/// Telegram description:
|
||||
/// AAAAAA[tab]BBBB[tab]CCCC[tab]DDDDDD[tab]EEEE[tab]FFFFFFFF[tab]GG[cr][lf] (42 bytes)
|
||||
/// Example:
|
||||
/// FFFFFE 51EA 0000 65324E 0087 F6319DFF 86
|
||||
/// FFDD3A 51F9 0000 65324E 0088 F631A60B 45
|
||||
/// ...
|
||||
/// </summary>
|
||||
/// <param name="optoState">OptoState.Read or OptoState.Flush</param>
|
||||
void ReadOptoData(DataStreamState optoState)
|
||||
{
|
||||
if (optoSerialPort is null) return;
|
||||
|
||||
lock (this)
|
||||
{
|
||||
int nrBytes = optoSerialPort.BytesToRead;
|
||||
if (nrBytes > 0)
|
||||
try
|
||||
{
|
||||
char[] buffer = new char[nrBytes];
|
||||
optoSerialPort.Read(buffer, 0, nrBytes);
|
||||
string received = new string(buffer);
|
||||
|
||||
string allRcvd = partOfTelegram + received;
|
||||
|
||||
while (true)
|
||||
int nrBytes = optoSerialPort.BytesToRead;
|
||||
if (nrBytes > 0)
|
||||
{
|
||||
int pos = allRcvd.IndexOf("\r\n");
|
||||
// This will now wait max 3 seconds (ReadTimeout)
|
||||
string line = optoSerialPort.ReadLine();
|
||||
|
||||
if (pos < 0)
|
||||
byte[] bytes = optoSerialPort.Encoding.GetBytes(line);
|
||||
log.Debug("ComPort: " + OptoComPortNr + " OPTHO RX ← " + HexFormatter.ToSerialHex(bytes));
|
||||
|
||||
if (optoState == DataStreamState.ProcessAndSave)
|
||||
{
|
||||
/// No CR+LF found, wait for more characters in the next invocation
|
||||
partOfTelegram = allRcvd;
|
||||
return;
|
||||
DiagnosticLedState4Data data =
|
||||
(DiagnosticLedState4Data)parser.ParseLine(line, false);
|
||||
|
||||
int bufferIx = BufferIdx(optoDataCount);
|
||||
|
||||
if (synchronized)
|
||||
{
|
||||
optoData[bufferIx].Counter = optoDataCount;
|
||||
optoData[bufferIx].SetFlags(OptoTelegramFlags.SyncError);
|
||||
}
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
log.Debug($"OPTHO {OptoComPortNr} Parsed optho data:" + data);
|
||||
logStream.Debug($"ID: {OptoComPortNr} " + data);
|
||||
|
||||
optoData[bufferIx].UpdateFromSmart(
|
||||
data,
|
||||
optoDataCount,
|
||||
Convert.ToSingle(Sequences.ProcessData.RefFlow.Val),
|
||||
ref volumeRawExtLast,
|
||||
ref timestampExtLast);
|
||||
|
||||
flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast);
|
||||
|
||||
OptoTelegramReceived(
|
||||
optoDataCount,
|
||||
true,
|
||||
volumeRawExtLast,
|
||||
timestampExtLast);
|
||||
}
|
||||
|
||||
optoDataCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/// CR+LF found
|
||||
if (optoState == DataStreamState.ProcessAndSave)
|
||||
{
|
||||
int bufferIx = BufferIdx(optoDataCount);
|
||||
// Flush mode
|
||||
DiagnosticLedState4Data data =
|
||||
(DiagnosticLedState4Data)parser.ParseLine(line, false);
|
||||
|
||||
if (pos < OptoTelegramRaw.Length - 2)
|
||||
{
|
||||
/// CR+LF found too early, truncate the beginning incl CR+LF and keep scanning in this loop
|
||||
allRcvd = allRcvd.Substring(pos + 2);
|
||||
if (synchronized)
|
||||
{
|
||||
optoData[bufferIx].Counter = optoDataCount;
|
||||
optoData[bufferIx].SetFlags(OptoTelegramFlags.SyncError);
|
||||
}
|
||||
synchronized = true;
|
||||
}
|
||||
else if (optoData[bufferIx].UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2),
|
||||
optoDataCount,
|
||||
Convert.ToSingle(Sequences.ProcessData.RefFlow.Val),
|
||||
ref volumeRawExtLast, ref timestampExtLast))
|
||||
{
|
||||
/// CR+LF was found && (pos >= OptoTelegramRaw.Length - 2) && the telegram is OK
|
||||
flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast);
|
||||
OptoTelegramReceived(optoDataCount, synchronized2, volumeRawExtLast, timestampExtLast);
|
||||
synchronized2 = synchronized;
|
||||
allRcvd = allRcvd.Substring(pos + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// CR+LF was found && (pos >= OptoTelegramRaw.Length - 2) but the telgram was not OK
|
||||
optoData[bufferIx].Counter = optoDataCount;
|
||||
optoDataCount++;
|
||||
allRcvd = allRcvd.Substring(pos + 2);
|
||||
}
|
||||
|
||||
optoDataCount++;
|
||||
}
|
||||
else /// optoState == OptoState.Flush
|
||||
{
|
||||
if (pos < OptoTelegramRaw.Length - 2)
|
||||
{
|
||||
/// CR+LF found too early, truncate the beginning incl CR+LF and keep scanning in this loop
|
||||
allRcvd = allRcvd.Substring(pos + 2);
|
||||
synchronized = true;
|
||||
}
|
||||
// CR+LF found and (pos >= OptoTelegram.Length - 2)
|
||||
else if (toBeFlushed.UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2),
|
||||
0,
|
||||
Convert.ToSingle(Sequences.ProcessData.RefFlow.Val),
|
||||
ref volumeRawExtLast, ref timestampExtLast))
|
||||
{
|
||||
flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast);
|
||||
synchronized2 = synchronized;
|
||||
allRcvd = allRcvd.Substring(pos + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
allRcvd = allRcvd.Substring(pos + 2);
|
||||
}
|
||||
}
|
||||
flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast);
|
||||
}
|
||||
}
|
||||
|
||||
//OnOptoReceived(this, new OptoReceivedEventArgs(s));
|
||||
}
|
||||
else
|
||||
catch (TimeoutException)
|
||||
{
|
||||
//OnOptoReceived(this, new OptoReceivedEventArgs("."));
|
||||
// ✅ No data received within 3 seconds
|
||||
log.Debug($"OPTHO {OptoComPortNr} ReadLine timeout (3s) - continuing.");
|
||||
|
||||
// Just continue without parsing
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error($"OPTHO {OptoComPortNr} Read error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ISmartReader.ResetNfcInterface(bool? nfc_on)
|
||||
{
|
||||
ResetNfcInterface(nfc_on);
|
||||
}
|
||||
|
||||
public string ReadOptoData()
|
||||
@@ -1124,48 +1116,114 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
string received = ".";
|
||||
lock (this)
|
||||
{
|
||||
int nrBytes = optoSerialPort.BytesToRead;
|
||||
if (nrBytes > 0)
|
||||
try
|
||||
{
|
||||
char[] buffer = new char[nrBytes];
|
||||
optoSerialPort.Read(buffer, 0, nrBytes);
|
||||
received = new string(buffer);
|
||||
string line = optoSerialPort.ReadLine(); // string
|
||||
byte[] bytes = optoSerialPort.Encoding.GetBytes(line);
|
||||
received = HexFormatter.ToSerialHex(bytes);
|
||||
log.Debug("RX ← " + received);
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
// ✅ No data received within 3 seconds
|
||||
log.Debug($"ReadOptoData() OPTHO {OptoComPortNr} ReadLine timeout (3s) - continuing.");
|
||||
|
||||
// Just continue without parsing
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error($"ReadOptoData() OPTHO {OptoComPortNr} Read error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
return received;
|
||||
}
|
||||
|
||||
void ISmartReader.SetNfcInterface()
|
||||
|
||||
public async Task<string> ReadOptoDataWithTimeoutAsync(int timeoutMs = 5000)
|
||||
{
|
||||
SetNfcInterface();
|
||||
if (optoSerialPort == null)
|
||||
return string.Empty;
|
||||
|
||||
var readTask = Task.Run(() =>
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (optoSerialPort== null) return string.Empty;
|
||||
try
|
||||
{
|
||||
string line = optoSerialPort.ReadLine();
|
||||
byte[] bytes = optoSerialPort.Encoding.GetBytes(line);
|
||||
string received = HexFormatter.ToSerialHex(bytes);
|
||||
|
||||
log.Debug("RX ← " + received);
|
||||
return line;
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
// ✅ No data received within 3 seconds
|
||||
log.Debug($"ReadOptoData() OPTHO {OptoComPortNr} ReadLine timeout (3s) - continuing.");
|
||||
|
||||
// Just continue without parsing
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error($"ReadOptoData() OPTHO {OptoComPortNr} Read error: {ex.Message}");
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
});
|
||||
|
||||
var completedTask = await Task.WhenAny(readTask, Task.Delay(timeoutMs));
|
||||
|
||||
if (completedTask == readTask)
|
||||
{
|
||||
return await readTask; // completed successfully
|
||||
}
|
||||
|
||||
log.Debug("ReadOptoData timeout after " + timeoutMs + " ms");
|
||||
return string.Empty; // timeout case
|
||||
}
|
||||
|
||||
public string ReadOptoDataWithTimeout(int timeoutMs = 5000)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ReadOptoDataWithTimeoutAsync(timeoutMs)
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1270,25 +1328,55 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
/// <returns>Filtered volume</returns>
|
||||
double VolumeFromSamples(OptoTelegramRaw[] optoData, int optoDataCount, int unwrappedIx, double scalingFactor, int samplesCount2 = 0)
|
||||
{
|
||||
log.Debug("-- Get VolumeFromSamples() --");
|
||||
if (samplesCount2 == 0)
|
||||
{
|
||||
if (unwrappedIx >= optoDataCount)
|
||||
{
|
||||
log.Debug(
|
||||
$"-- FAILED VolumeFromSamples() - unwrappedIx {unwrappedIx} >= optoDataCount{optoDataCount}--");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wrappedIx = BufferIdx(unwrappedIx);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
//TODO BUMI - do result as average from data - usually 5 samples
|
||||
|
||||
if (samplesCount2 < 0) samplesCount2 = 0;
|
||||
if ((unwrappedIx - samplesCount2) < 0 || (unwrappedIx + samplesCount2) >= optoDataCount) return 0;
|
||||
|
||||
Int64 sum = 0;
|
||||
|
||||
|
||||
double 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);
|
||||
|
||||
return sum / (double)(2 * samplesCount2 + 1);
|
||||
//return 0.0000625 * scalingFactor * sum / (double)(2 * samplesCount2 + 1);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1299,25 +1387,45 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
/// <returns>Filtered time</returns>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1536,5 +1644,204 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public async Task<string> DataEntry_ReadSerialNumber()
|
||||
{
|
||||
log.Debug("called DataEntry_ReadSerialNumber()");
|
||||
if (!string.IsNullOrEmpty(SerialNr)) return SerialNr;
|
||||
|
||||
//need to find serial number
|
||||
SerialNr = await DataEntry_ReadSerialNumberAsync();
|
||||
|
||||
return SerialNr;
|
||||
}
|
||||
|
||||
public Task<double> DataEntry_ReadBeginVolume()
|
||||
{
|
||||
log.Debug("called DataEntry_ReadBeginVolumer()");
|
||||
|
||||
Task<double> readedVolume = DataEntry_BeginVolumeAsync();
|
||||
|
||||
return readedVolume;
|
||||
}
|
||||
|
||||
public Task<double> DataEntry_ReadEndVolume()
|
||||
{
|
||||
log.Debug("called DataEntry_ReadBeginVolumer()");
|
||||
|
||||
Task<double> readedVolume = DataEntry_EndVolumeAsync();
|
||||
|
||||
return readedVolume;
|
||||
}
|
||||
|
||||
|
||||
public async Task<double> DataEntry_EndVolumeAsync()
|
||||
{
|
||||
|
||||
if (optoSerialPort == null || !optoSerialPort.IsOpen)
|
||||
{
|
||||
StartDataStreamProcessing();
|
||||
if (optoSerialPort == null || !optoSerialPort.IsOpen)
|
||||
{
|
||||
log.Error($"optoSerialPort COM: {this.OptoComPortNr} is not open - DataEntry_EndVolumeAsync()");
|
||||
return Double.NaN;
|
||||
}
|
||||
}
|
||||
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
log.Debug($"Try get End Volume! COM: {this.OptoComPortNr}");
|
||||
volumeLtr = Double.NaN;
|
||||
|
||||
int counter = 0;
|
||||
while (Double.IsNaN(volumeLtr) && counter < 2)
|
||||
{
|
||||
counter++;
|
||||
try
|
||||
{
|
||||
string readOptoDataWithTimeout = ReadOptoDataWithTimeout(2000);
|
||||
if (!string.IsNullOrEmpty(readOptoDataWithTimeout))
|
||||
{
|
||||
try
|
||||
{
|
||||
DiagnosticLedState4Data data =
|
||||
(DiagnosticLedState4Data)parser.ParseLine(readOptoDataWithTimeout, false);
|
||||
volumeLtr = data.RawVolume;
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Warn($"Parsing DiagnosticLedState4Data: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
log.Debug($"Try get End Volume! COM: {this.OptoComPortNr}, Volume: {volumeLtr}");
|
||||
if (optoSerialPort != null && optoSerialPort.IsOpen) CloseOptoSerialPort();
|
||||
|
||||
if (!Double.IsNaN(volumeLtr))
|
||||
{
|
||||
endWMState = volumeLtr;
|
||||
if (!Double.IsNaN(beginWMState) && !Double.IsNaN(endWMState))
|
||||
{
|
||||
//Solve roll over
|
||||
if (endWMState < beginWMState)
|
||||
{
|
||||
log.Debug($"Solve roll over! endWMState: {endWMState} < beginWMState: {beginWMState}");
|
||||
const double VOL_RANGE_LITERS = 16777216.0 * 0.00025; // 4,194.304 l
|
||||
endWMState += VOL_RANGE_LITERS;
|
||||
volumeLtr = endWMState;
|
||||
ReadPulses();
|
||||
log.Debug($"Solve roll over! Upgraded endWMState: {endWMState}, beginWMState: {beginWMState}");
|
||||
}
|
||||
}
|
||||
return endWMState;
|
||||
}
|
||||
//}
|
||||
|
||||
log.Warn("Default NaN value returned! Data Opto stream reading failed!");
|
||||
return Double.NaN;
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
public async Task<double> DataEntry_BeginVolumeAsync()
|
||||
{
|
||||
if (ConfigStruct == null)
|
||||
{
|
||||
log.Debug("ConfigStruct is null - created new in ReadSerialNr()");
|
||||
ConfigStruct = new ConfigStruct();
|
||||
}
|
||||
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
|
||||
log.Debug($"Try get Start Volume! COM: {this.OptoComPortNr}");
|
||||
|
||||
Start();
|
||||
|
||||
volumeLtr0 = Double.NaN;
|
||||
int counter = 0;
|
||||
while (Double.IsNaN(volumeLtr0) && counter < 10)
|
||||
{
|
||||
counter++;
|
||||
try
|
||||
{
|
||||
string readOptoDataWithTimeout = ReadOptoDataWithTimeout(5000);
|
||||
if (!string.IsNullOrEmpty(readOptoDataWithTimeout))
|
||||
{
|
||||
try
|
||||
{
|
||||
DiagnosticLedState4Data data =
|
||||
(DiagnosticLedState4Data)parser.ParseLine(readOptoDataWithTimeout, false);
|
||||
volumeLtr0 = data.RawVolume;
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Warn($"Parsing DiagnosticLedState4Data: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
log.Debug($"Try get Start Volume! COM: {this.OptoComPortNr}, Volume: {volumeLtr0}");
|
||||
if (optoSerialPort != null && optoSerialPort.IsOpen) CloseOptoSerialPort();
|
||||
|
||||
if (!Double.IsNaN(volumeLtr0))
|
||||
{
|
||||
beginWMState = volumeLtr0;
|
||||
ReadPulses();
|
||||
return beginWMState;
|
||||
}
|
||||
//}
|
||||
|
||||
log.Warn("Default NaN value returned! Data Opto stream reading failed!");
|
||||
return Double.NaN;
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<string> DataEntry_ReadSerialNumberAsync()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(SerialNr))
|
||||
return SerialNr;
|
||||
|
||||
if (ConfigStruct == null)
|
||||
{
|
||||
log.Debug("ConfigStruct is null - created new in ReadSerialNr()");
|
||||
ConfigStruct = new ConfigStruct();
|
||||
}
|
||||
|
||||
if (CommFailed || ConfigStruct == null)
|
||||
return CommErr.CommFailed.ToString();
|
||||
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
|
||||
|
||||
|
||||
log.Debug($"Try get ReadSerialNr! COM: {this.RfidComPortNr}");
|
||||
if (OptoHeadTest.ReadSerialNr())
|
||||
{
|
||||
SerialNr = this.ConfigStruct.PCBNumberString;
|
||||
log.Debug("ReadSerialNr successful");
|
||||
}
|
||||
|
||||
//optoHeadTest.CloseConnection();
|
||||
|
||||
return SerialNr;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Threading;
|
||||
using System.Web.UI.WebControls;
|
||||
using System.Windows.Forms;
|
||||
using TBF.Rig.Sequences;
|
||||
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication;
|
||||
|
||||
namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
{
|
||||
@@ -22,7 +22,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
InitializeComponent();
|
||||
if (config == null) return;
|
||||
|
||||
SmartCommunicationForm.TestMethodCfg = new TestMethodCfg_IPerl(null); // default values for iPerlCommunication
|
||||
iPerlCommunicationForm.cfg = new TestMethodCfg(null); // default values for iPerlCommunication
|
||||
|
||||
foreach(var head in ProcessData.IperlHeads)
|
||||
{
|
||||
@@ -78,14 +78,16 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
using (Tools.LogChecker logChecker = new Tools.LogChecker("RfidData", log4net.Core.Level.Debug))
|
||||
{
|
||||
ListItem rfidListItem = new ListItem();
|
||||
rfidListItem.Attributes.Add("style", "font-weight:bold");
|
||||
rfidListItem.Attributes.Add("style", "font-volume:bold");
|
||||
//rfidListItem.Attributes.Add("style", "font-weight:bold");
|
||||
bool isTestModeSuccessful = false;
|
||||
switch (rfidCommandComboBox.SelectedValue)
|
||||
{
|
||||
case "ReadPCB":
|
||||
rfidListItem.Text = $"PCB: {OpticalHeadTest.ReadRequest_PCB(iPerlHead)}";
|
||||
rfidListItem.Text = $"PCB: {iPerlHead.OptoHeadTest.ReadRequest_PCB()}";
|
||||
break;
|
||||
case "SetTestMode":
|
||||
rfidListItem.Text = OpticalHeadTest.SetTestMode(iPerlHead);
|
||||
rfidListItem.Text = iPerlHead.OptoHeadTest.SetTestMode(ref isTestModeSuccessful);
|
||||
optoListBox.Items.Clear();
|
||||
stopWorkerThread = false;
|
||||
optoThread = new Thread(OptoWorker);
|
||||
@@ -96,7 +98,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
}
|
||||
break;
|
||||
case "SetActiveMode":
|
||||
rfidListItem.Text = OpticalHeadTest.SetActiveMode(iPerlHead);
|
||||
|
||||
rfidListItem.Text = iPerlHead.OptoHeadTest.SetActiveMode(ref isTestModeSuccessful);
|
||||
stopWorkerThread = true;
|
||||
iPerlHead.StopDataStreamProcessing(); // close opto port
|
||||
break;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using log4net;
|
||||
using log4net;
|
||||
using Sensus.iPerl.NfcHandler;
|
||||
using Sensus.iPerl.RfidCom.Exceptions;
|
||||
using System;
|
||||
@@ -12,9 +12,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
internal class NfcServices
|
||||
{
|
||||
protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData");
|
||||
internal static int ReadRequest(TestMethodCfg_IPerl cfgIPerl, IperlHead iperlHead, MCI_Protocol.StructName structName, int offset, int length, out byte[] buffer)
|
||||
internal static int ReadRequest(TestMethodCfg cfg, IperlHead iperlHead, MCI_Protocol.StructName structName, int offset, int length, out byte[] buffer)
|
||||
{
|
||||
for (int i = 0; i < cfgIPerl.MaxCommRetries; i++)
|
||||
for (int i = 0; i < cfg.MaxCommRetries; i++)
|
||||
{
|
||||
|
||||
NfcDataHandler _nfcDataHandler = new NfcDataHandler();
|
||||
@@ -26,9 +26,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
try
|
||||
{
|
||||
rfidDataLogger.Info($"NFC COM{iperlHead.RfidComPortNr} ReadRequest : {structName}, {offset}, {length}");
|
||||
OpenConnection(_nfcDataHandler, cfgIPerl, iperlHead);
|
||||
OpenConnection(_nfcDataHandler, cfg, iperlHead);
|
||||
|
||||
buffer = MciRead(_nfcDataHandler, cfgIPerl, structName, (ushort)offset, length);
|
||||
buffer = MciRead(_nfcDataHandler, cfg, structName, (ushort)offset, length);
|
||||
_nfcDataHandler.RFProtocolOFF(); // turn off rf antenna due to possible interference
|
||||
|
||||
CloseComPort(_nfcDataHandler);
|
||||
@@ -44,7 +44,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
}
|
||||
catch (RfidValidationException)
|
||||
{
|
||||
Thread.Sleep(cfgIPerl.WaitTimeAfterFailure);
|
||||
Thread.Sleep(cfg.WaitTimeAfterFailure);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -57,7 +57,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
return 3;
|
||||
}
|
||||
|
||||
internal static int WriteRequest(TestMethodCfg_IPerl cfgIPerl, IperlHead iperlHead, MCI_Protocol.StructName structName, int offset, int length, byte[] buffer)
|
||||
internal static int WriteRequest(TestMethodCfg cfg, IperlHead iperlHead, MCI_Protocol.StructName structName, int offset, int length, byte[] buffer)
|
||||
{
|
||||
NfcDataHandler _nfcDataHandler = new NfcDataHandler();
|
||||
MessageEventHandlers(_nfcDataHandler);
|
||||
@@ -68,9 +68,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
try
|
||||
{
|
||||
rfidDataLogger.Info($"NFC COM{iperlHead.RfidComPortNr} WriteRequest : {structName}, {offset}, {length}, {ByteArrayToHexString(buffer)}");
|
||||
OpenConnection(_nfcDataHandler, cfgIPerl, iperlHead);
|
||||
OpenConnection(_nfcDataHandler, cfg, iperlHead);
|
||||
|
||||
MciWrite(_nfcDataHandler, cfgIPerl, structName, (ushort)offset, length, buffer);
|
||||
MciWrite(_nfcDataHandler, cfg, structName, (ushort)offset, length, buffer);
|
||||
_nfcDataHandler.RFProtocolOFF(); // turn off rf antenna due to possible interference
|
||||
|
||||
CloseComPort(_nfcDataHandler);
|
||||
@@ -83,14 +83,14 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
}
|
||||
}
|
||||
|
||||
private static void OpenConnection(NfcDataHandler nfcDataHandler, TestMethodCfg_IPerl cfgIPerl, IperlHead iperlHead)
|
||||
private static void OpenConnection(NfcDataHandler nfcDataHandler, TestMethodCfg cfg, IperlHead iperlHead)
|
||||
{
|
||||
string comPort = $"COM{iperlHead.RfidComPortNr}";
|
||||
int retryCount = 0 ;
|
||||
Open:
|
||||
nfcDataHandler.Close();
|
||||
Thread.Sleep(100);
|
||||
if (nfcDataHandler.OpenConnection(comPort, cfgIPerl.BaudRate, cfgIPerl.DataBits, cfgIPerl.ParityBit, cfgIPerl.StopBits))
|
||||
if (nfcDataHandler.OpenConnection(comPort, cfg.BaudRate, cfg.DataBits, cfg.ParityBit, cfg.StopBits))
|
||||
{
|
||||
rfidDataLogger.Info($"NFC COM{iperlHead.RfidComPortNr} Port Open");
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
if (!nfcDataHandler.ConnectDevice())
|
||||
{
|
||||
rfidDataLogger.Error($"NFC COM{iperlHead.RfidComPortNr} Error connect device.");
|
||||
for (int i = 0; i < cfgIPerl.MaxCommRetries; i++)
|
||||
for (int i = 0; i < cfg.MaxCommRetries; i++)
|
||||
{
|
||||
if (nfcDataHandler.Echo()) break;
|
||||
}
|
||||
@@ -110,7 +110,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
{
|
||||
retryCount++;
|
||||
rfidDataLogger.Error($"NFC COM{iperlHead.RfidComPortNr} Error connect reader. Reconnect comport {retryCount}");
|
||||
if (retryCount < cfgIPerl.MaxCommRetries)
|
||||
if (retryCount < cfg.MaxCommRetries)
|
||||
{
|
||||
nfcDataHandler.Close();
|
||||
iperlHead.ResetNfcInterface(); // reset NFC head via optoport - switch to RFID and back to NFC interface
|
||||
@@ -127,7 +127,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
nfcDataHandler.Close();
|
||||
}
|
||||
|
||||
private static byte[] MciRead(NfcDataHandler nfcDataHandler, TestMethodCfg_IPerl cfgIPerl, StructName structName, ushort offset, int length)
|
||||
private static byte[] MciRead(NfcDataHandler nfcDataHandler, TestMethodCfg cfg, StructName structName, ushort offset, int length)
|
||||
{
|
||||
bool isReadValues = false;
|
||||
int retryCount = 0;
|
||||
@@ -153,14 +153,14 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
{
|
||||
rfidDataLogger.Info($"MCI Error: Unidentified");
|
||||
retryCount++;
|
||||
if (retryCount < cfgIPerl.MaxCommRetries)
|
||||
if (retryCount < cfg.MaxCommRetries)
|
||||
goto Read;
|
||||
}
|
||||
else
|
||||
{
|
||||
rfidDataLogger.Info("Last error message: " + nfcDataHandler.LastErrorMessage);
|
||||
retryCount++;
|
||||
if (retryCount < cfgIPerl.MaxCommRetries)
|
||||
if (retryCount < cfg.MaxCommRetries)
|
||||
goto Read;
|
||||
}
|
||||
}
|
||||
@@ -168,13 +168,13 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
{
|
||||
rfidDataLogger.Error("MciRead Last error message: " + ex.Message);
|
||||
retryCount++;
|
||||
if (retryCount < cfgIPerl.MaxCommRetries)
|
||||
if (retryCount < cfg.MaxCommRetries)
|
||||
goto Read;
|
||||
}
|
||||
return new byte[length];
|
||||
}
|
||||
|
||||
private static void MciWrite(NfcDataHandler nfcDataHandler, TestMethodCfg_IPerl cfgIPerl, MCI_Protocol.StructName structName, ushort offset, int length, byte[] payload)
|
||||
private static void MciWrite(NfcDataHandler nfcDataHandler, TestMethodCfg cfg, MCI_Protocol.StructName structName, ushort offset, int length, byte[] payload)
|
||||
{
|
||||
int retryCount = 0;
|
||||
Write:
|
||||
@@ -199,7 +199,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
{
|
||||
rfidDataLogger.Error("MciWrite error message: " + ex.Message);
|
||||
retryCount++;
|
||||
if (retryCount < cfgIPerl.MaxCommRetries)
|
||||
if (retryCount < cfg.MaxCommRetries)
|
||||
goto Write;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,16 +149,16 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
return pars;
|
||||
}
|
||||
|
||||
public override bool UpdateFromDbEntity(ComponentProcedure dbEntity)
|
||||
{
|
||||
if (dbEntity == null) return false;
|
||||
try
|
||||
{
|
||||
ProcParams tmp = Serializer.Deserialize(new StringReader(dbEntity.Parameters)) as ProcParams;
|
||||
public override bool UpdateFromDbEntity(ComponentProcedure dbEntity)
|
||||
{
|
||||
if (dbEntity == null) return false;
|
||||
try
|
||||
{
|
||||
ProcParams tmp = Serializer.Deserialize(new StringReader(dbEntity.Parameters)) as ProcParams;
|
||||
|
||||
procedureParamsEntity = dbEntity;
|
||||
componentName = dbEntity.CmpntName;
|
||||
procedure = dbEntity.Procedure;
|
||||
procedureParamsEntity = dbEntity;
|
||||
componentName = dbEntity.CmpntName;
|
||||
procedure = dbEntity.Procedure;
|
||||
|
||||
if (tmp != null)
|
||||
{
|
||||
@@ -181,7 +181,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
}
|
||||
}
|
||||
|
||||
public ProcParams()
|
||||
|
||||
public ProcParams()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,29 +1,28 @@
|
||||
using Sensus.iPerl.RfidCom.Exceptions;
|
||||
using Sensus.iPerl.RfidCom.Exceptions;
|
||||
using Sensus.iPerl.RfidCom.Helper;
|
||||
using Sensus.iPerl.RfidCom;
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using log4net;
|
||||
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
|
||||
|
||||
namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
{
|
||||
internal class RfidServices
|
||||
{
|
||||
protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData");
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(SmartCommunicationForm));
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(iPerlCommunicationForm));
|
||||
|
||||
internal static int ReadRequest(TestMethodCfg_IPerl cfgIPerl, IperlHead iperlHead, MessageID messageID, int offset, int length, out byte[] buffer)
|
||||
internal static int ReadRequest(TestMethodCfg cfg, IperlHead iperlHead, MessageID messageID, int offset, int length, out byte[] buffer)
|
||||
{
|
||||
for (int i = 0; i < cfgIPerl.MaxCommRetries; i++)
|
||||
for (int i = 0; i < cfg.MaxCommRetries; i++)
|
||||
{
|
||||
rfidDataLogger.Error($"{iperlHead.CommInterface} Start {i} reading: COM{iperlHead.RfidComPortNr}: ReadRequestPort ({messageID},{offset}, {length}... timeout {cfgIPerl.CommTimeout})");
|
||||
rfidDataLogger.Error($"{iperlHead.CommInterface} Start {i} reading: COM{iperlHead.RfidComPortNr}: ReadRequestPort ({messageID},{offset}, {length}... timeout {cfg.CommTimeout})");
|
||||
using (RfidLogic writer = new RfidLogic($"COM{iperlHead.RfidComPortNr}"))
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] response = writer.ReadRequest((byte)messageID, offset, length, cfgIPerl.CommTimeout);
|
||||
byte[] response = writer.ReadRequest((byte)messageID, offset, length, cfg.CommTimeout);
|
||||
string hexString = RfidHelper.ConvertByteArrayToHexString(response);
|
||||
string swapHexString = RfidHelper.SwapHexcode(hexString);
|
||||
string decString = RfidHelper.HexLiteral2Unsigned(RfidHelper.SwapHexcode(hexString)).ToString();
|
||||
@@ -57,42 +56,42 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
if (/*RfidHelper.IsPassThrough(messageID)*/ messageID == MessageID.ASICRegisterReadTest || messageID == MessageID.RadioPassthrough)
|
||||
{
|
||||
rfidDataLogger.Info($"COM{iperlHead.RfidComPortNr}: ReadRequestPort ({messageID},...) {(i > 0 ? "<- Error: Invalid Pass-Through data." : "<- Info: Wait for Pass-Through data.")}");
|
||||
Thread.Sleep(cfgIPerl.PassThroughWaitTime);
|
||||
Thread.Sleep(cfg.PassThroughWaitTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(cfgIPerl.WaitTimeAfterFailure);
|
||||
Thread.Sleep(cfg.WaitTimeAfterFailure);
|
||||
}
|
||||
}
|
||||
catch (RfidValidationException)
|
||||
{
|
||||
Thread.Sleep(cfgIPerl.WaitTimeAfterFailure);
|
||||
Thread.Sleep(cfg.WaitTimeAfterFailure);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
rfidDataLogger.Error($"COM{iperlHead.RfidComPortNr}: ReadRequestPort ({messageID},...) {ex.Message}");
|
||||
Thread.Sleep(cfgIPerl.WaitTimeAfterFailure);
|
||||
Thread.Sleep(cfg.WaitTimeAfterFailure);
|
||||
}
|
||||
}
|
||||
}
|
||||
rfidDataLogger.Error($"{iperlHead.CommInterface} reading failed after {cfgIPerl.MaxCommRetries} retries: COM{iperlHead.RfidComPortNr}: ReadRequestPort ({messageID},...)");
|
||||
log.Error($"{iperlHead.CommInterface} reading failed after {cfgIPerl.MaxCommRetries} retries: COM{iperlHead.RfidComPortNr}: ReadRequestPort ({messageID},...)");
|
||||
rfidDataLogger.Error($"{iperlHead.CommInterface} reading failed after {cfg.MaxCommRetries} retries: COM{iperlHead.RfidComPortNr}: ReadRequestPort ({messageID},...)");
|
||||
log.Error($"{iperlHead.CommInterface} reading failed after {cfg.MaxCommRetries} retries: COM{iperlHead.RfidComPortNr}: ReadRequestPort ({messageID},...)");
|
||||
buffer = new byte[length];
|
||||
return 3;
|
||||
}
|
||||
|
||||
internal static int WriteRequest(TestMethodCfg_IPerl cfgIPerl, IperlHead iperlHead, MessageID messageID, int offset, int length, byte[] buffer)
|
||||
internal static int WriteRequest(TestMethodCfg cfg, IperlHead iperlHead, MessageID messageID, int offset, int length, byte[] buffer)
|
||||
{
|
||||
RfidLogic writer = new RfidLogic($"COM{iperlHead.RfidComPortNr}");
|
||||
string payload = RfidHelper.ConvertByteArrayToHexString(buffer);
|
||||
|
||||
for (var i = 0; i < cfgIPerl.MaxCommRetries; i++)
|
||||
for (var i = 0; i < cfg.MaxCommRetries; i++)
|
||||
{
|
||||
rfidDataLogger.Error($"{iperlHead.CommInterface} Start {i} writting: COM{iperlHead.RfidComPortNr}: WriteRequest ({messageID},{offset}, {length}, {payload}... timeout {cfgIPerl.CommTimeout})");
|
||||
rfidDataLogger.Error($"{iperlHead.CommInterface} Start {i} writting: COM{iperlHead.RfidComPortNr}: WriteRequest ({messageID},{offset}, {length}, {payload}... timeout {cfg.CommTimeout})");
|
||||
try
|
||||
{
|
||||
if (writer.ClosePort()) writer.OpenPort();
|
||||
writer.WriteRequest((byte)messageID, offset, length, buffer, cfgIPerl.CommTimeout, false);
|
||||
writer.WriteRequest((byte)messageID, offset, length, buffer, cfg.CommTimeout, false);
|
||||
writer.ClosePort();
|
||||
rfidDataLogger.InfoFormat($"{iperlHead.Name}({iperlHead.SerialNr},COM{iperlHead.RfidComPortNr}): WriteRequestPort({messageID}, {offset}, {length}, {payload})");
|
||||
return 0;
|
||||
@@ -106,7 +105,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
else
|
||||
{
|
||||
rfidDataLogger.Error($"COM{iperlHead.RfidComPortNr}: Error: {ex.Message}");
|
||||
Thread.Sleep(cfgIPerl.WaitTimeAfterFailure);
|
||||
Thread.Sleep(cfg.WaitTimeAfterFailure);
|
||||
if (i > 1)
|
||||
{
|
||||
rfidDataLogger.Error($"COM{iperlHead.RfidComPortNr}: Reopen the com port.");
|
||||
@@ -116,8 +115,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
}
|
||||
}
|
||||
writer.ClosePort();
|
||||
rfidDataLogger.Error($"RFID writing failed after {cfgIPerl.MaxCommRetries} retries: COM{iperlHead.RfidComPortNr}: WriteRequestPort ({messageID},...) {System.Text.Encoding.UTF8.GetString(buffer)}");
|
||||
log.Error($"RFID writing failed after {cfgIPerl.MaxCommRetries} retries: COM{iperlHead.RfidComPortNr}: WriteRequestPort ({messageID},...) {System.Text.Encoding.UTF8.GetString(buffer)}");
|
||||
rfidDataLogger.Error($"RFID writing failed after {cfg.MaxCommRetries} retries: COM{iperlHead.RfidComPortNr}: WriteRequestPort ({messageID},...) {System.Text.Encoding.UTF8.GetString(buffer)}");
|
||||
log.Error($"RFID writing failed after {cfg.MaxCommRetries} retries: COM{iperlHead.RfidComPortNr}: WriteRequestPort ({messageID},...) {System.Text.Encoding.UTF8.GetString(buffer)}");
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
|
||||
|
||||
namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
{
|
||||
@@ -7,11 +10,34 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
{
|
||||
const int Q2CorrFactorsAddr = 0x1878;
|
||||
|
||||
internal static int ReadRequest(TestMethodCfg_IPerl cfgIPerl, IperlHead iperlHead, MessageID messageID, int offset, int length, out byte[] buffer)
|
||||
internal static int ReadRequest(TestMethodCfg cfg, IperlHead iperlHead, MessageID messageID, int offset, int length, out byte[] buffer)
|
||||
{
|
||||
byte[] configurationBuffer = new byte[ConfigStruct.Length] { 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
|
||||
string pcbStr = iperlHead.RfidComPortNr.ToString().PadRight(10,'0') + iperlHead.Position.ToString("D2");
|
||||
long decVal = Convert.ToInt64(pcbStr);
|
||||
string nHexStr = decVal.ToString("X4");
|
||||
|
||||
ConfigStruct configStruct = new ConfigStruct();
|
||||
configStruct.PCBNumberString = nHexStr;
|
||||
configStruct.StatusMode = ProtocolStatuses.Active;
|
||||
configStruct.OpthoStatusMode = DiagnosticLedState.State4;
|
||||
configStruct.Version = "Good Version: 123456";
|
||||
|
||||
byte[] configurationBuffer;
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
using (var writer = new BinaryWriter(ms))
|
||||
{
|
||||
configStruct.WriteBinary(writer);
|
||||
writer.Flush();
|
||||
configurationBuffer = ms.ToArray(); // ← this is the binary output
|
||||
}
|
||||
|
||||
byte[] calibrationBuffer = new byte[CalibrationStructV4.Length] { 3, 0, 150, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 150, 10 };
|
||||
buffer = new byte[length];
|
||||
|
||||
return 0;//switch off
|
||||
|
||||
if (messageID == MessageID.Configuration)
|
||||
{
|
||||
@@ -34,7 +60,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
|
||||
return iperlHead.Name.Equals("iPerl13") ? 2 : 0; /// Simulates an error on position 13
|
||||
}
|
||||
|
||||
internal static int WriteRequest(TestMethodCfg_IPerl cfgIPerl, IperlHead iperlHead, MessageID messageID, int offset, int length, byte[] buffer)
|
||||
internal static int WriteRequest(TestMethodCfg cfg, IperlHead iperlHead, MessageID messageID, int offset, int length, byte[] buffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user