Update iPerl communication: adjust baud rate to 38400, refactor opto-datastream processing, integrate diagnostic LED parser, and enhance serial port configuration.

This commit is contained in:
Michal Buzik 2026-02-13 09:26:56 +01:00
parent 66b43350cc
commit e22a0767f4

View File

@ -6,17 +6,19 @@ 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.Xml;
using System.Text;
using System.Xml.Linq; // This line is correct and does not need to be changed.
using System.Windows;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed.parserer;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.hexLogger;
using OptoTelegramFlags = TBF.Rig.TestMethods.iPerlCommunication.common.OptoTelegramFlags;
using OptoTelegramRaw = TBF.Rig.TestMethods.iPerlCommunication.common.OptoTelegramRaw;
namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
{
@ -442,7 +444,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}");
}
@ -865,12 +867,14 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
if (DebugLevel == DebugMode.FailureDuringOperation) DebugLevel = DebugMode.Normal;
if (DebugLevel == DebugMode.Normal)
{
/// Open serial port: 9600 Bd, 8 data bits, 1 stop bit, no parity
/// Open serial port: 38400 Bd, 8 data bits, 1 stop bit, no parity
try
{
CloseOptoSerialPort();
optoSerialPort = new SerialPort(comPort, baudRate, parity, dataBits, stopBit);
optoSerialPort.Handshake = handshake;
optoSerialPort.NewLine = "\r\n";
optoSerialPort.Encoding = Encoding.ASCII; // or UTF8 if needed
optoSerialPort.Open();
log.FatalFormat($"{Name} OptoPort opened: {this}");
}
@ -906,7 +910,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)
{
@ -954,6 +958,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
bool synchronized2;
string partOfTelegram;
DiagnosticLedParser parser = new DiagnosticLedParser(DiagnosticLedState.State4);
/// <summary>
/// Reads opto-datastream via serial port. Invoked from RunDeviceBefore()
///
@ -973,86 +978,59 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
int nrBytes = optoSerialPort.BytesToRead;
if (nrBytes > 0)
{
char[] buffer = new char[nrBytes];
optoSerialPort.Read(buffer, 0, nrBytes);
string received = new string(buffer);
string line = optoSerialPort.ReadLine(); // string
byte[] bytes = optoSerialPort.Encoding.GetBytes(line);
string allRcvd = partOfTelegram + received;
Console.WriteLine("RX ← " + HexFormatter.ToSerialHex(bytes));
while (true)
try
{
int pos = allRcvd.IndexOf("\r\n");
/// CR+LF found
if (optoState == DataStreamState.ProcessAndSave)
{
DiagnosticLedState4Data data = (DiagnosticLedState4Data)parser.ParseLine(line, false);
int bufferIx = BufferIdx(optoDataCount);
if (pos < 0)
{
/// No CR+LF found, wait for more characters in the next invocation
partOfTelegram = allRcvd;
return;
}
else
{
/// CR+LF found
if (optoState == DataStreamState.ProcessAndSave)
if (synchronized)
{
int bufferIx = BufferIdx(optoDataCount);
optoData[bufferIx].Counter = optoDataCount;
optoData[bufferIx].SetFlags(OptoTelegramFlags.SyncError);
}
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);
}
if (data != null)
{
optoData[bufferIx].UpdateFromSmart(data, 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, true, volumeRawExtLast,
timestampExtLast);
}
else
{
/// CR+LF was found && (pos >= OptoTelegramRaw.Length - 2) but the telgram was not OK
optoData[bufferIx].Counter = optoDataCount;
optoDataCount++;
}
else /// optoState == OptoState.Flush
optoDataCount++;
}
else /// optoState == OptoState.Flush
{
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);
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);
}
}
}
catch (Exception e)
{
}
//OnOptoReceived(this, new OptoReceivedEventArgs(s));
}
@ -1069,13 +1047,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
string received = ".";
lock (this)
{
int nrBytes = optoSerialPort.BytesToRead;
if (nrBytes > 0)
{
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);
Console.WriteLine("RX ← " + received);
}
return received;
}