Introduce iPerl ASIC Reader with diagnostic LED control, RadioService, OptoHeadTest, SerialDriver, and TouchRead protocol improvements.

This commit is contained in:
Michal Buzik 2026-01-29 08:04:16 +01:00
parent 8fffb9e366
commit fff7951957
11 changed files with 874 additions and 83 deletions

View File

@ -3,8 +3,6 @@ using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using log4net;
using TBF.Rig.Output.Printers.Label;
using TBF.Rig.RegisterReaders.PoseidonReader.communication.C7.Utils;
using CliRunner = TBF.Rig.RegisterReaders.PoseidonReader.communication.C7.Utils.CliRunnerOld;
using OptoHeadStatus = TBF.Rig.RegisterReaders.PoseidonReader.communication.C7.Protocols.OptoHeadStatus;
using SerialPortData = TBF.Rig.RegisterReaders.PoseidonReader.communication.C7.Utils.SerialPortData;

View File

@ -2,104 +2,200 @@ namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4
{
/// <summary>
/// Device-specific TouchRead sub-commands.
/// These commands are used with the DeviceSpecific (0xFD) command.
/// These sub-commands are used together with the
/// <see cref="TouchReadCommand.DeviceSpecific"/> (0xFD) command.
/// </summary>
public enum TouchReadDeviceSubCommand : byte
{
// ---- Alarm / Mask -----------------------------------------
/// <summary>
/// View Alarm Mask (lower 16 bits).
/// Returns a 2-byte little-endian alarm bit field.
/// </summary>
ViewAlarmMask = 0x31,
/// <summary>
/// Set Alarm Mask (lower 16 bits).
/// Payload: 2-byte little-endian alarm bit field.
/// </summary>
SetAlarmMask = 0x32,
/// <summary>
/// View alarm persistence period (days).
/// Range: 890 days.
/// </summary>
ViewPersistence = 0x33,
/// <summary>
/// Set alarm persistence period (days).
/// Range: 890 days.
/// </summary>
SetPersistence = 0x34,
/// <summary>
/// View leak duration (hours).
/// Range: 24180 hours.
/// </summary>
ViewLeakDuration = 0x35,
/// <summary>
/// Set leak duration (hours).
/// Range: 24180 hours.
/// </summary>
SetLeakDuration = 0x36,
ViewAlarms = 0x37,
SetAlarms = 0x38,
// ==========================================================
// System / Time
// ==========================================================
/// <summary>
/// View system time.
/// Returns uint32 seconds since 2000-01-01.
/// Returns uint32 seconds since 2000-01-01 00:00:00.
/// </summary>
ViewSystemTime = 0x10,
/// <summary>
/// Set system time.
/// Payload: uint32 seconds since 2000-01-01.
/// If zero, device will reset and erase data.
/// If set to zero, the meter resets and erases data.
/// Protected by meter seal.
/// </summary>
SetSystemTime = 0x11,
// ==========================================================
// Alarm Mask / Alarm Configuration
// ==========================================================
// ---- Manufacture / Time -----------------------------------
ViewManufactureDate = 0x39,
SetManufactureDate = 0x3A,
/// <summary>View alarm mask (lower 16 bits).</summary>
ViewAlarmMask = 0x31,
ViewSecondsIdle = 0x3B,
ViewSecondsActive = 0x3D,
ViewSecondsUsed = 0x3F,
/// <summary>Set alarm mask (lower 16 bits).</summary>
SetAlarmMask = 0x32,
// ---- Snapshot / Logging -----------------------------------
ViewSnapshotData = 0x41,
ViewDatalogDuration = 0x43,
SetDatalogDuration = 0x44,
ReadDatalog = 0x45,
ClearDatalog = 0x46,
/// <summary>View alarm persistence period (days).</summary>
ViewPersistence = 0x33,
// ---- History ----------------------------------------------
ViewHistoryMask = 0x47,
SetHistoryMask = 0x48,
ReadHistory = 0x49,
ClearHistory = 0x4A,
/// <summary>Set alarm persistence period (days).</summary>
SetPersistence = 0x34,
// ---- Diagnostics ------------------------------------------
ViewDiagnostics = 0x4B,
ResetDiagnostics = 0x4C,
/// <summary>View leak duration (hours).</summary>
ViewLeakDuration = 0x35,
// ---- Calibration / Build ----------------------------------
ViewCalibration = 0x53,
SetCalibration = 0x54,
/// <summary>Set leak duration (hours).</summary>
SetLeakDuration = 0x36,
ViewIPerlBuild = 0x65,
SetIPerlBuild = 0x66,
/// <summary>View current alarm states.</summary>
ViewAlarms = 0x37,
// ---- Bootloader (dangerous!) ------------------------------
EnterBootloader = 0x81,
ReadFlash = 0x82,
EraseAll = 0x83,
EraseSegment = 0x84,
UpdateCode = 0x85,
ExitBootloader = 0x86
/// <summary>Set alarm states (protected by meter seal).</summary>
SetAlarms = 0x38,
// ==========================================================
// Manufacture / Counters
// ==========================================================
/// <summary>View manufacture date.</summary>
ViewManufactureDate = 0x39,
/// <summary>Set manufacture date (protected by meter seal).</summary>
SetManufactureDate = 0x3A,
/// <summary>View seconds idle.</summary>
ViewSecondsIdle = 0x3B,
/// <summary>View seconds active.</summary>
ViewSecondsActive = 0x3D,
/// <summary>View seconds used.</summary>
ViewSecondsUsed = 0x3F,
// ==========================================================
// Snapshot / Datalog
// ==========================================================
/// <summary>View snapshot data.</summary>
ViewSnapshotData = 0x41,
/// <summary>View datalog duration.</summary>
ViewDatalogDuration = 0x43,
/// <summary>Set datalog duration.</summary>
SetDatalogDuration = 0x44,
/// <summary>Read datalog.</summary>
ReadDatalog = 0x45,
/// <summary>Clear datalog.</summary>
ClearDatalog = 0x46,
// ==========================================================
// History
// ==========================================================
/// <summary>View history mask.</summary>
ViewHistoryMask = 0x47,
/// <summary>Set history mask.</summary>
SetHistoryMask = 0x48,
/// <summary>Read history.</summary>
ReadHistory = 0x49,
/// <summary>Clear history.</summary>
ClearHistory = 0x4A,
// ==========================================================
// Diagnostics / Status
// ==========================================================
/// <summary>View diagnostics.</summary>
ViewDiagnostics = 0x4B,
/// <summary>Reset diagnostics.</summary>
ResetDiagnostics = 0x4C,
/// <summary>View status file.</summary>
ViewStatusFile = 0x4F,
/// <summary>Set status file (protected by meter seal).</summary>
SetStatusFile = 0x50,
// ==========================================================
// Calibration / Configuration
// ==========================================================
/// <summary>View calibration structure.</summary>
ViewCalibrationStructure = 0x51,
/// <summary>Set calibration structure (protected by meter seal).</summary>
SetCalibrationStructure = 0x52,
/// <summary>View calibration.</summary>
ViewCalibration = 0x53,
/// <summary>Set calibration (protected by meter seal).</summary>
SetCalibration = 0x54,
/// <summary>View reboot count.</summary>
ViewRebootCount = 0x55,
/// <summary>Set reboot count (protected by meter seal).</summary>
SetRebootCount = 0x56,
/// <summary>View temperature.</summary>
ViewTemperature = 0x57,
/// <summary>Set temperature (protected by meter seal).</summary>
SetTemperature = 0x58,
// ==========================================================
// Diagnostic LED / Hardware
// ==========================================================
/// <summary>
/// Set diagnostic LED state.
/// Enables or disables high-speed LED serial output.
/// <para>
/// See <see cref="TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.DiagnosticLedState"/>
/// diagnostic LED output modes.
/// </para>
/// </summary>
SetDiagnosticLEDState = 0x60,
// ==========================================================
// Build / Firmware Info
// ==========================================================
/// <summary>View iPERL build information.</summary>
ViewIPerlBuild = 0x65,
/// <summary>Set iPERL build (protected by meter seal).</summary>
SetIPerlBuild = 0x66,
// ==========================================================
// Bootloader (DANGEROUS use with care)
// ==========================================================
/// <summary>Enter bootloader mode.</summary>
EnterBootloader = 0x81,
/// <summary>Read FLASH memory.</summary>
ReadFlash = 0x82,
/// <summary>Erase all FLASH memory.</summary>
EraseAll = 0x83,
/// <summary>Erase FLASH segment.</summary>
EraseSegment = 0x84,
/// <summary>Update firmware code.</summary>
UpdateCode = 0x85,
/// <summary>Exit bootloader mode.</summary>
ExitBootloader = 0x86
}
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed;
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4
{
@ -47,6 +48,14 @@ namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4
return this;
}
public TouchReadFrameBuilder AddDiagnosticLedState(DiagnosticLedState state)
{
_information.Add((byte)TouchReadCommand.DeviceSpecific);
_information.Add((byte)TouchReadDeviceSubCommand.SetDiagnosticLEDState);
_information.Add((byte)state);
return this;
}
public TouchReadFrameBuilder AddNullTerminatedAscii(string text)
{

View File

@ -1,13 +1,93 @@
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed
{
/// <summary>
/// Diagnostic LED output mode.
/// <para>
/// Determines the format and content of high-speed serial diagnostic data
/// emitted by the meter when the diagnostic LED is enabled.
/// </para>
/// <para>
/// Each state corresponds to a specific TAB-separated ASCII HEX frame layout
/// as defined in the iPERL TouchRead protocol documentation.
/// </para>
/// <para>
/// See <see cref="TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.TouchReadDeviceSubCommand.SetDiagnosticLEDState"/>
/// diagnostic LED States.
/// </para>
/// </summary>
public enum DiagnosticLedState : byte
{
/// <summary>
/// Diagnostic LED OFF - State #0.
/// <para>
/// Basic diagnostic output containing raw ADC, field strength,
/// flow rate, volume accumulator, and capacitor voltage.
/// </para>
/// </summary>
StateOFF = 0x00,
/// <summary>
/// Diagnostic LED State #1.
/// <para>
/// Basic diagnostic output containing raw ADC, field strength,
/// flow rate, volume accumulator, and capacitor voltage.
/// </para>
/// </summary>
State1 = 0x01,
/// <summary>
/// Diagnostic LED State #2.
/// <para>
/// Extends State #1 with LCD volume, meter state,
/// and low-flow cutoff indication.
/// </para>
/// </summary>
State2 = 0x02,
/// <summary>
/// Diagnostic LED State #3.
/// <para>
/// Extends State #1 with field calibration value,
/// ASIC timestamp, and field drive time.
/// </para>
/// </summary>
State3 = 0x03,
/// <summary>
/// Diagnostic LED State #4.
/// <para>
/// Extended diagnostic output including mean flow rate,
/// field measurements, integrator calibration values,
/// and ASIC state.
/// </para>
/// </summary>
State4 = 0x04,
/// <summary>
/// Diagnostic LED State #5.
/// <para>
/// Extends State #4 with water impedance measurement.
/// </para>
/// </summary>
State5 = 0x05,
/// <summary>
/// Diagnostic LED State #6.
/// <para>
/// Extends State #5 with electrode delta, spike detection data,
/// pipe status, LCD volume, and additional ASIC state.
/// </para>
/// </summary>
State6 = 0x06,
/// <summary>
/// Diagnostic LED State #7.
/// <para>
/// Extends State #6 with raw ADC before offset correction,
/// detrended ADC value, imaginary water impedance,
/// electrode voltage noise, and ADC offset learning status.
/// </para>
/// </summary>
State7 = 0x07
}
}
}

View File

@ -0,0 +1,10 @@
using log4net;
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication
{
public class OpthoHeadService
{
protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData");
}
}

View File

@ -0,0 +1,140 @@
using System;
using System.IO.Ports;
using Common;
using log4net;
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4;
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed;
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.Utils;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication
{
public class OptoHeadTest
{
protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData");
internal static string ReadRequest_PCB(ISmartReader iHead)
{
byte[] frame = new TouchReadFrameBuilder()
.RequestResponse(true)
.AddCommand(TouchReadCommand.ViewFactoryId)
.BuildBytes();
if (iHead.DebugLevel == DebugMode.Simulate)
{
return "-OK Simulated response-";
}
string serialNo = null;
try
{
if (iHead != null)
{
var driver = new SerialDriverBuilder()
.WithPort($"COM{iHead.RfidComPortNr}")
.WithBaudRate(57600)
.WithDataBits(8)
.WithParity(Parity.None)
.WithStopBits(StopBits.Two)
.WithTimeouts(1000, 1000)
.BuildAndConnect();
RadioService headService = new RadioService(driver);
serialNo = headService.ReadRequest_PCB(iHead);
return serialNo;
}
}
catch (Exception ex)
{
return (ex.Message.ToString());
}
return "";
}
public static string SetTestMode(ISmartReader aISmartReader)
{
//Set LED to state 1
byte[] request = new TouchReadFrameBuilder()
.RequestResponse(true)
.AddDiagnosticLedState(DiagnosticLedState.State1)
.BuildBytes();
if (aISmartReader.DebugLevel == DebugMode.Simulate)
{
return "-OK Simulated response-";
}
string serialNo = null;
try
{
if (aISmartReader != null)
{
var driver = new SerialDriverBuilder()
.WithPort($"COM{aISmartReader.RfidComPortNr}")
.WithBaudRate(57600)
.WithDataBits(8)
.WithParity(Parity.None)
.WithStopBits(StopBits.Two)
.WithTimeouts(1000, 1000)
.BuildAndConnect();
RadioService headService = new RadioService(driver);
serialNo = headService.SetTestMode(aISmartReader);
//correct or incorrect response
//okResponse, errorResponse
return serialNo;
}
}
catch (Exception ex)
{
return (ex.Message.ToString());
}
return "";
}
public static string SetActiveMode(ISmartReader aISmartReader)
{
//Set LED to state 1
byte[] request = new TouchReadFrameBuilder()
.RequestResponse(true)
.AddDiagnosticLedState(DiagnosticLedState.StateOFF)
.BuildBytes();
if (aISmartReader.DebugLevel == DebugMode.Simulate)
{
return "-OK Simulated response-";
}
string serialNo = null;
try
{
if (aISmartReader != null)
{
var driver = new SerialDriverBuilder()
.WithPort($"COM{aISmartReader.RfidComPortNr}")
.WithBaudRate(57600)
.WithDataBits(8)
.WithParity(Parity.None)
.WithStopBits(StopBits.Two)
.WithTimeouts(1000, 1000)
.BuildAndConnect();
RadioService headService = new RadioService(driver);
serialNo = headService.SetTestMode(aISmartReader);
//correct or incorrect response
//okResponse, errorResponse
return serialNo;
}
}
catch (Exception ex)
{
return (ex.Message.ToString());
}
return "";
}
}
}

View File

@ -0,0 +1,126 @@
using Common;
using log4net;
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4;
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed;
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.Utils;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication
{
public class RadioService
{
static string okResponse = "Command complete, no errors";
static string errorResponse = "Unable to execute";
private SerialDriver serialDriver;
public RadioService(SerialDriver serialDriver)
{
this.serialDriver = serialDriver;
}
public string ReadRequest_PCB(ISmartReader iHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
var request = new TouchReadFrameBuilder()
.RequestResponse(true)
.AddCommand(TouchReadCommand.ViewFactoryId)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 1000);
if (rawData == null)
return null;
// parse rawData
var parser = new TouchReadFrameParser();
TouchReadResponse decoded = parser.Parse(rawData);
if (decoded.IsOk)
{
return decoded.GetAsciiPayload();
}
return null;
}
public string SetTestMode(ISmartReader iHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
//Set LED to state 1
byte[] request = new TouchReadFrameBuilder()
.RequestResponse(true)
.AddDiagnosticLedState(DiagnosticLedState.State1)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 1000);
if (rawData == null)
return null;
// parse rawData
var parser = new TouchReadFrameParser();
TouchReadResponse decoded = parser.Parse(rawData);
if (decoded.IsOk)
{
string asciiPayload = decoded.GetAsciiPayload();
//correct or incorrect response
//okResponse, errorResponse
return asciiPayload;
}
return null;
}
/// <summary>
/// stop data streaming by LED
/// </summary>
/// <param name="iHead"></param>
/// <returns></returns>
public string SetActiveMode(ISmartReader iHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
//Set LED to state 1
byte[] request = new TouchReadFrameBuilder()
.RequestResponse(true)
.AddDiagnosticLedState(DiagnosticLedState.StateOFF)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 1000);
if (rawData == null)
return null;
// parse rawData
var parser = new TouchReadFrameParser();
TouchReadResponse decoded = parser.Parse(rawData);
if (decoded.IsOk)
{
string asciiPayload = decoded.GetAsciiPayload();
//correct or incorrect response
//okResponse, errorResponse
return asciiPayload;
}
return null;
}
}
}

View File

@ -0,0 +1,243 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Threading;
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.Utils
{
public class SerialDriver : IDisposable
{
public string ErrorMessage { get; private set; }
public Collection<byte> SerialPortReadBuffer = new Collection<byte>();
private SerialPort _serialPort;
private readonly List<byte[]> _binMessages = new List<byte[]>();
private bool _isReading;
// Stored configuration (used by Builder)
private readonly string _portName;
private readonly int _baudRate;
private readonly int _dataBits;
private readonly Parity _parity;
private readonly StopBits _stopBits;
private readonly int _readTimeout;
private readonly int _writeTimeout;
private readonly ManualResetEvent _responseReceived = new ManualResetEvent(false);
#region Constructors
// Default constructor (legacy support)
public SerialDriver()
{
_serialPort = new SerialPort();
}
// Builder constructor
internal SerialDriver(
string portName,
int baudRate,
int dataBits,
Parity parity,
StopBits stopBits,
int readTimeout,
int writeTimeout)
{
_portName = portName;
_baudRate = baudRate;
_dataBits = dataBits;
_parity = parity;
_stopBits = stopBits;
_readTimeout = readTimeout;
_writeTimeout = writeTimeout;
}
#endregion
#region Open / Close
// Builder-based open
public bool Open()
{
return OpenConnection(
_portName,
_baudRate,
_dataBits,
_parity,
_stopBits,
_readTimeout,
_writeTimeout
);
}
// Legacy API (unchanged)
public bool OpenConnection(
string comPort,
int baudrate,
int dataBits,
Parity parity,
StopBits stopbits,
int readTimeout = 1000,
int writeTimeout = 1000)
{
lock (this)
{
CloseConnection();
try
{
ErrorMessage = string.Empty;
_serialPort = new SerialPort(comPort, baudrate, parity, dataBits, stopbits)
{
ReadTimeout = readTimeout,
WriteTimeout = writeTimeout
};
_serialPort.DataReceived += DataReceivedHandler;
_serialPort.Open();
}
catch (Exception ex)
{
ErrorMessage = $"COM error: Open failed {comPort}. {ex.Message}";
return false;
}
if (!_serialPort.IsOpen)
{
ErrorMessage = $"COM error: Can't open {comPort}.";
return false;
}
}
return true;
}
public void CloseConnection()
{
if (_serialPort != null)
{
_serialPort.DataReceived -= DataReceivedHandler;
if (_serialPort.IsOpen)
_serialPort.Close();
_serialPort.Dispose();
_serialPort = null;
}
}
public bool IsOpen() => _serialPort?.IsOpen == true;
#endregion
#region Send / Receive
public bool SendMessage(byte[] sendDataBytes, int length, int readTimeout = 1000, int writeTimeout = 1000)
{
if (!IsOpen()) return false;
if (sendDataBytes.Length == 0) return true;
try
{
PrepareReading();
_serialPort.WriteTimeout = writeTimeout;
_serialPort.ReadTimeout = readTimeout;
_serialPort.Write(sendDataBytes, 0, length);
_isReading = true;
var stopwatch = Stopwatch.StartNew();
while (_isReading)
{
if (stopwatch.ElapsedMilliseconds > readTimeout)
{
ErrorMessage = "COM error: Receive timeout";
return false;
}
}
}
catch (Exception ex)
{
ErrorMessage = $"COM error: Transmit failed {_serialPort.PortName}. {ex.Message}";
return false;
}
return true;
}
private void PrepareReading()
{
_serialPort.DiscardInBuffer();
_binMessages.Clear();
_responseReceived.Reset();
_isReading = true;
}
public byte[] GetRawData()
{
return _binMessages.Count > 0 ? _binMessages[0] : null;
}
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
lock (this)
{
if (_serialPort == null || !_serialPort.IsOpen) return;
try
{
Thread.Sleep(50);
SerialPortReadBuffer = new Collection<byte>();
while (_serialPort.BytesToRead > 0)
{
SerialPortReadBuffer.Add((byte)_serialPort.ReadByte());
}
if (SerialPortReadBuffer.Count > 0)
{
_binMessages.Add(SerialPortReadBuffer.ToArray());
_responseReceived.Set();
}
}
catch
{
// Ignore shutdown race conditions
}
finally
{
_isReading = false;
}
}
}
public byte[] SendAndWait(byte[] data, int timeoutMs)
{
if (!IsOpen())
throw new InvalidOperationException("Serial port not open");
PrepareReading();
_serialPort.Write(data, 0, data.Length);
if (!_responseReceived.WaitOne(timeoutMs))
{
ErrorMessage = "COM error: response timeout";
return null;
}
return GetRawData();
}
#endregion
public void Dispose()
{
CloseConnection();
}
}
}

View File

@ -0,0 +1,82 @@
using System;
using System.IO.Ports;
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.Utils
{
public class SerialDriverBuilder
{
private string _portName;
private int _baudRate = 9600;
private int _dataBits = 8;
private Parity _parity = Parity.None;
private StopBits _stopBits = StopBits.One;
private int _readTimeout = 1000;
private int _writeTimeout = 1000;
public SerialDriverBuilder WithPort(string portName)
{
_portName = portName;
return this;
}
public SerialDriverBuilder WithBaudRate(int baudRate)
{
_baudRate = baudRate;
return this;
}
public SerialDriverBuilder WithDataBits(int dataBits)
{
_dataBits = dataBits;
return this;
}
public SerialDriverBuilder WithParity(Parity parity)
{
_parity = parity;
return this;
}
public SerialDriverBuilder WithStopBits(StopBits stopBits)
{
_stopBits = stopBits;
return this;
}
public SerialDriverBuilder WithTimeouts(int readTimeout, int writeTimeout)
{
_readTimeout = readTimeout;
_writeTimeout = writeTimeout;
return this;
}
/// <summary>
/// Build driver WITHOUT opening connection
/// </summary>
public SerialDriver Build()
{
return new SerialDriver(
_portName,
_baudRate,
_dataBits,
_parity,
_stopBits,
_readTimeout,
_writeTimeout
);
}
/// <summary>
/// Build driver AND open connection
/// </summary>
public SerialDriver BuildAndConnect()
{
var driver = Build();
if (!driver.Open())
{
throw new InvalidOperationException(driver.ErrorMessage);
}
return driver;
}
}
}

View File

@ -7,6 +7,7 @@ using System.Windows.Forms;
using Common;
using TBF.Rig.Generic;
using TBF.Rig.RegisterReaders.CommonRR.IPerl.communication;
using TBF.Rig.RegisterReaders.iPerlASICReader.communication;
using TBF.Rig.RegisterReaders.iPerlReaderUNI.common;
using TBF.Rig.RegisterReaders.iPerlReaderUNI.test;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
@ -89,20 +90,21 @@ namespace TBF.Rig.RegisterReaders.iPerlASICReader.implementations
{
a.RfidOutputListBox.Items.Clear();
using (Tools.LogChecker logChecker = new Tools.LogChecker("RfidData", log4net.Core.Level.Debug))
using (Tools.LogChecker logChecker = new Tools.LogChecker("ASIC_RfidData", log4net.Core.Level.Debug))
{
ListItem rfidListItem = new ListItem();
rfidListItem.Attributes.Add("style", "font-weight:bold");
Operations selectedOperation;
if(!ItemsForIperlOperations.TryGetValue((string)a.RfidCommandComboBox.SelectedValue, out selectedOperation))
selectedOperation = Operations.EmptyCmd;
switch (selectedOperation)
{
case Operations.ReadPcbCmd:
rfidListItem.Text = $"PCB: {OpticalHeadTest.ReadRequest_PCB(a.ISmartReader)}";
rfidListItem.Text = $"PCB: {OptoHeadTest.ReadRequest_PCB(a.ISmartReader)}";
break;
case Operations.SetTestModeCmd:
rfidListItem.Text = OpticalHeadTest.SetTestMode(a.ISmartReader);
rfidListItem.Text = OptoHeadTest.SetTestMode(a.ISmartReader);
a.OptoListBox.Items.Clear();
stopWorkerThread = false;
optoThread = new Thread(OptoWorker);
@ -114,7 +116,7 @@ namespace TBF.Rig.RegisterReaders.iPerlASICReader.implementations
break;
case Operations.SetActiveModeCmd:
rfidListItem.Text = OpticalHeadTest.SetActiveMode(a.ISmartReader);
rfidListItem.Text = OptoHeadTest.SetActiveMode(a.ISmartReader);
stopWorkerThread = true;
a.ISmartReader.StopDataStreamProcessing(); // close opto port
break;

View File

@ -1279,6 +1279,11 @@
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\TouchReadFrameParser.cs" />
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\TouchReadProtocol.cs" />
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\TouchReadResponse.cs" />
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\OpthoHeadService.cs" />
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\OptoHeadTest.cs" />
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\RadioService.cs" />
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\Utils\SerialDriverBuilder.cs" />
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\Utils\SerialDriver.cs" />
<Compile Include="Rig\RegisterReaders\iPerlASICReader\Factory.cs" />
<Compile Include="Rig\RegisterReaders\iPerlASICReader\implementations\IPerlASICImplHeadTestCtrl.cs" />
<Compile Include="Rig\RegisterReaders\iPerlASICReader\implementations\SmartReader.cs" />