Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3b7562a57 | ||
|
|
5fd68c624d | ||
|
|
c57652a22f | ||
|
|
43ce586e41 | ||
|
|
cd38c23298 | ||
|
|
fff7951957 | ||
|
|
8fffb9e366 | ||
|
|
0fdd229141 | ||
|
|
2f1ada3f5b | ||
|
|
988a8c6642 | ||
|
|
42ee9eaee3 | ||
|
|
3f28051d79 | ||
|
|
65f13cc868 | ||
|
|
cd8ba3cda3 |
@@ -34,6 +34,8 @@ MergeResultsDBs/bin/
|
|||||||
MergeResultsDBs/obj/
|
MergeResultsDBs/obj/
|
||||||
NfcC7_Dll/bin/
|
NfcC7_Dll/bin/
|
||||||
NfcC7_Dll/obj/
|
NfcC7_Dll/obj/
|
||||||
|
NfcC7_DLL.Tests/bin/
|
||||||
|
NfcC7_DLL.Tests/obj/
|
||||||
OrderManagement/bin/
|
OrderManagement/bin/
|
||||||
OrderManagement/obj/
|
OrderManagement/obj/
|
||||||
ProductionTracing/bin/
|
ProductionTracing/bin/
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
||||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\micha\.nuget\packages\</NuGetPackageFolders>
|
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\micha\.nuget\packages\</NuGetPackageFolders>
|
||||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.14.0</NuGetToolVersion>
|
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">7.0.0</NuGetToolVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||||
<SourceRoot Include="C:\Users\micha\.nuget\packages\" />
|
<SourceRoot Include="C:\Users\micha\.nuget\packages\" />
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace TBF.Rig.RegisterReaders.IPerlReader
|
|||||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||||
public IComponentCfgCtrl GetControl(IList<Component> cmpntEntities)
|
public IComponentCfgCtrl GetControl(IList<Component> cmpntEntities)
|
||||||
{
|
{
|
||||||
return new IPerlUniCfgCtrl();
|
return new iPerlASICReader.IPerlUniCfgCtrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ namespace TBF.Rig.RegisterReaders.IPerlReader
|
|||||||
muxBoardNrTextBox.Text = config.MuxBoardNr.ToString();
|
muxBoardNrTextBox.Text = config.MuxBoardNr.ToString();
|
||||||
groupTextBox.Text = config.Group.ToString();
|
groupTextBox.Text = config.Group.ToString();
|
||||||
comboBoxCommunicationInterface.SelectedItem = config.CommunicationInterface.ToString();
|
comboBoxCommunicationInterface.SelectedItem = config.CommunicationInterface.ToString();
|
||||||
tabPage2.Controls.Add(new IperlUniHeadTestCtrl(config));
|
tabPage2.Controls.Add(new iPerlASICReader.IperlASICUniHeadTestCtrl(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Unlock()
|
public void Unlock()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TBF.Rig.RegisterReaders.CommonRR.IPerl.communication;
|
using TBF.Rig.RegisterReaders.CommonRR.IPerl.communication;
|
||||||
|
using TBF.Rig.RegisterReaders.IPerlReader.implementations;
|
||||||
using TBF.Rig.RegisterReaders.iPerlReaderUNI;
|
using TBF.Rig.RegisterReaders.iPerlReaderUNI;
|
||||||
using TBF.Rig.RegisterReaders.iPerlReaderUNI.common;
|
using TBF.Rig.RegisterReaders.iPerlReaderUNI.common;
|
||||||
using TBF.Rig.RegisterReaders.PoseidonReader.implementations;
|
using TBF.Rig.RegisterReaders.PoseidonReader.implementations;
|
||||||
@@ -20,7 +21,7 @@ namespace TBF.Rig.RegisterReaders.IPerlReader
|
|||||||
|
|
||||||
public IperlUniHeadTestCtrl(iPerlReaderUNI.IPerlCfg config)
|
public IperlUniHeadTestCtrl(iPerlReaderUNI.IPerlCfg config)
|
||||||
{
|
{
|
||||||
this._ctrl = new PoseidonImplHeadTestCtrl();
|
this._ctrl = new IPerlImplHeadTestCtrl();
|
||||||
Ctrl.config = config;
|
Ctrl.config = config;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
if (config == null) return;
|
if (config == null) return;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Web.UI.WebControls;
|
using System.Web.UI.WebControls;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using Common;
|
||||||
using TBF.Rig.Generic;
|
using TBF.Rig.Generic;
|
||||||
using TBF.Rig.RegisterReaders.CommonRR.IPerl.communication;
|
using TBF.Rig.RegisterReaders.CommonRR.IPerl.communication;
|
||||||
using TBF.Rig.RegisterReaders.iPerlReaderUNI.common;
|
using TBF.Rig.RegisterReaders.iPerlReaderUNI.common;
|
||||||
@@ -37,35 +38,51 @@ namespace TBF.Rig.RegisterReaders.IPerlReader.implementations
|
|||||||
optoThread.Abort();
|
optoThread.Abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const string StrReadPcbCmd = "ReadPCB";
|
||||||
|
private const string StrSetTestModeCmd = "SetTestMode";
|
||||||
|
private const string StrSetActiveModeCmd = "SetActiveMode";
|
||||||
|
private const string StrReadOptoDataCmd = "ReadOptoData";
|
||||||
|
private const string StrStopReadOptoDataCmd = "StopReadOptoData";
|
||||||
|
private const string StrResetNfcHeadCmd = "ResetNfcHead";
|
||||||
|
private const string StrSetNfcHeadCmd = "SetNfcHead";
|
||||||
|
private const string StrSetRfidHeadCmd = "SetRfidHead";
|
||||||
|
private const string StrEmptyCmd = "";
|
||||||
|
|
||||||
private const string ReadPCBCmd = "ReadPCB";
|
public enum Operations
|
||||||
private const string SetTestModeCmd = "SetTestMode";
|
|
||||||
private const string SetActiveModeCmd = "SetActiveMode";
|
|
||||||
private const string ReadOptoDataCmd = "ReadOptoData";
|
|
||||||
private const string StopReadOptoDataCmd = "StopReadOptoData";
|
|
||||||
private const string ResetNfcHeadCmd = "ResetNfcHead";
|
|
||||||
private const string SetNfcHeadCmd = "SetNfcHead";
|
|
||||||
private const string SetRfidHeadCmd = "SetRfidHead";
|
|
||||||
private const string EmptyCmd = "";
|
|
||||||
|
|
||||||
private static readonly Dictionary<string, string> ItemsForIperlOperations = new Dictionary<string, string>
|
|
||||||
{
|
{
|
||||||
{"Read PCB", ReadPCBCmd},
|
[Description(StrReadPcbCmd)]ReadPcbCmd,
|
||||||
{"Set Test Mode", SetTestModeCmd},
|
[Description(StrSetTestModeCmd)]SetTestModeCmd,
|
||||||
{"Set Active Mode", SetActiveModeCmd},
|
[Description(StrSetActiveModeCmd)]SetActiveModeCmd,
|
||||||
|
[Description(StrReadOptoDataCmd)]ReadOptoDataCmd,
|
||||||
|
[Description(StrStopReadOptoDataCmd)]StopReadOptoDataCmd,
|
||||||
|
[Description(StrResetNfcHeadCmd)]ResetNfcHeadCmd,
|
||||||
|
[Description(StrSetNfcHeadCmd)]SetNfcHeadCmd,
|
||||||
|
[Description(StrSetRfidHeadCmd)]SetRfidHeadCmd,
|
||||||
|
[Description(StrEmptyCmd)]EmptyCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, Operations> ItemsForIperlOperations = new Dictionary<string, Operations>
|
||||||
|
{
|
||||||
|
{"Read PCB", Operations.ReadPcbCmd},
|
||||||
|
{"Set Test Mode", Operations.SetTestModeCmd},
|
||||||
|
{"Set Active Mode", Operations.SetActiveModeCmd},
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
{"Start Read Opto Data", ReadOptoDataCmd},
|
{"Start Read Opto Data", Operations.ReadOptoDataCmd},
|
||||||
{"Stop Read Opto Data", StopReadOptoDataCmd},
|
{"Stop Read Opto Data", Operations.StopReadOptoDataCmd},
|
||||||
#endif
|
#endif
|
||||||
{" ", EmptyCmd},
|
{" ", Operations.EmptyCmd},
|
||||||
{"Reset NFC Head", ResetNfcHeadCmd},
|
{"Reset NFC Head", Operations.ResetNfcHeadCmd},
|
||||||
{"Set NFC Head Interface", SetNfcHeadCmd},
|
{"Set NFC Head Interface", Operations.SetNfcHeadCmd},
|
||||||
{"Set RFID Head interface", SetRfidHeadCmd}
|
{"Set RFID Head interface", Operations.SetRfidHeadCmd}
|
||||||
};
|
};
|
||||||
|
|
||||||
public (string Name, string Value)[] GetComboOperationsPairs()
|
public (string Name, string Value)[] GetComboOperationsPairs()
|
||||||
{
|
{
|
||||||
return ItemsForIperlOperations.Select(kvp => (kvp.Key, kvp.Value)).ToArray();
|
//return ItemsForIperlOperations.Select(kvp => (kvp.Key, kvp.Value)).ToArray();
|
||||||
|
return ItemsForIperlOperations.Select(kvp => (kvp.Key, kvp.Value.ToDescription())).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CommandTestButtonClick(object sender, MouseEventArgs e, Arguments a)
|
public void CommandTestButtonClick(object sender, MouseEventArgs e, Arguments a)
|
||||||
@@ -76,12 +93,15 @@ namespace TBF.Rig.RegisterReaders.IPerlReader.implementations
|
|||||||
{
|
{
|
||||||
ListItem rfidListItem = new ListItem();
|
ListItem rfidListItem = new ListItem();
|
||||||
rfidListItem.Attributes.Add("style", "font-weight:bold");
|
rfidListItem.Attributes.Add("style", "font-weight:bold");
|
||||||
switch (a.RfidCommandComboBox.SelectedValue)
|
Operations selectedOperation;
|
||||||
|
if(!ItemsForIperlOperations.TryGetValue((string)a.RfidCommandComboBox.SelectedValue, out selectedOperation))
|
||||||
|
selectedOperation = Operations.EmptyCmd;
|
||||||
|
switch (selectedOperation)
|
||||||
{
|
{
|
||||||
case ReadPCBCmd:
|
case Operations.ReadPcbCmd:
|
||||||
rfidListItem.Text = $"PCB: {OpticalHeadTest.ReadRequest_PCB(a.ISmartReader)}";
|
rfidListItem.Text = $"PCB: {OpticalHeadTest.ReadRequest_PCB(a.ISmartReader)}";
|
||||||
break;
|
break;
|
||||||
case SetTestModeCmd:
|
case Operations.SetTestModeCmd:
|
||||||
rfidListItem.Text = OpticalHeadTest.SetTestMode(a.ISmartReader);
|
rfidListItem.Text = OpticalHeadTest.SetTestMode(a.ISmartReader);
|
||||||
a.OptoListBox.Items.Clear();
|
a.OptoListBox.Items.Clear();
|
||||||
stopWorkerThread = false;
|
stopWorkerThread = false;
|
||||||
@@ -91,22 +111,23 @@ namespace TBF.Rig.RegisterReaders.IPerlReader.implementations
|
|||||||
a.ISmartReader.StartDataStreamProcessing(); // open opto port
|
a.ISmartReader.StartDataStreamProcessing(); // open opto port
|
||||||
optoThread.Start();
|
optoThread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SetActiveModeCmd:
|
case Operations.SetActiveModeCmd:
|
||||||
rfidListItem.Text = OpticalHeadTest.SetActiveMode(a.ISmartReader);
|
rfidListItem.Text = OpticalHeadTest.SetActiveMode(a.ISmartReader);
|
||||||
stopWorkerThread = true;
|
stopWorkerThread = true;
|
||||||
a.ISmartReader.StopDataStreamProcessing(); // close opto port
|
a.ISmartReader.StopDataStreamProcessing(); // close opto port
|
||||||
break;
|
break;
|
||||||
case ResetNfcHeadCmd:
|
case Operations.ResetNfcHeadCmd:
|
||||||
a.ISmartReader.ResetNfcInterface();
|
a.ISmartReader.ResetNfcInterface();
|
||||||
break;
|
break;
|
||||||
case SetNfcHeadCmd:
|
case Operations.SetNfcHeadCmd:
|
||||||
a.ISmartReader.SetNfcInterface();
|
a.ISmartReader.SetNfcInterface();
|
||||||
break;
|
break;
|
||||||
case SetRfidHeadCmd:
|
case Operations.SetRfidHeadCmd:
|
||||||
a.ISmartReader.SetRfidInterface();
|
a.ISmartReader.SetRfidInterface();
|
||||||
break;
|
break;
|
||||||
case ReadOptoDataCmd:
|
case Operations.ReadOptoDataCmd:
|
||||||
a.OptoListBox.Items.Clear();
|
a.OptoListBox.Items.Clear();
|
||||||
stopWorkerThread = false;
|
stopWorkerThread = false;
|
||||||
optoThread = new Thread(OptoWorker);
|
optoThread = new Thread(OptoWorker);
|
||||||
@@ -115,17 +136,20 @@ namespace TBF.Rig.RegisterReaders.IPerlReader.implementations
|
|||||||
stopWorkerThread = true;
|
stopWorkerThread = true;
|
||||||
a.ISmartReader.StopDataStreamProcessing(); // close opto port
|
a.ISmartReader.StopDataStreamProcessing(); // close opto port
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!optoThread.IsAlive)
|
if (!optoThread.IsAlive)
|
||||||
{
|
{
|
||||||
a.ISmartReader.StartDataStreamProcessing(); // open opto port
|
a.ISmartReader.StartDataStreamProcessing(); // open opto port
|
||||||
optoThread.Start();
|
optoThread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case StopReadOptoDataCmd:
|
case Operations.StopReadOptoDataCmd:
|
||||||
stopWorkerThread = true;
|
stopWorkerThread = true;
|
||||||
a.ISmartReader.StopDataStreamProcessing(); // close opto port
|
a.ISmartReader.StopDataStreamProcessing(); // close opto port
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.RfidOutputListBox.Items.Add(rfidListItem);
|
a.RfidOutputListBox.Items.Add(rfidListItem);
|
||||||
a.RfidOutputListBox.Items.AddRange(logChecker.Messages.ToArray());
|
a.RfidOutputListBox.Items.AddRange(logChecker.Messages.ToArray());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ using System.Text.RegularExpressions;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using log4net;
|
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 CliRunner = TBF.Rig.RegisterReaders.PoseidonReader.communication.C7.Utils.CliRunnerOld;
|
||||||
using OptoHeadStatus = TBF.Rig.RegisterReaders.PoseidonReader.communication.C7.Protocols.OptoHeadStatus;
|
using OptoHeadStatus = TBF.Rig.RegisterReaders.PoseidonReader.communication.C7.Protocols.OptoHeadStatus;
|
||||||
using SerialPortData = TBF.Rig.RegisterReaders.PoseidonReader.communication.C7.Utils.SerialPortData;
|
using SerialPortData = TBF.Rig.RegisterReaders.PoseidonReader.communication.C7.Utils.SerialPortData;
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using NfcC7_DLL.NfcHandler.Protocols;
|
|
||||||
|
|
||||||
namespace TBF.Rig.RegisterReaders.PoseidonReader.communication.C7.Protocols
|
namespace TBF.Rig.RegisterReaders.PoseidonReader.communication.C7.Protocols
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using NfcC7_DLL.NfcHandler.Utils;
|
|
||||||
|
|
||||||
namespace TBF.Rig.RegisterReaders.PoseidonReader.communication.C7.Utils
|
namespace TBF.Rig.RegisterReaders.PoseidonReader.communication.C7.Utils
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using TBF.Rig.Generic;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.implementations;
|
||||||
|
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader
|
||||||
|
{
|
||||||
|
public class Factory: IComponentFactory
|
||||||
|
{
|
||||||
|
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
|
||||||
|
|
||||||
|
public override string ToString() { return ClassName; }
|
||||||
|
|
||||||
|
public IComponent DummyComponent() { return new SmartReader(); }
|
||||||
|
|
||||||
|
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new SmartReader(cfg); }
|
||||||
|
|
||||||
|
public IComponentCfg DefaultConfig() { return new iPerlReaderUNI.IPerlCfg(this); } // TODO ????
|
||||||
|
|
||||||
|
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||||
|
{
|
||||||
|
return ComponentCfgBase.CreateFromDbEntity(iPerlReaderUNI.IPerlCfg.Serializer, component, this); // TODO ????
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using Common;
|
||||||
|
using Config.Entities;
|
||||||
|
using TBF.Rig.Generic;
|
||||||
|
using TBF.Rig.RegisterReaders.CommonRR;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlReaderUNI;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader
|
||||||
|
{
|
||||||
|
public class IPerlCfg : ComponentCfgBase, Generic.IComponentCfg
|
||||||
|
{
|
||||||
|
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(IPerlCfg) })[0];
|
||||||
|
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||||
|
public IComponentCfgCtrl GetControl(IList<Component> cmpntEntities)
|
||||||
|
{
|
||||||
|
return new IPerlUniCfgCtrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Serialized parameters
|
||||||
|
///
|
||||||
|
public bool UseTcpIP;
|
||||||
|
public string OptoIPAddress;
|
||||||
|
public ushort OptoTcpipPortNr;
|
||||||
|
public int HeadCommunicationComPortNr;
|
||||||
|
public int OptoComPortNr;
|
||||||
|
public int RfidComPortNr; /// 0 = use MuxBoardNr
|
||||||
|
public int MuxBoardNr; /// 0 = use RfidComPort(Nr), otherwise mux. board nr. 1 .. 4
|
||||||
|
public int Group; /// Number written to QuidoRS to connct the watermeter to RfidComPort, 1 .. 10
|
||||||
|
public CommunicationInterface CommunicationInterface; /// Communication Interface: RFID or NFC
|
||||||
|
|
||||||
|
/// <summary> Procedure parameters </summary>
|
||||||
|
[XmlIgnore]
|
||||||
|
public ProcParams ProcParams;
|
||||||
|
public override IParamsProvider GetRuntimeProcParamsProvider() { return ProcParams; }
|
||||||
|
public override IParamsProvider CreateProcParamsProvider() { return new ProcParams(true); }
|
||||||
|
|
||||||
|
[XmlIgnore]
|
||||||
|
public MeterType MeterType { get { return (ProcParams != null) ? ProcParams.MeterType : MeterType.AutoDetect; } }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Private parameterless constructor invoked by all other (public) constructors
|
||||||
|
IPerlCfg()
|
||||||
|
{
|
||||||
|
Name = "iPerl";
|
||||||
|
ParentName = string.Empty;
|
||||||
|
OptoComPortNr = 10;
|
||||||
|
RfidComPortNr = 0; /// = use mux. board
|
||||||
|
MuxBoardNr = 1;
|
||||||
|
ProcParams = CreateProcParamsProvider() as ProcParams;
|
||||||
|
CommunicationInterface = CommunicationInterface.RFID;
|
||||||
|
HeadCommunicationComPortNr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPerlCfg(IComponentFactory factory)
|
||||||
|
: this()
|
||||||
|
{
|
||||||
|
this.Factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ToString(int i)
|
||||||
|
{
|
||||||
|
return $"{Name} Group1 (mux#)={MuxBoardNr}, Group2={Group}, Opto=Com{OptoComPortNr}, {CommunicationInterface}=Com{RfidComPortNr}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
///
|
||||||
|
/// Copyright (c) 2015-2017 Sensus Metering Systems
|
||||||
|
///
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using Common;
|
||||||
|
using TBF.Resources;
|
||||||
|
using TBF.Rig.Generic;
|
||||||
|
using TBF.Rig.RegisterReaders.CommonRR;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader
|
||||||
|
{
|
||||||
|
public partial class IPerlUniCfgCtrl : UserControl, IComponentCfgCtrl
|
||||||
|
{
|
||||||
|
public bool ShowMore { get { return false; } }
|
||||||
|
|
||||||
|
iPerlReaderUNI.IPerlCfg config;
|
||||||
|
public IComponentCfg Config
|
||||||
|
{
|
||||||
|
get { return config as IComponentCfg; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
config = value as iPerlReaderUNI.IPerlCfg;
|
||||||
|
Redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPerlUniCfgCtrl()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WaterMeterCfgCtrl_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
nameLabel.Text = Strings.Name;
|
||||||
|
classNameLabel.Text = config.Factory.ClassName;
|
||||||
|
Redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Closing()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Redraw()
|
||||||
|
{
|
||||||
|
if (config == null) return; /// Control was not loaded, settings were not changed
|
||||||
|
nameTextBox.Text = config.Name;
|
||||||
|
radioButton1.Checked = config.UseTcpIP;
|
||||||
|
radioButton2.Checked = !config.UseTcpIP;
|
||||||
|
ipAddressTextBox.Text = (config.OptoIPAddress != null) ? config.OptoIPAddress : "0.0.0.0";
|
||||||
|
tcpipPortTextBox.Text = config.OptoTcpipPortNr.ToString();
|
||||||
|
headPortNrTextBox.Text = config.HeadCommunicationComPortNr.ToString();
|
||||||
|
optoSerialPortTextBox.Text = config.OptoComPortNr.ToString();
|
||||||
|
rfidPortNrTextBox.Text = config.RfidComPortNr.ToString();
|
||||||
|
muxBoardNrTextBox.Text = config.MuxBoardNr.ToString();
|
||||||
|
groupTextBox.Text = config.Group.ToString();
|
||||||
|
comboBoxCommunicationInterface.SelectedItem = config.CommunicationInterface.ToString();
|
||||||
|
tabPage2.Controls.Add(new IperlASICUniHeadTestCtrl(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Unlock()
|
||||||
|
{
|
||||||
|
nameTextBox.Enabled = true;
|
||||||
|
radioButton1.Enabled = true;
|
||||||
|
radioButton2.Enabled = true;
|
||||||
|
ipAddressTextBox.Enabled = true;
|
||||||
|
tcpipPortTextBox.Enabled = true;
|
||||||
|
optoSerialPortTextBox.Enabled = true;
|
||||||
|
rfidPortNrTextBox.Enabled = true;
|
||||||
|
headPortNrTextBox.Enabled = true;
|
||||||
|
muxBoardNrTextBox.Enabled = true;
|
||||||
|
groupTextBox.Enabled = true;
|
||||||
|
comboBoxCommunicationInterface.Enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||||
|
{
|
||||||
|
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||||
|
|
||||||
|
int dummy;
|
||||||
|
if (radioButton1.Checked)
|
||||||
|
{
|
||||||
|
IPAddress dummyIPAddress;
|
||||||
|
if (!IPAddress.TryParse(ipAddressTextBox.Text, out dummyIPAddress))
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "'IP address' is not valid";
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort sdummy;
|
||||||
|
if (!ushort.TryParse(tcpipPortTextBox.Text, out sdummy))
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "'TCP/IP port nr.' is not valid";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!int.TryParse(optoSerialPortTextBox.Text, out dummy) || dummy < 1 || dummy > 999)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "'Opto serial port nr.' is not valid";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!int.TryParse(rfidPortNrTextBox.Text, out dummy) || dummy < 0 || dummy > 999)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "'RFID serial port nr.' is not valid";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!int.TryParse(headPortNrTextBox.Text, out dummy) || dummy < 0 || dummy > 999)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "'Head communication serial port nr.' is not valid";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!int.TryParse(muxBoardNrTextBox.Text, out dummy) || dummy < 1 || dummy > 4)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + string.Format(Strings.Invalid_0, muxBoardNrLabel.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!int.TryParse(groupTextBox.Text, out dummy) || dummy < 1 || dummy > 10)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + string.Format(Strings.Invalid_0, groupLabel.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CfgUpdateFlags UpdateCfg()
|
||||||
|
{
|
||||||
|
CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
|
||||||
|
|
||||||
|
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||||
|
|
||||||
|
config.Name = nameTextBox.Text;
|
||||||
|
|
||||||
|
if (radioButton1.Checked)
|
||||||
|
{
|
||||||
|
config.UseTcpIP = true;
|
||||||
|
config.OptoIPAddress = ipAddressTextBox.Text;
|
||||||
|
config.OptoTcpipPortNr = ushort.Parse(tcpipPortTextBox.Text);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
config.UseTcpIP = false;
|
||||||
|
config.OptoComPortNr = int.Parse(optoSerialPortTextBox.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
config.RfidComPortNr = int.Parse(rfidPortNrTextBox.Text);
|
||||||
|
config.MuxBoardNr = int.Parse(muxBoardNrTextBox.Text);
|
||||||
|
config.Group = int.Parse(groupTextBox.Text);
|
||||||
|
config.CommunicationInterface = (CommunicationInterface)comboBoxCommunicationInterface.SelectedIndex;
|
||||||
|
config.HeadCommunicationComPortNr = int.Parse(headPortNrTextBox.Text);
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,441 @@
|
|||||||
|
///
|
||||||
|
/// Copyright (c) 2015-2017 Sensus Metering Systems
|
||||||
|
///
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader
|
||||||
|
{
|
||||||
|
partial class IPerlUniCfgCtrl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||||
|
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||||
|
this.label4 = new System.Windows.Forms.Label();
|
||||||
|
this.label3 = new System.Windows.Forms.Label();
|
||||||
|
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||||
|
this.comboBoxCommunicationInterface = new System.Windows.Forms.ComboBox();
|
||||||
|
this.label1 = new System.Windows.Forms.Label();
|
||||||
|
this.rfidPortNrTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.rfidSerialPortNrLabel = new System.Windows.Forms.Label();
|
||||||
|
this.optoDataGroupBox = new System.Windows.Forms.GroupBox();
|
||||||
|
this.tcpipPortLabel = new System.Windows.Forms.Label();
|
||||||
|
this.tcpipPortTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.ipAddressLabel = new System.Windows.Forms.Label();
|
||||||
|
this.ipAddressTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.radioButton1 = new System.Windows.Forms.RadioButton();
|
||||||
|
this.radioButton2 = new System.Windows.Forms.RadioButton();
|
||||||
|
this.optoSerialPortLabel = new System.Windows.Forms.Label();
|
||||||
|
this.optoSerialPortTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.groupTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.groupLabel = new System.Windows.Forms.Label();
|
||||||
|
this.muxBoardNrTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.muxBoardNrLabel = new System.Windows.Forms.Label();
|
||||||
|
this.nameTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.nameLabel = new System.Windows.Forms.Label();
|
||||||
|
this.classNameLabel = new System.Windows.Forms.Label();
|
||||||
|
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||||
|
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
||||||
|
this.label2 = new System.Windows.Forms.Label();
|
||||||
|
this.headPortNrTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.tabControl1.SuspendLayout();
|
||||||
|
this.tabPage1.SuspendLayout();
|
||||||
|
this.groupBox1.SuspendLayout();
|
||||||
|
this.optoDataGroupBox.SuspendLayout();
|
||||||
|
this.groupBox2.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// tabControl1
|
||||||
|
//
|
||||||
|
this.tabControl1.Controls.Add(this.tabPage1);
|
||||||
|
this.tabControl1.Controls.Add(this.tabPage2);
|
||||||
|
this.tabControl1.Location = new System.Drawing.Point(3, 3);
|
||||||
|
this.tabControl1.Name = "tabControl1";
|
||||||
|
this.tabControl1.SelectedIndex = 0;
|
||||||
|
this.tabControl1.Size = new System.Drawing.Size(611, 432);
|
||||||
|
this.tabControl1.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// tabPage1
|
||||||
|
//
|
||||||
|
this.tabPage1.Controls.Add(this.groupBox2);
|
||||||
|
this.tabPage1.Controls.Add(this.label4);
|
||||||
|
this.tabPage1.Controls.Add(this.label3);
|
||||||
|
this.tabPage1.Controls.Add(this.groupBox1);
|
||||||
|
this.tabPage1.Controls.Add(this.optoDataGroupBox);
|
||||||
|
this.tabPage1.Controls.Add(this.groupTextBox);
|
||||||
|
this.tabPage1.Controls.Add(this.groupLabel);
|
||||||
|
this.tabPage1.Controls.Add(this.muxBoardNrTextBox);
|
||||||
|
this.tabPage1.Controls.Add(this.muxBoardNrLabel);
|
||||||
|
this.tabPage1.Controls.Add(this.nameTextBox);
|
||||||
|
this.tabPage1.Controls.Add(this.nameLabel);
|
||||||
|
this.tabPage1.Controls.Add(this.classNameLabel);
|
||||||
|
this.tabPage1.Location = new System.Drawing.Point(4, 25);
|
||||||
|
this.tabPage1.Name = "tabPage1";
|
||||||
|
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
|
||||||
|
this.tabPage1.Size = new System.Drawing.Size(603, 403);
|
||||||
|
this.tabPage1.TabIndex = 0;
|
||||||
|
this.tabPage1.Text = "Config";
|
||||||
|
this.tabPage1.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// label4
|
||||||
|
//
|
||||||
|
this.label4.AutoSize = true;
|
||||||
|
this.label4.Location = new System.Drawing.Point(208, 101);
|
||||||
|
this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
|
this.label4.Name = "label4";
|
||||||
|
this.label4.Size = new System.Drawing.Size(40, 16);
|
||||||
|
this.label4.TabIndex = 25;
|
||||||
|
this.label4.Text = "1 .. 10";
|
||||||
|
//
|
||||||
|
// label3
|
||||||
|
//
|
||||||
|
this.label3.AutoSize = true;
|
||||||
|
this.label3.Location = new System.Drawing.Point(208, 72);
|
||||||
|
this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
|
this.label3.Name = "label3";
|
||||||
|
this.label3.Size = new System.Drawing.Size(33, 16);
|
||||||
|
this.label3.TabIndex = 24;
|
||||||
|
this.label3.Text = "1 .. 4";
|
||||||
|
//
|
||||||
|
// groupBox1
|
||||||
|
//
|
||||||
|
this.groupBox1.Controls.Add(this.comboBoxCommunicationInterface);
|
||||||
|
this.groupBox1.Controls.Add(this.label1);
|
||||||
|
this.groupBox1.Controls.Add(this.rfidPortNrTextBox);
|
||||||
|
this.groupBox1.Controls.Add(this.rfidSerialPortNrLabel);
|
||||||
|
this.groupBox1.Location = new System.Drawing.Point(10, 259);
|
||||||
|
this.groupBox1.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.groupBox1.Name = "groupBox1";
|
||||||
|
this.groupBox1.Padding = new System.Windows.Forms.Padding(4);
|
||||||
|
this.groupBox1.Size = new System.Drawing.Size(552, 68);
|
||||||
|
this.groupBox1.TabIndex = 23;
|
||||||
|
this.groupBox1.TabStop = false;
|
||||||
|
this.groupBox1.Text = "RFID / NFC communication (in case mux. board is not used)";
|
||||||
|
//
|
||||||
|
// comboBoxCommunicationInterface
|
||||||
|
//
|
||||||
|
this.comboBoxCommunicationInterface.Enabled = false;
|
||||||
|
this.comboBoxCommunicationInterface.FormattingEnabled = true;
|
||||||
|
this.comboBoxCommunicationInterface.Items.AddRange(new object[] {
|
||||||
|
"RFID",
|
||||||
|
"NFC"});
|
||||||
|
this.comboBoxCommunicationInterface.Location = new System.Drawing.Point(201, 27);
|
||||||
|
this.comboBoxCommunicationInterface.Name = "comboBoxCommunicationInterface";
|
||||||
|
this.comboBoxCommunicationInterface.Size = new System.Drawing.Size(71, 24);
|
||||||
|
this.comboBoxCommunicationInterface.TabIndex = 9;
|
||||||
|
//
|
||||||
|
// label1
|
||||||
|
//
|
||||||
|
this.label1.AutoSize = true;
|
||||||
|
this.label1.Location = new System.Drawing.Point(41, 30);
|
||||||
|
this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
|
this.label1.Name = "label1";
|
||||||
|
this.label1.Size = new System.Drawing.Size(153, 16);
|
||||||
|
this.label1.TabIndex = 8;
|
||||||
|
this.label1.Text = "Communication Interface";
|
||||||
|
//
|
||||||
|
// rfidPortNrTextBox
|
||||||
|
//
|
||||||
|
this.rfidPortNrTextBox.Enabled = false;
|
||||||
|
this.rfidPortNrTextBox.Location = new System.Drawing.Point(439, 26);
|
||||||
|
this.rfidPortNrTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.rfidPortNrTextBox.Name = "rfidPortNrTextBox";
|
||||||
|
this.rfidPortNrTextBox.Size = new System.Drawing.Size(44, 22);
|
||||||
|
this.rfidPortNrTextBox.TabIndex = 7;
|
||||||
|
//
|
||||||
|
// rfidSerialPortNrLabel
|
||||||
|
//
|
||||||
|
this.rfidSerialPortNrLabel.AutoSize = true;
|
||||||
|
this.rfidSerialPortNrLabel.Location = new System.Drawing.Point(321, 30);
|
||||||
|
this.rfidSerialPortNrLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
|
this.rfidSerialPortNrLabel.Name = "rfidSerialPortNrLabel";
|
||||||
|
this.rfidSerialPortNrLabel.Size = new System.Drawing.Size(88, 16);
|
||||||
|
this.rfidSerialPortNrLabel.TabIndex = 6;
|
||||||
|
this.rfidSerialPortNrLabel.Text = "Serial port nr.:";
|
||||||
|
//
|
||||||
|
// optoDataGroupBox
|
||||||
|
//
|
||||||
|
this.optoDataGroupBox.Controls.Add(this.tcpipPortLabel);
|
||||||
|
this.optoDataGroupBox.Controls.Add(this.tcpipPortTextBox);
|
||||||
|
this.optoDataGroupBox.Controls.Add(this.ipAddressLabel);
|
||||||
|
this.optoDataGroupBox.Controls.Add(this.ipAddressTextBox);
|
||||||
|
this.optoDataGroupBox.Controls.Add(this.radioButton1);
|
||||||
|
this.optoDataGroupBox.Controls.Add(this.radioButton2);
|
||||||
|
this.optoDataGroupBox.Controls.Add(this.optoSerialPortLabel);
|
||||||
|
this.optoDataGroupBox.Controls.Add(this.optoSerialPortTextBox);
|
||||||
|
this.optoDataGroupBox.Location = new System.Drawing.Point(10, 131);
|
||||||
|
this.optoDataGroupBox.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.optoDataGroupBox.Name = "optoDataGroupBox";
|
||||||
|
this.optoDataGroupBox.Padding = new System.Windows.Forms.Padding(4);
|
||||||
|
this.optoDataGroupBox.Size = new System.Drawing.Size(552, 119);
|
||||||
|
this.optoDataGroupBox.TabIndex = 18;
|
||||||
|
this.optoDataGroupBox.TabStop = false;
|
||||||
|
this.optoDataGroupBox.Text = "Opto-data";
|
||||||
|
//
|
||||||
|
// tcpipPortLabel
|
||||||
|
//
|
||||||
|
this.tcpipPortLabel.AutoSize = true;
|
||||||
|
this.tcpipPortLabel.Location = new System.Drawing.Point(41, 87);
|
||||||
|
this.tcpipPortLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
|
this.tcpipPortLabel.Name = "tcpipPortLabel";
|
||||||
|
this.tcpipPortLabel.Size = new System.Drawing.Size(54, 16);
|
||||||
|
this.tcpipPortLabel.TabIndex = 4;
|
||||||
|
this.tcpipPortLabel.Text = "Port nr..:";
|
||||||
|
//
|
||||||
|
// tcpipPortTextBox
|
||||||
|
//
|
||||||
|
this.tcpipPortTextBox.Enabled = false;
|
||||||
|
this.tcpipPortTextBox.Location = new System.Drawing.Point(143, 84);
|
||||||
|
this.tcpipPortTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.tcpipPortTextBox.Name = "tcpipPortTextBox";
|
||||||
|
this.tcpipPortTextBox.Size = new System.Drawing.Size(51, 22);
|
||||||
|
this.tcpipPortTextBox.TabIndex = 5;
|
||||||
|
//
|
||||||
|
// ipAddressLabel
|
||||||
|
//
|
||||||
|
this.ipAddressLabel.AutoSize = true;
|
||||||
|
this.ipAddressLabel.Location = new System.Drawing.Point(41, 59);
|
||||||
|
this.ipAddressLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
|
this.ipAddressLabel.Name = "ipAddressLabel";
|
||||||
|
this.ipAddressLabel.Size = new System.Drawing.Size(78, 16);
|
||||||
|
this.ipAddressLabel.TabIndex = 2;
|
||||||
|
this.ipAddressLabel.Text = "IP address.:";
|
||||||
|
//
|
||||||
|
// ipAddressTextBox
|
||||||
|
//
|
||||||
|
this.ipAddressTextBox.Enabled = false;
|
||||||
|
this.ipAddressTextBox.Location = new System.Drawing.Point(143, 55);
|
||||||
|
this.ipAddressTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.ipAddressTextBox.Name = "ipAddressTextBox";
|
||||||
|
this.ipAddressTextBox.Size = new System.Drawing.Size(129, 22);
|
||||||
|
this.ipAddressTextBox.TabIndex = 3;
|
||||||
|
//
|
||||||
|
// radioButton1
|
||||||
|
//
|
||||||
|
this.radioButton1.AutoSize = true;
|
||||||
|
this.radioButton1.Checked = true;
|
||||||
|
this.radioButton1.Enabled = false;
|
||||||
|
this.radioButton1.Location = new System.Drawing.Point(29, 23);
|
||||||
|
this.radioButton1.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.radioButton1.Name = "radioButton1";
|
||||||
|
this.radioButton1.Size = new System.Drawing.Size(99, 20);
|
||||||
|
this.radioButton1.TabIndex = 0;
|
||||||
|
this.radioButton1.TabStop = true;
|
||||||
|
this.radioButton1.Text = "Use TCP/IP";
|
||||||
|
this.radioButton1.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// radioButton2
|
||||||
|
//
|
||||||
|
this.radioButton2.AutoSize = true;
|
||||||
|
this.radioButton2.Enabled = false;
|
||||||
|
this.radioButton2.Location = new System.Drawing.Point(312, 23);
|
||||||
|
this.radioButton2.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.radioButton2.Name = "radioButton2";
|
||||||
|
this.radioButton2.Size = new System.Drawing.Size(115, 20);
|
||||||
|
this.radioButton2.TabIndex = 1;
|
||||||
|
this.radioButton2.Text = "Use serial port";
|
||||||
|
this.radioButton2.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// optoSerialPortLabel
|
||||||
|
//
|
||||||
|
this.optoSerialPortLabel.AutoSize = true;
|
||||||
|
this.optoSerialPortLabel.Location = new System.Drawing.Point(321, 55);
|
||||||
|
this.optoSerialPortLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
|
this.optoSerialPortLabel.Name = "optoSerialPortLabel";
|
||||||
|
this.optoSerialPortLabel.Size = new System.Drawing.Size(88, 16);
|
||||||
|
this.optoSerialPortLabel.TabIndex = 6;
|
||||||
|
this.optoSerialPortLabel.Text = "Serial port nr.:";
|
||||||
|
//
|
||||||
|
// optoSerialPortTextBox
|
||||||
|
//
|
||||||
|
this.optoSerialPortTextBox.Enabled = false;
|
||||||
|
this.optoSerialPortTextBox.Location = new System.Drawing.Point(439, 52);
|
||||||
|
this.optoSerialPortTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.optoSerialPortTextBox.Name = "optoSerialPortTextBox";
|
||||||
|
this.optoSerialPortTextBox.Size = new System.Drawing.Size(44, 22);
|
||||||
|
this.optoSerialPortTextBox.TabIndex = 7;
|
||||||
|
//
|
||||||
|
// groupTextBox
|
||||||
|
//
|
||||||
|
this.groupTextBox.Enabled = false;
|
||||||
|
this.groupTextBox.Location = new System.Drawing.Point(153, 97);
|
||||||
|
this.groupTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.groupTextBox.Name = "groupTextBox";
|
||||||
|
this.groupTextBox.Size = new System.Drawing.Size(44, 22);
|
||||||
|
this.groupTextBox.TabIndex = 22;
|
||||||
|
//
|
||||||
|
// groupLabel
|
||||||
|
//
|
||||||
|
this.groupLabel.AutoSize = true;
|
||||||
|
this.groupLabel.Location = new System.Drawing.Point(6, 101);
|
||||||
|
this.groupLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
|
this.groupLabel.Name = "groupLabel";
|
||||||
|
this.groupLabel.Size = new System.Drawing.Size(54, 16);
|
||||||
|
this.groupLabel.TabIndex = 21;
|
||||||
|
this.groupLabel.Text = "Group 2";
|
||||||
|
//
|
||||||
|
// muxBoardNrTextBox
|
||||||
|
//
|
||||||
|
this.muxBoardNrTextBox.Enabled = false;
|
||||||
|
this.muxBoardNrTextBox.Location = new System.Drawing.Point(153, 69);
|
||||||
|
this.muxBoardNrTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.muxBoardNrTextBox.Name = "muxBoardNrTextBox";
|
||||||
|
this.muxBoardNrTextBox.Size = new System.Drawing.Size(44, 22);
|
||||||
|
this.muxBoardNrTextBox.TabIndex = 20;
|
||||||
|
//
|
||||||
|
// muxBoardNrLabel
|
||||||
|
//
|
||||||
|
this.muxBoardNrLabel.AutoSize = true;
|
||||||
|
this.muxBoardNrLabel.Location = new System.Drawing.Point(6, 72);
|
||||||
|
this.muxBoardNrLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
|
this.muxBoardNrLabel.Name = "muxBoardNrLabel";
|
||||||
|
this.muxBoardNrLabel.Size = new System.Drawing.Size(131, 16);
|
||||||
|
this.muxBoardNrLabel.TabIndex = 19;
|
||||||
|
this.muxBoardNrLabel.Text = "Group 1 (mux. board)";
|
||||||
|
//
|
||||||
|
// nameTextBox
|
||||||
|
//
|
||||||
|
this.nameTextBox.Enabled = false;
|
||||||
|
this.nameTextBox.Location = new System.Drawing.Point(153, 40);
|
||||||
|
this.nameTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.nameTextBox.Name = "nameTextBox";
|
||||||
|
this.nameTextBox.Size = new System.Drawing.Size(160, 22);
|
||||||
|
this.nameTextBox.TabIndex = 17;
|
||||||
|
//
|
||||||
|
// nameLabel
|
||||||
|
//
|
||||||
|
this.nameLabel.AutoSize = true;
|
||||||
|
this.nameLabel.Location = new System.Drawing.Point(6, 44);
|
||||||
|
this.nameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
|
this.nameLabel.Name = "nameLabel";
|
||||||
|
this.nameLabel.Size = new System.Drawing.Size(44, 16);
|
||||||
|
this.nameLabel.TabIndex = 16;
|
||||||
|
this.nameLabel.Text = "Name";
|
||||||
|
//
|
||||||
|
// classNameLabel
|
||||||
|
//
|
||||||
|
this.classNameLabel.AutoSize = true;
|
||||||
|
this.classNameLabel.Location = new System.Drawing.Point(149, 11);
|
||||||
|
this.classNameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
|
this.classNameLabel.Name = "classNameLabel";
|
||||||
|
this.classNameLabel.Size = new System.Drawing.Size(78, 16);
|
||||||
|
this.classNameLabel.TabIndex = 15;
|
||||||
|
this.classNameLabel.Text = "ClassName";
|
||||||
|
//
|
||||||
|
// tabPage2
|
||||||
|
//
|
||||||
|
this.tabPage2.Location = new System.Drawing.Point(4, 25);
|
||||||
|
this.tabPage2.Name = "tabPage2";
|
||||||
|
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
|
||||||
|
this.tabPage2.Size = new System.Drawing.Size(603, 403);
|
||||||
|
this.tabPage2.TabIndex = 1;
|
||||||
|
this.tabPage2.Text = "Test";
|
||||||
|
this.tabPage2.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// groupBox2
|
||||||
|
//
|
||||||
|
this.groupBox2.Controls.Add(this.headPortNrTextBox);
|
||||||
|
this.groupBox2.Controls.Add(this.label2);
|
||||||
|
this.groupBox2.Location = new System.Drawing.Point(10, 335);
|
||||||
|
this.groupBox2.Name = "groupBox2";
|
||||||
|
this.groupBox2.Size = new System.Drawing.Size(552, 50);
|
||||||
|
this.groupBox2.TabIndex = 26;
|
||||||
|
this.groupBox2.TabStop = false;
|
||||||
|
this.groupBox2.Text = "Head Communication";
|
||||||
|
//
|
||||||
|
// label2
|
||||||
|
//
|
||||||
|
this.label2.AutoSize = true;
|
||||||
|
this.label2.Location = new System.Drawing.Point(321, 18);
|
||||||
|
this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||||
|
this.label2.Name = "label2";
|
||||||
|
this.label2.Size = new System.Drawing.Size(88, 16);
|
||||||
|
this.label2.TabIndex = 7;
|
||||||
|
this.label2.Text = "Serial port nr.:";
|
||||||
|
//
|
||||||
|
// headPortNrTextBox
|
||||||
|
//
|
||||||
|
this.headPortNrTextBox.Enabled = false;
|
||||||
|
this.headPortNrTextBox.Location = new System.Drawing.Point(439, 15);
|
||||||
|
this.headPortNrTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.headPortNrTextBox.Name = "headPortNrTextBox";
|
||||||
|
this.headPortNrTextBox.Size = new System.Drawing.Size(44, 22);
|
||||||
|
this.headPortNrTextBox.TabIndex = 8;
|
||||||
|
//
|
||||||
|
// IperlHeadCfgCtrl
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.Controls.Add(this.tabControl1);
|
||||||
|
this.Margin = new System.Windows.Forms.Padding(4);
|
||||||
|
this.Name = "IPerlUniCfgCtrl";
|
||||||
|
this.Size = new System.Drawing.Size(617, 438);
|
||||||
|
this.Load += new System.EventHandler(this.WaterMeterCfgCtrl_Load);
|
||||||
|
this.tabControl1.ResumeLayout(false);
|
||||||
|
this.tabPage1.ResumeLayout(false);
|
||||||
|
this.tabPage1.PerformLayout();
|
||||||
|
this.groupBox1.ResumeLayout(false);
|
||||||
|
this.groupBox1.PerformLayout();
|
||||||
|
this.optoDataGroupBox.ResumeLayout(false);
|
||||||
|
this.optoDataGroupBox.PerformLayout();
|
||||||
|
this.groupBox2.ResumeLayout(false);
|
||||||
|
this.groupBox2.PerformLayout();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.TabControl tabControl1;
|
||||||
|
private System.Windows.Forms.TabPage tabPage1;
|
||||||
|
private System.Windows.Forms.Label label4;
|
||||||
|
private System.Windows.Forms.Label label3;
|
||||||
|
private System.Windows.Forms.GroupBox groupBox1;
|
||||||
|
private System.Windows.Forms.ComboBox comboBoxCommunicationInterface;
|
||||||
|
private System.Windows.Forms.Label label1;
|
||||||
|
private System.Windows.Forms.TextBox rfidPortNrTextBox;
|
||||||
|
private System.Windows.Forms.Label rfidSerialPortNrLabel;
|
||||||
|
private System.Windows.Forms.GroupBox optoDataGroupBox;
|
||||||
|
private System.Windows.Forms.Label tcpipPortLabel;
|
||||||
|
private System.Windows.Forms.TextBox tcpipPortTextBox;
|
||||||
|
private System.Windows.Forms.Label ipAddressLabel;
|
||||||
|
private System.Windows.Forms.TextBox ipAddressTextBox;
|
||||||
|
private System.Windows.Forms.RadioButton radioButton1;
|
||||||
|
private System.Windows.Forms.RadioButton radioButton2;
|
||||||
|
private System.Windows.Forms.Label optoSerialPortLabel;
|
||||||
|
private System.Windows.Forms.TextBox optoSerialPortTextBox;
|
||||||
|
private System.Windows.Forms.TextBox groupTextBox;
|
||||||
|
private System.Windows.Forms.Label groupLabel;
|
||||||
|
private System.Windows.Forms.TextBox muxBoardNrTextBox;
|
||||||
|
private System.Windows.Forms.Label muxBoardNrLabel;
|
||||||
|
private System.Windows.Forms.TextBox nameTextBox;
|
||||||
|
private System.Windows.Forms.Label nameLabel;
|
||||||
|
private System.Windows.Forms.Label classNameLabel;
|
||||||
|
private System.Windows.Forms.TabPage tabPage2;
|
||||||
|
private System.Windows.Forms.GroupBox groupBox2;
|
||||||
|
private System.Windows.Forms.TextBox headPortNrTextBox;
|
||||||
|
private System.Windows.Forms.Label label2;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
+137
@@ -0,0 +1,137 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader
|
||||||
|
{
|
||||||
|
partial class IperlASICUniHeadTestCtrl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.optoTestGroupBox = new System.Windows.Forms.GroupBox();
|
||||||
|
this.optoListBox = new System.Windows.Forms.ListBox();
|
||||||
|
this.rfidOutputListBox = new System.Windows.Forms.ListBox();
|
||||||
|
this.RfidTestGroupBox = new System.Windows.Forms.GroupBox();
|
||||||
|
this.label2 = new System.Windows.Forms.Label();
|
||||||
|
this.rfidCommandComboBox = new System.Windows.Forms.ComboBox();
|
||||||
|
this.commandTestButton = new System.Windows.Forms.Button();
|
||||||
|
this.optoTestGroupBox.SuspendLayout();
|
||||||
|
this.RfidTestGroupBox.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// optoTestGroupBox
|
||||||
|
//
|
||||||
|
this.optoTestGroupBox.Controls.Add(this.optoListBox);
|
||||||
|
this.optoTestGroupBox.Location = new System.Drawing.Point(5, 4);
|
||||||
|
this.optoTestGroupBox.Name = "optoTestGroupBox";
|
||||||
|
this.optoTestGroupBox.Size = new System.Drawing.Size(591, 161);
|
||||||
|
this.optoTestGroupBox.TabIndex = 2;
|
||||||
|
this.optoTestGroupBox.TabStop = false;
|
||||||
|
this.optoTestGroupBox.Text = "Opto-data";
|
||||||
|
//
|
||||||
|
// optoListBox
|
||||||
|
//
|
||||||
|
this.optoListBox.FormattingEnabled = true;
|
||||||
|
this.optoListBox.ItemHeight = 16;
|
||||||
|
this.optoListBox.Location = new System.Drawing.Point(7, 22);
|
||||||
|
this.optoListBox.Name = "optoListBox";
|
||||||
|
this.optoListBox.Size = new System.Drawing.Size(573, 132);
|
||||||
|
this.optoListBox.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// rfidOutputListBox
|
||||||
|
//
|
||||||
|
this.rfidOutputListBox.FormattingEnabled = true;
|
||||||
|
this.rfidOutputListBox.ItemHeight = 16;
|
||||||
|
this.rfidOutputListBox.Location = new System.Drawing.Point(5, 54);
|
||||||
|
this.rfidOutputListBox.Name = "rfidOutputListBox";
|
||||||
|
this.rfidOutputListBox.SelectionMode = System.Windows.Forms.SelectionMode.None;
|
||||||
|
this.rfidOutputListBox.Size = new System.Drawing.Size(575, 164);
|
||||||
|
this.rfidOutputListBox.TabIndex = 3;
|
||||||
|
//
|
||||||
|
// RfidTestGroupBox
|
||||||
|
//
|
||||||
|
this.RfidTestGroupBox.Controls.Add(this.rfidOutputListBox);
|
||||||
|
this.RfidTestGroupBox.Controls.Add(this.label2);
|
||||||
|
this.RfidTestGroupBox.Controls.Add(this.rfidCommandComboBox);
|
||||||
|
this.RfidTestGroupBox.Controls.Add(this.commandTestButton);
|
||||||
|
this.RfidTestGroupBox.Location = new System.Drawing.Point(5, 171);
|
||||||
|
this.RfidTestGroupBox.Name = "RfidTestGroupBox";
|
||||||
|
this.RfidTestGroupBox.Size = new System.Drawing.Size(591, 224);
|
||||||
|
this.RfidTestGroupBox.TabIndex = 3;
|
||||||
|
this.RfidTestGroupBox.TabStop = false;
|
||||||
|
this.RfidTestGroupBox.Text = "RFID / NFC data";
|
||||||
|
//
|
||||||
|
// label2
|
||||||
|
//
|
||||||
|
this.label2.AutoSize = true;
|
||||||
|
this.label2.Location = new System.Drawing.Point(2, 25);
|
||||||
|
this.label2.Name = "label2";
|
||||||
|
this.label2.Size = new System.Drawing.Size(69, 16);
|
||||||
|
this.label2.TabIndex = 2;
|
||||||
|
this.label2.Text = "Command";
|
||||||
|
//
|
||||||
|
// rfidCommandComboBox
|
||||||
|
//
|
||||||
|
this.rfidCommandComboBox.FormattingEnabled = true;
|
||||||
|
this.rfidCommandComboBox.Location = new System.Drawing.Point(86, 19);
|
||||||
|
this.rfidCommandComboBox.Name = "rfidCommandComboBox";
|
||||||
|
this.rfidCommandComboBox.Size = new System.Drawing.Size(341, 24);
|
||||||
|
this.rfidCommandComboBox.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// commandTestButton
|
||||||
|
//
|
||||||
|
this.commandTestButton.Location = new System.Drawing.Point(449, 19);
|
||||||
|
this.commandTestButton.Name = "commandTestButton";
|
||||||
|
this.commandTestButton.Size = new System.Drawing.Size(126, 24);
|
||||||
|
this.commandTestButton.TabIndex = 0;
|
||||||
|
this.commandTestButton.Text = "Send command";
|
||||||
|
this.commandTestButton.UseVisualStyleBackColor = true;
|
||||||
|
this.commandTestButton.MouseClick += new System.Windows.Forms.MouseEventHandler(this.CommandTestButtonClick);
|
||||||
|
//
|
||||||
|
// IperlHeadTestCtrl
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.Controls.Add(this.optoTestGroupBox);
|
||||||
|
this.Controls.Add(this.RfidTestGroupBox);
|
||||||
|
this.Name = "IperlASICUniHeadTestCtrl";
|
||||||
|
this.Size = new System.Drawing.Size(611, 432);
|
||||||
|
this.Load += new System.EventHandler(this.UserControl_Load);
|
||||||
|
this.optoTestGroupBox.ResumeLayout(false);
|
||||||
|
this.RfidTestGroupBox.ResumeLayout(false);
|
||||||
|
this.RfidTestGroupBox.PerformLayout();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.GroupBox optoTestGroupBox;
|
||||||
|
private System.Windows.Forms.ListBox rfidOutputListBox;
|
||||||
|
private System.Windows.Forms.GroupBox RfidTestGroupBox;
|
||||||
|
private System.Windows.Forms.Label label2;
|
||||||
|
private System.Windows.Forms.ComboBox rfidCommandComboBox;
|
||||||
|
private System.Windows.Forms.Button commandTestButton;
|
||||||
|
private System.Windows.Forms.ListBox optoListBox;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TBF.Rig.RegisterReaders.CommonRR.IPerl.communication;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.implementations;
|
||||||
|
using TBF.Rig.RegisterReaders.IPerlReader.implementations;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlReaderUNI;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlReaderUNI.common;
|
||||||
|
using TBF.Rig.Sequences;
|
||||||
|
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader
|
||||||
|
{
|
||||||
|
public partial class IperlASICUniHeadTestCtrl : UserControl
|
||||||
|
{
|
||||||
|
private IUniHeadTestCtrl _ctrl;
|
||||||
|
private IUniHeadTestCtrl Ctrl { get => _ctrl; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public IperlASICUniHeadTestCtrl(iPerlReaderUNI.IPerlCfg config)
|
||||||
|
{
|
||||||
|
this._ctrl = new IPerlASICImplHeadTestCtrl();
|
||||||
|
Ctrl.config = config;
|
||||||
|
InitializeComponent();
|
||||||
|
if (config == null) return;
|
||||||
|
|
||||||
|
SmartCommunicationForm.TestMethodCfg = new TestMethodCfg(null); // default values for iPerlCommunication
|
||||||
|
|
||||||
|
foreach(var head in ProcessData.SmartHeadsUni)
|
||||||
|
{
|
||||||
|
if (head != null && head.Name == config.Name) { Ctrl.ISmartReader = head; }
|
||||||
|
}
|
||||||
|
|
||||||
|
rfidCommandComboBox.DisplayMember = "Name";
|
||||||
|
rfidCommandComboBox.ValueMember = "Value";
|
||||||
|
var items = Ctrl.GetComboOperationsPairs();
|
||||||
|
/*
|
||||||
|
// CTRL+ALT+double click - hidden poweruser menu
|
||||||
|
if (((Keyboard.ModifierKeys & Keys.Control) == Keys.Control) && ((Keyboard.ModifierKeys & Keys.Alt) == Keys.Alt) && Users.CurrentUser.AuthorizedAs == AuthorizedAs.PowerUser)
|
||||||
|
{
|
||||||
|
Array.Resize(ref items, items.Length + 1);
|
||||||
|
items[items.Length - 1] = new { Name = "Kluc", Value = "Kluc" };
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
rfidCommandComboBox.DataSource = items.Select(i => i.Name).ToArray();
|
||||||
|
|
||||||
|
Ctrl.Initialize();
|
||||||
|
|
||||||
|
Ctrl.OptoReceivedHandler += (EventHandler<OptoReceivedEventArgs>)((sndr, args) =>
|
||||||
|
{
|
||||||
|
if (this.InvokeRequired)
|
||||||
|
this.Invoke((Delegate)new EventHandler<OptoReceivedEventArgs>(this.OnOptoReceived2), sndr, (object)args);
|
||||||
|
else
|
||||||
|
this.OnOptoReceived2(sndr, args);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnOptoReceived2(object sender, OptoReceivedEventArgs args)
|
||||||
|
{
|
||||||
|
optoListBox.Items.Insert(0,args.Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CommandTestButtonClick(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
Ctrl.CommandTestButtonClick(sender, e, new Arguments()
|
||||||
|
{
|
||||||
|
ISmartReader = Ctrl.ISmartReader,
|
||||||
|
OptoListBox = optoListBox,
|
||||||
|
RfidCommandComboBox = rfidCommandComboBox,
|
||||||
|
RfidOutputListBox = rfidOutputListBox
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void UserControl_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
this.ParentForm.FormClosing += new FormClosingEventHandler(ParentForm_FormClosing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParentForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||||
|
{
|
||||||
|
//OnHandleDestroyed(new EventArgs());
|
||||||
|
Ctrl.Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol
|
||||||
|
{
|
||||||
|
public static class Constants
|
||||||
|
{
|
||||||
|
public const byte Start = 0x53; //'S'
|
||||||
|
public const byte Write = 0x57; // 'W'
|
||||||
|
public const byte Read = 0x52; // 'R'
|
||||||
|
public const byte End = 0x0D; //'.'
|
||||||
|
public const byte Question = (byte)0x3F; // '?'
|
||||||
|
public static readonly byte[] Version = {0x76, 0x65, 0x72, 0x73 }; // 'v' 'e' 'r' 's'
|
||||||
|
|
||||||
|
public const byte StatusOk = 0x01;
|
||||||
|
public const byte StatusNok = 0x00;
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol
|
||||||
|
{
|
||||||
|
public sealed class IperlHatFrame
|
||||||
|
{
|
||||||
|
public byte Start { get; }
|
||||||
|
public byte Direction { get; }
|
||||||
|
public byte End { get; }
|
||||||
|
public byte Length { get; }
|
||||||
|
|
||||||
|
public byte[] CommandInformation { get; }
|
||||||
|
public byte[] Payload { get; }
|
||||||
|
|
||||||
|
public IperlHatFrame(byte start, byte direction, byte length, byte[] commandBytes, byte[] payload, byte end)
|
||||||
|
{
|
||||||
|
Start = start;
|
||||||
|
Direction = direction;
|
||||||
|
Length = length;
|
||||||
|
CommandInformation = commandBytes ?? Array.Empty<byte>();
|
||||||
|
Payload = payload ?? Array.Empty<byte>();
|
||||||
|
End = end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+158
@@ -0,0 +1,158 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.protocolCommons;
|
||||||
|
using TBF.Rig.RegisterReaders.PoseidonReader.communication.C7;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol
|
||||||
|
{
|
||||||
|
public sealed class IperlHatFrameBuilder
|
||||||
|
{
|
||||||
|
|
||||||
|
private byte _direction;
|
||||||
|
private readonly List<byte> _commandBytes = new List<byte>();
|
||||||
|
private readonly List<byte> _payload = new List<byte>();
|
||||||
|
|
||||||
|
public IperlHatFrameBuilder RequestResponse(bool enabled)
|
||||||
|
{
|
||||||
|
_direction = enabled ? Constants.Write : Constants.Read;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IperlHatFrameBuilder AddCommand(ProtocolCommand command)
|
||||||
|
{
|
||||||
|
_commandBytes.Add((byte)command);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IperlHatFrameBuilder AddSubCommand(ProtocolCommand subCommand)
|
||||||
|
{
|
||||||
|
if (_commandBytes.Count == 0 ||
|
||||||
|
_commandBytes[0] != (byte)ProtocolCommand.DeviceSpecific)
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Sub-command is only valid for DeviceSpecific (0xFD) commands.");
|
||||||
|
|
||||||
|
_commandBytes.Add((byte)subCommand);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IperlHatFrameBuilder AddSubCommand(ProtocolStatuses subCommand)
|
||||||
|
{
|
||||||
|
if (_commandBytes.Count == 0 ||
|
||||||
|
_commandBytes[0] != (byte)ProtocolCommand.SetState)
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Sub-command is only valid for SetState (0xA1) commands.");
|
||||||
|
|
||||||
|
_commandBytes.Add((byte)subCommand);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IperlHatFrameBuilder AddDeviceCommand(
|
||||||
|
ProtocolDeviceSubCommand subCommand)
|
||||||
|
{
|
||||||
|
_commandBytes.Add((byte)ProtocolCommand.DeviceSpecific);
|
||||||
|
_commandBytes.Add((byte)subCommand);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IperlHatFrameBuilder SetVersionCommand()
|
||||||
|
{
|
||||||
|
_commandBytes.Add((byte)ProtocolCommand.Question);
|
||||||
|
_payload.AddRange(Constants.Version);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IperlHatFrameBuilder AddPayload(byte[] payload)
|
||||||
|
{
|
||||||
|
if (payload != null)
|
||||||
|
_payload.AddRange(payload);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IperlHatFrameBuilder AddPayload(DiagnosticLedState state)
|
||||||
|
{
|
||||||
|
_payload.Add((byte)state);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IperlHatFrameBuilder AddPayload(byte payload)
|
||||||
|
{
|
||||||
|
_payload.Add(payload);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IperlHatFrameBuilder AddDiagnosticLedState(DiagnosticLedState state)
|
||||||
|
{
|
||||||
|
RequestResponse(true);
|
||||||
|
AddDeviceCommand(ProtocolDeviceSubCommand.SetDiagnosticLEDState);
|
||||||
|
AddPayload((byte)state);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IperlHatFrameBuilder AddNullTerminatedAscii(string text)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(text))
|
||||||
|
_commandBytes.AddRange(
|
||||||
|
System.Text.Encoding.ASCII.GetBytes(text));
|
||||||
|
|
||||||
|
_commandBytes.Add(0x00);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IperlHatFrame BuildFrame()
|
||||||
|
{
|
||||||
|
if (_commandBytes.Count == 0)
|
||||||
|
throw new InvalidOperationException("No command specified.");
|
||||||
|
|
||||||
|
byte length = (byte)(4 + _commandBytes.Count + _payload.Count); // 4 = START + dirrection + LEN + END
|
||||||
|
|
||||||
|
|
||||||
|
return new IperlHatFrame(
|
||||||
|
Constants.Start,
|
||||||
|
_direction,
|
||||||
|
length,
|
||||||
|
_commandBytes.ToArray(),
|
||||||
|
_payload.ToArray(),
|
||||||
|
Constants.End);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] BuildBytes()
|
||||||
|
{
|
||||||
|
IperlHatFrame frame = BuildFrame();
|
||||||
|
|
||||||
|
if (frame.CommandInformation.Length > 0 && frame.CommandInformation[0] == Constants.Question)
|
||||||
|
{
|
||||||
|
var bytes = new List<byte>
|
||||||
|
{
|
||||||
|
frame.Start,
|
||||||
|
frame.Direction,
|
||||||
|
};
|
||||||
|
|
||||||
|
bytes.AddRange(frame.CommandInformation);
|
||||||
|
bytes.AddRange(frame.Payload);
|
||||||
|
bytes.Add(frame.End);
|
||||||
|
|
||||||
|
return bytes.ToArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var bytes = new List<byte>
|
||||||
|
{
|
||||||
|
frame.Start,
|
||||||
|
frame.Direction,
|
||||||
|
frame.Length,
|
||||||
|
};
|
||||||
|
|
||||||
|
bytes.AddRange(frame.CommandInformation);
|
||||||
|
bytes.AddRange(frame.Payload);
|
||||||
|
bytes.Add(frame.End);
|
||||||
|
|
||||||
|
return bytes.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+133
@@ -0,0 +1,133 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol
|
||||||
|
{
|
||||||
|
public sealed class IperlHatFrameParser
|
||||||
|
{
|
||||||
|
|
||||||
|
public IperlHatResponse Parse(byte[] data)
|
||||||
|
{
|
||||||
|
if (data == null)
|
||||||
|
throw new ArgumentNullException(nameof(data));
|
||||||
|
|
||||||
|
if (data.Length < 5)
|
||||||
|
throw new FormatException("Frame too short.");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (data[0] != Constants.Start)
|
||||||
|
{
|
||||||
|
//if version parse version
|
||||||
|
if (data[0] == Constants.Question)
|
||||||
|
{
|
||||||
|
//Define Question answer
|
||||||
|
var prefix = new List<byte>{ Constants.Question };
|
||||||
|
var end = new List<byte>{ Constants.End };
|
||||||
|
|
||||||
|
if (IsPrefixValid(data, prefix, end))
|
||||||
|
{
|
||||||
|
//whole payload may be like "vers: Harry T:B800, V:06.06.01, FW:190215, 7ECE, B1.6.01, HW:4, Serial:0"
|
||||||
|
prefix = new List<byte>{ Constants.Question };
|
||||||
|
byte[] payloadVersion = ExtractPayloadUsePrefix(data, prefix, end);
|
||||||
|
return new IperlHatResponse(Constants.Question, payloadVersion.Length > 0 ? Constants.StatusOk : Constants.StatusNok, payloadVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new FormatException("Invalid START byte.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data[1] != Constants.Read)
|
||||||
|
throw new FormatException("Frame is no Response.");
|
||||||
|
|
||||||
|
byte length = data[2];
|
||||||
|
if (length != data.Length)
|
||||||
|
throw new FormatException("Length mismatch.");
|
||||||
|
|
||||||
|
byte direction = data[1];
|
||||||
|
byte status = data[3];
|
||||||
|
|
||||||
|
var prefixCommand = new List<byte>{ Constants.Start,direction,length,status };
|
||||||
|
var endCommand = new List<byte>{ Constants.End };
|
||||||
|
|
||||||
|
byte[] payload = ExtractPayloadUsePrefix(data,prefixCommand,endCommand);
|
||||||
|
|
||||||
|
return new IperlHatResponse(0x00, status, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static byte[] ExtractPayloadUsePrefix(byte[] data, List<byte> prefix, List<byte> end)
|
||||||
|
{
|
||||||
|
// payload exists only if frame longer than:
|
||||||
|
// START + DIRECTION + LEN + CTRL + END = 5 bytes
|
||||||
|
// OR VERSION_START + VERSION = 5 bytes
|
||||||
|
if (data.Length <= 5)
|
||||||
|
return Array.Empty<byte>();
|
||||||
|
|
||||||
|
//check prefix is equal
|
||||||
|
int prefixLength = prefix.Count;
|
||||||
|
byte[] commandPrefix = new byte[prefixLength];
|
||||||
|
Buffer.BlockCopy(data, 0, commandPrefix, 0, prefixLength);
|
||||||
|
|
||||||
|
if (StartsWithPrefix(end, commandPrefix))
|
||||||
|
{
|
||||||
|
return Array.Empty<byte>();
|
||||||
|
}
|
||||||
|
|
||||||
|
int payloadLength = data.Length - (prefix.Count + end.Count);
|
||||||
|
byte[] payload = new byte[payloadLength];
|
||||||
|
Buffer.BlockCopy(data, prefix.Count, payload, 0, payloadLength);
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsPrefixValid(byte[] data, List<byte> prefix, List<byte> end)
|
||||||
|
{
|
||||||
|
int prefixLength = prefix.Count;
|
||||||
|
// payload exists only if frame longer than:
|
||||||
|
// OR VERSION_START + VERSION = 5 bytes - "?VERS" version implemented
|
||||||
|
if (data.Length <= prefixLength) // need be and on END
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//check prefix is equal
|
||||||
|
byte[] commandPrefix = new byte[prefixLength];
|
||||||
|
Buffer.BlockCopy(data, 0, commandPrefix, 0, prefixLength);
|
||||||
|
|
||||||
|
if (StartsWithPrefix(end, commandPrefix))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool StartsWithPrefix(List<byte> data, byte[] prefix)
|
||||||
|
{
|
||||||
|
if (data.Count < prefix.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < prefix.Length; i++)
|
||||||
|
{
|
||||||
|
if (data[i] != prefix[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ExtractVersionPayload(byte[] data)
|
||||||
|
{
|
||||||
|
// payload exists only if frame longer than:
|
||||||
|
// START + LEN + CTRL + STATUS + CHK_HI + CHK_LO = 6 bytes
|
||||||
|
if (data.Length <= 5)
|
||||||
|
return Array.Empty<byte>();
|
||||||
|
|
||||||
|
int payloadLength = data.Length - 4;
|
||||||
|
byte[] payload = new byte[payloadLength];
|
||||||
|
Buffer.BlockCopy(data, 5, payload, 0, payloadLength);
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol
|
||||||
|
{
|
||||||
|
public static class IperlHatProtocol
|
||||||
|
{
|
||||||
|
public const byte START = 0x0D;
|
||||||
|
|
||||||
|
// Control bits (CNTRL1)
|
||||||
|
public const byte RESPONSE_FLAG = 0x08; // RF
|
||||||
|
}
|
||||||
|
}
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol
|
||||||
|
{
|
||||||
|
public sealed class IperlHatResponse
|
||||||
|
{
|
||||||
|
public byte Control { get; } //classic control byte - valid for question now
|
||||||
|
private byte Status { get; }
|
||||||
|
public byte[] Payload { get; }
|
||||||
|
|
||||||
|
public bool IsOk => Status == Constants.StatusOk;
|
||||||
|
|
||||||
|
public IperlHatResponse(byte control, byte status, byte[] payload)
|
||||||
|
{
|
||||||
|
Control = control;
|
||||||
|
Status = status;
|
||||||
|
Payload = payload ?? Array.Empty<byte>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string GetAsciiPayload()
|
||||||
|
{
|
||||||
|
if (Payload.Length == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int length = Array.IndexOf(Payload, (byte)0x00);
|
||||||
|
if (length < 0)
|
||||||
|
length = Payload.Length;
|
||||||
|
|
||||||
|
return System.Text.Encoding.ASCII.GetString(Payload, 0, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+75
@@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.utils;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed
|
||||||
|
{
|
||||||
|
public sealed class DiagnosticLedParser
|
||||||
|
{
|
||||||
|
private readonly DiagnosticLedState _state;
|
||||||
|
|
||||||
|
public DiagnosticLedParser(DiagnosticLedState state)
|
||||||
|
{
|
||||||
|
_state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiagnosticLedData ParseLine(string line, bool checkLineTermination = true)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(line))
|
||||||
|
throw new ArgumentNullException(nameof(line));
|
||||||
|
|
||||||
|
if (checkLineTermination && !line.EndsWith("\r\n"))
|
||||||
|
throw new FormatException("Invalid diagnostic LED line termination");
|
||||||
|
|
||||||
|
string trimmed = line.TrimEnd('\r', '\n');
|
||||||
|
string[] parts = trimmed.Split('\t');
|
||||||
|
|
||||||
|
if (parts.Length < 2)
|
||||||
|
throw new FormatException("Too few diagnostic LED fields");
|
||||||
|
|
||||||
|
// ---- Checksum ----
|
||||||
|
string checksumHex = parts[parts.Length - 1];
|
||||||
|
|
||||||
|
int lastTab = trimmed.LastIndexOf('\t');
|
||||||
|
if (lastTab < 0)
|
||||||
|
throw new FormatException("Checksum separator not found");
|
||||||
|
|
||||||
|
string beforeChecksum = trimmed.Substring(0, lastTab + 1);
|
||||||
|
|
||||||
|
byte expected = DiagnosticChecksum.Compute(beforeChecksum);
|
||||||
|
byte actual = DiagnosticHex.ParseByte(checksumHex);
|
||||||
|
|
||||||
|
if (expected != actual)
|
||||||
|
throw new FormatException("Diagnostic LED checksum mismatch");
|
||||||
|
|
||||||
|
// ---- Dispatch ----
|
||||||
|
switch (_state)
|
||||||
|
{
|
||||||
|
case DiagnosticLedState.State1:
|
||||||
|
return new DiagnosticLedState1Data(line, parts);
|
||||||
|
|
||||||
|
case DiagnosticLedState.State2:
|
||||||
|
return new DiagnosticLedState2Data(line, parts);
|
||||||
|
|
||||||
|
case DiagnosticLedState.State3:
|
||||||
|
return new DiagnosticLedState3Data(line, parts);
|
||||||
|
|
||||||
|
case DiagnosticLedState.State4:
|
||||||
|
return new DiagnosticLedState4Data(line, parts);
|
||||||
|
|
||||||
|
case DiagnosticLedState.State5:
|
||||||
|
return new DiagnosticLedState5Data(line, parts);
|
||||||
|
|
||||||
|
case DiagnosticLedState.State6:
|
||||||
|
return new DiagnosticLedState6Data(line, parts);
|
||||||
|
|
||||||
|
case DiagnosticLedState.State7:
|
||||||
|
return new DiagnosticLedState7Data(line, parts);
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException("Unknown diagnostic LED state");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.protocolCommons;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol;
|
||||||
|
|
||||||
|
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="ProtocolDeviceSubCommand.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
|
||||||
|
}
|
||||||
|
}
|
||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Base class for all Diagnostic LED data frames.
|
||||||
|
///
|
||||||
|
/// <para>
|
||||||
|
/// The iPERL meter emits diagnostic LED frames when the
|
||||||
|
/// Diagnostic LED is enabled using the
|
||||||
|
/// <c>Set Diagnostic LED State (0xFD 0x60)</c> command.
|
||||||
|
/// </para>
|
||||||
|
///
|
||||||
|
/// <para>
|
||||||
|
/// All diagnostic LED states (State #1 – State #7) share a common
|
||||||
|
/// set of leading fields, followed by state-specific extensions.
|
||||||
|
/// This class represents those common fields.
|
||||||
|
/// </para>
|
||||||
|
///
|
||||||
|
/// <list type="table">
|
||||||
|
/// <listheader>
|
||||||
|
/// <term>Pos</term>
|
||||||
|
/// <description>Common field description</description>
|
||||||
|
/// </listheader>
|
||||||
|
/// <item><term>0 – xxxxxx</term><description>Signed 24-bit ADC value (two’s complement)</description></item>
|
||||||
|
/// <item><term>1 – aaaa</term><description>Unsigned 16-bit field strength (internal units)</description></item>
|
||||||
|
/// <item><term>2 – yyyy</term><description>Signed 16-bit raw flow rate (¼ ml per bit)</description></item>
|
||||||
|
/// <item><term>3 – vvvvvv</term><description>Unsigned 24-bit raw volume accumulation (¼ ml per bit)</description></item>
|
||||||
|
/// <item><term>4 – cccc</term><description>Unsigned 16-bit millivolt delta on the field drive capacitor</description></item>
|
||||||
|
/// </list>
|
||||||
|
///
|
||||||
|
/// <para>
|
||||||
|
/// Each derived state class parses additional fields starting at
|
||||||
|
/// position 5, according to the selected diagnostic LED state.
|
||||||
|
/// </para>
|
||||||
|
///
|
||||||
|
/// <para>
|
||||||
|
/// The raw ASCII line (including checksum and CRLF) is preserved
|
||||||
|
/// for logging, debugging, and offline analysis.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
public abstract class DiagnosticLedData
|
||||||
|
{
|
||||||
|
|
||||||
|
public abstract int GetByteCount();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw diagnostic LED line exactly as received from the meter,
|
||||||
|
/// including checksum and CRLF.
|
||||||
|
/// </summary>
|
||||||
|
public string RawLine { get; }
|
||||||
|
|
||||||
|
// ----- Common fields (present in all LED states) -----
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signed 24-bit ADC value (two’s complement).
|
||||||
|
/// </summary>
|
||||||
|
public int Adc24 { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unsigned 16-bit field strength in internal (non-legacy) units.
|
||||||
|
/// </summary>
|
||||||
|
public ushort FieldStrength { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signed 16-bit raw flow rate in units of ¼ milliliter per bit.
|
||||||
|
/// </summary>
|
||||||
|
public short RawFlow { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unsigned 24-bit raw volume accumulation in units of ¼ milliliter per bit.
|
||||||
|
/// </summary>
|
||||||
|
public uint RawVolume { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unsigned 16-bit millivolt delta measured on the field drive capacitor.
|
||||||
|
/// </summary>
|
||||||
|
public ushort CapacitorMv { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the base diagnostic LED data with the raw input line.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="raw">
|
||||||
|
/// Raw ASCII line received from the diagnostic LED output.
|
||||||
|
/// </param>
|
||||||
|
protected DiagnosticLedData(string raw)
|
||||||
|
{
|
||||||
|
RawLine = raw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer
|
||||||
|
{
|
||||||
|
public static class DiagnosticLedFrameSpec
|
||||||
|
{
|
||||||
|
public static int GetExpectedAsciiLength(DiagnosticLedState state)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case DiagnosticLedState.State1: return 33;
|
||||||
|
case DiagnosticLedState.State2: return 48;
|
||||||
|
case DiagnosticLedState.State3: return 50;
|
||||||
|
case DiagnosticLedState.State4: return 84;
|
||||||
|
case DiagnosticLedState.State5: return 89;
|
||||||
|
case DiagnosticLedState.State6: return 112;
|
||||||
|
case DiagnosticLedState.State7: return 139;
|
||||||
|
default: throw new ArgumentOutOfRangeException(nameof(state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetExpectedFieldCount(DiagnosticLedState state)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case DiagnosticLedState.State1: return 6;
|
||||||
|
case DiagnosticLedState.State2: return 9;
|
||||||
|
case DiagnosticLedState.State3: return 9;
|
||||||
|
case DiagnosticLedState.State4: return 15;
|
||||||
|
case DiagnosticLedState.State5: return 16;
|
||||||
|
case DiagnosticLedState.State6: return 21;
|
||||||
|
case DiagnosticLedState.State7: return 26;
|
||||||
|
default: throw new ArgumentOutOfRangeException(nameof(state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.utils;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Diagnostic LED State #1 data frame.
|
||||||
|
///
|
||||||
|
/// <para>
|
||||||
|
/// Frame format: TAB-separated ASCII hexadecimal fields, terminated by CRLF.
|
||||||
|
/// The checksum is an 8-bit sum of all previous ASCII bytes including
|
||||||
|
/// the TAB character before the checksum field.
|
||||||
|
/// </para>
|
||||||
|
///
|
||||||
|
/// <list type="table">
|
||||||
|
/// <listheader>
|
||||||
|
/// <term>Pos</term>
|
||||||
|
/// <description>Field description</description>
|
||||||
|
/// </listheader>
|
||||||
|
/// <item><term>0 – xxxxxx</term><description>Signed 24-bit ADC value (two’s complement)</description></item>
|
||||||
|
/// <item><term>1 – aaaa</term><description>Unsigned 16-bit field strength (internal units)</description></item>
|
||||||
|
/// <item><term>2 – yyyy</term><description>Signed 16-bit raw flow rate (¼ ml per bit)</description></item>
|
||||||
|
/// <item><term>3 – vvvvvv</term><description>Unsigned 24-bit raw volume accumulation (¼ ml per bit)</description></item>
|
||||||
|
/// <item><term>4 – cccc</term><description>Unsigned 16-bit millivolt delta on the field drive capacitor</description></item>
|
||||||
|
/// <item><term>5 – ss</term><description>Unsigned 8-bit checksum (sum of all previous ASCII bytes
|
||||||
|
/// including the TAB before the checksum field)</description></item>
|
||||||
|
/// </list>
|
||||||
|
/// </summary>
|
||||||
|
public class DiagnosticLedState1Data : DiagnosticLedData
|
||||||
|
{
|
||||||
|
public DiagnosticLedState1Data(string raw, string[] f)
|
||||||
|
: base(raw)
|
||||||
|
{
|
||||||
|
Adc24 = DiagnosticHex.ParseInt24(f[0]);
|
||||||
|
FieldStrength = DiagnosticHex.ParseUInt16(f[1]);
|
||||||
|
RawFlow = DiagnosticHex.ParseInt16(f[2]);
|
||||||
|
RawVolume = DiagnosticHex.ParseUInt24(f[3]);
|
||||||
|
CapacitorMv = DiagnosticHex.ParseUInt16(f[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"DiagnosticLedState1Data: Adc24={Adc24}, FieldStrength={FieldStrength}, RawFlow={RawFlow}, RawVolume={RawVolume}, CapacitorMv={CapacitorMv}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format: xxxxxx aaaa yyyy vvvvvv cccc ss
|
||||||
|
/// Chars total = 26
|
||||||
|
/// Tabs = 5
|
||||||
|
/// CRLF = 2
|
||||||
|
/// Total bytes = 33
|
||||||
|
/// </summary>
|
||||||
|
/// <returns> Total bytes</returns>
|
||||||
|
public override int GetByteCount()
|
||||||
|
{
|
||||||
|
return 33;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.utils;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Diagnostic LED State #2 data frame.
|
||||||
|
///
|
||||||
|
/// <para>
|
||||||
|
/// State #2 extends the common diagnostic LED fields with information
|
||||||
|
/// about the LCD-displayed volume, the current meter operating state,
|
||||||
|
/// and whether the meter is in low-flow cutoff mode.
|
||||||
|
/// </para>
|
||||||
|
///
|
||||||
|
/// <para>
|
||||||
|
/// Frame format: TAB-separated ASCII hexadecimal fields, terminated by CRLF.
|
||||||
|
/// The checksum is an 8-bit sum of all previous ASCII bytes including
|
||||||
|
/// the TAB character before the checksum field.
|
||||||
|
/// </para>
|
||||||
|
///
|
||||||
|
/// <list type="table">
|
||||||
|
/// <listheader>
|
||||||
|
/// <term>Pos</term>
|
||||||
|
/// <description>Field description</description>
|
||||||
|
/// </listheader>
|
||||||
|
/// <item><term>0 – xxxxxx</term><description>Signed 24-bit ADC value (two’s complement)</description></item>
|
||||||
|
/// <item><term>1 – aaaa</term><description>Unsigned 16-bit field strength (internal units)</description></item>
|
||||||
|
/// <item><term>2 – yyyy</term><description>Signed 16-bit raw flow rate (¼ ml per bit)</description></item>
|
||||||
|
/// <item><term>3 – vvvvvv</term><description>Unsigned 24-bit raw volume accumulation (¼ ml per bit)</description></item>
|
||||||
|
/// <item><term>4 – cccc</term><description>Unsigned 16-bit millivolt delta on the field drive capacitor</description></item>
|
||||||
|
/// <item><term>5 – gggggggg</term><description>Unsigned 32-bit volume displayed on the LCD</description></item>
|
||||||
|
/// <item><term>6 – mm</term><description>Unsigned 8-bit meter state (see Table 17-23 in protocol documentation)</description></item>
|
||||||
|
/// <item><term>7 – ff</term><description>Unsigned 8-bit boolean flag indicating low-flow cutoff
|
||||||
|
/// state (0 = false, 1 = true)</description></item>
|
||||||
|
/// <item><term>8 – ss</term><description>Unsigned 8-bit checksum (sum of all previous ASCII bytes including
|
||||||
|
/// the TAB before the checksum field)</description></item>
|
||||||
|
/// </list>
|
||||||
|
/// </summary>
|
||||||
|
public sealed class DiagnosticLedState2Data : DiagnosticLedData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Volume displayed on LCD (raw units).
|
||||||
|
/// </summary>
|
||||||
|
public uint LcdVolume { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Meter state (see Table 17-23).
|
||||||
|
/// </summary>
|
||||||
|
public byte MeterState { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if meter is in low-flow cutoff.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsLowFlowCutoff { get; }
|
||||||
|
|
||||||
|
public DiagnosticLedState2Data(string rawLine, string[] fields)
|
||||||
|
: base(rawLine)
|
||||||
|
{
|
||||||
|
// ---- Common fields (0–4) ----
|
||||||
|
Adc24 = DiagnosticHex.ParseInt24(fields[0]);
|
||||||
|
FieldStrength = DiagnosticHex.ParseUInt16(fields[1]);
|
||||||
|
RawFlow = DiagnosticHex.ParseInt16(fields[2]);
|
||||||
|
RawVolume = DiagnosticHex.ParseUInt24(fields[3]);
|
||||||
|
CapacitorMv = DiagnosticHex.ParseUInt16(fields[4]);
|
||||||
|
|
||||||
|
// ---- State #2 specific ----
|
||||||
|
LcdVolume = DiagnosticHex.ParseUInt32(fields[5]);
|
||||||
|
MeterState = DiagnosticHex.ParseByte(fields[6]);
|
||||||
|
IsLowFlowCutoff = DiagnosticHex.ParseByte(fields[7]) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"DiagnosticLedState2Data: Adc24={Adc24}, FieldStrength={FieldStrength}, RawFlow={RawFlow}, RawVolume={RawVolume}, CapacitorMv={CapacitorMv}, LcdVolume={LcdVolume}, MeterState={MeterState}, IsLowFlowCutoff={IsLowFlowCutoff}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format: xxxxxx aaaa yyyy vvvvvv cccc gggggggg mm ff ss
|
||||||
|
/// Chars total = 38
|
||||||
|
/// Tabs = 8
|
||||||
|
/// CRLF = 2
|
||||||
|
/// Total bytes = 48
|
||||||
|
/// </summary>
|
||||||
|
/// <returns> Total bytes</returns>
|
||||||
|
public override int GetByteCount()
|
||||||
|
{
|
||||||
|
return 48;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.utils;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Diagnostic LED State #3 data frame.
|
||||||
|
///
|
||||||
|
/// <para>
|
||||||
|
/// State #3 extends the common diagnostic LED fields with calibration
|
||||||
|
/// and timing information related to the field drive and ASIC operation.
|
||||||
|
/// </para>
|
||||||
|
///
|
||||||
|
/// <para>
|
||||||
|
/// Frame format: TAB-separated ASCII hexadecimal fields, terminated by CRLF.
|
||||||
|
/// The checksum is an 8-bit sum of all previous ASCII bytes including
|
||||||
|
/// the TAB character before the checksum field.
|
||||||
|
/// </para>
|
||||||
|
///
|
||||||
|
/// <list type="table">
|
||||||
|
/// <listheader>
|
||||||
|
/// <term>Pos</term>
|
||||||
|
/// <description>Field description</description>
|
||||||
|
/// </listheader>
|
||||||
|
/// <item><term>0 – xxxxxx</term><description>Signed 24-bit ADC value (two’s complement)</description></item>
|
||||||
|
/// <item><term>1 – aaaa</term><description>Unsigned 16-bit field strength (internal units)</description></item>
|
||||||
|
/// <item><term>2 – yyyy</term><description>Signed 16-bit raw flow rate (¼ ml per bit)</description></item>
|
||||||
|
/// <item><term>3 – vvvvvv</term><description>Unsigned 24-bit raw volume accumulation (¼ ml per bit)</description></item>
|
||||||
|
/// <item><term>4 – cccc</term><description>Unsigned 16-bit millivolt delta on the field drive capacitor</description></item>
|
||||||
|
/// <item><term>5 – tttt</term><description>Unsigned 16-bit field calibration value</description></item>
|
||||||
|
/// <item><term>6 – bbbbbbbb</term><description>Unsigned 32-bit ASIC timestamp (8192 ticks per second,
|
||||||
|
/// rolls over at 2^32)</description></item>
|
||||||
|
/// <item><term>7 – ff</term><description>Unsigned 8-bit field drive time in microseconds</description></item>
|
||||||
|
/// <item><term>8 – ss</term><description>Unsigned 8-bit checksum (sum of all previous ASCII bytes including
|
||||||
|
/// the TAB before the checksum field)</description></item>
|
||||||
|
/// </list>
|
||||||
|
/// </summary>
|
||||||
|
public sealed class DiagnosticLedState3Data : DiagnosticLedData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unsigned 16-bit field calibration value.
|
||||||
|
/// </summary>
|
||||||
|
public ushort FieldCalibration { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ASIC timestamp in units of 1 / 8192 seconds.
|
||||||
|
/// Rolls over at 2^32.
|
||||||
|
/// </summary>
|
||||||
|
public uint AsicTimestamp { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Field drive time in microseconds.
|
||||||
|
/// </summary>
|
||||||
|
public byte FieldDriveTimeUs { get; }
|
||||||
|
|
||||||
|
public DiagnosticLedState3Data(string rawLine, string[] fields)
|
||||||
|
: base(rawLine)
|
||||||
|
{
|
||||||
|
// ---- Common fields (0–4) ----
|
||||||
|
Adc24 = DiagnosticHex.ParseInt24(fields[0]);
|
||||||
|
FieldStrength = DiagnosticHex.ParseUInt16(fields[1]);
|
||||||
|
RawFlow = DiagnosticHex.ParseInt16(fields[2]);
|
||||||
|
RawVolume = DiagnosticHex.ParseUInt24(fields[3]);
|
||||||
|
CapacitorMv = DiagnosticHex.ParseUInt16(fields[4]);
|
||||||
|
|
||||||
|
// ---- State #3 specific fields ----
|
||||||
|
FieldCalibration = DiagnosticHex.ParseUInt16(fields[5]);
|
||||||
|
AsicTimestamp = DiagnosticHex.ParseUInt32(fields[6]);
|
||||||
|
FieldDriveTimeUs = DiagnosticHex.ParseByte(fields[7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"DiagnosticLedState3Data: Adc24={Adc24}, FieldStrength={FieldStrength}, RawFlow={RawFlow}, RawVolume={RawVolume}, CapacitorMv={CapacitorMv}, FieldCalibration={FieldCalibration}, AsicTimestamp={AsicTimestamp}, FieldDriveTimeUs={FieldDriveTimeUs}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format: xxxxxx aaaa yyyy vvvvvv cccc tttt bbbbbbbb ff ss
|
||||||
|
/// Chars total = 40
|
||||||
|
/// Tabs = 8
|
||||||
|
/// CRLF = 2
|
||||||
|
/// Total bytes = 50
|
||||||
|
/// </summary>
|
||||||
|
/// <returns> Total bytes</returns>
|
||||||
|
public override int GetByteCount()
|
||||||
|
{
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+91
@@ -0,0 +1,91 @@
|
|||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.utils;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Diagnostic LED State #4 data frame.
|
||||||
|
/// <para>Frame format (TAB-separated ASCII HEX fields, CRLF terminated).</para>
|
||||||
|
/// <list type="table">
|
||||||
|
/// <listheader>
|
||||||
|
/// <term># / Field</term>
|
||||||
|
/// <description>Description</description>
|
||||||
|
/// </listheader>
|
||||||
|
/// <item><term>0 – xxxxxx</term><description>signed 24-bit ADC value</description></item>
|
||||||
|
/// <item><term>1 – aaaa</term><description>unsigned 16-bit Field strength</description></item>
|
||||||
|
/// <item><term>2 – yyyy</term><description>signed 16-bit Raw flow rate (1/4 ml per bit)</description></item>
|
||||||
|
/// <item><term>3 – vvvvvv</term><description>unsigned 24-bit Raw volume accumulation</description></item>
|
||||||
|
/// <item><term>4 – cccc</term><description>unsigned 16-bit Capacitor mV delta</description></item>
|
||||||
|
/// <item><term>5 – tttt</term><description>unsigned 16-bit Field calibration</description></item>
|
||||||
|
/// <item><term>6 – bbbbbbbb</term><description>unsigned 32-bit ASIC timestamp</description></item>
|
||||||
|
/// <item><term>7 – ff</term><description>unsigned 8-bit Field drive time (µs)</description></item>
|
||||||
|
/// <item><term>8 – mmmmmmmm</term><description>signed 32-bit Mean flow rate</description></item>
|
||||||
|
/// <item><term>9 – gggg</term><description>unsigned 16-bit Field 1 measurement</description></item>
|
||||||
|
/// <item><term>10 – hhhh</term><description>unsigned 16-bit Field 2 measurement</description></item>
|
||||||
|
/// <item><term>11 – cccc</term><description>unsigned 16-bit Integrator calibration positive</description></item>
|
||||||
|
/// <item><term>12 – nnnn</term><description>unsigned 16-bit Integrator calibration negative</description></item>
|
||||||
|
/// <item><term>13 – qq</term><description>unsigned 8-bit ASIC state</description></item>
|
||||||
|
/// <item><term>14 – ss</term><description>unsigned 8-bit Checksum</description></item>
|
||||||
|
/// </list>
|
||||||
|
/// </summary>
|
||||||
|
public sealed class DiagnosticLedState4Data : DiagnosticLedData
|
||||||
|
{
|
||||||
|
public ushort FieldCalibration { get; }
|
||||||
|
public uint AsicTimestamp { get; }
|
||||||
|
public byte FieldDriveTimeUs { get; }
|
||||||
|
|
||||||
|
public int MeanFlowRate { get; }
|
||||||
|
|
||||||
|
public ushort Field1Measurement { get; }
|
||||||
|
public ushort Field2Measurement { get; }
|
||||||
|
|
||||||
|
public ushort IntegratorCalibrationPositive { get; }
|
||||||
|
public ushort IntegratorCalibrationNegative { get; }
|
||||||
|
|
||||||
|
public byte AsicState { get; }
|
||||||
|
|
||||||
|
public DiagnosticLedState4Data(string rawLine, string[] fields)
|
||||||
|
: base(rawLine)
|
||||||
|
{
|
||||||
|
// ---- Common fields (0–4) ----
|
||||||
|
Adc24 = DiagnosticHex.ParseInt24(fields[0]);
|
||||||
|
FieldStrength = DiagnosticHex.ParseUInt16(fields[1]);
|
||||||
|
RawFlow = DiagnosticHex.ParseInt16(fields[2]);
|
||||||
|
RawVolume = DiagnosticHex.ParseUInt24(fields[3]);
|
||||||
|
CapacitorMv = DiagnosticHex.ParseUInt16(fields[4]);
|
||||||
|
|
||||||
|
// ---- State #4 specific ----
|
||||||
|
FieldCalibration = DiagnosticHex.ParseUInt16(fields[5]);
|
||||||
|
AsicTimestamp = DiagnosticHex.ParseUInt32(fields[6]);
|
||||||
|
FieldDriveTimeUs = DiagnosticHex.ParseByte(fields[7]);
|
||||||
|
|
||||||
|
MeanFlowRate = unchecked((int)DiagnosticHex.ParseUInt32(fields[8]));
|
||||||
|
|
||||||
|
Field1Measurement = DiagnosticHex.ParseUInt16(fields[9]);
|
||||||
|
Field2Measurement = DiagnosticHex.ParseUInt16(fields[10]);
|
||||||
|
|
||||||
|
IntegratorCalibrationPositive = DiagnosticHex.ParseUInt16(fields[11]);
|
||||||
|
IntegratorCalibrationNegative = DiagnosticHex.ParseUInt16(fields[12]);
|
||||||
|
|
||||||
|
AsicState = DiagnosticHex.ParseByte(fields[13]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"DiagnosticLedState4Data: Adc24={Adc24}, FieldStrength={FieldStrength}, RawFlow={RawFlow}, RawVolume={RawVolume}, CapacitorMv={CapacitorMv}, FieldCalibration={FieldCalibration}, AsicTimestamp={AsicTimestamp}, FieldDriveTimeUs={FieldDriveTimeUs}, MeanFlowRate={MeanFlowRate}, Field1Measurement={Field1Measurement}, Field2Measurement={Field2Measurement}, IntegratorCalibrationPositive={IntegratorCalibrationPositive}, IntegratorCalibrationNegative={IntegratorCalibrationNegative}, AsicState={AsicState}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format: xxxxxx aaaa yyyy vvvvvv cccc tttt bbbbbbbb mmmmmmmm ff gggg hhhh cccc nnnn qq ss
|
||||||
|
/// Chars total = 68
|
||||||
|
/// Tabs = 14
|
||||||
|
/// CRLF = 2
|
||||||
|
/// Total bytes = 84
|
||||||
|
/// </summary>
|
||||||
|
/// <returns> Total bytes</returns>
|
||||||
|
public override int GetByteCount()
|
||||||
|
{
|
||||||
|
return 84;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+111
@@ -0,0 +1,111 @@
|
|||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.utils;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Diagnostic LED State #5 data frame.
|
||||||
|
/// <para>
|
||||||
|
/// Frame format: TAB-separated ASCII HEX fields, CRLF terminated.
|
||||||
|
/// </para>
|
||||||
|
/// <list type="table">
|
||||||
|
/// <listheader>
|
||||||
|
/// <term># / Field</term>
|
||||||
|
/// <description>Description</description>
|
||||||
|
/// </listheader>
|
||||||
|
/// <item><term>0 – xxxxxx</term><description>signed 24-bit ADC value</description></item>
|
||||||
|
/// <item><term>1 – aaaa</term><description>unsigned 16-bit Field strength (internal units)</description></item>
|
||||||
|
/// <item><term>2 – yyyy</term><description>signed 16-bit Raw flow rate (1/4 ml per bit)</description></item>
|
||||||
|
/// <item><term>3 – vvvvvv</term><description>unsigned 24-bit Raw volume accumulation (1/4 ml per bit)</description></item>
|
||||||
|
/// <item><term>4 – cccc</term><description>unsigned 16-bit Millivolts delta on field drive capacitor</description></item>
|
||||||
|
/// <item><term>5 – tttt</term><description>unsigned 16-bit Field calibration value</description></item>
|
||||||
|
/// <item><term>6 – bbbbbbbb</term><description>unsigned 32-bit ASIC timestamp (8192 ticks/sec, rolls over at 2^32)</description></item>
|
||||||
|
/// <item><term>7 – ff</term><description>unsigned 8-bit Field drive time in microseconds</description></item>
|
||||||
|
/// <item><term>8 – mmmmmmmm</term><description>signed 32-bit Mean flow rate (rolls over at 2^32)</description></item>
|
||||||
|
/// <item><term>9 – gggg</term><description>unsigned 16-bit Field 1 measurement</description></item>
|
||||||
|
/// <item><term>10 – hhhh</term><description>unsigned 16-bit Field 2 measurement</description></item>
|
||||||
|
/// <item><term>11 – cccc</term><description>unsigned 16-bit Integrator calibration positive</description></item>
|
||||||
|
/// <item><term>12 – nnnn</term><description>unsigned 16-bit Integrator calibration negative</description></item>
|
||||||
|
/// <item><term>13 – qq</term><description>unsigned 8-bit ASIC state</description></item>
|
||||||
|
/// <item><term>14 – iiii</term><description>signed 16-bit Water impedance measurement</description></item>
|
||||||
|
/// <item><term>15 – ss</term><description>unsigned 8-bit Checksum</description></item>
|
||||||
|
/// </list>
|
||||||
|
/// </summary>
|
||||||
|
public sealed class DiagnosticLedState5Data : DiagnosticLedData
|
||||||
|
{
|
||||||
|
/// <summary>Field calibration value (tttt).</summary>
|
||||||
|
public ushort FieldCalibration { get; }
|
||||||
|
|
||||||
|
/// <summary>ASIC timestamp (bbbbbbbb), 8192 ticks per second.</summary>
|
||||||
|
public uint AsicTimestamp { get; }
|
||||||
|
|
||||||
|
/// <summary>Field drive time in microseconds (ff).</summary>
|
||||||
|
public byte FieldDriveTimeUs { get; }
|
||||||
|
|
||||||
|
/// <summary>Mean flow rate (mmmmmmmm), signed 32-bit.</summary>
|
||||||
|
public int MeanFlowRate { get; }
|
||||||
|
|
||||||
|
/// <summary>Field 1 measurement (gggg).</summary>
|
||||||
|
public ushort Field1Measurement { get; }
|
||||||
|
|
||||||
|
/// <summary>Field 2 measurement (hhhh).</summary>
|
||||||
|
public ushort Field2Measurement { get; }
|
||||||
|
|
||||||
|
/// <summary>Integrator calibration positive (cccc).</summary>
|
||||||
|
public ushort IntegratorCalibrationPositive { get; }
|
||||||
|
|
||||||
|
/// <summary>Integrator calibration negative (nnnn).</summary>
|
||||||
|
public ushort IntegratorCalibrationNegative { get; }
|
||||||
|
|
||||||
|
/// <summary>ASIC state (qq).</summary>
|
||||||
|
public byte AsicState { get; }
|
||||||
|
|
||||||
|
/// <summary>Water impedance measurement (iiii), signed 16-bit.</summary>
|
||||||
|
public short WaterImpedance { get; }
|
||||||
|
|
||||||
|
public DiagnosticLedState5Data(string rawLine, string[] fields)
|
||||||
|
: base(rawLine)
|
||||||
|
{
|
||||||
|
// ---- Common fields ----
|
||||||
|
Adc24 = DiagnosticHex.ParseInt24(fields[0]);
|
||||||
|
FieldStrength = DiagnosticHex.ParseUInt16(fields[1]);
|
||||||
|
RawFlow = DiagnosticHex.ParseInt16(fields[2]);
|
||||||
|
RawVolume = DiagnosticHex.ParseUInt24(fields[3]);
|
||||||
|
CapacitorMv = DiagnosticHex.ParseUInt16(fields[4]);
|
||||||
|
|
||||||
|
// ---- State #5 specific ----
|
||||||
|
FieldCalibration = DiagnosticHex.ParseUInt16(fields[5]);
|
||||||
|
AsicTimestamp = DiagnosticHex.ParseUInt32(fields[6]);
|
||||||
|
FieldDriveTimeUs = DiagnosticHex.ParseByte(fields[7]);
|
||||||
|
|
||||||
|
MeanFlowRate = unchecked((int)DiagnosticHex.ParseUInt32(fields[8]));
|
||||||
|
|
||||||
|
Field1Measurement = DiagnosticHex.ParseUInt16(fields[9]);
|
||||||
|
Field2Measurement = DiagnosticHex.ParseUInt16(fields[10]);
|
||||||
|
|
||||||
|
IntegratorCalibrationPositive = DiagnosticHex.ParseUInt16(fields[11]);
|
||||||
|
IntegratorCalibrationNegative = DiagnosticHex.ParseUInt16(fields[12]);
|
||||||
|
|
||||||
|
AsicState = DiagnosticHex.ParseByte(fields[13]);
|
||||||
|
WaterImpedance = DiagnosticHex.ParseInt16(fields[14]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"DiagnosticLedState5Data: Adc24={Adc24}, FieldStrength={FieldStrength}, RawFlow={RawFlow}, RawVolume={RawVolume}, CapacitorMv={CapacitorMv}, FieldCalibration={FieldCalibration}, AsicTimestamp={AsicTimestamp}, FieldDriveTimeUs={FieldDriveTimeUs}, MeanFlowRate={MeanFlowRate}, Field1Measurement={Field1Measurement}, Field2Measurement={Field2Measurement}, IntegratorCalibrationPositive={IntegratorCalibrationPositive}, IntegratorCalibrationNegative={IntegratorCalibrationNegative}, AsicState={AsicState}, WaterImpedance={WaterImpedance}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format: xxxxxx aaaa yyyy vvvvvv cccc tttt bbbbbbbb mmmmmmmm ff iiii ss
|
||||||
|
/// Chars total = 72
|
||||||
|
/// Tabs = 15
|
||||||
|
/// CRLF = 2
|
||||||
|
/// Total bytes = 89
|
||||||
|
/// </summary>
|
||||||
|
/// <returns> Total bytes</returns>
|
||||||
|
public override int GetByteCount()
|
||||||
|
{
|
||||||
|
return 89;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+152
@@ -0,0 +1,152 @@
|
|||||||
|
using System;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.utils;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Diagnostic LED State #6 data frame.
|
||||||
|
/// <para>
|
||||||
|
/// Frame format: TAB-separated ASCII HEX fields, CRLF terminated.
|
||||||
|
/// </para>
|
||||||
|
/// <list type="table">
|
||||||
|
/// <listheader>
|
||||||
|
/// <term># / Field</term>
|
||||||
|
/// <description>Description</description>
|
||||||
|
/// </listheader>
|
||||||
|
/// <item><term>0 – xxxxxx</term><description>signed 24-bit ADC value</description></item>
|
||||||
|
/// <item><term>1 – aaaa</term><description>unsigned 16-bit Field strength (internal units)</description></item>
|
||||||
|
/// <item><term>2 – yyyy</term><description>signed 16-bit Raw flow rate (1/4 ml per bit)</description></item>
|
||||||
|
/// <item><term>3 – vvvvvv</term><description>unsigned 24-bit Raw volume accumulation (1/4 ml per bit)</description></item>
|
||||||
|
/// <item><term>4 – cccc</term><description>unsigned 16-bit Millivolts delta on field drive capacitor</description></item>
|
||||||
|
/// <item><term>5 – tttt</term><description>unsigned 16-bit Field calibration value</description></item>
|
||||||
|
/// <item><term>6 – bbbbbbbb</term><description>unsigned 32-bit ASIC timestamp (8192 ticks/sec, rolls over at 2^32)</description></item>
|
||||||
|
/// <item><term>7 – ff</term><description>unsigned 8-bit Field drive time in microseconds</description></item>
|
||||||
|
/// <item><term>8 – mmmmmmmm</term><description>signed 32-bit Mean flow rate (rolls over at 2^32)</description></item>
|
||||||
|
/// <item><term>9 – gggg</term><description>unsigned 16-bit Field 1 measurement</description></item>
|
||||||
|
/// <item><term>10 – hhhh</term><description>unsigned 16-bit Field 2 measurement</description></item>
|
||||||
|
/// <item><term>11 – cccc</term><description>unsigned 16-bit Integrator calibration positive</description></item>
|
||||||
|
/// <item><term>12 – nnnn</term><description>unsigned 16-bit Integrator calibration negative</description></item>
|
||||||
|
/// <item><term>13 – qq</term><description>unsigned 8-bit ASIC state 0</description></item>
|
||||||
|
/// <item><term>14 – iiii</term><description>signed 16-bit Water impedance measurement</description></item>
|
||||||
|
/// <item><term>15 – rrrr</term><description>signed 16-bit Electrode delta (mV)</description></item>
|
||||||
|
/// <item><term>16 – pp</term><description>unsigned 8-bit Spike detection diagnostic</description></item>
|
||||||
|
/// <item><term>17 – ll</term><description>unsigned 8-bit Pipe status</description></item>
|
||||||
|
/// <item><term>18 – dddddddd</term><description>unsigned 32-bit LCD volume</description></item>
|
||||||
|
/// <item><term>19 – oo</term><description>unsigned 8-bit ASIC state 1</description></item>
|
||||||
|
/// <item><term>20 – ss</term><description>unsigned 8-bit Checksum</description></item>
|
||||||
|
/// </list>
|
||||||
|
/// </summary>
|
||||||
|
public sealed class DiagnosticLedState6Data : DiagnosticLedData
|
||||||
|
{
|
||||||
|
public ushort FieldCalibration { get; }
|
||||||
|
public uint AsicTimestamp { get; }
|
||||||
|
public byte FieldDriveTimeUs { get; }
|
||||||
|
|
||||||
|
public int MeanFlowRate { get; }
|
||||||
|
|
||||||
|
public ushort Field1Measurement { get; }
|
||||||
|
public ushort Field2Measurement { get; }
|
||||||
|
|
||||||
|
public ushort IntegratorCalibrationPositive { get; }
|
||||||
|
public ushort IntegratorCalibrationNegative { get; }
|
||||||
|
|
||||||
|
public byte AsicState0 { get; }
|
||||||
|
|
||||||
|
public short WaterImpedance { get; }
|
||||||
|
public short ElectrodeDeltaMv { get; }
|
||||||
|
|
||||||
|
public byte SpikeDetection { get; }
|
||||||
|
public byte PipeStatus { get; }
|
||||||
|
|
||||||
|
public uint LcdVolume { get; }
|
||||||
|
|
||||||
|
public byte AsicState1 { get; }
|
||||||
|
|
||||||
|
public DiagnosticLedState6Data(string rawLine, string[] fields)
|
||||||
|
: base(rawLine)
|
||||||
|
{
|
||||||
|
// ---- Common fields (0–4) ----
|
||||||
|
Adc24 = DiagnosticHex.ParseInt24(fields[0]);
|
||||||
|
FieldStrength = DiagnosticHex.ParseUInt16(fields[1]);
|
||||||
|
RawFlow = DiagnosticHex.ParseInt16(fields[2]);
|
||||||
|
RawVolume = DiagnosticHex.ParseUInt24(fields[3]);
|
||||||
|
CapacitorMv = DiagnosticHex.ParseUInt16(fields[4]);
|
||||||
|
|
||||||
|
// ---- State #6 specific ----
|
||||||
|
FieldCalibration = DiagnosticHex.ParseUInt16(fields[5]);
|
||||||
|
AsicTimestamp = DiagnosticHex.ParseUInt32(fields[6]);
|
||||||
|
FieldDriveTimeUs = DiagnosticHex.ParseByte(fields[7]);
|
||||||
|
|
||||||
|
MeanFlowRate = unchecked((int)DiagnosticHex.ParseUInt32(fields[8]));
|
||||||
|
|
||||||
|
Field1Measurement = DiagnosticHex.ParseUInt16(fields[9]);
|
||||||
|
Field2Measurement = DiagnosticHex.ParseUInt16(fields[10]);
|
||||||
|
|
||||||
|
IntegratorCalibrationPositive = DiagnosticHex.ParseUInt16(fields[11]);
|
||||||
|
IntegratorCalibrationNegative = DiagnosticHex.ParseUInt16(fields[12]);
|
||||||
|
|
||||||
|
AsicState0 = DiagnosticHex.ParseByte(fields[13]);
|
||||||
|
|
||||||
|
WaterImpedance = DiagnosticHex.ParseInt16(fields[14]);
|
||||||
|
ElectrodeDeltaMv = DiagnosticHex.ParseInt16(fields[15]);
|
||||||
|
|
||||||
|
SpikeDetection = DiagnosticHex.ParseByte(fields[16]);
|
||||||
|
PipeStatus = DiagnosticHex.ParseByte(fields[17]);
|
||||||
|
|
||||||
|
LcdVolume = DiagnosticHex.ParseUInt32(fields[18]);
|
||||||
|
AsicState1 = DiagnosticHex.ParseByte(fields[19]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pipe status interpreted as <see cref="PipeStatus"/>.
|
||||||
|
/// If the value is outside the defined range, returns null.
|
||||||
|
/// </summary>
|
||||||
|
public PipeStatus PipeStatusEnumValue
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!Enum.IsDefined(typeof(PipeStatus), PipeStatus))
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Unknown pipe status value: 0x" + PipeStatus.ToString("X2"));
|
||||||
|
|
||||||
|
return (PipeStatus)PipeStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Spike Detection interpreted as <see cref="SpikeDetectionStatus"/>.
|
||||||
|
/// If the value is outside the defined range, returns null.
|
||||||
|
/// </summary>
|
||||||
|
public SpikeDetectionStatus SpikeDetectionEnumValue
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!Enum.IsDefined(typeof(SpikeDetectionStatus), SpikeDetection))
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Unknown Spike Detection value: 0x" + SpikeDetection.ToString("X2"));
|
||||||
|
|
||||||
|
return (SpikeDetectionStatus)SpikeDetection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"DiagnosticLedState6Data: Adc24={Adc24}, FieldStrength={FieldStrength}, RawFlow={RawFlow}, RawVolume={RawVolume}, CapacitorMv={CapacitorMv}, FieldCalibration={FieldCalibration}, AsicTimestamp={AsicTimestamp}, FieldDriveTimeUs={FieldDriveTimeUs}, MeanFlowRate={MeanFlowRate}, Field1Measurement={Field1Measurement}, Field2Measurement={Field2Measurement}, IntegratorCalibrationPositive={IntegratorCalibrationPositive}, IntegratorCalibrationNegative={IntegratorCalibrationNegative}, AsicState0={AsicState0}, WaterImpedance={WaterImpedance}, SpikeDetection={SpikeDetection}, PipeStatus={PipeStatus}, LcdVolume={LcdVolume}, AsicState1={AsicState1}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format: xxxxxx aaaa yyyy vvvvvv cccc tttt bbbbbbbb mmmmmmmm ff iiii rrrr pp ll dddddddd oo ss
|
||||||
|
/// Chars total = 90
|
||||||
|
/// Tabs = 20
|
||||||
|
/// CRLF = 2
|
||||||
|
/// Total bytes = 112
|
||||||
|
/// </summary>
|
||||||
|
/// <returns> Total bytes</returns>
|
||||||
|
public override int GetByteCount()
|
||||||
|
{
|
||||||
|
return 112;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+155
@@ -0,0 +1,155 @@
|
|||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.utils;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Diagnostic LED State #7 data frame.
|
||||||
|
/// <para>
|
||||||
|
/// Frame format: TAB-separated ASCII HEX fields, CRLF terminated.
|
||||||
|
/// This state extends State #6 with additional ADC and learning diagnostics.
|
||||||
|
/// </para>
|
||||||
|
/// <list type="table">
|
||||||
|
/// <listheader>
|
||||||
|
/// <term># / Field</term>
|
||||||
|
/// <description>Description</description>
|
||||||
|
/// </listheader>
|
||||||
|
/// <item><term>0 – xxxxxx</term><description>signed 24-bit ADC value</description></item>
|
||||||
|
/// <item><term>1 – aaaa</term><description>unsigned 16-bit Field strength (internal units)</description></item>
|
||||||
|
/// <item><term>2 – yyyy</term><description>signed 16-bit Raw flow rate (1/4 ml per bit)</description></item>
|
||||||
|
/// <item><term>3 – vvvvvv</term><description>unsigned 24-bit Raw volume accumulation (1/4 ml per bit)</description></item>
|
||||||
|
/// <item><term>4 – cccc</term><description>unsigned 16-bit Millivolts delta on field drive capacitor</description></item>
|
||||||
|
/// <item><term>5 – tttt</term><description>unsigned 16-bit Field calibration value</description></item>
|
||||||
|
/// <item><term>6 – bbbbbbbb</term><description>unsigned 32-bit ASIC timestamp (8192 ticks/sec)</description></item>
|
||||||
|
/// <item><term>7 – ff</term><description>unsigned 8-bit Field drive time (µs)</description></item>
|
||||||
|
/// <item><term>8 – mmmmmmmm</term><description>signed 32-bit Mean flow rate</description></item>
|
||||||
|
/// <item><term>9 – gggg</term><description>unsigned 16-bit Field 1 measurement</description></item>
|
||||||
|
/// <item><term>10 – hhhh</term><description>unsigned 16-bit Field 2 measurement</description></item>
|
||||||
|
/// <item><term>11 – cccc</term><description>unsigned 16-bit Integrator calibration positive</description></item>
|
||||||
|
/// <item><term>12 – nnnn</term><description>unsigned 16-bit Integrator calibration negative</description></item>
|
||||||
|
/// <item><term>13 – qq</term><description>unsigned 8-bit ASIC state 0</description></item>
|
||||||
|
/// <item><term>14 – iiii</term><description>signed 16-bit Water impedance measurement</description></item>
|
||||||
|
/// <item><term>15 – rrrr</term><description>signed 16-bit Electrode delta (mV)</description></item>
|
||||||
|
/// <item><term>16 – pp</term><description>unsigned 8-bit Spike detection diagnostic</description></item>
|
||||||
|
/// <item><term>17 – ll</term><description>unsigned 8-bit Pipe status</description></item>
|
||||||
|
/// <item><term>18 – dddddddd</term><description>unsigned 32-bit LCD volume</description></item>
|
||||||
|
/// <item><term>19 – oo</term><description>unsigned 8-bit ASIC state 1</description></item>
|
||||||
|
/// <item><term>20 – xxxxxx</term><description>signed 24-bit Raw ADC value (before offset correction)</description></item>
|
||||||
|
/// <item><term>21 – yyyyyy</term><description>signed 24-bit Detrended ADC value</description></item>
|
||||||
|
/// <item><term>22 – iiii</term><description>signed 16-bit Imaginary water impedance</description></item>
|
||||||
|
/// <item><term>23 – nnnn</term><description>unsigned 16-bit Electrode voltage noise level</description></item>
|
||||||
|
/// <item><term>24 – aa</term><description>unsigned 8-bit ADC offset learning status</description></item>
|
||||||
|
/// <item><term>25 – ss</term><description>unsigned 8-bit Checksum</description></item>
|
||||||
|
/// </list>
|
||||||
|
/// </summary>
|
||||||
|
public sealed class DiagnosticLedState7Data : DiagnosticLedData
|
||||||
|
{
|
||||||
|
// ----- State #6 fields -----
|
||||||
|
|
||||||
|
public ushort FieldCalibration { get; }
|
||||||
|
public uint AsicTimestamp { get; }
|
||||||
|
public byte FieldDriveTimeUs { get; }
|
||||||
|
|
||||||
|
public int MeanFlowRate { get; }
|
||||||
|
|
||||||
|
public ushort Field1Measurement { get; }
|
||||||
|
public ushort Field2Measurement { get; }
|
||||||
|
|
||||||
|
public ushort IntegratorCalibrationPositive { get; }
|
||||||
|
public ushort IntegratorCalibrationNegative { get; }
|
||||||
|
|
||||||
|
public byte AsicState0 { get; }
|
||||||
|
|
||||||
|
public short WaterImpedance { get; }
|
||||||
|
public short ElectrodeDeltaMv { get; }
|
||||||
|
|
||||||
|
public byte SpikeDetection { get; }
|
||||||
|
public byte PipeStatus { get; }
|
||||||
|
|
||||||
|
public uint LcdVolume { get; }
|
||||||
|
|
||||||
|
public byte AsicState1 { get; }
|
||||||
|
|
||||||
|
// ----- State #7 extensions -----
|
||||||
|
|
||||||
|
/// <summary>Raw ADC value before offset correction (signed 24-bit).</summary>
|
||||||
|
public int RawAdcBeforeOffset { get; }
|
||||||
|
|
||||||
|
/// <summary>Detrended ADC value (signed 24-bit).</summary>
|
||||||
|
public int DetrendedAdc { get; }
|
||||||
|
|
||||||
|
/// <summary>Imaginary water impedance (signed 16-bit).</summary>
|
||||||
|
public short ImaginaryWaterImpedance { get; }
|
||||||
|
|
||||||
|
/// <summary>Electrode voltage noise level (unsigned 16-bit).</summary>
|
||||||
|
public ushort ElectrodeVoltageNoise { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ADC offset learning status bitfield.
|
||||||
|
/// Bit 0: currently learning
|
||||||
|
/// Bit 1: completed first learning cycle
|
||||||
|
/// Other bits reserved.
|
||||||
|
/// </summary>
|
||||||
|
public byte AdcOffsetLearningStatus { get; }
|
||||||
|
|
||||||
|
public DiagnosticLedState7Data(string rawLine, string[] fields)
|
||||||
|
: base(rawLine)
|
||||||
|
{
|
||||||
|
// ---- Common fields (0–4) ----
|
||||||
|
Adc24 = DiagnosticHex.ParseInt24(fields[0]);
|
||||||
|
FieldStrength = DiagnosticHex.ParseUInt16(fields[1]);
|
||||||
|
RawFlow = DiagnosticHex.ParseInt16(fields[2]);
|
||||||
|
RawVolume = DiagnosticHex.ParseUInt24(fields[3]);
|
||||||
|
CapacitorMv = DiagnosticHex.ParseUInt16(fields[4]);
|
||||||
|
|
||||||
|
// ---- State #6 fields ----
|
||||||
|
FieldCalibration = DiagnosticHex.ParseUInt16(fields[5]);
|
||||||
|
AsicTimestamp = DiagnosticHex.ParseUInt32(fields[6]);
|
||||||
|
FieldDriveTimeUs = DiagnosticHex.ParseByte(fields[7]);
|
||||||
|
|
||||||
|
MeanFlowRate = unchecked((int)DiagnosticHex.ParseUInt32(fields[8]));
|
||||||
|
|
||||||
|
Field1Measurement = DiagnosticHex.ParseUInt16(fields[9]);
|
||||||
|
Field2Measurement = DiagnosticHex.ParseUInt16(fields[10]);
|
||||||
|
|
||||||
|
IntegratorCalibrationPositive = DiagnosticHex.ParseUInt16(fields[11]);
|
||||||
|
IntegratorCalibrationNegative = DiagnosticHex.ParseUInt16(fields[12]);
|
||||||
|
|
||||||
|
AsicState0 = DiagnosticHex.ParseByte(fields[13]);
|
||||||
|
|
||||||
|
WaterImpedance = DiagnosticHex.ParseInt16(fields[14]);
|
||||||
|
ElectrodeDeltaMv = DiagnosticHex.ParseInt16(fields[15]);
|
||||||
|
|
||||||
|
SpikeDetection = DiagnosticHex.ParseByte(fields[16]);
|
||||||
|
PipeStatus = DiagnosticHex.ParseByte(fields[17]);
|
||||||
|
|
||||||
|
LcdVolume = DiagnosticHex.ParseUInt32(fields[18]);
|
||||||
|
AsicState1 = DiagnosticHex.ParseByte(fields[19]);
|
||||||
|
|
||||||
|
// ---- State #7 extensions ----
|
||||||
|
RawAdcBeforeOffset = DiagnosticHex.ParseInt24(fields[20]);
|
||||||
|
DetrendedAdc = DiagnosticHex.ParseInt24(fields[21]);
|
||||||
|
ImaginaryWaterImpedance = DiagnosticHex.ParseInt16(fields[22]);
|
||||||
|
ElectrodeVoltageNoise = DiagnosticHex.ParseUInt16(fields[23]);
|
||||||
|
AdcOffsetLearningStatus = DiagnosticHex.ParseByte(fields[24]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"DiagnosticLedState7Data: Adc24={Adc24}, FieldStrength={FieldStrength}, RawFlow={RawFlow}, RawVolume={RawVolume}, CapacitorMv={CapacitorMv}, FieldCalibration={FieldCalibration}, AsicTimestamp={AsicTimestamp}, FieldDriveTimeUs={FieldDriveTimeUs}, MeanFlowRate={MeanFlowRate}, Field1Measurement={Field1Measurement}, Field2Measurement={Field2Measurement}, IntegratorCalibrationPositive={IntegratorCalibrationPositive}, IntegratorCalibrationNegative={IntegratorCalibrationNegative}, AsicState0={AsicState0}, WaterImpedance={WaterImpedance}, ElectrodeDeltaMv={ElectrodeDeltaMv}, SpikeDetection={SpikeDetection}, PipeStatus={PipeStatus}, LcdVolume={LcdVolume}, AsicState1={AsicState1}, RawAdcBeforeOffset={RawAdcBeforeOffset}, DetrendedAdc={DetrendedAdc}, ImaginaryWaterImpedance={ImaginaryWaterImpedance}, ElectrodeVoltageNoise={ElectrodeVoltageNoise}, AdcOffsetLearningStatus={AdcOffsetLearningStatus}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format:
|
||||||
|
/// Chars total = 112
|
||||||
|
/// Tabs = 25
|
||||||
|
/// CRLF = 2
|
||||||
|
/// Total bytes = 139
|
||||||
|
/// </summary>
|
||||||
|
/// <returns> Total bytes</returns>
|
||||||
|
public override int GetByteCount()
|
||||||
|
{
|
||||||
|
return 139;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer
|
||||||
|
{
|
||||||
|
public enum PipeStatus : byte
|
||||||
|
{
|
||||||
|
MetroLowFlowCut = 0,
|
||||||
|
MetroFlowReverse = 1,
|
||||||
|
MetroFlowForward = 2,
|
||||||
|
MetroEmptyPipe = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer
|
||||||
|
{
|
||||||
|
public enum SpikeDetectionStatus : byte
|
||||||
|
{
|
||||||
|
NoSpike = 0,
|
||||||
|
AdcSpike = 1,
|
||||||
|
SpikeHoldOff = 2,
|
||||||
|
SpikeHighFlow = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.utils
|
||||||
|
{
|
||||||
|
internal static class DiagnosticChecksum
|
||||||
|
{
|
||||||
|
public static byte Compute(string lineWithoutChecksum)
|
||||||
|
{
|
||||||
|
byte sum = 0;
|
||||||
|
foreach (char c in lineWithoutChecksum)
|
||||||
|
sum += (byte)c;
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.utils
|
||||||
|
{
|
||||||
|
internal static class DiagnosticHex
|
||||||
|
{
|
||||||
|
public static int ParseInt24(string hex)
|
||||||
|
{
|
||||||
|
int value = Convert.ToInt32(hex, 16);
|
||||||
|
if ((value & 0x800000) != 0)
|
||||||
|
value |= unchecked((int)0xFF000000); // sign extend
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint ParseUInt24(string hex)
|
||||||
|
{
|
||||||
|
return Convert.ToUInt32(hex, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static short ParseInt16(string hex)
|
||||||
|
{
|
||||||
|
return unchecked((short)Convert.ToUInt16(hex, 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ushort ParseUInt16(string hex)
|
||||||
|
{
|
||||||
|
return Convert.ToUInt16(hex, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint ParseUInt32(string hex)
|
||||||
|
{
|
||||||
|
return Convert.ToUInt32(hex, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte ParseByte(string hex)
|
||||||
|
{
|
||||||
|
return Convert.ToByte(hex, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger
|
||||||
|
{
|
||||||
|
public static class HexFormatter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Formats a single byte as 0xNN.
|
||||||
|
/// Example: 0x0D
|
||||||
|
/// </summary>
|
||||||
|
public static string ToHex(byte value)
|
||||||
|
{
|
||||||
|
return "0x" + value.ToString("X2");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// int to byte securely
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||||
|
public static byte ToHexByte(int value)
|
||||||
|
{
|
||||||
|
if (value < 0 || value > 255)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(value),
|
||||||
|
"Value must be between 0 and 255.");
|
||||||
|
|
||||||
|
return (byte)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Formats a byte array as 0xNN 0xNN ...
|
||||||
|
/// </summary>
|
||||||
|
public static string ToHex(byte[] data)
|
||||||
|
{
|
||||||
|
if (data == null || data.Length == 0)
|
||||||
|
return "<empty>";
|
||||||
|
|
||||||
|
var sb = new System.Text.StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < data.Length; i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
sb.Append(' ');
|
||||||
|
|
||||||
|
sb.Append("0x");
|
||||||
|
sb.Append(data[i].ToString("X2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Formats a byte array exactly as shown in serial terminals.
|
||||||
|
/// Example: "0D 04 08 01 00 1A"
|
||||||
|
/// </summary>
|
||||||
|
public static string ToSerialHex(byte[] data)
|
||||||
|
{
|
||||||
|
if (data == null || data.Length == 0)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
var sb = new System.Text.StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < data.Length; i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
sb.Append(' ');
|
||||||
|
|
||||||
|
sb.Append(data[i].ToString("X2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string ToHexWithAscii(byte value)
|
||||||
|
{
|
||||||
|
char c = (value >= 32 && value <= 126) ? (char)value : '.';
|
||||||
|
return $"0x{value:X2} ('{c}')";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToSerialHexWithAscii(byte[] data)
|
||||||
|
{
|
||||||
|
if (data == null || data.Length == 0)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
var hex = new StringBuilder(data.Length * 3);
|
||||||
|
var ascii = new StringBuilder(data.Length);
|
||||||
|
|
||||||
|
foreach (byte b in data)
|
||||||
|
{
|
||||||
|
hex.Append(b.ToString("X2")).Append(' ');
|
||||||
|
|
||||||
|
// Printable ASCII range
|
||||||
|
if (b >= 32 && b <= 126)
|
||||||
|
{
|
||||||
|
ascii.Append((char)b);
|
||||||
|
}
|
||||||
|
// Binary numbers 0–9 -> show digit
|
||||||
|
else if (b <= 9)
|
||||||
|
{
|
||||||
|
ascii.Append((char)('0' + b));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ascii.Append('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove last trailing space in hex
|
||||||
|
if (hex.Length > 0)
|
||||||
|
hex.Length--;
|
||||||
|
|
||||||
|
return $"{hex} | {ascii}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static string ToHex(int value)
|
||||||
|
{
|
||||||
|
return $"0x{(byte)value:X2}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] IntToBytesBE(int value, int byteCount)
|
||||||
|
{
|
||||||
|
var result = new byte[byteCount];
|
||||||
|
|
||||||
|
for (int i = 0; i < byteCount; i++)
|
||||||
|
result[byteCount - 1 - i] = (byte)(value >> (8 * i));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] IntToBytesLE(int value, int byteCount)
|
||||||
|
{
|
||||||
|
var result = new byte[byteCount];
|
||||||
|
|
||||||
|
for (int i = 0; i < byteCount; i++)
|
||||||
|
result[i] = (byte)(value >> (8 * i));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] AsciiToBytes(string text)
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(text)
|
||||||
|
? Array.Empty<byte>()
|
||||||
|
: System.Text.Encoding.ASCII.GetBytes(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a hex string to a byte array.
|
||||||
|
/// Like: string hex = "3F 76 65 72 73 3A 20 48 61 72 72 79 20 54 3A 42 38 30 30 2C 20";
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hex"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="ArgumentNullException"></exception>
|
||||||
|
public static byte[] HexStringToByteArray(string hex)
|
||||||
|
{
|
||||||
|
if (hex == null)
|
||||||
|
throw new ArgumentNullException(nameof(hex));
|
||||||
|
|
||||||
|
return hex
|
||||||
|
.Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
.Select(b => byte.Parse(b, NumberStyles.HexNumber, CultureInfo.InvariantCulture))
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger
|
||||||
|
{
|
||||||
|
public class IpelHatCommandDecoder
|
||||||
|
{
|
||||||
|
public static string DescribeCommand(byte command)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string DescribeDirection(byte direction)
|
||||||
|
{
|
||||||
|
if (direction == IperlHatProtocol.Constants.Write)
|
||||||
|
return "(WRITE - OUTGOING)";
|
||||||
|
|
||||||
|
if (direction == IperlHatProtocol.Constants.Read)
|
||||||
|
return "(READ - INCOMING)";
|
||||||
|
|
||||||
|
return "INVALID CONTROL BITS (unsupported pattern)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger
|
||||||
|
{
|
||||||
|
public static class IperlHatLogger
|
||||||
|
{
|
||||||
|
public static string DescribeTx(byte[] frame)
|
||||||
|
{
|
||||||
|
if (frame == null || frame.Length < 5)
|
||||||
|
return "Invalid frame";
|
||||||
|
|
||||||
|
if (frame[2] == IperlHatProtocol.Constants.Question)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
"TX Frame\n" +
|
||||||
|
$" START : {HexFormatter.ToHex(frame[0])}\n" +
|
||||||
|
$" DIRECTION : {HexFormatter.ToHex(frame[1])} ({IpelHatCommandDecoder.DescribeDirection(frame[1])})\n" +
|
||||||
|
$" COMMAND : {HexFormatter.ToHexWithAscii(frame[2])}\n" +
|
||||||
|
$" INFO : {HexFormatter.ToSerialHexWithAscii(GetInformatioQuestion(frame))}\n" +
|
||||||
|
$" END : {HexFormatter.ToHex(frame[frame.Length - 1])}\n" +
|
||||||
|
$" RAW : {HexFormatter.ToHex(frame)}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return
|
||||||
|
"TX Frame\n" +
|
||||||
|
$" START : {HexFormatter.ToHex(frame[0])}\n" +
|
||||||
|
$" DIRECTION : {HexFormatter.ToHex(frame[1])} ({HexFormatter.ToHexWithAscii(frame[1])}) {IpelHatCommandDecoder.DescribeDirection(frame[1])}\n" +
|
||||||
|
$" LEN : {HexFormatter.ToHex(frame[2])} - {(int)frame[2]}\n" +
|
||||||
|
$" COMMAND : {HexFormatter.ToHexWithAscii(frame[3])}\n" +
|
||||||
|
$" INFO : {HexFormatter.ToSerialHexWithAscii(GetInformation(frame))}\n" +
|
||||||
|
$" END : {HexFormatter.ToHex(frame[frame.Length - 1])}\n" +
|
||||||
|
$" RAW : {HexFormatter.ToHex(frame)}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//payload
|
||||||
|
private static byte[] GetInformation(byte[] frame)
|
||||||
|
{
|
||||||
|
int infoLength = frame.Length - 5; // START + DIRECTION + LEN + COMMAND + END
|
||||||
|
if (infoLength <= 0)
|
||||||
|
return Array.Empty<byte>();
|
||||||
|
|
||||||
|
var info = new byte[infoLength];
|
||||||
|
Buffer.BlockCopy(frame, 4, info, 0, infoLength);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
//payload for question
|
||||||
|
private static byte[] GetInformatioQuestion(byte[] frame)
|
||||||
|
{
|
||||||
|
int infoLength = frame.Length - 4; // START + DIRECTION + COMMAND + END
|
||||||
|
if (infoLength <= 0)
|
||||||
|
return Array.Empty<byte>();
|
||||||
|
|
||||||
|
var info = new byte[infoLength];
|
||||||
|
Buffer.BlockCopy(frame, 3, info, 0, infoLength);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string DescribeRx(byte[] frame, TouchReadResponse response)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
"RX Frame\n" +
|
||||||
|
$" START : {HexFormatter.ToHex(frame[0])}\n" +
|
||||||
|
$" LEN : {HexFormatter.ToHex(frame[1])} ({frame[1]})\n" +
|
||||||
|
$" CONTROL : {HexFormatter.ToHex(response.Control)}\n" +
|
||||||
|
$" STATUS : {HexFormatter.ToHex(response.Status)} ({DescribeStatus(response.Status)})\n" +
|
||||||
|
$" PAYLOAD : {HexFormatter.ToHex(response.Payload)}\n" +
|
||||||
|
$" RAW : {HexFormatter.ToHex(frame)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string DescribeStatus(byte status)
|
||||||
|
{
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case 0x01: return "Command complete, no errors";
|
||||||
|
case 0x02: return "Unable to execute";
|
||||||
|
case 0x04: return "Unsupported control bits";
|
||||||
|
default: return "Unknown status";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger
|
||||||
|
{
|
||||||
|
public static class TouchReadControlDecoder
|
||||||
|
{
|
||||||
|
public static string Describe(byte control)
|
||||||
|
{
|
||||||
|
if (control == 0x00)
|
||||||
|
return "RF=0 (No response expected)";
|
||||||
|
|
||||||
|
if (control == 0x08)
|
||||||
|
return "RF=1 (Response expected)";
|
||||||
|
|
||||||
|
return "INVALID CONTROL BITS (unsupported pattern)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger
|
||||||
|
{
|
||||||
|
public static class TouchReadLogger
|
||||||
|
{
|
||||||
|
public static string DescribeTx(byte[] frame)
|
||||||
|
{
|
||||||
|
if (frame == null || frame.Length < 6)
|
||||||
|
return "Invalid frame";
|
||||||
|
|
||||||
|
return
|
||||||
|
"TX Frame\n" +
|
||||||
|
$" START : {HexFormatter.ToHex(frame[0])}\n" +
|
||||||
|
$" LEN : {HexFormatter.ToHex(frame[1])} ({frame[1]})\n" +
|
||||||
|
$" CONTROL : {HexFormatter.ToHex(frame[2])} - {TouchReadControlDecoder.Describe(frame[2])}\n" +
|
||||||
|
$" INFO : {HexFormatter.ToHex(GetInformation(frame))}\n" +
|
||||||
|
$" CHECKSUM: {HexFormatter.ToHex(frame[frame.Length - 2])} {HexFormatter.ToHex(frame[frame.Length - 1])}\n" +
|
||||||
|
$" RAW : {HexFormatter.ToHex(frame)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] GetInformation(byte[] frame)
|
||||||
|
{
|
||||||
|
int infoLength = frame.Length - 5; // CTRL + INFO + CHK(2)
|
||||||
|
if (infoLength <= 0)
|
||||||
|
return Array.Empty<byte>();
|
||||||
|
|
||||||
|
var info = new byte[infoLength];
|
||||||
|
Buffer.BlockCopy(frame, 3, info, 0, infoLength);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string DescribeRx(byte[] frame, TouchReadResponse response)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
"RX Frame\n" +
|
||||||
|
$" START : {HexFormatter.ToHex(frame[0])}\n" +
|
||||||
|
$" LEN : {HexFormatter.ToHex(frame[1])} ({frame[1]})\n" +
|
||||||
|
$" CONTROL : {HexFormatter.ToHex(response.Control)}\n" +
|
||||||
|
$" STATUS : {HexFormatter.ToHex(response.Status)} ({DescribeStatus(response.Status)})\n" +
|
||||||
|
$" PAYLOAD : {HexFormatter.ToHex(response.Payload)}\n" +
|
||||||
|
$" RAW : {HexFormatter.ToHex(frame)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string DescribeStatus(byte status)
|
||||||
|
{
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case 0x01: return "Command complete, no errors";
|
||||||
|
case 0x02: return "Unable to execute";
|
||||||
|
case 0x04: return "Unsupported control bits";
|
||||||
|
default: return "Unknown status";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.led
|
||||||
|
{
|
||||||
|
public interface ITouchReadLedParser
|
||||||
|
{
|
||||||
|
TouchReadLedData Parse(TouchReadLedMessage message);
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.led
|
||||||
|
{
|
||||||
|
public class ShortVariableLedParser : ITouchReadLedParser
|
||||||
|
{
|
||||||
|
public TouchReadLedData Parse(TouchReadLedMessage msg)
|
||||||
|
{
|
||||||
|
return new TouchReadLedData(msg.Raw)
|
||||||
|
{
|
||||||
|
MeterId = msg.Fields[0],
|
||||||
|
Reading = decimal.Parse(msg.Fields[1],
|
||||||
|
CultureInfo.InvariantCulture)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.led
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Parsed data from a unidirectional TouchRead LED message.
|
||||||
|
/// The exact populated fields depend on the configured reading mode.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class TouchReadLedData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Raw LED message including delimiters.
|
||||||
|
/// Example: ";12345678,00012345.67,m3;"
|
||||||
|
/// </summary>
|
||||||
|
public string Raw { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Meter factory ID or serial number (if present).
|
||||||
|
/// </summary>
|
||||||
|
public string MeterId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Customer programmable ID (if present).
|
||||||
|
/// </summary>
|
||||||
|
public string CustomerId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parsed meter reading value.
|
||||||
|
/// </summary>
|
||||||
|
public decimal? Reading { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Engineering units (e.g. "m3", "ft3", "gal").
|
||||||
|
/// </summary>
|
||||||
|
public string Units { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional alarm/status field (bitfield or text).
|
||||||
|
/// </summary>
|
||||||
|
public string AlarmStatus { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Timestamp when the LED data was received.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime Timestamp { get; }
|
||||||
|
|
||||||
|
public TouchReadLedData(string raw)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(raw))
|
||||||
|
throw new ArgumentException("Raw LED data must not be null or empty.", nameof(raw));
|
||||||
|
|
||||||
|
Raw = raw;
|
||||||
|
Timestamp = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper to safely parse a decimal value using invariant culture.
|
||||||
|
/// </summary>
|
||||||
|
public static decimal? ParseDecimal(string value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (decimal.TryParse(
|
||||||
|
value,
|
||||||
|
NumberStyles.Number,
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
out var result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.led
|
||||||
|
{
|
||||||
|
public class TouchReadLedMessage
|
||||||
|
{
|
||||||
|
public string Raw { get; }
|
||||||
|
public string[] Fields { get; }
|
||||||
|
|
||||||
|
public TouchReadLedMessage(string raw)
|
||||||
|
{
|
||||||
|
Raw = raw ?? throw new ArgumentNullException(nameof(raw));
|
||||||
|
|
||||||
|
if (!raw.StartsWith(";") || !raw.EndsWith(";"))
|
||||||
|
throw new FormatException("Invalid LED message framing");
|
||||||
|
|
||||||
|
string content = raw.Substring(1, raw.Length - 2);
|
||||||
|
Fields = content.Split(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+140
@@ -0,0 +1,140 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.protocolCommons
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Common iPERL TouchRead bidirectional commands.
|
||||||
|
/// These commands consist of a single-byte command code
|
||||||
|
/// placed in the Information field.
|
||||||
|
/// </summary>
|
||||||
|
public enum ProtocolCommand : byte
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Simple (legacy) commands (e.g. View Factory ID = 0x01)
|
||||||
|
/// </summary>
|
||||||
|
Simple = 0x00,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View Factory ID (ex-works serial number).
|
||||||
|
/// Returns a 0–12 byte ASCII string terminated by NULL.
|
||||||
|
/// Response only if RF flag is set.
|
||||||
|
/// </summary>
|
||||||
|
ViewFactoryId = 0x01,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set Factory ID (0–12 ASCII characters, NULL terminated).
|
||||||
|
/// Protected by meter seal.
|
||||||
|
/// </summary>
|
||||||
|
SetFactoryId = 0x02,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View Customer Programmable ID (1–12 ASCII characters).
|
||||||
|
/// </summary>
|
||||||
|
ViewProgrammableId = 0x03,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set Customer Programmable ID (1–12 ASCII characters, NULL terminated).
|
||||||
|
/// </summary>
|
||||||
|
SetProgrammableId = 0x04,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View Version and Type string.
|
||||||
|
/// Example: B1.22,SMW002,B0.02
|
||||||
|
/// </summary>
|
||||||
|
ViewVersionAndType = 0x05,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View Customer Programmable Text (0–20 ASCII characters).
|
||||||
|
/// </summary>
|
||||||
|
ViewProgrammableText = 0x07,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set Customer Programmable Text (0–20 ASCII characters, NULL terminated).
|
||||||
|
/// </summary>
|
||||||
|
SetProgrammableText = 0x08,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View number of reading digits and decimal shift.
|
||||||
|
/// Payload: uint8 digits, int8 decimal shift.
|
||||||
|
/// </summary>
|
||||||
|
ViewNumberOfReadingDigits = 0x09,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set number of reading digits and decimal shift.
|
||||||
|
/// Digits range: 4–8, Decimal shift: -5..0.
|
||||||
|
/// </summary>
|
||||||
|
SetNumberOfReadingDigits = 0x0A,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View reading units.
|
||||||
|
/// Returns numeric unit code (m3, ft3, gallons).
|
||||||
|
/// </summary>
|
||||||
|
ViewReadingUnits = 0x0B,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set reading units.
|
||||||
|
/// Valid values: 0x00=m3, 0x01=ft3, 0x04=US gallons, 0xFF=off.
|
||||||
|
/// </summary>
|
||||||
|
SetReadingUnits = 0x0C,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View reading multiplier (resolution).
|
||||||
|
/// Range: -7..+5 or 0x80 (disabled).
|
||||||
|
/// </summary>
|
||||||
|
ViewReadingMultiplier = 0x0F,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set reading multiplier (resolution).
|
||||||
|
/// </summary>
|
||||||
|
SetReadingMultiplier = 0x10,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View preset total (volume accumulator).
|
||||||
|
/// Returns 8 ASCII digits + NULL.
|
||||||
|
/// </summary>
|
||||||
|
ViewPresetTotal = 0x13,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set preset total (0–8 ASCII digits, NULL terminated).
|
||||||
|
/// Protected by meter seal.
|
||||||
|
/// </summary>
|
||||||
|
SetPresetTotal = 0x14,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View reading mode (unidirectional TouchRead format).
|
||||||
|
/// </summary>
|
||||||
|
ViewReadingMode = 0x15,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set reading mode.
|
||||||
|
/// Values: Short Variable, Extended, Fixed, Smart Meter.
|
||||||
|
/// </summary>
|
||||||
|
SetReadingMode = 0x16,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View build information (firmware details).
|
||||||
|
/// </summary>
|
||||||
|
ViewBuildInformation = 0x17,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View meter state.
|
||||||
|
/// </summary>
|
||||||
|
ViewState = 0x19,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set meter state (operating mode).
|
||||||
|
/// Protected by meter seal.
|
||||||
|
/// </summary>
|
||||||
|
SetState = 0x1A,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Device-specific command prefix.
|
||||||
|
/// Must be followed by a device sub-command byte.
|
||||||
|
/// </summary>
|
||||||
|
DeviceSpecific = 0xFD,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Question - specific switch to add additional payload request like "vers"
|
||||||
|
/// Mandatory add payload
|
||||||
|
/// </summary>
|
||||||
|
Question = 0x3F,
|
||||||
|
}
|
||||||
|
}
|
||||||
+201
@@ -0,0 +1,201 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.protocolCommons
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Device-specific TouchRead sub-commands.
|
||||||
|
/// These sub-commands are used together with the
|
||||||
|
/// <see cref="TouchReadCommand.DeviceSpecific"/> (0xFD) command.
|
||||||
|
/// </summary>
|
||||||
|
public enum ProtocolDeviceSubCommand : byte
|
||||||
|
{
|
||||||
|
// ==========================================================
|
||||||
|
// System / Time
|
||||||
|
// ==========================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View system time.
|
||||||
|
/// 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 set to zero, the meter resets and erases data.
|
||||||
|
/// Protected by meter seal.
|
||||||
|
/// </summary>
|
||||||
|
SetSystemTime = 0x11,
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// Alarm Mask / Alarm Configuration
|
||||||
|
// ==========================================================
|
||||||
|
|
||||||
|
/// <summary>View alarm mask (lower 16 bits).</summary>
|
||||||
|
ViewAlarmMask = 0x31,
|
||||||
|
|
||||||
|
/// <summary>Set alarm mask (lower 16 bits).</summary>
|
||||||
|
SetAlarmMask = 0x32,
|
||||||
|
|
||||||
|
/// <summary>View alarm persistence period (days).</summary>
|
||||||
|
ViewPersistence = 0x33,
|
||||||
|
|
||||||
|
/// <summary>Set alarm persistence period (days).</summary>
|
||||||
|
SetPersistence = 0x34,
|
||||||
|
|
||||||
|
/// <summary>View leak duration (hours).</summary>
|
||||||
|
ViewLeakDuration = 0x35,
|
||||||
|
|
||||||
|
/// <summary>Set leak duration (hours).</summary>
|
||||||
|
SetLeakDuration = 0x36,
|
||||||
|
|
||||||
|
/// <summary>View current alarm states.</summary>
|
||||||
|
ViewAlarms = 0x37,
|
||||||
|
|
||||||
|
/// <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
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.protocolCommons
|
||||||
|
{
|
||||||
|
public enum ProtocolStatuses : byte
|
||||||
|
{
|
||||||
|
Idle = 0x01,
|
||||||
|
Active = 0x02,
|
||||||
|
Inactive = 0x03,
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol
|
||||||
|
{
|
||||||
|
public sealed class TouchReadFrame
|
||||||
|
{
|
||||||
|
public byte Start { get; }
|
||||||
|
public byte Length { get; }
|
||||||
|
public byte Control { get; }
|
||||||
|
public byte[] Information { get; }
|
||||||
|
public ushort Checksum { get; }
|
||||||
|
|
||||||
|
public TouchReadFrame(
|
||||||
|
byte start,
|
||||||
|
byte length,
|
||||||
|
byte control,
|
||||||
|
byte[] information,
|
||||||
|
ushort checksum)
|
||||||
|
{
|
||||||
|
Start = start;
|
||||||
|
Length = length;
|
||||||
|
Control = control;
|
||||||
|
Information = information ?? Array.Empty<byte>();
|
||||||
|
Checksum = checksum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+125
@@ -0,0 +1,125 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.protocolCommons;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol
|
||||||
|
{
|
||||||
|
public sealed class TouchReadFrameBuilder
|
||||||
|
{
|
||||||
|
private const byte START = 0x0D;
|
||||||
|
private byte _control;
|
||||||
|
private readonly List<byte> _information = new List<byte>();
|
||||||
|
|
||||||
|
public TouchReadFrameBuilder RequestResponse(bool enabled)
|
||||||
|
{
|
||||||
|
_control = enabled ? (byte)0x08 : (byte)0x00;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TouchReadFrameBuilder AddCommand(ProtocolCommand command)
|
||||||
|
{
|
||||||
|
_information.Add((byte)command);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TouchReadFrameBuilder AddSubCommand(ProtocolDeviceSubCommand subCommand)
|
||||||
|
{
|
||||||
|
if (_information.Count == 0 ||
|
||||||
|
_information[0] != (byte)ProtocolCommand.DeviceSpecific)
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Sub-command is only valid for DeviceSpecific (0xFD) commands.");
|
||||||
|
|
||||||
|
_information.Add((byte)subCommand);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TouchReadFrameBuilder AddDeviceCommand(
|
||||||
|
ProtocolDeviceSubCommand subCommand)
|
||||||
|
{
|
||||||
|
_information.Add((byte)ProtocolCommand.DeviceSpecific);
|
||||||
|
_information.Add((byte)subCommand);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TouchReadFrameBuilder AddPayload(byte[] payload)
|
||||||
|
{
|
||||||
|
if (payload != null)
|
||||||
|
_information.AddRange(payload);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TouchReadFrameBuilder AddDiagnosticLedState(DiagnosticLedState state)
|
||||||
|
{
|
||||||
|
_information.Add((byte)ProtocolCommand.DeviceSpecific);
|
||||||
|
_information.Add((byte)ProtocolDeviceSubCommand.SetDiagnosticLEDState);
|
||||||
|
_information.Add((byte)state);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TouchReadFrameBuilder AddNullTerminatedAscii(string text)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(text))
|
||||||
|
_information.AddRange(
|
||||||
|
System.Text.Encoding.ASCII.GetBytes(text));
|
||||||
|
|
||||||
|
_information.Add(0x00);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TouchReadFrame BuildFrame()
|
||||||
|
{
|
||||||
|
if (_information.Count == 0)
|
||||||
|
throw new InvalidOperationException("No command specified.");
|
||||||
|
|
||||||
|
byte length = (byte)(1 + _information.Count + 2);
|
||||||
|
|
||||||
|
var raw = new List<byte>
|
||||||
|
{
|
||||||
|
START,
|
||||||
|
length,
|
||||||
|
_control
|
||||||
|
};
|
||||||
|
|
||||||
|
raw.AddRange(_information);
|
||||||
|
|
||||||
|
ushort checksum = CalculateChecksum(raw);
|
||||||
|
raw.Add((byte)(checksum >> 8));
|
||||||
|
raw.Add((byte)(checksum & 0xFF));
|
||||||
|
|
||||||
|
return new TouchReadFrame(
|
||||||
|
START,
|
||||||
|
length,
|
||||||
|
_control,
|
||||||
|
_information.ToArray(),
|
||||||
|
checksum);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] BuildBytes()
|
||||||
|
{
|
||||||
|
TouchReadFrame frame = BuildFrame();
|
||||||
|
|
||||||
|
var bytes = new List<byte>
|
||||||
|
{
|
||||||
|
frame.Start,
|
||||||
|
frame.Length,
|
||||||
|
frame.Control
|
||||||
|
};
|
||||||
|
|
||||||
|
bytes.AddRange(frame.Information);
|
||||||
|
bytes.Add((byte)(frame.Checksum >> 8));
|
||||||
|
bytes.Add((byte)(frame.Checksum & 0xFF));
|
||||||
|
|
||||||
|
return bytes.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ushort CalculateChecksum(IEnumerable<byte> data)
|
||||||
|
{
|
||||||
|
ushort sum = 0;
|
||||||
|
foreach (var b in data)
|
||||||
|
sum += b;
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol
|
||||||
|
{
|
||||||
|
public sealed class TouchReadFrameParser
|
||||||
|
{
|
||||||
|
private const byte START = 0x0D;
|
||||||
|
|
||||||
|
public TouchReadResponse Parse(byte[] data)
|
||||||
|
{
|
||||||
|
if (data == null)
|
||||||
|
throw new ArgumentNullException(nameof(data));
|
||||||
|
|
||||||
|
if (data.Length < 6)
|
||||||
|
throw new FormatException("Frame too short.");
|
||||||
|
|
||||||
|
if (data[0] != START)
|
||||||
|
throw new FormatException("Invalid START byte.");
|
||||||
|
|
||||||
|
byte length = data[1];
|
||||||
|
if (length + 2 != data.Length)
|
||||||
|
throw new FormatException("Length mismatch.");
|
||||||
|
|
||||||
|
ushort receivedChecksum =
|
||||||
|
(ushort)((data[data.Length - 2] << 8) |
|
||||||
|
data[data.Length - 1]);
|
||||||
|
|
||||||
|
ushort calculatedChecksum = CalculateChecksum(data, data.Length - 2);
|
||||||
|
if (receivedChecksum != calculatedChecksum)
|
||||||
|
throw new FormatException("Checksum error.");
|
||||||
|
|
||||||
|
byte control = data[2];
|
||||||
|
byte status = data[3];
|
||||||
|
|
||||||
|
byte[] payload = ExtractPayload(data);
|
||||||
|
|
||||||
|
return new TouchReadResponse(control, status, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ushort CalculateChecksum(byte[] data, int count)
|
||||||
|
{
|
||||||
|
ushort sum = 0;
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
sum += data[i];
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ExtractPayload(byte[] data)
|
||||||
|
{
|
||||||
|
// payload exists only if frame longer than:
|
||||||
|
// START + LEN + CTRL + STATUS + CHK_HI + CHK_LO = 6 bytes
|
||||||
|
if (data.Length <= 6)
|
||||||
|
return Array.Empty<byte>();
|
||||||
|
|
||||||
|
int payloadLength = data.Length - 6;
|
||||||
|
byte[] payload = new byte[payloadLength];
|
||||||
|
Buffer.BlockCopy(data, 4, payload, 0, payloadLength);
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol
|
||||||
|
{
|
||||||
|
public static class TouchReadProtocol
|
||||||
|
{
|
||||||
|
public const byte START = 0x0D;
|
||||||
|
|
||||||
|
// Control bits (CNTRL1)
|
||||||
|
public const byte RESPONSE_FLAG = 0x08; // RF
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol
|
||||||
|
{
|
||||||
|
public sealed class TouchReadResponse
|
||||||
|
{
|
||||||
|
public byte Control { get; }
|
||||||
|
public byte Status { get; }
|
||||||
|
public byte[] Payload { get; }
|
||||||
|
|
||||||
|
public bool IsOk => Status == 0x01;
|
||||||
|
|
||||||
|
public TouchReadResponse(byte control, byte status, byte[] payload)
|
||||||
|
{
|
||||||
|
Control = control;
|
||||||
|
Status = status;
|
||||||
|
Payload = payload ?? Array.Empty<byte>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetAsciiPayload()
|
||||||
|
{
|
||||||
|
if (Payload.Length == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int length = Array.IndexOf(Payload, (byte)0x00);
|
||||||
|
if (length < 0)
|
||||||
|
length = Payload.Length;
|
||||||
|
|
||||||
|
return System.Text.Encoding.ASCII.GetString(Payload, 0, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication
|
||||||
|
{
|
||||||
|
public class OpthoHeadService
|
||||||
|
{
|
||||||
|
protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO.Ports;
|
||||||
|
using Common;
|
||||||
|
using log4net;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.Utils;
|
||||||
|
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication
|
||||||
|
{
|
||||||
|
public class OptoHeadTest : IDisposable
|
||||||
|
{
|
||||||
|
protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData");
|
||||||
|
|
||||||
|
private static SerialDriver serialDriver;
|
||||||
|
|
||||||
|
public static SerialDriver BuildConnection(ISmartReader iHead)
|
||||||
|
{
|
||||||
|
return new SerialDriverBuilder()
|
||||||
|
.WithPort($"COM{iHead.RfidComPortNr}")
|
||||||
|
.WithBaudRate(2400)
|
||||||
|
.WithDataBits(8)
|
||||||
|
.WithParity(Parity.None)
|
||||||
|
.WithStopBits(StopBits.One)
|
||||||
|
.WithTimeouts(4000, 2000)
|
||||||
|
.BuildAndConnect();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CloseConnection()
|
||||||
|
{
|
||||||
|
if (serialDriver != null)
|
||||||
|
serialDriver.CloseConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string ReadRequest_PCB(ISmartReader iHead)
|
||||||
|
{
|
||||||
|
if (iHead.DebugLevel == DebugMode.Simulate)
|
||||||
|
{
|
||||||
|
return "-OK Simulated response-";
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (iHead != null)
|
||||||
|
{
|
||||||
|
if (serialDriver == null)
|
||||||
|
serialDriver = BuildConnection(iHead);
|
||||||
|
|
||||||
|
RadioService headService = new RadioService(serialDriver);
|
||||||
|
string serialNo = headService.ReadRequest_PCB(iHead);
|
||||||
|
return serialNo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return (ex.Message.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SetTestMode(ISmartReader iHead)
|
||||||
|
{
|
||||||
|
if (iHead.DebugLevel == DebugMode.Simulate)
|
||||||
|
{
|
||||||
|
return "-OK Simulated response-";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (iHead != null)
|
||||||
|
{
|
||||||
|
if (serialDriver == null)
|
||||||
|
serialDriver = BuildConnection(iHead);
|
||||||
|
|
||||||
|
RadioService headService = new RadioService(serialDriver);
|
||||||
|
string answer = headService.SetTestMode(iHead);
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return (ex.Message.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SetActiveMode(ISmartReader iHead)
|
||||||
|
{
|
||||||
|
if (iHead.DebugLevel == DebugMode.Simulate)
|
||||||
|
{
|
||||||
|
return "-OK Simulated response-";
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (iHead != null)
|
||||||
|
{
|
||||||
|
if (serialDriver == null)
|
||||||
|
serialDriver = BuildConnection(iHead);
|
||||||
|
|
||||||
|
RadioService headService = new RadioService(serialDriver);
|
||||||
|
string answer = headService.SetActiveMode(iHead);
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return (ex.Message.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
CloseConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
using Common;
|
||||||
|
using log4net;
|
||||||
|
using TBF.Rig.Modbus.Meret.AdjustableScale;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.protocolCommons;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol;
|
||||||
|
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 IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.ViewFactoryId)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
|
||||||
|
byte[] rawData = serialDriver.SendAndWait(request, 10000);
|
||||||
|
if (rawData == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// parse rawData
|
||||||
|
var parser = new IperlHatFrameParser();
|
||||||
|
IperlHatResponse decoded = parser.Parse(rawData);
|
||||||
|
if (decoded.IsOk)
|
||||||
|
{
|
||||||
|
return decoded.GetAsciiPayload();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SetTestMode(ISmartReader iHead)
|
||||||
|
{
|
||||||
|
if (!serialDriver.IsOpen())
|
||||||
|
{
|
||||||
|
serialDriver.Open();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set LED to state 4
|
||||||
|
byte[] request = new IperlHatFrameBuilder()
|
||||||
|
.AddDiagnosticLedState(DiagnosticLedState.State4)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] rawData = serialDriver.SendAndWait(request, 1000);
|
||||||
|
if (rawData == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
|
||||||
|
// parse rawData
|
||||||
|
var parser = new IperlHatFrameParser();
|
||||||
|
IperlHatResponse decoded = parser.Parse(rawData);
|
||||||
|
if (decoded.IsOk)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
//correct or incorrect response
|
||||||
|
//okResponse, errorResponse
|
||||||
|
|
||||||
|
return "Set Test Mode - OK";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Set Test Mode - FAILED";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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 IperlHatFrameBuilder()
|
||||||
|
.AddDiagnosticLedState(DiagnosticLedState.StateOFF)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] rawData = serialDriver.SendAndWait(request, 1000);
|
||||||
|
if (rawData == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
|
||||||
|
// parse rawData
|
||||||
|
var parser = new IperlHatFrameParser();
|
||||||
|
IperlHatResponse decoded = parser.Parse(rawData);
|
||||||
|
if (decoded.IsOk)
|
||||||
|
{
|
||||||
|
|
||||||
|
return "Set Active Mode - OK";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Set Active Mode - FAILED";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,290 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO.Ports;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using FluentNHibernate.Conventions;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.communication.Utils
|
||||||
|
{
|
||||||
|
public class SerialDriver : IDisposable
|
||||||
|
{
|
||||||
|
public string ErrorMessage { get; private set; }
|
||||||
|
private List<byte> SerialPortReadBuffer = new List<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.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
|
||||||
|
{
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
if (_serialPort == null || !_serialPort.IsOpen) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.Sleep(5);
|
||||||
|
|
||||||
|
if (!SerialPortReadBuffer.IsEmpty())
|
||||||
|
{
|
||||||
|
SerialPortReadBuffer.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int iWordCounter = 0;
|
||||||
|
bool isStart = false;
|
||||||
|
bool isQuestion = false;
|
||||||
|
int iLength = 0;
|
||||||
|
while (true)//_serialPort.BytesToRead > 0
|
||||||
|
{
|
||||||
|
byte readByte = (byte)_serialPort.ReadByte();
|
||||||
|
|
||||||
|
//I have START
|
||||||
|
if (readByte == C4.IperlHatProtocol.Constants.Start)
|
||||||
|
{
|
||||||
|
iWordCounter++;
|
||||||
|
isStart = true;
|
||||||
|
}
|
||||||
|
// I have QUESTION
|
||||||
|
if (readByte == C4.IperlHatProtocol.Constants.Question)
|
||||||
|
{
|
||||||
|
iWordCounter++;
|
||||||
|
isQuestion = true;
|
||||||
|
}
|
||||||
|
//I count length from start
|
||||||
|
if (iWordCounter > 0)
|
||||||
|
iWordCounter++;
|
||||||
|
|
||||||
|
if (iWordCounter > 0)
|
||||||
|
{
|
||||||
|
//Store byte to data
|
||||||
|
SerialPortReadBuffer.Add(readByte);
|
||||||
|
}
|
||||||
|
// we have length
|
||||||
|
if (iLength == 0 && isStart && SerialPortReadBuffer.Count > 2 )
|
||||||
|
{
|
||||||
|
iLength = (int)SerialPortReadBuffer[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we have enough bytes
|
||||||
|
if (isStart && iLength > 0 && SerialPortReadBuffer.Count >= iLength)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//if we read END
|
||||||
|
if (isQuestion && readByte == C4.IperlHatProtocol.Constants.End)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SerialPortReadBuffer.Count > 0)
|
||||||
|
{
|
||||||
|
_binMessages.AddRange(SerialPortReadBuffer.ToArray());
|
||||||
|
_responseReceived.Set();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (TimeoutException te)
|
||||||
|
{
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Web.UI.WebControls;
|
||||||
|
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;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.implementations
|
||||||
|
{
|
||||||
|
public class IPerlASICImplHeadTestCtrl : IUniHeadTestCtrl
|
||||||
|
{
|
||||||
|
Thread optoThread;
|
||||||
|
public ISmartReader ISmartReader { get; set; }
|
||||||
|
public bool stopWorkerThread { get; set; }
|
||||||
|
public event EventHandler<OptoReceivedEventArgs> OptoReceivedHandler;
|
||||||
|
|
||||||
|
public IComponentCfg
|
||||||
|
|
||||||
|
|
||||||
|
config { get; set; }
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
stopWorkerThread = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Destroy()
|
||||||
|
{
|
||||||
|
stopWorkerThread = true;
|
||||||
|
if (optoThread != null)
|
||||||
|
{
|
||||||
|
optoThread.Abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string StrReadPcbCmd = "ReadPCB";
|
||||||
|
private const string StrSetTestModeCmd = "SetTestMode";
|
||||||
|
private const string StrSetActiveModeCmd = "SetActiveMode";
|
||||||
|
private const string StrReadOptoDataCmd = "ReadOptoData";
|
||||||
|
private const string StrStopReadOptoDataCmd = "StopReadOptoData";
|
||||||
|
private const string StrResetNfcHeadCmd = "ResetNfcHead";
|
||||||
|
private const string StrSetNfcHeadCmd = "SetNfcHead";
|
||||||
|
private const string StrSetRfidHeadCmd = "SetRfidHead";
|
||||||
|
private const string StrEmptyCmd = "";
|
||||||
|
|
||||||
|
public enum Operations
|
||||||
|
{
|
||||||
|
[Description(StrReadPcbCmd)]ReadPcbCmd,
|
||||||
|
[Description(StrSetTestModeCmd)]SetTestModeCmd,
|
||||||
|
[Description(StrSetActiveModeCmd)]SetActiveModeCmd,
|
||||||
|
[Description(StrReadOptoDataCmd)]ReadOptoDataCmd,
|
||||||
|
[Description(StrStopReadOptoDataCmd)]StopReadOptoDataCmd,
|
||||||
|
[Description(StrResetNfcHeadCmd)]ResetNfcHeadCmd,
|
||||||
|
[Description(StrSetNfcHeadCmd)]SetNfcHeadCmd,
|
||||||
|
[Description(StrSetRfidHeadCmd)]SetRfidHeadCmd,
|
||||||
|
[Description(StrEmptyCmd)]EmptyCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, Operations> ItemsForIperlOperations = new Dictionary<string, Operations>
|
||||||
|
{
|
||||||
|
{"Read PCB", Operations.ReadPcbCmd},
|
||||||
|
{"Set Test Mode", Operations.SetTestModeCmd},
|
||||||
|
{"Set Active Mode", Operations.SetActiveModeCmd},
|
||||||
|
#if DEBUG
|
||||||
|
{"Start Read Opto Data", Operations.ReadOptoDataCmd},
|
||||||
|
{"Stop Read Opto Data", Operations.StopReadOptoDataCmd},
|
||||||
|
#endif
|
||||||
|
{" ", Operations.EmptyCmd},
|
||||||
|
{"Reset NFC Head", Operations.ResetNfcHeadCmd},
|
||||||
|
{"Set NFC Head Interface", Operations.SetNfcHeadCmd},
|
||||||
|
{"Set RFID Head interface", Operations.SetRfidHeadCmd}
|
||||||
|
};
|
||||||
|
|
||||||
|
public (string Name, string Value)[] GetComboOperationsPairs()
|
||||||
|
{
|
||||||
|
//return ItemsForIperlOperations.Select(kvp => (kvp.Key, kvp.Value)).ToArray();
|
||||||
|
return ItemsForIperlOperations.Select(kvp => (kvp.Key, kvp.Value.ToDescription())).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CommandTestButtonClick(object sender, MouseEventArgs e, Arguments a)
|
||||||
|
{
|
||||||
|
a.RfidOutputListBox.Items.Clear();
|
||||||
|
|
||||||
|
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: {OptoHeadTest.ReadRequest_PCB(a.ISmartReader)}";
|
||||||
|
break;
|
||||||
|
case Operations.SetTestModeCmd:
|
||||||
|
rfidListItem.Text = OptoHeadTest.SetTestMode(a.ISmartReader);
|
||||||
|
a.OptoListBox.Items.Clear();
|
||||||
|
stopWorkerThread = false;
|
||||||
|
optoThread = new Thread(OptoWorker);
|
||||||
|
if (!optoThread.IsAlive)
|
||||||
|
{
|
||||||
|
a.ISmartReader.StartDataStreamProcessing(); // open opto port
|
||||||
|
optoThread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case Operations.SetActiveModeCmd:
|
||||||
|
rfidListItem.Text = OptoHeadTest.SetActiveMode(a.ISmartReader);
|
||||||
|
stopWorkerThread = true;
|
||||||
|
a.ISmartReader.StopDataStreamProcessing(); // close opto port
|
||||||
|
break;
|
||||||
|
case Operations.ResetNfcHeadCmd:
|
||||||
|
a.ISmartReader.ResetNfcInterface();
|
||||||
|
break;
|
||||||
|
case Operations.SetNfcHeadCmd:
|
||||||
|
a.ISmartReader.SetNfcInterface();
|
||||||
|
break;
|
||||||
|
case Operations.SetRfidHeadCmd:
|
||||||
|
a.ISmartReader.SetRfidInterface();
|
||||||
|
break;
|
||||||
|
case Operations.ReadOptoDataCmd:
|
||||||
|
a.OptoListBox.Items.Clear();
|
||||||
|
stopWorkerThread = false;
|
||||||
|
optoThread = new Thread(OptoWorker);
|
||||||
|
if (optoThread.IsAlive)
|
||||||
|
{
|
||||||
|
stopWorkerThread = true;
|
||||||
|
a.ISmartReader.StopDataStreamProcessing(); // close opto port
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!optoThread.IsAlive)
|
||||||
|
{
|
||||||
|
a.ISmartReader.StartDataStreamProcessing(); // open opto port
|
||||||
|
optoThread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case Operations.StopReadOptoDataCmd:
|
||||||
|
stopWorkerThread = true;
|
||||||
|
a.ISmartReader.StopDataStreamProcessing(); // close opto port
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.RfidOutputListBox.Items.Add(rfidListItem);
|
||||||
|
a.RfidOutputListBox.Items.AddRange(logChecker.Messages.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OptoWorker()
|
||||||
|
{
|
||||||
|
while (!this.stopWorkerThread)
|
||||||
|
{
|
||||||
|
Thread.Sleep(250);
|
||||||
|
if (this.stopWorkerThread)
|
||||||
|
break;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string buffer = ISmartReader.ReadOptoData();
|
||||||
|
if (string.IsNullOrEmpty(buffer))
|
||||||
|
{
|
||||||
|
this.OnOptoReceived((object)this, new OptoReceivedEventArgs("."));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
OnOptoReceived((object)this, new OptoReceivedEventArgs(buffer));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
this.OnOptoReceived((object)this, new OptoReceivedEventArgs(ex.Message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnOptoReceived(object sender, OptoReceivedEventArgs args)
|
||||||
|
{
|
||||||
|
if (this.OptoReceivedHandler == null)
|
||||||
|
return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.OptoReceivedHandler(sender, args);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlASICReader.implementations
|
||||||
|
{
|
||||||
|
public enum OptoTelegramFlags : byte
|
||||||
|
{
|
||||||
|
OK = 0,
|
||||||
|
OK_TestStart,
|
||||||
|
OK_TestEnd,
|
||||||
|
InvalidTelegram, /// Wrong telegram format of checksum error
|
||||||
|
SyncError,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OptoTelegramRaw
|
||||||
|
{
|
||||||
|
private DiagnosticLedState4Data data;
|
||||||
|
private static CultureInfo culture;
|
||||||
|
///
|
||||||
|
/// Strobed value
|
||||||
|
///
|
||||||
|
public static decimal TestStartTimestampDec;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Stored values
|
||||||
|
///
|
||||||
|
public OptoTelegramFlags Flags;
|
||||||
|
|
||||||
|
public DateTime DateTime; /// From PC
|
||||||
|
public float RefFlow; /// [m3/h]
|
||||||
|
public int Counter;
|
||||||
|
|
||||||
|
public Int16 FlowRaw;
|
||||||
|
public UInt32 VolumeRaw;
|
||||||
|
public Int64 VolumeRawExt;
|
||||||
|
public UInt32 Timestamp;
|
||||||
|
public Int64 TimestampExt;
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Calculated values
|
||||||
|
///
|
||||||
|
public double Flow(double scalingFactor) { return 0.225 * scalingFactor * (double)FlowRaw; }
|
||||||
|
public double Volume(double scalingFactor) { return 0.0000625 * scalingFactor * (double)VolumeRawExt; }
|
||||||
|
public decimal TimestampDec() { return (decimal)TimestampExt / (decimal)8192; }
|
||||||
|
public double VolumeDelta(double scalingFactor,OptoTelegramRaw previous) { return (previous == null) ? 0 : Volume(scalingFactor) - previous.Volume(scalingFactor); }
|
||||||
|
public decimal TimeDelta() { return TimestampDec() - TestStartTimestampDec; }
|
||||||
|
public string Label()
|
||||||
|
{
|
||||||
|
if (Flags == OptoTelegramFlags.OK_TestStart) return "#### start test ####";
|
||||||
|
else if (Flags == OptoTelegramFlags.OK_TestEnd) return "#### end of test ####";
|
||||||
|
else return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static OptoTelegramRaw()
|
||||||
|
{
|
||||||
|
culture = CultureInfo.CreateSpecificCulture("DE"); /// This is to use comma as decimal number separator
|
||||||
|
}
|
||||||
|
|
||||||
|
public OptoTelegramRaw()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateFromSmart(DiagnosticLedState4Data data,int counter, float refFlow, ref Int64 volumeRawExtLast, ref Int64 timestampExtLast)
|
||||||
|
{
|
||||||
|
|
||||||
|
DateTime = DateTime.Now;
|
||||||
|
Counter = counter;
|
||||||
|
RefFlow = refFlow;
|
||||||
|
|
||||||
|
FlowRaw = data.RawFlow;
|
||||||
|
VolumeRaw = data.RawVolume;
|
||||||
|
Timestamp = data.AsicTimestamp;
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Cope with 'VolumeRaw' overflow
|
||||||
|
///
|
||||||
|
Int64 uncorrected = (Int64)(((UInt64)volumeRawExtLast & 0xFFFFFFFFFF000000UL) | VolumeRaw);
|
||||||
|
if (Math.Abs(uncorrected - volumeRawExtLast) <= 0x800000L)
|
||||||
|
{
|
||||||
|
VolumeRawExt = volumeRawExtLast = uncorrected;
|
||||||
|
}
|
||||||
|
else if (Math.Abs(uncorrected + 0x1000000L - volumeRawExtLast) <= 0x800000L)
|
||||||
|
{
|
||||||
|
VolumeRawExt = volumeRawExtLast = uncorrected + 0x1000000L;
|
||||||
|
}
|
||||||
|
else if (Math.Abs(uncorrected - 0x1000000L - volumeRawExtLast) <= 0x800000L)
|
||||||
|
{
|
||||||
|
VolumeRawExt = volumeRawExtLast = uncorrected - 0x1000000L;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VolumeRawExt = volumeRawExtLast = uncorrected;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Cope with 'Timestamp' overflow
|
||||||
|
///
|
||||||
|
uncorrected = (Int64)(((UInt64)timestampExtLast & 0xFFFFFFFF00000000UL) | Timestamp);
|
||||||
|
if (Math.Abs(uncorrected - timestampExtLast) <= 0x80000000L)
|
||||||
|
{
|
||||||
|
TimestampExt = timestampExtLast = uncorrected;
|
||||||
|
}
|
||||||
|
else if (Math.Abs(uncorrected + 0x100000000L - timestampExtLast) <= 0x80000000L)
|
||||||
|
{
|
||||||
|
TimestampExt = timestampExtLast = uncorrected + 0x100000000L;
|
||||||
|
}
|
||||||
|
else if (Math.Abs(uncorrected - 0x100000000L - timestampExtLast) <= 0x80000000L)
|
||||||
|
{
|
||||||
|
TimestampExt = timestampExtLast = uncorrected - 0x100000000L;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TimestampExt = timestampExtLast = uncorrected;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetFlags(OptoTelegramFlags flags)
|
||||||
|
{
|
||||||
|
this.Flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string ToString(double scalingFactor, OptoTelegramRaw previous)
|
||||||
|
{
|
||||||
|
if (Flags == OptoTelegramFlags.SyncError)
|
||||||
|
{
|
||||||
|
return "Sychronization error";
|
||||||
|
}
|
||||||
|
else if (Flags == OptoTelegramFlags.InvalidTelegram)
|
||||||
|
{
|
||||||
|
return "Invalid telegram";
|
||||||
|
}
|
||||||
|
else /// if (flags == OptoTelegramFlags.OK / OptoTelegramFlags.OK_TestStart / OptoTelegramFlags.OK_TestEnd)
|
||||||
|
{
|
||||||
|
return string.Format("{0}:{1}:{2}.{3}\t{4} :\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}\t{11}\t{12}\t{13}\t{14}\t{15}",
|
||||||
|
DateTime.Hour.ToString("D2"),
|
||||||
|
DateTime.Minute.ToString("D2"),
|
||||||
|
DateTime.Second.ToString("D2"),
|
||||||
|
DateTime.Millisecond.ToString("D4"),
|
||||||
|
Counter,
|
||||||
|
FlowRaw.ToString("X4"),
|
||||||
|
VolumeRaw.ToString("X6"),
|
||||||
|
Timestamp.ToString("X8"),
|
||||||
|
Flow(scalingFactor).ToString("F2", culture),
|
||||||
|
Volume(scalingFactor).ToString("F4", culture),
|
||||||
|
TimestampDec().ToString("F4", culture),
|
||||||
|
(RefFlow * 1000).ToString("F2", culture),
|
||||||
|
VolumeDelta(scalingFactor, previous).ToString("F4", culture),
|
||||||
|
TimeDelta().ToString("F3", culture),
|
||||||
|
scalingFactor.ToString("F1", culture),
|
||||||
|
Label());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,7 @@ namespace TBF.Rig.RegisterReaders.iPerlReaderUNI
|
|||||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||||
public IComponentCfgCtrl GetControl(IList<Component> cmpntEntities)
|
public IComponentCfgCtrl GetControl(IList<Component> cmpntEntities)
|
||||||
{
|
{
|
||||||
return new IPerlReader.IPerlUniCfgCtrl();
|
return new iPerlASICReader.IPerlUniCfgCtrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
using System.Web.UI;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlReaderUNI.iCommon;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlReaderUNI.IPerlS4
|
||||||
|
{
|
||||||
|
public class IperlHeadTestCtrl : UNIHeadTestCtrl
|
||||||
|
{
|
||||||
|
System.Windows.Forms.ListBox rfidOutputListBox;
|
||||||
|
|
||||||
|
public IperlHeadTestCtrl(ListBox rfidOutputListBox)
|
||||||
|
{
|
||||||
|
this.rfidOutputListBox = rfidOutputListBox;
|
||||||
|
|
||||||
|
var foo = new[]
|
||||||
|
{
|
||||||
|
new {Name = "Read PCB", Value = "ReadPCB" },
|
||||||
|
new {Name = "Set Test Mode", Value = "SetTestMode" },
|
||||||
|
new {Name = "Set Active Mode", Value = "SetActiveMode" },
|
||||||
|
#if DEBUG
|
||||||
|
new {Name = "Start Read Opto Data", Value = "ReadOptoData" },
|
||||||
|
new {Name = "Stop Read Opto Data", Value = "StopReadOptoData" },
|
||||||
|
#endif
|
||||||
|
new {Name = " ", Value = "" },
|
||||||
|
new {Name = "Reset NFC Head", Value = "ResetNfcHead" },
|
||||||
|
new {Name = "Set NFC Head Interface", Value = "SetNfcHead" },
|
||||||
|
new {Name = "Set RFID Head interface", Value = "SetRfidHead" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void CommandTestButtonClick(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
rfidOutputListBox.Items.Clear();
|
||||||
|
|
||||||
|
using (Tools.LogChecker logChecker = new Tools.LogChecker("RfidData", log4net.Core.Level.Debug))
|
||||||
|
{
|
||||||
|
ListItem rfidListItem = new ListItem();
|
||||||
|
rfidListItem.Attributes.Add("style", "font-weight:bold");
|
||||||
|
switch (rfidCommandComboBox.SelectedValue)
|
||||||
|
{
|
||||||
|
case "ReadPCB":
|
||||||
|
rfidListItem.Text = $"PCB: {OpticalHeadTest.ReadRequest_PCB(_iPerlReader)}";
|
||||||
|
break;
|
||||||
|
case "SetTestMode":
|
||||||
|
rfidListItem.Text = OpticalHeadTest.SetTestMode(_iPerlReader);
|
||||||
|
optoListBox.Items.Clear();
|
||||||
|
stopWorkerThread = false;
|
||||||
|
optoThread = new Thread(OptoWorker);
|
||||||
|
if (!optoThread.IsAlive)
|
||||||
|
{
|
||||||
|
_iPerlReader.StartDataStreamProcessing(); // open opto port
|
||||||
|
optoThread.Start();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "SetActiveMode":
|
||||||
|
rfidListItem.Text = OpticalHeadTest.SetActiveMode(_iPerlReader);
|
||||||
|
stopWorkerThread = true;
|
||||||
|
_iPerlReader.StopDataStreamProcessing(); // close opto port
|
||||||
|
break;
|
||||||
|
case "ResetNfcHead":
|
||||||
|
_iPerlReader.ResetNfcInterface();
|
||||||
|
break;
|
||||||
|
case "SetNfcHead":
|
||||||
|
_iPerlReader.SetNfcInterface();
|
||||||
|
break;
|
||||||
|
case "SetRfidHead":
|
||||||
|
_iPerlReader.SetRfidInterface();
|
||||||
|
break;
|
||||||
|
case "ReadOptoData":
|
||||||
|
optoListBox.Items.Clear();
|
||||||
|
stopWorkerThread = false;
|
||||||
|
optoThread = new Thread(OptoWorker);
|
||||||
|
if (optoThread.IsAlive)
|
||||||
|
{
|
||||||
|
stopWorkerThread = true;
|
||||||
|
_iPerlReader.StopDataStreamProcessing(); // close opto port
|
||||||
|
}
|
||||||
|
if (!optoThread.IsAlive)
|
||||||
|
{
|
||||||
|
_iPerlReader.StartDataStreamProcessing(); // open opto port
|
||||||
|
optoThread.Start();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "StopReadOptoData":
|
||||||
|
stopWorkerThread = true;
|
||||||
|
_iPerlReader.StopDataStreamProcessing(); // close opto port
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rfidOutputListBox.Items.Add(rfidListItem);
|
||||||
|
rfidOutputListBox.Items.AddRange(logChecker.Messages.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,7 +56,7 @@ namespace TBF.Rig.RegisterReaders.iPerlReaderUNI
|
|||||||
muxBoardNrTextBox.Text = config.MuxBoardNr.ToString();
|
muxBoardNrTextBox.Text = config.MuxBoardNr.ToString();
|
||||||
groupTextBox.Text = config.Group.ToString();
|
groupTextBox.Text = config.Group.ToString();
|
||||||
comboBoxCommunicationInterface.SelectedItem = config.CommunicationInterface.ToString();
|
comboBoxCommunicationInterface.SelectedItem = config.CommunicationInterface.ToString();
|
||||||
tabPage2.Controls.Add(new IPerlReader.IperlUniHeadTestCtrl(config));
|
tabPage2.Controls.Add(new iPerlASICReader.IperlASICUniHeadTestCtrl(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Unlock()
|
public void Unlock()
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using TBF.Rig.RegisterReaders.CommonRR.IPerl;
|
|||||||
using TBF.Rig.TestMethods.SmartTest;
|
using TBF.Rig.TestMethods.SmartTest;
|
||||||
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
|
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
|
||||||
|
|
||||||
|
|
||||||
namespace TBF.Rig.RegisterReaders.iPerlReaderUNI
|
namespace TBF.Rig.RegisterReaders.iPerlReaderUNI
|
||||||
{
|
{
|
||||||
public class TestMethodCfg : ComponentCfgBase, ITestMethodCfg
|
public class TestMethodCfg : ComponentCfgBase, ITestMethodCfg
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace TBF.Rig.RegisterReaders.iPerlReaderUNI.iCommon
|
||||||
|
{
|
||||||
|
public interface UNIHeadTestCtrl
|
||||||
|
{
|
||||||
|
void CommandTestButtonClick(object sender, MouseEventArgs e);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,8 @@ using log4net;
|
|||||||
using Sensus.iPerl.RfidCom.Helper;
|
using Sensus.iPerl.RfidCom.Helper;
|
||||||
using System;
|
using System;
|
||||||
using TBF.Rig.RegisterReaders.CommonRR;
|
using TBF.Rig.RegisterReaders.CommonRR;
|
||||||
|
using TBF.Rig.RegisterReaders.CommonRR.IPerl;
|
||||||
|
using TBF.Rig.TestMethods.iPerlCommunication;
|
||||||
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
|
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
|
||||||
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
|
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
|
||||||
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.implementations;
|
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.implementations;
|
||||||
@@ -25,7 +27,18 @@ namespace TBF.Rig.RegisterReaders.iPerlReaderUNI.test
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
byte[] pcb = null;
|
byte[] pcb = null;
|
||||||
int readRetVal = IPerlCorrections.ReadRequestPort(SmartCommunicationForm.TestMethodCfg, iHead, MessageID.Configuration, Sensus.iPerl.NfcHandler.MCI_Protocol.StructName.Configuration, 16, 5, out pcb);
|
|
||||||
|
ITestMethodCfg iTestMethodCfg = SmartCommunicationForm.TestMethodCfg;
|
||||||
|
if (iTestMethodCfg == null)
|
||||||
|
{
|
||||||
|
//TODO find from components
|
||||||
|
TestMethod testMethod = TbfComponents.FindFirstComponentImpl<TestMethod>() as TestMethod;
|
||||||
|
if (testMethod != null)
|
||||||
|
{
|
||||||
|
iTestMethodCfg = testMethod.TestMethodCfg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int readRetVal = IPerlCorrections.ReadRequestPort(iTestMethodCfg, iHead, MessageID.Configuration, Sensus.iPerl.NfcHandler.MCI_Protocol.StructName.Configuration, 16, 5, out pcb);
|
||||||
if (readRetVal == 0)
|
if (readRetVal == 0)
|
||||||
{
|
{
|
||||||
return RfidHelper.HexLiteral2Unsigned(RfidHelper.SwapHexcode(BitConverter.ToString(pcb).Replace("-", string.Empty))).ToString();
|
return RfidHelper.HexLiteral2Unsigned(RfidHelper.SwapHexcode(BitConverter.ToString(pcb).Replace("-", string.Empty))).ToString();
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using log4net;
|
|||||||
using log4net.Repository.Hierarchy;
|
using log4net.Repository.Hierarchy;
|
||||||
using TBF.Rig.Generic;
|
using TBF.Rig.Generic;
|
||||||
using TBF.Rig.Sequences;
|
using TBF.Rig.Sequences;
|
||||||
|
using TBF.Rig.TestMethods.SmartTest;
|
||||||
|
|
||||||
namespace TBF.Rig
|
namespace TBF.Rig
|
||||||
{
|
{
|
||||||
@@ -134,7 +135,8 @@ namespace TBF.Rig
|
|||||||
new RegisterReaders.FrequencyMeterFromUniCB.Factory(), ///
|
new RegisterReaders.FrequencyMeterFromUniCB.Factory(), ///
|
||||||
//new RegisterReaders.iPerlReaderUNI.Factory(), /// 'UNI RegisterReader for Smart Meters'
|
//new RegisterReaders.iPerlReaderUNI.Factory(), /// 'UNI RegisterReader for Smart Meters'
|
||||||
new RegisterReaders.PoseidonReader.Factory(),
|
new RegisterReaders.PoseidonReader.Factory(),
|
||||||
new RegisterReaders.IPerlReader.Factory(), /// the same functionality as TestMethods.iPerlCommunication.iPerlHead.Factory(),
|
new RegisterReaders.IPerlReader.Factory(), /// the same functionality as TestMethods.iPerlCommunication.iPerlHead.Factory(),
|
||||||
|
new RegisterReaders.iPerlASICReader.Factory(), /// ASIC IPerl, C4 communication
|
||||||
new RegisterReaders.PulsesFromUniCB.Factory(), /// 'RegisterReader'
|
new RegisterReaders.PulsesFromUniCB.Factory(), /// 'RegisterReader'
|
||||||
new RegisterReaders.StandingStartStop.Factory(), /// 'RegisterReader for standing start/stop'
|
new RegisterReaders.StandingStartStop.Factory(), /// 'RegisterReader for standing start/stop'
|
||||||
new TestMethods.iPerlCommunication.iPerlHead.Factory(), /// 'RegisterReader for iPerl'
|
new TestMethods.iPerlCommunication.iPerlHead.Factory(), /// 'RegisterReader for iPerl'
|
||||||
@@ -190,6 +192,7 @@ namespace TBF.Rig
|
|||||||
new TestMethods.FlyingStartTankCollection.Compound.Factory(),
|
new TestMethods.FlyingStartTankCollection.Compound.Factory(),
|
||||||
new TestMethods.GrabImage.Factory(),
|
new TestMethods.GrabImage.Factory(),
|
||||||
new TestMethods.iPerlCommunication.TestMethodFactory(), /// iPerlCommunication
|
new TestMethods.iPerlCommunication.TestMethodFactory(), /// iPerlCommunication
|
||||||
|
new TestMethods.SmartTest.TestMethodFactory(), /// Smart Meter Tests
|
||||||
new TestMethods.LeakTest.Factory(),
|
new TestMethods.LeakTest.Factory(),
|
||||||
new TestMethods.LiveStream.Factory(),
|
new TestMethods.LiveStream.Factory(),
|
||||||
new TestMethods.ManualEntry.Factory(),
|
new TestMethods.ManualEntry.Factory(),
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ using TBF.Boxes;
|
|||||||
using TBF.Resources;
|
using TBF.Resources;
|
||||||
using TBF.UiBridge;
|
using TBF.UiBridge;
|
||||||
using TBF.Rig.GenericDevices;
|
using TBF.Rig.GenericDevices;
|
||||||
|
using TBF.Rig.RegisterReaders.PoseidonReader;
|
||||||
|
using TBF.Rig.RegisterReaders.PoseidonReader.implementations;
|
||||||
|
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
|
||||||
|
|
||||||
namespace TBF.Rig.TestMethods.FlyingStartMassCollection
|
namespace TBF.Rig.TestMethods.FlyingStartMassCollection
|
||||||
{
|
{
|
||||||
@@ -751,25 +754,56 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
|
|||||||
if (oneMTR != null && regReader != null)
|
if (oneMTR != null && regReader != null)
|
||||||
{
|
{
|
||||||
oneMTR.RegReaderType = (int)regReader.RegisterReaderType;
|
oneMTR.RegReaderType = (int)regReader.RegisterReaderType;
|
||||||
oneMTR.PulsesPerLiter = regReader.PulsesPerLtr;
|
if (regReader is PoseidonReader poseidon) //is Poseidon reader family
|
||||||
|
|
||||||
/// Optionally supress pulses from the large water meter
|
|
||||||
oneMTR.PulsesMeter = (isAux == 0 && compoundTestParams.SupressTrills) ? 0 : Convert.ToDouble(regReader.WMPulses);
|
|
||||||
oneMTR.PulsesMaster = Convert.ToDouble(regReader.WMRefPulses);
|
|
||||||
oneMTR.TestTime = cBrd.TestTime;
|
|
||||||
oneMTR.VolumeStart = 0;
|
|
||||||
oneMTR.VolumeEnd = 0;
|
|
||||||
oneMTR.VolumeRef = tstRslt.VolumeCTV;
|
|
||||||
|
|
||||||
if (oneMTR.PulsesMaster != 0)
|
|
||||||
{
|
{
|
||||||
oneMTR.PulsesMeter *= (tstRslt.PulsesMaster / oneMTR.PulsesMaster);
|
oneMTR.PulsesPerLiter = 0;
|
||||||
oneMTR.PulsesMaster = tstRslt.PulsesMaster;
|
|
||||||
|
/// Optionally supress pulses from the large water meter
|
||||||
|
oneMTR.PulsesMeter = 0;
|
||||||
|
oneMTR.PulsesMaster = 0;
|
||||||
|
oneMTR.TestTime = cBrd.TestTime;
|
||||||
|
oneMTR.VolumeStart = 0;
|
||||||
|
oneMTR.VolumeEnd = 0;
|
||||||
|
oneMTR.VolumeRef = tstRslt.VolumeCTV;
|
||||||
|
|
||||||
|
if (oneMTR.PulsesMaster != 0)
|
||||||
|
{
|
||||||
|
oneMTR.PulsesMeter *= (tstRslt.PulsesMaster / oneMTR.PulsesMaster);
|
||||||
|
oneMTR.PulsesMaster = tstRslt.PulsesMaster;
|
||||||
|
}
|
||||||
|
|
||||||
|
oneMTR.VolumeMeter = poseidon.WMVolume;
|
||||||
|
|
||||||
|
oneMTR.Error =
|
||||||
|
Formulas.ErrorFromVolumes(oneMTR.VolumeMeter,
|
||||||
|
tstRslt.VolumeCTV); /// Main/Aux meter error is not usedfor evaluation
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oneMTR.PulsesPerLiter = regReader.PulsesPerLtr;
|
||||||
|
|
||||||
oneMTR.VolumeMeter = oneMTR.PulsesMeter * regReader.LtrsPerPulse; /// liter
|
/// Optionally supress pulses from the large water meter
|
||||||
|
oneMTR.PulsesMeter = (isAux == 0 && compoundTestParams.SupressTrills)
|
||||||
|
? 0
|
||||||
|
: Convert.ToDouble(regReader.WMPulses);
|
||||||
|
oneMTR.PulsesMaster = Convert.ToDouble(regReader.WMRefPulses);
|
||||||
|
oneMTR.TestTime = cBrd.TestTime;
|
||||||
|
oneMTR.VolumeStart = 0;
|
||||||
|
oneMTR.VolumeEnd = 0;
|
||||||
|
oneMTR.VolumeRef = tstRslt.VolumeCTV;
|
||||||
|
|
||||||
oneMTR.Error = Formulas.ErrorFromVolumes(oneMTR.VolumeMeter, tstRslt.VolumeCTV); /// Main/Aux meter error is not usedfor evaluation
|
if (oneMTR.PulsesMaster != 0)
|
||||||
|
{
|
||||||
|
oneMTR.PulsesMeter *= (tstRslt.PulsesMaster / oneMTR.PulsesMaster);
|
||||||
|
oneMTR.PulsesMaster = tstRslt.PulsesMaster;
|
||||||
|
}
|
||||||
|
|
||||||
|
oneMTR.VolumeMeter = oneMTR.PulsesMeter * regReader.LtrsPerPulse; /// liter
|
||||||
|
|
||||||
|
oneMTR.Error =
|
||||||
|
Formulas.ErrorFromVolumes(oneMTR.VolumeMeter,
|
||||||
|
tstRslt.VolumeCTV); /// Main/Aux meter error is not usedfor evaluation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -887,16 +921,58 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
|
|||||||
if (dstrReader != null)
|
if (dstrReader != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
meterRslt.TimestampStart = dstrReader.TimestampSecStart;
|
if (dstrReader is SmartReader poseidon) //is Poseidon reader family
|
||||||
meterRslt.TimestampEnd = !dstrReader.NoSamples ? dstrReader.TimestampSecEnd : (dstrReader.TimestampSecStart + tstRslt.TestTime);
|
{
|
||||||
meterRslt.TestTime = meterRslt.TimestampEnd - meterRslt.TimestampStart;
|
log.Info("Poseidon reader detected - Results");
|
||||||
meterRslt.VolumeStart = dstrReader.VolumeLtrStart; /// liter
|
meterRslt.TimestampStart = poseidon.TimestampSecStart;
|
||||||
meterRslt.VolumeEnd = dstrReader.VolumeLtrEnd; /// liter
|
meterRslt.TimestampEnd = !poseidon.NoSamples
|
||||||
meterRslt.VolumeMeter = Math.Abs(dstrReader.VolumeLtrEnd - dstrReader.VolumeLtrStart);
|
? poseidon.TimestampSecEnd
|
||||||
meterRslt.VolumeRef = tstRslt.VolumeCTV * meterRslt.TestTime / tstRslt.TestTime;
|
: (poseidon.TimestampSecStart + tstRslt.TestTime);
|
||||||
meterRslt.PulsesMaster = tstRslt.PulsesMaster * meterRslt.TestTime / tstRslt.TestTime;
|
meterRslt.TestTime = meterRslt.TimestampEnd - meterRslt.TimestampStart;
|
||||||
|
meterRslt.VolumeStart = poseidon.VolumeLtrStart; /// liter
|
||||||
|
meterRslt.VolumeEnd = poseidon.VolumeLtrStart + poseidon.WMVolume; //dstrReader.VolumeLtrEnd; /// liter
|
||||||
|
meterRslt.VolumeMeter = poseidon.WMVolume;
|
||||||
|
|
||||||
if (iPerl != null)
|
if (!(meterRslt.TestTime == 0 || tstRslt.TestTime == 0))
|
||||||
|
{
|
||||||
|
meterRslt.VolumeRef = tstRslt.VolumeCTV * meterRslt.TestTime / tstRslt.TestTime;
|
||||||
|
meterRslt.PulsesMaster =
|
||||||
|
tstRslt.PulsesMaster * meterRslt.TestTime / tstRslt.TestTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meterRslt.VolumeRef = tstRslt.VolumeCTV;
|
||||||
|
meterRslt.PulsesMaster = tstRslt.PulsesMaster;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info($"meterRslt.TimestampStart = {meterRslt.TimestampStart} \n" +
|
||||||
|
$"meterRslt.TimestampEnd = {meterRslt.TimestampEnd }\n" +
|
||||||
|
$"meterRslt.TestTime = {meterRslt.TestTime}\n" +
|
||||||
|
$"meterRslt.VolumeStart = {meterRslt.VolumeStart}\n" +
|
||||||
|
$"meterRslt.VolumeEnd = {meterRslt.VolumeEnd}\n" +
|
||||||
|
$"meterRslt.VolumeMeter = {meterRslt.VolumeMeter}\n" +
|
||||||
|
$"meterRslt.VolumeRef = {meterRslt.VolumeRef}\n" +
|
||||||
|
$"meterRslt.PulsesMaster = {meterRslt.PulsesMaster}\n");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meterRslt.TimestampStart = dstrReader.TimestampSecStart;
|
||||||
|
meterRslt.TimestampEnd = !dstrReader.NoSamples
|
||||||
|
? dstrReader.TimestampSecEnd
|
||||||
|
: (dstrReader.TimestampSecStart + tstRslt.TestTime);
|
||||||
|
meterRslt.TestTime = meterRslt.TimestampEnd - meterRslt.TimestampStart;
|
||||||
|
meterRslt.VolumeStart = dstrReader.VolumeLtrStart; /// liter
|
||||||
|
meterRslt.VolumeEnd = dstrReader.VolumeLtrEnd; /// liter
|
||||||
|
meterRslt.VolumeMeter =
|
||||||
|
Math.Abs(dstrReader.VolumeLtrEnd - dstrReader.VolumeLtrStart);
|
||||||
|
meterRslt.VolumeRef = tstRslt.VolumeCTV * meterRslt.TestTime / tstRslt.TestTime;
|
||||||
|
meterRslt.PulsesMaster =
|
||||||
|
tstRslt.PulsesMaster * meterRslt.TestTime / tstRslt.TestTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iPerl != null)
|
||||||
{
|
{
|
||||||
if (iPerl.ResultCode != 0 && (meterRslt.WaterMeter.ResultCode & (int)Results.Entities.ResultCode.OptoErrorCodeMask) == 0)
|
if (iPerl.ResultCode != 0 && (meterRslt.WaterMeter.ResultCode & (int)Results.Entities.ResultCode.OptoErrorCodeMask) == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
///
|
||||||
|
/// Copyright (c) 2015-2021 Sensus Slovensko a.s.
|
||||||
|
///
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO.Ports;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using Common;
|
||||||
|
using Config.Entities;
|
||||||
|
using TBF.Rig.Generic;
|
||||||
|
using TBF.Rig.RegisterReaders.CommonRR.IPerl;
|
||||||
|
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
|
||||||
|
|
||||||
|
|
||||||
|
namespace TBF.Rig.TestMethods.SmartTest
|
||||||
|
{
|
||||||
|
public class TestMethodCfg : ComponentCfgBase, ITestMethodCfg
|
||||||
|
{
|
||||||
|
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(TestMethodCfg) })[0];
|
||||||
|
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||||
|
|
||||||
|
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new TestMethodCfgCtrl(); }
|
||||||
|
|
||||||
|
|
||||||
|
public override IParamsProvider GetRuntimeTestParamsProvider() { return TestParams; }
|
||||||
|
public override IParamsProvider CreateTestParamsProvider() { return new iPerlCommunicationParams(true); }
|
||||||
|
public override IParamsProvider GetUITestParamsProvider(Test test)
|
||||||
|
{
|
||||||
|
return (test.Method == Name) ? base.GetUITestParamsProvider(test) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Private parameterless constructor invoked by all other (public) constructors
|
||||||
|
TestMethodCfg()
|
||||||
|
{
|
||||||
|
Name = "iPerlCommunication";
|
||||||
|
ParentName = string.Empty;
|
||||||
|
CommTimeout = 1800; /// ms
|
||||||
|
MaxCommRetries = 4;
|
||||||
|
WaitTimeAfterFailure = 2200;
|
||||||
|
PassThroughWaitTime = 1500;
|
||||||
|
NrThreads = 2; /// 1, 2 or 4 threads
|
||||||
|
IperlCheckErrorsToStop = 10;
|
||||||
|
MciTimeoutMs = 4000; // ms, NFC interface
|
||||||
|
BaudRate = 57600; // NFC Interface
|
||||||
|
DataBits = 8; // NFC Interface
|
||||||
|
ParityBit = Parity.None; // NFC Interface
|
||||||
|
StopBits = StopBits.Two; // NFC Interface
|
||||||
|
|
||||||
|
TestParams = CreateTestParamsProvider() as iPerlCommunicationParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestMethodCfg(IComponentFactory factory)
|
||||||
|
: this()
|
||||||
|
{
|
||||||
|
this.Factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ToString(int i)
|
||||||
|
{
|
||||||
|
return string.Format("Name={0}, CommTimeout={1}, MaxRetries={2}, NrThreads={3}", Name, CommTimeout, MaxCommRetries, NrThreads);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CommTimeout { get; set; }
|
||||||
|
public int DelayBetweenRetries { get; set; }
|
||||||
|
public int MaxCommRetries { get; set; }
|
||||||
|
public int WaitTimeAfterFailure { get; set; }
|
||||||
|
public int PassThroughWaitTime { get; set; }
|
||||||
|
public int NrThreads { get; set; }
|
||||||
|
public int IperlCheckErrorsToStop { get; set; }
|
||||||
|
public int MciTimeoutMs { get; set; }
|
||||||
|
public int BaudRate { get; set; }
|
||||||
|
public int DataBits { get; set; }
|
||||||
|
public Parity ParityBit { get; set; }
|
||||||
|
public StopBits StopBits { get; set; }
|
||||||
|
|
||||||
|
/// <summary> Test parameters </summary>
|
||||||
|
[XmlIgnore]
|
||||||
|
public iPerlCommunicationParams TestParams;
|
||||||
|
|
||||||
|
|
||||||
|
public bool UseWebService { get; set; }
|
||||||
|
public string BaseUrl { get; set; }
|
||||||
|
public string RelativeUrl { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,975 @@
|
|||||||
|
///
|
||||||
|
/// Copyright (c) 2015-2023 Sensus Slovensko a.s.
|
||||||
|
///
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using Common;
|
||||||
|
using Config.Entities;
|
||||||
|
using log4net;
|
||||||
|
using RestClient;
|
||||||
|
using Results.Entities;
|
||||||
|
using TBF.Resources;
|
||||||
|
using TBF.Rig.Generic;
|
||||||
|
using TBF.Rig.Sequences;
|
||||||
|
using TBF.Rig.TestMethods.iPerlCommunication;
|
||||||
|
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
|
||||||
|
using TBF.UiBridge;
|
||||||
|
using iPerlCommunicationParams = TBF.Rig.TestMethods.iPerlCommunication.iPerlCommunicationParams;
|
||||||
|
|
||||||
|
|
||||||
|
/// Point definition
|
||||||
|
|
||||||
|
namespace TBF.Rig.TestMethods.SmartTest
|
||||||
|
{
|
||||||
|
public class iPerlCommunicationSeq : SequenceBase
|
||||||
|
{
|
||||||
|
private static readonly ILog log = LogManager.GetLogger(typeof(iPerlCommunicationSeq));
|
||||||
|
|
||||||
|
public const string Q2correctedFromCmd = "Q2 corrected from ";
|
||||||
|
public const string StrictQ2ErrorCheckStr = "Strict Q2 error check ";
|
||||||
|
public const string Q2correctionCheckCmd = "Q2 correction check ";
|
||||||
|
public const string IperlCheckCmd = "iPERL_check ";
|
||||||
|
public const string SimulateCmd = "simulate ";
|
||||||
|
|
||||||
|
|
||||||
|
System.Windows.Forms.Form modelessDlg;
|
||||||
|
///
|
||||||
|
delegate void SmartCommunicationFormDlgt(iPerlCommunicationSeq myRef, TestMethod method, Test test, ITestParams testParams);
|
||||||
|
///
|
||||||
|
void OpenIPerlCommForm(iPerlCommunicationSeq myRef, TestMethod method, Test test, ITestParams testParams)
|
||||||
|
{
|
||||||
|
myRef.modelessDlg = new SmartCommunicationForm(method, test, testParams);
|
||||||
|
myRef.modelessDlg.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CloseIPerlCommForm()
|
||||||
|
{
|
||||||
|
UiBridge.Bridge.OnCloseModelessForm(this, null);
|
||||||
|
modelessDlg = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flying start mass collection method sequence
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="test">Test entity</param>
|
||||||
|
/// <returns>
|
||||||
|
/// Event.Done . . . . . . . OK
|
||||||
|
/// Event.UiCmdStop . . . . Stopped by the user using the on-screen button STOP
|
||||||
|
/// Event.OpArgumentError . Target flow is out of range
|
||||||
|
/// Event.Error . . . . . . Unspecified error
|
||||||
|
/// </returns>
|
||||||
|
public IList<Event> Execute(Test test, int repetitionNr, TestMethod method, ITestParams testParams)
|
||||||
|
{
|
||||||
|
TestMethodCfg cfgIPerl = method.Cfg as TestMethodCfg;
|
||||||
|
|
||||||
|
IList<Event> e; /// Events from currently running operations
|
||||||
|
checkUiOp = new Operations.CheckUIOp(true); /// Runs in more then one state
|
||||||
|
modelessDlg = null;
|
||||||
|
|
||||||
|
processDataLoggingOp = new TBF.Rig.Operations.ProcessDataLoggingOp(processDataLogger, this, false);
|
||||||
|
|
||||||
|
string cmd;
|
||||||
|
|
||||||
|
// Normalize activity once (also prevents NullReferenceException on .ToLower()).
|
||||||
|
var activity = testParams?.Activity;
|
||||||
|
var activityLower = activity?.ToLowerInvariant();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(activityLower) &&
|
||||||
|
activityLower.Equals(cmd = iPerlCommunicationConstants.GetDefaultQ2CorrectionsStr.ToLower()))
|
||||||
|
{
|
||||||
|
TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 });
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted));
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.FlowSetting));
|
||||||
|
|
||||||
|
/// Get 'wmType' from IperlHead procedure parameters
|
||||||
|
int wmType = 0;
|
||||||
|
#if IPERL
|
||||||
|
/*foreach (var wm in ProcessData.BatchRslts.Batch.WaterMeters)
|
||||||
|
{
|
||||||
|
if (wm != null && !wm.Disabled && wm.WMTypeId() > 0)
|
||||||
|
{
|
||||||
|
wmType = wm.WMTypeId();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
// if (cfgIPerl.UseWebService)
|
||||||
|
// {
|
||||||
|
// IsQ2PreCorrectionCalculated = GetQ2PreCorrectionsOrBackups(cfgIPerl, wmType, out CalculatedQ2PreCorrectionLR, out CalculatedQ2PreCorrectionRL);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// Generate test results
|
||||||
|
Results.Entities.TestRslt tstRslt = BatchRslts.GetTestRslt(test.Name, 0);
|
||||||
|
if (tstRslt != null)
|
||||||
|
{
|
||||||
|
tstRslt.StartTime = DateTime.Now;
|
||||||
|
tstRslt.TestDone = true;
|
||||||
|
foreach (var wm in BatchRslts.Batch.WaterMeters)
|
||||||
|
{
|
||||||
|
if (!wm.Disabled)
|
||||||
|
{
|
||||||
|
foreach(var mtr in wm.MeterTestRslts)
|
||||||
|
{
|
||||||
|
if (mtr.TestRslt == tstRslt)
|
||||||
|
{
|
||||||
|
mtr.Passed = /*!cfgIPerl.UseWebService ||*/ IsQ2PreCorrectionCalculated;
|
||||||
|
mtr.TestDone = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.Completed));
|
||||||
|
Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, ProcessData.BatchRslts.GetTestRslt(test.Name, 0)));
|
||||||
|
allResults.Info(TestResult2CsvLine(test.Name, 0)); /// Append the results to the CSV-file
|
||||||
|
|
||||||
|
return new List<Event> { Event.Done };
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(activityLower) &&
|
||||||
|
activityLower.Contains(cmd = Q2correctedFromCmd.ToLowerInvariant()))
|
||||||
|
{
|
||||||
|
TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 });
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted));
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.FlowSetting));
|
||||||
|
|
||||||
|
string[] args = testParams.Activity.Substring(cmd.Length).Split(new char[] { ' ' });
|
||||||
|
string fromTestName = (args.Length >= 1) ? args[0] : string.Empty;
|
||||||
|
bool isPlus = (args.Length >= 2) ? args[1].ToLower().Contains("plus") : false;
|
||||||
|
MakeQ2CorrectedFrom(test.Name, fromTestName, isPlus);
|
||||||
|
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.Completed));
|
||||||
|
Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, ProcessData.BatchRslts.GetTestRslt(test.Name, 0)));
|
||||||
|
allResults.Info(TestResult2CsvLine(test.Name, 0)); /// Append the results to the CSV-file
|
||||||
|
|
||||||
|
return new List<Event> { Event.Done };
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(activityLower) &&
|
||||||
|
activityLower.Contains(cmd = StrictQ2ErrorCheckStr.ToLowerInvariant()))
|
||||||
|
{
|
||||||
|
TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 });
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted));
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.FlowSetting));
|
||||||
|
|
||||||
|
string fromTestName = testParams.Activity.Substring(cmd.Length);
|
||||||
|
|
||||||
|
StrictQ2ErrorCheck(test.Name, fromTestName);
|
||||||
|
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.Completed));
|
||||||
|
Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, ProcessData.BatchRslts.GetTestRslt(test.Name, 0)));
|
||||||
|
allResults.Info(TestResult2CsvLine(test.Name, 0)); /// Append the results to the CSV-file
|
||||||
|
|
||||||
|
return new List<Event> { Event.Done };
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(activityLower) &&
|
||||||
|
activityLower.Contains(cmd = Q2correctionCheckCmd.ToLowerInvariant()))
|
||||||
|
{
|
||||||
|
TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 });
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted));
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.FlowSetting));
|
||||||
|
|
||||||
|
string[] testNames = testParams.Activity.Substring(cmd.Length).Split(new char[] { ' ' });
|
||||||
|
|
||||||
|
if (testNames.Length >= 2)
|
||||||
|
{
|
||||||
|
CheckQ2Correction(test.Name, testNames[0], testNames[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.Completed));
|
||||||
|
Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, ProcessData.BatchRslts.GetTestRslt(test.Name, 0)));
|
||||||
|
allResults.Info(TestResult2CsvLine(test.Name, 0)); /// Append the results to the CSV-file
|
||||||
|
|
||||||
|
return new List<Event> { Event.Done };
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(activityLower) &&
|
||||||
|
activityLower.Contains(cmd = IperlCheckCmd.ToLowerInvariant()))
|
||||||
|
{
|
||||||
|
TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 });
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted));
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.FlowSetting));
|
||||||
|
|
||||||
|
string[] args = testParams.Activity.Substring(cmd.Length).Split(new char[] { ' ' });
|
||||||
|
|
||||||
|
//int maxTestIndex = (ProcessData.BenchInfo is TBF.Rig.DataContainer.BenchInfo.Component)
|
||||||
|
// ? (ProcessData.BenchInfo as TBF.Rig.DataContainer.BenchInfo.Component).MaxTestIndex
|
||||||
|
// : int.MaxValue;
|
||||||
|
|
||||||
|
Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(test.Name, 0);
|
||||||
|
|
||||||
|
if (tstRslt != null)
|
||||||
|
{
|
||||||
|
tstRslt.StartTime = DateTime.Now;
|
||||||
|
|
||||||
|
int wrongMetersCount = 0;
|
||||||
|
string message = string.Empty;
|
||||||
|
|
||||||
|
for (int i = 0; i < BatchRslts.WMPositionsCount; i++)
|
||||||
|
{
|
||||||
|
Results.Entities.WaterMeter wm = BatchRslts.Batch.WaterMeters[i];
|
||||||
|
Results.Entities.MeterTestRslt mtr = ProcessData.BatchRslts.GetMeterTestRslt(test.Name, i, CompoundMeterId.Single);
|
||||||
|
|
||||||
|
///// Reference to iPerl water meter or null:
|
||||||
|
//TestMethods.iPerlCommunication.iPerlHead.IperlHead iPerlHead = ((sensPath.RegisterReaders != null) && (i < sensPath.RegisterReaders.Length))
|
||||||
|
// ? (sensPath.RegisterReaders[i] as TestMethods.iPerlCommunication.iPerlHead.IperlHead)
|
||||||
|
// : null;
|
||||||
|
|
||||||
|
if ((wm != null) && (mtr != null))
|
||||||
|
{
|
||||||
|
int errorIndicators = 0;
|
||||||
|
bool anyErrorOfThisMeter = false;
|
||||||
|
foreach (var arg in args)
|
||||||
|
{
|
||||||
|
#if TURA_SPECIAL
|
||||||
|
if (arg.ToLower() == "q2factors")
|
||||||
|
{
|
||||||
|
if ((wm.ProdQ2CorrRL != wm.Q2CorrRL) || (wm.ProdQ2CorrLR != wm.Q2CorrLR))
|
||||||
|
{
|
||||||
|
anyErrorOfThisMeter = true;
|
||||||
|
message += string.Format("Q2 korekčné faktory vodomera {0} nesedia{1}", wm.WMPosition, Environment.NewLine);
|
||||||
|
errorIndicators |= (int)ErrorFlagMask.E26; /// Q2 correction factors not valid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (arg.ToLower() == "direction")
|
||||||
|
{
|
||||||
|
//if (wm.Pruefindex > maxTestIndex)
|
||||||
|
//{
|
||||||
|
// anyErrorOfThisMeter = true;
|
||||||
|
// message += string.Format("Príliš veľa opakovaní testu vodomera {0}{1}", wm.WMPosition, Environment.NewLine);
|
||||||
|
// errorIndicators |= (int)ErrorFlagMask.E27; /// Wrong direction (positive/negative counting)
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg.ToLower() == "prevworkstep")
|
||||||
|
{
|
||||||
|
if (wm.LastRecordIsNok)
|
||||||
|
{
|
||||||
|
wm.ErrorFlags |= (int)ErrorFlagMask.E28; /// Set E28
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((wm.ErrorFlags & (int)ErrorFlagMask.E28) != 0)
|
||||||
|
{
|
||||||
|
anyErrorOfThisMeter = true;
|
||||||
|
message += string.Format("iPerl{0} : Predchádzajúci krok nebol zaznamenaný{1}", wm.WMPosition, Environment.NewLine);
|
||||||
|
errorIndicators |= (int)ErrorFlagMask.E28; /// Previous workstep missing or NOK (production tracing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mtr.TestDone = true;
|
||||||
|
mtr.ErrorIndicators = errorIndicators;
|
||||||
|
///
|
||||||
|
if (anyErrorOfThisMeter)
|
||||||
|
{
|
||||||
|
/// This iPerl check did not pass
|
||||||
|
mtr.Passed = false;
|
||||||
|
wrongMetersCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/// Check passed OK
|
||||||
|
mtr.Passed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tstRslt.EndTime = DateTime.Now;
|
||||||
|
tstRslt.TestDone = true;
|
||||||
|
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.Completed));
|
||||||
|
Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, tstRslt));
|
||||||
|
allResults.Info(TestResult2CsvLine(test.Name, 0)); /// Append the results to the CSV-file
|
||||||
|
|
||||||
|
if (wrongMetersCount >= cfgIPerl.IperlCheckErrorsToStop)
|
||||||
|
{
|
||||||
|
State.Create("iPerlCommunicationSeq : Show check result")
|
||||||
|
.AddOperation(new Operations.LargeMessageBoxOp(message))
|
||||||
|
.EnterState();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
e = StateMachine.WaitRunDevsRunOps();
|
||||||
|
}
|
||||||
|
while (!e.Contains(Event.Continue) && !e.Contains(Event.Abort));
|
||||||
|
|
||||||
|
if (e.Contains(Event.Abort))
|
||||||
|
{
|
||||||
|
Bridge.OnError(this, string.Format("Niečo nie je v poriadku !"));
|
||||||
|
return new List<Event> { Event.UiCmdStop };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<Event> { Event.Done };
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(activity) &&
|
||||||
|
activity.Contains(cmd = SimulateCmd))
|
||||||
|
{
|
||||||
|
TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 });
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted));
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.FlowSetting));
|
||||||
|
|
||||||
|
if (testParams.Activity.ToLower().Contains("q3")) MakeSimulated(test, 1, 0, -0.5f);
|
||||||
|
else if (testParams.Activity.Substring(cmd.Length).ToLower() == "q2") MakeSimulated(test, 1, 0, 0.5f);
|
||||||
|
else if (testParams.Activity.Substring(cmd.Length).ToLower() == "q1") MakeSimulated(test, 1, 0, -5.1f);
|
||||||
|
else if (testParams.Activity.Substring(cmd.Length).ToLower() == "compound ok") MakeSimulatedCompound(test, 1, 0, 0.7f, 1.0f);
|
||||||
|
else if (testParams.Activity.Substring(cmd.Length).ToLower() == "compound nok") MakeSimulatedCompound(test, 1, 0, 4.7f, 0.9f);
|
||||||
|
else if (testParams.Activity.Substring(cmd.Length).ToLower() == "compound rise") MakeSimulatedCompound(test, 1, 0, 0.7f, 0.0f);
|
||||||
|
else if (testParams.Activity.Substring(cmd.Length).ToLower() == "compound fall") MakeSimulatedCompound(test, 1, 0, 0.7f, 0.9f);
|
||||||
|
else if (testParams.Activity.Substring(cmd.Length).ToLower() == "iperls")
|
||||||
|
{
|
||||||
|
string[] pcbNrs = new string[] { "831232435539", "831232435562", "831232435587",
|
||||||
|
"831232432141", "831232432497", "831232763641" };
|
||||||
|
|
||||||
|
TestRslt tstRslt = BatchRslts.GetTestRslt(test.Name, test.Part);
|
||||||
|
if (tstRslt != null)
|
||||||
|
{
|
||||||
|
Results.Utils.GetCounterStates(tstRslt, Program.LocalSettings.Counters);
|
||||||
|
|
||||||
|
/// Auxiliary results ... not required
|
||||||
|
|
||||||
|
/// Main results
|
||||||
|
tstRslt.MethodClass = TbfComponents.FindComponent(test.Method).ClassName;
|
||||||
|
tstRslt.TestDone = true;
|
||||||
|
tstRslt.StartTime = tstRslt.Batch.StartTime;
|
||||||
|
tstRslt.EndTime = DateTime.Now;
|
||||||
|
tstRslt.FlowSetTime = 0;
|
||||||
|
tstRslt.MassOfEvapWater = 0;
|
||||||
|
tstRslt.TestTime = 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < BatchRslts.Batch.WaterMeters.Count; i++)
|
||||||
|
{
|
||||||
|
MeterTestRslt meterRslt =
|
||||||
|
BatchRslts.GetMeterTestRslt(test.Name, i, CompoundMeterId.Single);
|
||||||
|
|
||||||
|
if (meterRslt != null)
|
||||||
|
{
|
||||||
|
meterRslt.WaterMeter.SerialNr = pcbNrs[i % pcbNrs.Length];
|
||||||
|
meterRslt.Passed = true;
|
||||||
|
meterRslt.TestDone = true;
|
||||||
|
}
|
||||||
|
//if (iperlHeads[i] != null)
|
||||||
|
//{
|
||||||
|
// iperlHeads[i].CommFailed = iperlHeads[i].Disabled = false;
|
||||||
|
// iperlHeads[i].SerialNr = pcbNrs[i % pcbNrs.Length];
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.Completed));
|
||||||
|
Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, ProcessData.BatchRslts.GetTestRslt(Common.Utils.GetTestName(test.Name, 1, 1), 0)));
|
||||||
|
allResults.Info(TestResult2CsvLine(test.Name, 0)); /// Append the results to the CSV-file
|
||||||
|
|
||||||
|
//------------------------------------------------
|
||||||
|
Bridge.OnActivity(this, testParams.Activity);
|
||||||
|
//------------------------------------------------
|
||||||
|
|
||||||
|
State.Create(string.Format("iPerlCommunicationSeq : {0}", testParams.Activity))
|
||||||
|
.AddOperation(checkUiOp)
|
||||||
|
.EnterState();
|
||||||
|
e = StateMachine.WaitRunDevsRunOps();
|
||||||
|
|
||||||
|
if (TestAndLogUiCmdStop(test, e))
|
||||||
|
{
|
||||||
|
return new List<Event> { Event.UiCmdStop };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
///
|
||||||
|
/// Show the modeless dialog with error indication
|
||||||
|
///
|
||||||
|
///
|
||||||
|
// IMPORTANT:
|
||||||
|
// Avoid Control.Invoke(Delegate, object[]) because it tries to convert each argument
|
||||||
|
// to the delegate parameter types at runtime (and currently it expects a different TestMethod type).
|
||||||
|
//Program.MainWnd.Invoke((Action)(() => OpenIPerlCommForm(this, method, test, testParams)));
|
||||||
|
Program.MainWnd.Invoke(new SmartCommunicationFormDlgt(OpenIPerlCommForm), new object[] { this, method, test, testParams });
|
||||||
|
|
||||||
|
//------------------------------------------------
|
||||||
|
Bridge.OnActivity(this, Strings.iPerl_Communication_in_progress);
|
||||||
|
//------------------------------------------------
|
||||||
|
|
||||||
|
bool stopPressed = false; /// true when STOP button pressed
|
||||||
|
bool completed = false;
|
||||||
|
|
||||||
|
State.Create("iPerlCommunicationSeq : Wait until the entry form is closed")
|
||||||
|
.AddOperation(checkUiOp)
|
||||||
|
.EnterState();
|
||||||
|
do {
|
||||||
|
e = StateMachine.WaitRunDevsRunOps();
|
||||||
|
stopPressed = TestAndLogUiCmdStop(test, e);
|
||||||
|
completed = (modelessDlg is GenericDevices.IHasCompleted)
|
||||||
|
&& (modelessDlg as GenericDevices.IHasCompleted).Completed;
|
||||||
|
}
|
||||||
|
while (!stopPressed && !completed);
|
||||||
|
|
||||||
|
if (stopPressed)
|
||||||
|
{
|
||||||
|
CloseIPerlCommForm();
|
||||||
|
return new List<Event> { Event.UiCmdStop };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TBF.UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(test.Name, Progress.Completed));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test 'Quit'
|
||||||
|
modelessDlg = null; /// Modeless dialog is closed now
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<Event> { Event.Done };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read default Q2 correction factors from a REST service (= Web service).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cfgIPerl">iPerlCommunication component configuration</param>
|
||||||
|
/// <param name="wmType">Water meter type (WZ Typ)</param>
|
||||||
|
/// <param name="q2PreCorrectionLR">Default Q2 correction LR</param>
|
||||||
|
/// <param name="q2PreCorrectionRL">Default Q2 correction RL</param>
|
||||||
|
/// <returns>true when successful</returns>
|
||||||
|
static bool ReadCorrectionsFromWebService(TestMethodCfg_IPerl cfgIPerl, int wmType, out int q2PreCorrectionLR, out int q2PreCorrectionRL)
|
||||||
|
{
|
||||||
|
if (wmType == 0)
|
||||||
|
{
|
||||||
|
/// No REST service call when wmType == 0, factors are 0
|
||||||
|
q2PreCorrectionLR = 0;
|
||||||
|
q2PreCorrectionRL = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
GetQ2PreCorrectionClient client = new GetQ2PreCorrectionClient(cfgIPerl.BaseUrl);
|
||||||
|
client.GetToken("ReadUser", "sensus", "https://deluh1web03.world.fluidtechnology.net/SensusCore/api/v1/Locations/1/Login2").Wait();
|
||||||
|
Q2PreCorrection response = client.GetQ2Correction(string.Format(cfgIPerl.RelativeUrl, wmType)).Result;
|
||||||
|
if (response != null && response.AreDataCalculated)
|
||||||
|
{
|
||||||
|
q2PreCorrectionLR = response.CorrLR;
|
||||||
|
q2PreCorrectionRL = response.CorrRL;
|
||||||
|
log.WarnFormat("Q2 corrections from a REST client for WM Type = {0} are: LR = {1}, RL = {2}", wmType, q2PreCorrectionLR, q2PreCorrectionRL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.ErrorFormat("Failed to obtain Q2 corrections from a REST client for WM Type = {0}", wmType);
|
||||||
|
q2PreCorrectionLR = 0;
|
||||||
|
q2PreCorrectionRL = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
log.ErrorFormat("Failed to obtain Q2 corrections from a REST client for WM Type = {0}: {1}", wmType, exc.Message);
|
||||||
|
q2PreCorrectionLR = 0;
|
||||||
|
q2PreCorrectionRL = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Obtain Q2 correction factors from a REST service or from local settings (stored backup values)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cfgIPerl">iPerlCommunication component configuration</param>
|
||||||
|
/// <param name="wmType">Water meter type (WZ Typ)</param>
|
||||||
|
/// <param name="q2PreCorrectionLR">Default Q2 correction LR</param>
|
||||||
|
/// <param name="q2PreCorrectionRL">Default Q2 correction RL</param>
|
||||||
|
/// <returns>true when successful</returns>
|
||||||
|
public static bool GetQ2PreCorrectionsOrBackups(TestMethodCfg_IPerl cfgIPerl, int wmType, out int q2PreCorrectionLR, out int q2PreCorrectionRL)
|
||||||
|
{
|
||||||
|
/// Get Q2 pre-correction values from REST service
|
||||||
|
bool restOK = ReadCorrectionsFromWebService(cfgIPerl, wmType, out q2PreCorrectionLR, out q2PreCorrectionRL);
|
||||||
|
|
||||||
|
/// Store / load Q2 pre-correction values
|
||||||
|
Point storedValue;
|
||||||
|
if (restOK)
|
||||||
|
{
|
||||||
|
/// Q2 pre-correction values were successfully obtained from a REST service for the specified wmType
|
||||||
|
if (!Program.LocalSettings.Q2PreCorrections.TryGetValue(wmType, out storedValue))
|
||||||
|
{
|
||||||
|
/// No Q2 pre-correction values in the dictionary for the specified wmType => save them
|
||||||
|
Program.LocalSettings.Q2PreCorrections.Add(wmType, new Point(q2PreCorrectionLR, q2PreCorrectionRL));
|
||||||
|
log.WarnFormat("Q2 corrections added to dictionary for WM Type = {0}: LR = {1}, RL = {2}", wmType, q2PreCorrectionLR, q2PreCorrectionRL);
|
||||||
|
}
|
||||||
|
else if (storedValue.X != q2PreCorrectionLR || storedValue.Y != q2PreCorrectionRL)
|
||||||
|
{
|
||||||
|
/// Different Q2 pre-correction values in the dictionary for the specified wmType => overwrite them with ones from the REST service
|
||||||
|
Program.LocalSettings.Q2PreCorrections[wmType] = new Point(q2PreCorrectionLR, q2PreCorrectionRL);
|
||||||
|
log.WarnFormat("Q2 corrections modified in dictionary for WM Type = {0}: LR = {1}, RL = {2}", wmType, q2PreCorrectionLR, q2PreCorrectionRL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/// Q2 pre-correction values in the dictionary are the same and were not changed
|
||||||
|
log.WarnFormat("Q2 corrections in dictionary for WM Type = {0} are the same and were not changed", wmType, q2PreCorrectionLR, q2PreCorrectionRL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/// No Q2 pre-correction values from a REST service => read the dictionary
|
||||||
|
if (Program.LocalSettings.Q2PreCorrections.TryGetValue(wmType, out storedValue))
|
||||||
|
{
|
||||||
|
/// Q2 pre-correction values successfully read from the dictionary
|
||||||
|
q2PreCorrectionLR = storedValue.X;
|
||||||
|
q2PreCorrectionRL = storedValue.Y;
|
||||||
|
log.WarnFormat("Q2 corrections loaded from dictionary for WM Type = {0}: LR = {1}, RL = {2}", wmType, q2PreCorrectionLR, q2PreCorrectionRL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/// Q2 pre-correction values not found in the dictionary => use zeros
|
||||||
|
q2PreCorrectionLR = 0;
|
||||||
|
q2PreCorrectionRL = 0;
|
||||||
|
log.ErrorFormat("Q2 corrections not found in the dictionary for WM Type = {0}, using zeros", wmType, q2PreCorrectionLR, q2PreCorrectionRL);
|
||||||
|
|
||||||
|
/// Everything failed => using zero values
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Q2 pre-corections were obtained from REST service or stored backup values were used
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Virtually apply Q2 correction to a test used for the correction calculation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="testName">This test name</param>
|
||||||
|
/// <param name="oriTestRslt">Name of Q2 test done before Q2 correction (Q2adj)</param>
|
||||||
|
/// <remarks>Assuming this test does not have multiple parts (part = 0)</remarks>
|
||||||
|
void MakeQ2CorrectedFrom(string testName, string oriTestName, bool isPlus = false)
|
||||||
|
{
|
||||||
|
Results.Entities.TestRslt oriTestRslt = ProcessData.BatchRslts.GetTestRslt(oriTestName, 0);
|
||||||
|
Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(testName, 0);
|
||||||
|
|
||||||
|
if (oriTestRslt == null || tstRslt == null) return;
|
||||||
|
|
||||||
|
tstRslt.Components = oriTestRslt.Components;
|
||||||
|
|
||||||
|
/// Auxiliary results, as in SequenceBase.UpdateTemoPressDensAmb()
|
||||||
|
tstRslt.AmbTempMean = oriTestRslt.AmbTempMean;
|
||||||
|
tstRslt.AmbTempStart = oriTestRslt.AmbTempStart;
|
||||||
|
tstRslt.AmbTempEnd = oriTestRslt.AmbTempEnd;
|
||||||
|
tstRslt.AmbTempMin = oriTestRslt.AmbTempMin;
|
||||||
|
tstRslt.AmbTempMax = oriTestRslt.AmbTempMax;
|
||||||
|
tstRslt.AmbPressMean = oriTestRslt.AmbPressMean;
|
||||||
|
tstRslt.AmbPressStart = oriTestRslt.AmbPressStart;
|
||||||
|
tstRslt.AmbPressEnd = oriTestRslt.AmbPressEnd;
|
||||||
|
tstRslt.AmbPressMin = oriTestRslt.AmbPressMin;
|
||||||
|
tstRslt.AmbPressMax = oriTestRslt.AmbPressMax;
|
||||||
|
tstRslt.AmbHumiMean = oriTestRslt.AmbHumiMean;
|
||||||
|
tstRslt.AmbHumiStart = oriTestRslt.AmbHumiStart;
|
||||||
|
tstRslt.AmbHumiEnd = oriTestRslt.AmbHumiEnd;
|
||||||
|
tstRslt.AmbHumiMin = oriTestRslt.AmbHumiMin;
|
||||||
|
tstRslt.AmbHumiMax = oriTestRslt.AmbHumiMax;
|
||||||
|
tstRslt.PressUpMean = oriTestRslt.PressUpMean;
|
||||||
|
tstRslt.PressUpStart = oriTestRslt.PressUpStart;
|
||||||
|
tstRslt.PressUpEnd = oriTestRslt.PressUpEnd;
|
||||||
|
tstRslt.PressUpMin = oriTestRslt.PressUpMin;
|
||||||
|
tstRslt.PressUpMax = oriTestRslt.PressUpMax;
|
||||||
|
tstRslt.PressDownMean = oriTestRslt.PressDownMean;
|
||||||
|
tstRslt.PressDownStart = oriTestRslt.PressDownStart;
|
||||||
|
tstRslt.PressDownEnd = oriTestRslt.PressDownEnd;
|
||||||
|
tstRslt.PressDownMin = oriTestRslt.PressDownMin;
|
||||||
|
tstRslt.PressDownMax = oriTestRslt.PressDownMax;
|
||||||
|
tstRslt.PressDeltaMean = oriTestRslt.PressDeltaMean;
|
||||||
|
tstRslt.PressDeltaStart = oriTestRslt.PressDeltaStart;
|
||||||
|
tstRslt.PressDeltaEnd = oriTestRslt.PressDeltaEnd;
|
||||||
|
tstRslt.PressDeltaMin = oriTestRslt.PressDeltaMin;
|
||||||
|
tstRslt.PressDeltaMax = oriTestRslt.PressDeltaMax;
|
||||||
|
tstRslt.ConductMean = oriTestRslt.ConductMean;
|
||||||
|
tstRslt.ConductStart = oriTestRslt.ConductStart;
|
||||||
|
tstRslt.ConductEnd = oriTestRslt.ConductEnd;
|
||||||
|
tstRslt.ConductMin = oriTestRslt.ConductMin;
|
||||||
|
tstRslt.ConductMax = oriTestRslt.ConductMax;
|
||||||
|
tstRslt.TempUpMean = oriTestRslt.TempUpMean;
|
||||||
|
tstRslt.TempUpStart = oriTestRslt.TempUpStart;
|
||||||
|
tstRslt.TempUpEnd = oriTestRslt.TempUpEnd;
|
||||||
|
tstRslt.TempUpMin = oriTestRslt.TempUpMin;
|
||||||
|
tstRslt.TempUpMax = oriTestRslt.TempUpMax;
|
||||||
|
tstRslt.TempDownMean = oriTestRslt.TempDownMean;
|
||||||
|
tstRslt.TempDownStart = oriTestRslt.TempDownStart;
|
||||||
|
tstRslt.TempDownEnd = oriTestRslt.TempDownEnd;
|
||||||
|
tstRslt.TempDownMin = oriTestRslt.TempDownMin;
|
||||||
|
tstRslt.TempDownMax = oriTestRslt.TempDownMax;
|
||||||
|
tstRslt.TempDivMean = oriTestRslt.TempDivMean;
|
||||||
|
tstRslt.TempDivStart = oriTestRslt.TempDivStart;
|
||||||
|
tstRslt.TempDivEnd = oriTestRslt.TempDivEnd;
|
||||||
|
tstRslt.TempDivMin = oriTestRslt.TempDivMin;
|
||||||
|
tstRslt.TempDivMax = oriTestRslt.TempDivMax;
|
||||||
|
tstRslt.DensityIn = oriTestRslt.DensityIn;
|
||||||
|
tstRslt.DensityLine = oriTestRslt.DensityLine;
|
||||||
|
tstRslt.DensityDiv = oriTestRslt.DensityDiv;
|
||||||
|
|
||||||
|
tstRslt.StartTime = oriTestRslt.StartTime;
|
||||||
|
tstRslt.EndTime = oriTestRslt.EndTime;
|
||||||
|
tstRslt.FlowSetTime = oriTestRslt.FlowSetTime;
|
||||||
|
tstRslt.TestTime = oriTestRslt.TestTime;
|
||||||
|
tstRslt.PulsesMaster = oriTestRslt.PulsesMaster;
|
||||||
|
tstRslt.ConstMasterRaw = oriTestRslt.ConstMasterRaw;
|
||||||
|
tstRslt.ConstMaster = oriTestRslt.ConstMaster;
|
||||||
|
tstRslt.MassStartRaw = oriTestRslt.MassStartRaw;
|
||||||
|
tstRslt.MassStart = oriTestRslt.MassStart;
|
||||||
|
tstRslt.MassEndRaw = oriTestRslt.MassEndRaw;
|
||||||
|
tstRslt.MassEnd = oriTestRslt.MassEnd;
|
||||||
|
tstRslt.MassOfEvapWater = oriTestRslt.MassOfEvapWater;
|
||||||
|
//tstRslt.FlowMass = oriTestRslt.FlowMass;
|
||||||
|
//tstRslt.FlowVolume = oriTestRslt.FlowVolume;
|
||||||
|
tstRslt.VolumeCTV = oriTestRslt.VolumeCTV;
|
||||||
|
tstRslt.VolumeMaster = oriTestRslt.VolumeMaster;
|
||||||
|
tstRslt.ErrorMaster = oriTestRslt.ErrorMaster;
|
||||||
|
|
||||||
|
tstRslt.FlowMean = oriTestRslt.FlowMean;
|
||||||
|
tstRslt.FlowMin = oriTestRslt.FlowMin;
|
||||||
|
tstRslt.FlowMax = oriTestRslt.FlowMax;
|
||||||
|
|
||||||
|
tstRslt.Custom1 = oriTestRslt.Custom1;
|
||||||
|
tstRslt.Custom2 = oriTestRslt.Custom2;
|
||||||
|
tstRslt.Custom3 = oriTestRslt.Custom3;
|
||||||
|
tstRslt.Custom4 = oriTestRslt.Custom4;
|
||||||
|
tstRslt.Custom5 = oriTestRslt.Custom5;
|
||||||
|
tstRslt.Custom6 = oriTestRslt.Custom6;
|
||||||
|
tstRslt.Custom7 = oriTestRslt.Custom7;
|
||||||
|
tstRslt.Custom8 = oriTestRslt.Custom8;
|
||||||
|
|
||||||
|
for (int i = 0; i < ProcessData.BatchRslts.WMPositionsCount; i++)
|
||||||
|
{
|
||||||
|
// Fix for CS7036: Added the missing 'meterId' argument to the GetMeterTestRslt method call.
|
||||||
|
var q3mtr = ProcessData.BatchRslts.GetMeterTestRslt("Q3", i, CompoundMeterId.SingleOrCompound);
|
||||||
|
double q3error = (q3mtr != null) ? q3mtr.Error : 0;
|
||||||
|
|
||||||
|
Results.Entities.MeterTestRslt oriMeterRslt = ProcessData.BatchRslts.GetMeterTestRslt(oriTestName, i, CompoundMeterId.SingleOrCompound);
|
||||||
|
Results.Entities.MeterTestRslt meterRslt = ProcessData.BatchRslts.GetMeterTestRslt(testName, i, CompoundMeterId.SingleOrCompound);
|
||||||
|
|
||||||
|
/// Reference to iPerl water meter or null:
|
||||||
|
TestMethods.iPerlCommunication.iPerlHead.IperlHead iPerl = ((sensPath != null) && (sensPath.RegisterReaders != null) && (i < sensPath.RegisterReaders.Length))
|
||||||
|
? (sensPath.RegisterReaders[i] as TestMethods.iPerlCommunication.iPerlHead.IperlHead)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (iPerl != null && meterRslt != null && oriMeterRslt != null)
|
||||||
|
{
|
||||||
|
#if ORACLE_DB
|
||||||
|
meterRslt.ErrorBC = oriMeterRslt.Error;
|
||||||
|
#endif
|
||||||
|
meterRslt.PulsesMeter = oriMeterRslt.PulsesMeter;
|
||||||
|
meterRslt.PulsesMaster = oriMeterRslt.PulsesMaster;
|
||||||
|
meterRslt.PulsesPerLiter = oriMeterRslt.PulsesPerLiter;
|
||||||
|
meterRslt.VolumeRef = oriMeterRslt.VolumeRef;
|
||||||
|
meterRslt.TestTime = oriMeterRslt.TestTime;
|
||||||
|
|
||||||
|
if (q3error * oriMeterRslt.Error < 0)
|
||||||
|
{
|
||||||
|
/// iPerl with Q2 correction => generate an artificial error equal to +1/10 of the original one (relative to Q2 target error)
|
||||||
|
meterRslt.Error = 0.1 * oriMeterRslt.Error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/// iPerl with Q2 correction => generate an artificial error equal to -1/10 of the original one (relative to Q2 target error)
|
||||||
|
meterRslt.Error = - 0.1 * oriMeterRslt.Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
meterRslt.VolumeMeter = meterRslt.VolumeRef * (100.0 + meterRslt.Error) / 100.0;
|
||||||
|
double signature = (oriMeterRslt.VolumeEnd > oriMeterRslt.VolumeStart) ? (+1) : (-1);
|
||||||
|
meterRslt.VolumeStart = oriMeterRslt.VolumeStart;
|
||||||
|
meterRslt.VolumeEnd = meterRslt.VolumeStart + signature * meterRslt.VolumeMeter;
|
||||||
|
|
||||||
|
meterRslt.Passed = (meterRslt.Error >= tstRslt.ErrLimLo() + tstRslt.ErrLimMargin()
|
||||||
|
&& meterRslt.Error <= tstRslt.ErrLimHi() - tstRslt.ErrLimMargin());
|
||||||
|
meterRslt.TestDone = true;
|
||||||
|
tstRslt.TestDone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Evaluate a given Q2 test result agains stricter error limits when Oruefindex == 1.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="testName">This test name</param>
|
||||||
|
/// <param name="oriTestRslt">Name of Q2 test done before Q2 correction (Q2adj)</param>
|
||||||
|
/// <remarks>Assuming this test does not have multiple parts (part = 0)</remarks>
|
||||||
|
void StrictQ2ErrorCheck(string testName, string oriTestName)
|
||||||
|
{
|
||||||
|
Results.Entities.TestRslt oriTestRslt = ProcessData.BatchRslts.GetTestRslt(oriTestName, 0);
|
||||||
|
Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(testName, 0);
|
||||||
|
|
||||||
|
if (oriTestRslt == null || tstRslt == null) return;
|
||||||
|
|
||||||
|
tstRslt.Components = oriTestRslt.Components;
|
||||||
|
|
||||||
|
/// Auxiliary results, as in SequenceBase.UpdateTemoPressDensAmb()
|
||||||
|
tstRslt.AmbTempMean = oriTestRslt.AmbTempMean;
|
||||||
|
tstRslt.AmbTempStart = oriTestRslt.AmbTempStart;
|
||||||
|
tstRslt.AmbTempEnd = oriTestRslt.AmbTempEnd;
|
||||||
|
tstRslt.AmbTempMin = oriTestRslt.AmbTempMin;
|
||||||
|
tstRslt.AmbTempMax = oriTestRslt.AmbTempMax;
|
||||||
|
tstRslt.AmbPressMean = oriTestRslt.AmbPressMean;
|
||||||
|
tstRslt.AmbPressStart = oriTestRslt.AmbPressStart;
|
||||||
|
tstRslt.AmbPressEnd = oriTestRslt.AmbPressEnd;
|
||||||
|
tstRslt.AmbPressMin = oriTestRslt.AmbPressMin;
|
||||||
|
tstRslt.AmbPressMax = oriTestRslt.AmbPressMax;
|
||||||
|
tstRslt.AmbHumiMean = oriTestRslt.AmbHumiMean;
|
||||||
|
tstRslt.AmbHumiStart = oriTestRslt.AmbHumiStart;
|
||||||
|
tstRslt.AmbHumiEnd = oriTestRslt.AmbHumiEnd;
|
||||||
|
tstRslt.AmbHumiMin = oriTestRslt.AmbHumiMin;
|
||||||
|
tstRslt.AmbHumiMax = oriTestRslt.AmbHumiMax;
|
||||||
|
tstRslt.PressUpMean = oriTestRslt.PressUpMean;
|
||||||
|
tstRslt.PressUpStart = oriTestRslt.PressUpStart;
|
||||||
|
tstRslt.PressUpEnd = oriTestRslt.PressUpEnd;
|
||||||
|
tstRslt.PressUpMin = oriTestRslt.PressUpMin;
|
||||||
|
tstRslt.PressUpMax = oriTestRslt.PressUpMax;
|
||||||
|
tstRslt.PressDownMean = oriTestRslt.PressDownMean;
|
||||||
|
tstRslt.PressDownStart = oriTestRslt.PressDownStart;
|
||||||
|
tstRslt.PressDownEnd = oriTestRslt.PressDownEnd;
|
||||||
|
tstRslt.PressDownMin = oriTestRslt.PressDownMin;
|
||||||
|
tstRslt.PressDownMax = oriTestRslt.PressDownMax;
|
||||||
|
tstRslt.PressDeltaMean = oriTestRslt.PressDeltaMean;
|
||||||
|
tstRslt.PressDeltaStart = oriTestRslt.PressDeltaStart;
|
||||||
|
tstRslt.PressDeltaEnd = oriTestRslt.PressDeltaEnd;
|
||||||
|
tstRslt.PressDeltaMin = oriTestRslt.PressDeltaMin;
|
||||||
|
tstRslt.PressDeltaMax = oriTestRslt.PressDeltaMax;
|
||||||
|
tstRslt.ConductMean = oriTestRslt.ConductMean;
|
||||||
|
tstRslt.ConductStart = oriTestRslt.ConductStart;
|
||||||
|
tstRslt.ConductEnd = oriTestRslt.ConductEnd;
|
||||||
|
tstRslt.ConductMin = oriTestRslt.ConductMin;
|
||||||
|
tstRslt.ConductMax = oriTestRslt.ConductMax;
|
||||||
|
tstRslt.TempUpMean = oriTestRslt.TempUpMean;
|
||||||
|
tstRslt.TempUpStart = oriTestRslt.TempUpStart;
|
||||||
|
tstRslt.TempUpEnd = oriTestRslt.TempUpEnd;
|
||||||
|
tstRslt.TempUpMin = oriTestRslt.TempUpMin;
|
||||||
|
tstRslt.TempUpMax = oriTestRslt.TempUpMax;
|
||||||
|
tstRslt.TempDownMean = oriTestRslt.TempDownMean;
|
||||||
|
tstRslt.TempDownStart = oriTestRslt.TempDownStart;
|
||||||
|
tstRslt.TempDownEnd = oriTestRslt.TempDownEnd;
|
||||||
|
tstRslt.TempDownMin = oriTestRslt.TempDownMin;
|
||||||
|
tstRslt.TempDownMax = oriTestRslt.TempDownMax;
|
||||||
|
tstRslt.TempDivMean = oriTestRslt.TempDivMean;
|
||||||
|
tstRslt.TempDivStart = oriTestRslt.TempDivStart;
|
||||||
|
tstRslt.TempDivEnd = oriTestRslt.TempDivEnd;
|
||||||
|
tstRslt.TempDivMin = oriTestRslt.TempDivMin;
|
||||||
|
tstRslt.TempDivMax = oriTestRslt.TempDivMax;
|
||||||
|
tstRslt.DensityIn = oriTestRslt.DensityIn;
|
||||||
|
tstRslt.DensityLine = oriTestRslt.DensityLine;
|
||||||
|
tstRslt.DensityDiv = oriTestRslt.DensityDiv;
|
||||||
|
|
||||||
|
tstRslt.StartTime = oriTestRslt.StartTime;
|
||||||
|
tstRslt.EndTime = oriTestRslt.EndTime;
|
||||||
|
tstRslt.FlowSetTime = oriTestRslt.FlowSetTime;
|
||||||
|
tstRslt.TestTime = oriTestRslt.TestTime;
|
||||||
|
tstRslt.PulsesMaster = oriTestRslt.PulsesMaster;
|
||||||
|
tstRslt.ConstMasterRaw = oriTestRslt.ConstMasterRaw;
|
||||||
|
tstRslt.ConstMaster = oriTestRslt.ConstMaster;
|
||||||
|
tstRslt.MassStartRaw = oriTestRslt.MassStartRaw;
|
||||||
|
tstRslt.MassStart = oriTestRslt.MassStart;
|
||||||
|
tstRslt.MassEndRaw = oriTestRslt.MassEndRaw;
|
||||||
|
tstRslt.MassEnd = oriTestRslt.MassEnd;
|
||||||
|
tstRslt.MassOfEvapWater = oriTestRslt.MassOfEvapWater;
|
||||||
|
//tstRslt.FlowMass = oriTestRslt.FlowMass;
|
||||||
|
//tstRslt.FlowVolume = oriTestRslt.FlowVolume;
|
||||||
|
tstRslt.VolumeCTV = oriTestRslt.VolumeCTV;
|
||||||
|
tstRslt.VolumeMaster = oriTestRslt.VolumeMaster;
|
||||||
|
tstRslt.ErrorMaster = oriTestRslt.ErrorMaster;
|
||||||
|
|
||||||
|
tstRslt.FlowMean = oriTestRslt.FlowMean;
|
||||||
|
tstRslt.FlowMin = oriTestRslt.FlowMin;
|
||||||
|
tstRslt.FlowMax = oriTestRslt.FlowMax;
|
||||||
|
|
||||||
|
tstRslt.Custom1 = oriTestRslt.Custom1;
|
||||||
|
tstRslt.Custom2 = oriTestRslt.Custom2;
|
||||||
|
tstRslt.Custom3 = oriTestRslt.Custom3;
|
||||||
|
tstRslt.Custom4 = oriTestRslt.Custom4;
|
||||||
|
tstRslt.Custom5 = oriTestRslt.Custom5;
|
||||||
|
tstRslt.Custom6 = oriTestRslt.Custom6;
|
||||||
|
tstRslt.Custom7 = oriTestRslt.Custom7;
|
||||||
|
tstRslt.Custom8 = oriTestRslt.Custom8;
|
||||||
|
|
||||||
|
for (int i = 0; i < ProcessData.BatchRslts.WMPositionsCount; i++)
|
||||||
|
{
|
||||||
|
Results.Entities.MeterTestRslt oriMeterRslt = ProcessData.BatchRslts.GetMeterTestRslt(oriTestName, i, CompoundMeterId.Single);
|
||||||
|
Results.Entities.MeterTestRslt meterRslt = ProcessData.BatchRslts.GetMeterTestRslt(testName, i, CompoundMeterId.Single);
|
||||||
|
|
||||||
|
/// Reference to iPerl water meter or null:
|
||||||
|
TestMethods.iPerlCommunication.iPerlHead.IperlHead iPerl = ((sensPath != null) && (sensPath.RegisterReaders != null) && (i < sensPath.RegisterReaders.Length))
|
||||||
|
? (sensPath.RegisterReaders[i] as TestMethods.iPerlCommunication.iPerlHead.IperlHead)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (meterRslt != null && oriMeterRslt != null)
|
||||||
|
{
|
||||||
|
#if ORACLE_DB
|
||||||
|
meterRslt.ErrorBC = oriMeterRslt.Error;
|
||||||
|
#endif
|
||||||
|
meterRslt.PulsesMeter = oriMeterRslt.PulsesMeter;
|
||||||
|
meterRslt.PulsesMaster = oriMeterRslt.PulsesMaster;
|
||||||
|
meterRslt.PulsesPerLiter = oriMeterRslt.PulsesPerLiter;
|
||||||
|
meterRslt.VolumeRef = oriMeterRslt.VolumeRef;
|
||||||
|
meterRslt.TestTime = oriMeterRslt.TestTime;
|
||||||
|
|
||||||
|
if (iPerl != null && ProcessData.BatchRslts.Batch.WaterMeters[i] != null &&
|
||||||
|
!ProcessData.BatchRslts.Batch.WaterMeters[i].Disabled)
|
||||||
|
{
|
||||||
|
/// Either no iPerl head or no Q2 correction
|
||||||
|
meterRslt.Error = oriMeterRslt.Error;
|
||||||
|
meterRslt.VolumeMeter = oriMeterRslt.VolumeMeter;
|
||||||
|
meterRslt.VolumeStart = oriMeterRslt.VolumeStart;
|
||||||
|
meterRslt.VolumeEnd = oriMeterRslt.VolumeEnd;
|
||||||
|
#if ORACLE_DB
|
||||||
|
if ((ProcessData.BatchRslts.Batch.WaterMeters[i].Pruefindex % 100) == 1)
|
||||||
|
{
|
||||||
|
meterRslt.Passed = (oriMeterRslt.Error >= tstRslt.ErrLimLo() + tstRslt.ErrLimMargin()
|
||||||
|
&& oriMeterRslt.Error <= tstRslt.ErrLimHi() - tstRslt.ErrLimMargin());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
meterRslt.Passed = oriMeterRslt.Passed;
|
||||||
|
}
|
||||||
|
meterRslt.TestDone = true;
|
||||||
|
tstRslt.TestDone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check results of 2 tests: before Q2 correction and after Q2 correction.
|
||||||
|
/// Evaluate whether Q2 correction works OK.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="testName">This test name</param>
|
||||||
|
/// <param name="testNameQ2bc">Name of Q2 test done before correction</param>
|
||||||
|
/// <param name="testNameQ2ac">Name of Q2 test done after correction</param>
|
||||||
|
/// <remarks>Assuming these tests do not have multiple parts (part = 0)</remarks>
|
||||||
|
void CheckQ2Correction(string testName, string testNameQ2bc, string testNameQ2ac)
|
||||||
|
{
|
||||||
|
Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(testName, 0);
|
||||||
|
Results.Entities.TestRslt testRsltQ2bc = ProcessData.BatchRslts.GetTestRslt(testNameQ2bc, 0);
|
||||||
|
Results.Entities.TestRslt testRsltQ2ac = ProcessData.BatchRslts.GetTestRslt(testNameQ2ac, 0);
|
||||||
|
|
||||||
|
if ((tstRslt == null) || (testRsltQ2bc == null) || (testRsltQ2ac == null)) return;
|
||||||
|
|
||||||
|
tstRslt.Components = testRsltQ2ac.Components;
|
||||||
|
|
||||||
|
/// Auxiliary results, as in SequenceBase.UpdateTemoPressDensAmb()
|
||||||
|
tstRslt.AmbTempMean = testRsltQ2ac.AmbTempMean;
|
||||||
|
tstRslt.AmbTempStart = testRsltQ2ac.AmbTempStart;
|
||||||
|
tstRslt.AmbTempEnd = testRsltQ2ac.AmbTempEnd;
|
||||||
|
tstRslt.AmbTempMin = testRsltQ2ac.AmbTempMin;
|
||||||
|
tstRslt.AmbTempMax = testRsltQ2ac.AmbTempMax;
|
||||||
|
tstRslt.AmbPressMean = testRsltQ2ac.AmbPressMean;
|
||||||
|
tstRslt.AmbPressStart = testRsltQ2ac.AmbPressStart;
|
||||||
|
tstRslt.AmbPressEnd = testRsltQ2ac.AmbPressEnd;
|
||||||
|
tstRslt.AmbPressMin = testRsltQ2ac.AmbPressMin;
|
||||||
|
tstRslt.AmbPressMax = testRsltQ2ac.AmbPressMax;
|
||||||
|
tstRslt.AmbHumiMean = testRsltQ2ac.AmbHumiMean;
|
||||||
|
tstRslt.AmbHumiStart = testRsltQ2ac.AmbHumiStart;
|
||||||
|
tstRslt.AmbHumiEnd = testRsltQ2ac.AmbHumiEnd;
|
||||||
|
tstRslt.AmbHumiMin = testRsltQ2ac.AmbHumiMin;
|
||||||
|
tstRslt.AmbHumiMax = testRsltQ2ac.AmbHumiMax;
|
||||||
|
tstRslt.PressUpMean = testRsltQ2ac.PressUpMean;
|
||||||
|
tstRslt.PressUpStart = testRsltQ2ac.PressUpStart;
|
||||||
|
tstRslt.PressUpEnd = testRsltQ2ac.PressUpEnd;
|
||||||
|
tstRslt.PressUpMin = testRsltQ2ac.PressUpMin;
|
||||||
|
tstRslt.PressUpMax = testRsltQ2ac.PressUpMax;
|
||||||
|
tstRslt.PressDownMean = testRsltQ2ac.PressDownMean;
|
||||||
|
tstRslt.PressDownStart = testRsltQ2ac.PressDownStart;
|
||||||
|
tstRslt.PressDownEnd = testRsltQ2ac.PressDownEnd;
|
||||||
|
tstRslt.PressDownMin = testRsltQ2ac.PressDownMin;
|
||||||
|
tstRslt.PressDownMax = testRsltQ2ac.PressDownMax;
|
||||||
|
tstRslt.PressDeltaMean = testRsltQ2ac.PressDeltaMean;
|
||||||
|
tstRslt.PressDeltaStart = testRsltQ2ac.PressDeltaStart;
|
||||||
|
tstRslt.PressDeltaEnd = testRsltQ2ac.PressDeltaEnd;
|
||||||
|
tstRslt.PressDeltaMin = testRsltQ2ac.PressDeltaMin;
|
||||||
|
tstRslt.PressDeltaMax = testRsltQ2ac.PressDeltaMax;
|
||||||
|
tstRslt.ConductMean = testRsltQ2ac.ConductMean;
|
||||||
|
tstRslt.ConductStart = testRsltQ2ac.ConductStart;
|
||||||
|
tstRslt.ConductEnd = testRsltQ2ac.ConductEnd;
|
||||||
|
tstRslt.ConductMin = testRsltQ2ac.ConductMin;
|
||||||
|
tstRslt.ConductMax = testRsltQ2ac.ConductMax;
|
||||||
|
tstRslt.TempUpMean = testRsltQ2ac.TempUpMean;
|
||||||
|
tstRslt.TempUpStart = testRsltQ2ac.TempUpStart;
|
||||||
|
tstRslt.TempUpEnd = testRsltQ2ac.TempUpEnd;
|
||||||
|
tstRslt.TempUpMin = testRsltQ2ac.TempUpMin;
|
||||||
|
tstRslt.TempUpMax = testRsltQ2ac.TempUpMax;
|
||||||
|
tstRslt.TempDownMean = testRsltQ2ac.TempDownMean;
|
||||||
|
tstRslt.TempDownStart = testRsltQ2ac.TempDownStart;
|
||||||
|
tstRslt.TempDownEnd = testRsltQ2ac.TempDownEnd;
|
||||||
|
tstRslt.TempDownMin = testRsltQ2ac.TempDownMin;
|
||||||
|
tstRslt.TempDownMax = testRsltQ2ac.TempDownMax;
|
||||||
|
tstRslt.TempDivMean = testRsltQ2ac.TempDivMean;
|
||||||
|
tstRslt.TempDivStart = testRsltQ2ac.TempDivStart;
|
||||||
|
tstRslt.TempDivEnd = testRsltQ2ac.TempDivEnd;
|
||||||
|
tstRslt.TempDivMin = testRsltQ2ac.TempDivMin;
|
||||||
|
tstRslt.TempDivMax = testRsltQ2ac.TempDivMax;
|
||||||
|
tstRslt.DensityIn = testRsltQ2ac.DensityIn;
|
||||||
|
tstRslt.DensityLine = testRsltQ2ac.DensityLine;
|
||||||
|
tstRslt.DensityDiv = testRsltQ2ac.DensityDiv;
|
||||||
|
|
||||||
|
tstRslt.StartTime = testRsltQ2ac.StartTime;
|
||||||
|
tstRslt.EndTime = testRsltQ2ac.EndTime;
|
||||||
|
tstRslt.FlowSetTime = testRsltQ2ac.FlowSetTime;
|
||||||
|
tstRslt.TestTime = testRsltQ2ac.TestTime;
|
||||||
|
tstRslt.PulsesMaster = testRsltQ2ac.PulsesMaster;
|
||||||
|
tstRslt.ConstMasterRaw = testRsltQ2ac.ConstMasterRaw;
|
||||||
|
tstRslt.ConstMaster = testRsltQ2ac.ConstMaster;
|
||||||
|
tstRslt.MassStartRaw = testRsltQ2ac.MassStartRaw;
|
||||||
|
tstRslt.MassStart = testRsltQ2ac.MassStart;
|
||||||
|
tstRslt.MassEndRaw = testRsltQ2ac.MassEndRaw;
|
||||||
|
tstRslt.MassEnd = testRsltQ2ac.MassEnd;
|
||||||
|
tstRslt.MassOfEvapWater = testRsltQ2ac.MassOfEvapWater;
|
||||||
|
//tstRslt.FlowMass = testRsltQ2ac.FlowMass;
|
||||||
|
//tstRslt.FlowVolume = testRsltQ2ac.FlowVolume;
|
||||||
|
tstRslt.VolumeCTV = testRsltQ2ac.VolumeCTV;
|
||||||
|
tstRslt.VolumeMaster = testRsltQ2ac.VolumeMaster;
|
||||||
|
tstRslt.ErrorMaster = testRsltQ2ac.ErrorMaster;
|
||||||
|
|
||||||
|
tstRslt.FlowMean = testRsltQ2ac.FlowMean;
|
||||||
|
tstRslt.FlowMin = testRsltQ2ac.FlowMin;
|
||||||
|
tstRslt.FlowMax = testRsltQ2ac.FlowMax;
|
||||||
|
|
||||||
|
tstRslt.Custom1 = testRsltQ2ac.Custom1;
|
||||||
|
tstRslt.Custom2 = testRsltQ2ac.Custom2;
|
||||||
|
tstRslt.Custom3 = testRsltQ2ac.Custom3;
|
||||||
|
tstRslt.Custom4 = testRsltQ2ac.Custom4;
|
||||||
|
tstRslt.Custom5 = testRsltQ2ac.Custom5;
|
||||||
|
tstRslt.Custom6 = testRsltQ2ac.Custom6;
|
||||||
|
tstRslt.Custom7 = testRsltQ2ac.Custom7;
|
||||||
|
tstRslt.Custom8 = testRsltQ2ac.Custom8;
|
||||||
|
|
||||||
|
for (int i = 0; i < ProcessData.BatchRslts.WMPositionsCount; i++)
|
||||||
|
{
|
||||||
|
Results.Entities.MeterTestRslt meterRslt = ProcessData.BatchRslts.GetMeterTestRslt(testName, i, CompoundMeterId.Single);
|
||||||
|
Results.Entities.MeterTestRslt meterRsltQ2bc = ProcessData.BatchRslts.GetMeterTestRslt(testNameQ2bc, i, CompoundMeterId.Single);
|
||||||
|
Results.Entities.MeterTestRslt meterRsltQ2ac = ProcessData.BatchRslts.GetMeterTestRslt(testNameQ2ac, i, CompoundMeterId.Single);
|
||||||
|
|
||||||
|
if ((meterRslt != null) && (meterRsltQ2bc != null) && (meterRsltQ2ac != null))
|
||||||
|
{
|
||||||
|
meterRslt.PulsesMeter = meterRsltQ2ac.PulsesMeter;
|
||||||
|
meterRslt.PulsesMaster = meterRsltQ2ac.PulsesMaster;
|
||||||
|
meterRslt.PulsesPerLiter = meterRsltQ2ac.PulsesPerLiter;
|
||||||
|
meterRslt.VolumeRef = meterRsltQ2ac.VolumeRef;
|
||||||
|
meterRslt.TestTime = meterRsltQ2ac.TestTime;
|
||||||
|
meterRslt.VolumeStart = meterRsltQ2ac.VolumeStart;
|
||||||
|
meterRslt.VolumeEnd = meterRsltQ2ac.VolumeEnd;
|
||||||
|
meterRslt.VolumeMeter = meterRsltQ2ac.VolumeMeter;
|
||||||
|
meterRslt.Error = meterRsltQ2ac.Error;
|
||||||
|
meterRslt.TestDone = meterRsltQ2ac.TestDone;
|
||||||
|
tstRslt.TestDone = true;
|
||||||
|
|
||||||
|
if (((meterRsltQ2bc.Error < -0.51) && (meterRsltQ2ac.Error < meterRsltQ2bc.Error)) ||
|
||||||
|
((meterRsltQ2bc.Error > +0.51) && (meterRsltQ2ac.Error > meterRsltQ2bc.Error)))
|
||||||
|
{
|
||||||
|
meterRslt.Passed = false; /// Q2 correction check failed
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meterRslt.Passed = true; /// Q2 correction check passed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -158,6 +158,22 @@ namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (smartHead is RegisterReaders.iPerlASICReader.implementations.SmartReader smartReaderASIC )
|
||||||
|
{
|
||||||
|
if (correctionsList.Any(x => x is IPerlASICCorrections))
|
||||||
|
continue;
|
||||||
|
//(SmartCommunicationForm parent, ISmartTestMethod testMethod, ITestMethodCfg cfg, IList<Config.Entities.Test> tests, IList<ITestParams> multiTestParams)
|
||||||
|
correctionsList.Add(new IPerlASICCorrections(this,/*log, rfidDataLogger,*/ componentBase, cfg, tests, multiTestParams));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (smartHead is RegisterReaders.IPerlReader.implementations.SmartReader smartiPerlReader )
|
||||||
|
{
|
||||||
|
if (correctionsList.Any(x => x is IPerlCorrections))
|
||||||
|
continue;
|
||||||
|
correctionsList.Add(new IPerlCorrections( this,componentBase, cfg, tests, multiTestParams));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
throw new Exception("Unknown smart head type");
|
throw new Exception("Unknown smart head type");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -325,11 +341,11 @@ namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication
|
|||||||
{
|
{
|
||||||
checkBoxesEditMode = false;
|
checkBoxesEditMode = false;
|
||||||
|
|
||||||
ITestMethodCfg cfg = (componentBase as ITestMethodCfg);
|
ITestMethodCfg cfg = (componentBase.Cfg as ITestMethodCfg);
|
||||||
ISmartTestMethod smartTestMethod = componentBase as ISmartTestMethod;
|
ISmartTestMethod smartTestMethod = componentBase as ISmartTestMethod;
|
||||||
|
|
||||||
//TODO get corrections based on defined meter
|
//TODO get corrections based on defined meter
|
||||||
_corrections = GetNewCorrectionList(smartTestMethod, smartTestMethod.TestMethodCfg, tests, multiTestParams);
|
_corrections = GetNewCorrectionList(smartTestMethod, cfg, tests, multiTestParams);
|
||||||
InitializeMeterTypeItems();
|
InitializeMeterTypeItems();
|
||||||
UpdateHeads();
|
UpdateHeads();
|
||||||
|
|
||||||
@@ -410,7 +426,10 @@ namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication
|
|||||||
if (waterMeterPositions0 == null) waterMeterPositions0 = new List<int>();
|
if (waterMeterPositions0 == null) waterMeterPositions0 = new List<int>();
|
||||||
//iperlHeads = ProcessData.SmartHeadsUni;
|
//iperlHeads = ProcessData.SmartHeadsUni;
|
||||||
string comparedTypeReader = SelectedTypeReader;
|
string comparedTypeReader = SelectedTypeReader;
|
||||||
if (string.IsNullOrEmpty(SelectedTypeReader))
|
|
||||||
|
//TODO BUMI solve problem with init first
|
||||||
|
//ProcessData.SmartHeadsUni?.ForEach( head => iperlHeads.Add(head));
|
||||||
|
if (string.IsNullOrEmpty(SelectedTypeReader) )
|
||||||
{
|
{
|
||||||
comparedTypeReader = ProcessData.SmartHeadsUni?.First()?.GetType().Name;
|
comparedTypeReader = ProcessData.SmartHeadsUni?.First()?.GetType().Name;
|
||||||
}
|
}
|
||||||
@@ -418,12 +437,13 @@ namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication
|
|||||||
ICorrections corre = null;
|
ICorrections corre = null;
|
||||||
foreach (ICorrections correction in _corrections)
|
foreach (ICorrections correction in _corrections)
|
||||||
{
|
{
|
||||||
if (correction.TypeIdentificatorName() == SelectedTypeReader)
|
if (correction.TypeIdentificatorName() == comparedTypeReader)
|
||||||
{
|
{
|
||||||
corre = correction;
|
corre = correction;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (corre == null) corre = _corrections.First();
|
||||||
|
|
||||||
if (corre != null)
|
if (corre != null)
|
||||||
{
|
{
|
||||||
@@ -700,7 +720,11 @@ namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication
|
|||||||
//currentGroup++;
|
//currentGroup++;
|
||||||
|
|
||||||
int wtId = 0;
|
int wtId = 0;
|
||||||
foreach (var wt in Correction.GetAllThreads())
|
var threads = Correction?.GetAllThreads();
|
||||||
|
if (threads == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var wt in threads)
|
||||||
{
|
{
|
||||||
wt.Start(new Boxes.IntBox(wtId++)); /// Start worker threads !!!
|
wt.Start(new Boxes.IntBox(wtId++)); /// Start worker threads !!!
|
||||||
}
|
}
|
||||||
@@ -860,6 +884,7 @@ namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication
|
|||||||
checkBoxImage41, checkBoxImage42, checkBoxImage43, checkBoxImage44, checkBoxImage45,
|
checkBoxImage41, checkBoxImage42, checkBoxImage43, checkBoxImage44, checkBoxImage45,
|
||||||
checkBoxImage46, checkBoxImage47, checkBoxImage48,
|
checkBoxImage46, checkBoxImage47, checkBoxImage48,
|
||||||
};
|
};
|
||||||
|
if (ckbIndex == null) return;
|
||||||
for (int i = 0; i < 48; i++)
|
for (int i = 0; i < 48; i++)
|
||||||
{
|
{
|
||||||
int wmNr0 = ckbIndex[i];
|
int wmNr0 = ckbIndex[i];
|
||||||
|
|||||||
@@ -15,11 +15,15 @@ namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication
|
|||||||
public class iPerlCommunicationParams : TestParamsBase, IParamsProvider, ITestParams
|
public class iPerlCommunicationParams : TestParamsBase, IParamsProvider, ITestParams
|
||||||
{
|
{
|
||||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(iPerlCommunicationParams) })[0];
|
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(iPerlCommunicationParams) })[0];
|
||||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
|
||||||
|
|
||||||
public string Activity; /// Communication activity
|
public override XmlSerializer GetSerializer()
|
||||||
public bool SimultWithPrevious;
|
{
|
||||||
public bool SimultWithNext;
|
return Serializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public override void InitializeAll()
|
public override void InitializeAll()
|
||||||
{
|
{
|
||||||
|
|||||||
+2879
File diff suppressed because it is too large
Load Diff
+3
-2
@@ -533,7 +533,8 @@ namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.implementations
|
|||||||
Thread.Sleep(cfg == null ? 250 : Math.Max(250, cfg.DelayBetweenRetries));
|
Thread.Sleep(cfg == null ? 250 : Math.Max(250, cfg.DelayBetweenRetries));
|
||||||
if (smartHead.DebugLevel == DebugMode.FailureDuringOperation) smartHead.DebugLevel = DebugMode.Normal;
|
if (smartHead.DebugLevel == DebugMode.FailureDuringOperation) smartHead.DebugLevel = DebugMode.Normal;
|
||||||
|
|
||||||
if (smartHead is IperlHead iperlHead)
|
if (smartHead is SmartReader iperlHead)
|
||||||
|
//if (smartHead is IperlHead iperlHead)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (iperlHead.DebugLevel != DebugMode.Normal) // Simulation
|
if (iperlHead.DebugLevel != DebugMode.Normal) // Simulation
|
||||||
@@ -541,7 +542,7 @@ namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.implementations
|
|||||||
return SimulationServices.ReadRequest(iperlHead, messageID, offset, length, out buffer);
|
return SimulationServices.ReadRequest(iperlHead, messageID, offset, length, out buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iperlHead.CommInterface == CommunicationInterface.NFC.ToDescription()) // NFC Interface
|
if (iperlHead.CommInterface == CommunicationInterface.NFC) // NFC Interface
|
||||||
{
|
{
|
||||||
return NfcServices.ReadRequest(cfg, iperlHead, structName, offset, length, out buffer);
|
return NfcServices.ReadRequest(cfg, iperlHead, structName, offset, length, out buffer);
|
||||||
}
|
}
|
||||||
|
|||||||
+69
-4
@@ -1251,6 +1251,66 @@
|
|||||||
<Compile Include="Rig\RegisterReaders\DataStream\Reader\ProcParams.cs" />
|
<Compile Include="Rig\RegisterReaders\DataStream\Reader\ProcParams.cs" />
|
||||||
<Compile Include="Rig\RegisterReaders\DataStream\Reader\Reader.cs" />
|
<Compile Include="Rig\RegisterReaders\DataStream\Reader\Reader.cs" />
|
||||||
<Compile Include="Rig\RegisterReaders\DataStream\Reader\ReaderCfg.cs" />
|
<Compile Include="Rig\RegisterReaders\DataStream\Reader\ReaderCfg.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\DiagnosticLedParser.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\DiagnosticLedState.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\parserer\DiagnosticLedData.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\parserer\DiagnosticLedFrameSpec.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\parserer\DiagnosticLedState1Data.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\parserer\DiagnosticLedState2Data.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\parserer\DiagnosticLedState3Data.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\parserer\DiagnosticLedState4Data.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\parserer\DiagnosticLedState5Data.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\parserer\DiagnosticLedState6Data.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\parserer\DiagnosticLedState7Data.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\parserer\PipeStatus.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\parserer\SpikeDetectionStatus.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\utils\DiagnosticChecksum.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\utils\DiagnosticHex.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\hexLogger\HexFormatter.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\hexLogger\IpelHatCommandDecoder.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\hexLogger\IperlHatLogger.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\hexLogger\TouchReadControlDecoder.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\hexLogger\TouchReadLogger.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\IperlHatProtocol\Constants.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\IperlHatProtocol\IperlHatFrame.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\IperlHatProtocol\IperlHatFrameBuilder.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\IperlHatProtocol\IperlHatFrameParser.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\IperlHatProtocol\IperlHatProtocol.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\IperlHatProtocol\IperlHatResponse.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\led\ITouchReadLedParser.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\led\ShortVariableLedParser.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\led\TouchReadLedData.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\led\TouchReadLedMessage.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\protocolCommons\ProtocolCommand.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\protocolCommons\ProtocolDeviceSubCommand.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\protocolCommons\ProtocolStatuses.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\wiredProtocol\TouchReadFrame.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\wiredProtocol\TouchReadFrameBuilder.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\wiredProtocol\TouchReadFrameParser.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\wiredProtocol\TouchReadProtocol.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\wiredProtocol\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\OptoTelegramRaw.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\implementations\SmartReader.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\IPerlCfg.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\IPerlUniCfgCtrl.cs">
|
||||||
|
<SubType>UserControl</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\IPerlUniCfgCtrl.designer.cs">
|
||||||
|
<DependentUpon>IPerlUniCfgCtrl.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\IperlASICUniHeadTestCtrl.cs">
|
||||||
|
<SubType>UserControl</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\IperlASICUniHeadTestCtrl.Designer.cs">
|
||||||
|
<DependentUpon>IperlASICUniHeadTestCtrl.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Rig\RegisterReaders\iPerlReaderUNI\common\IUniHeadTestCtrl.cs" />
|
<Compile Include="Rig\RegisterReaders\iPerlReaderUNI\common\IUniHeadTestCtrl.cs" />
|
||||||
<Compile Include="Rig\RegisterReaders\iPerlReaderUNI\Factory.cs" />
|
<Compile Include="Rig\RegisterReaders\iPerlReaderUNI\Factory.cs" />
|
||||||
<Compile Include="Rig\RegisterReaders\iPerlReaderUNI\IPerlUniCfgCtrl.cs">
|
<Compile Include="Rig\RegisterReaders\iPerlReaderUNI\IPerlUniCfgCtrl.cs">
|
||||||
@@ -1619,8 +1679,10 @@
|
|||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Rig\TestMethods\SmartMeterFlyingStartMassCollection\Factory.cs" />
|
<Compile Include="Rig\TestMethods\SmartMeterFlyingStartMassCollection\Factory.cs" />
|
||||||
<Compile Include="Rig\TestMethods\SmartMeterFlyingStartMassCollection\TestMethodCfg.cs" />
|
<Compile Include="Rig\TestMethods\SmartMeterFlyingStartMassCollection\TestMethodCfg.cs" />
|
||||||
|
<Compile Include="Rig\TestMethods\SmartTest\iPerlCommunicationSeq.cs" />
|
||||||
<Compile Include="Rig\TestMethods\SmartTest\SequenceConditionOp.cs" />
|
<Compile Include="Rig\TestMethods\SmartTest\SequenceConditionOp.cs" />
|
||||||
<Compile Include="Rig\TestMethods\SmartTest\TestMethod.cs" />
|
<Compile Include="Rig\TestMethods\SmartTest\TestMethod.cs" />
|
||||||
|
<Compile Include="Rig\TestMethods\SmartTest\TestMethodCfg.cs" />
|
||||||
<Compile Include="Rig\TestMethods\SmartTest\TestMethodCfgCtrl.cs">
|
<Compile Include="Rig\TestMethods\SmartTest\TestMethodCfgCtrl.cs">
|
||||||
<SubType>UserControl</SubType>
|
<SubType>UserControl</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -2068,6 +2130,7 @@
|
|||||||
<Compile Include="Rig\Uni\SharedDialogs\SmartMetersCommunication\common\ICorrections.cs" />
|
<Compile Include="Rig\Uni\SharedDialogs\SmartMetersCommunication\common\ICorrections.cs" />
|
||||||
<Compile Include="Rig\Uni\SharedDialogs\SmartMetersCommunication\common\ISmartReader.cs" />
|
<Compile Include="Rig\Uni\SharedDialogs\SmartMetersCommunication\common\ISmartReader.cs" />
|
||||||
<Compile Include="Rig\Uni\SharedDialogs\SmartMetersCommunication\implementations\EnumExtensions.cs" />
|
<Compile Include="Rig\Uni\SharedDialogs\SmartMetersCommunication\implementations\EnumExtensions.cs" />
|
||||||
|
<Compile Include="Rig\Uni\SharedDialogs\SmartMetersCommunication\implementations\IPerlASICCorrections.cs" />
|
||||||
<Compile Include="Rig\Uni\SharedDialogs\SmartMetersCommunication\implementations\IPerlCorrections.cs" />
|
<Compile Include="Rig\Uni\SharedDialogs\SmartMetersCommunication\implementations\IPerlCorrections.cs" />
|
||||||
<Compile Include="Rig\Uni\SharedDialogs\SmartMetersCommunication\implementations\PoseidonCorrections.cs" />
|
<Compile Include="Rig\Uni\SharedDialogs\SmartMetersCommunication\implementations\PoseidonCorrections.cs" />
|
||||||
<Compile Include="Rig\Uni\SharedDialogs\SmartMetersCommunication\SmartComponentBase.cs" />
|
<Compile Include="Rig\Uni\SharedDialogs\SmartMetersCommunication\SmartComponentBase.cs" />
|
||||||
@@ -3288,6 +3351,12 @@
|
|||||||
<EmbeddedResource Include="Rig\RegisterReaders\FrequencyMeterFromUniCB\RRCfgCtrl.resx">
|
<EmbeddedResource Include="Rig\RegisterReaders\FrequencyMeterFromUniCB\RRCfgCtrl.resx">
|
||||||
<DependentUpon>RRCfgCtrl.cs</DependentUpon>
|
<DependentUpon>RRCfgCtrl.cs</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Rig\RegisterReaders\iPerlASICReader\IPerlUniCfgCtrl.resx">
|
||||||
|
<DependentUpon>IPerlUniCfgCtrl.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Rig\RegisterReaders\iPerlASICReader\IperlASICUniHeadTestCtrl.resx">
|
||||||
|
<DependentUpon>IperlASICUniHeadTestCtrl.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Rig\RegisterReaders\iPerlReaderUNI\IPerlUniCfgCtrl.resx">
|
<EmbeddedResource Include="Rig\RegisterReaders\iPerlReaderUNI\IPerlUniCfgCtrl.resx">
|
||||||
<DependentUpon>IPerlUniCfgCtrl.cs</DependentUpon>
|
<DependentUpon>IPerlUniCfgCtrl.cs</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
@@ -4001,10 +4070,6 @@
|
|||||||
<Project>{0C0A1F4D-1363-4544-A7C5-196C76D26CCA}</Project>
|
<Project>{0C0A1F4D-1363-4544-A7C5-196C76D26CCA}</Project>
|
||||||
<Name>GraphLib</Name>
|
<Name>GraphLib</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\NfcC7_DLL\NfcC7_DLL.csproj">
|
|
||||||
<Project>{53e75979-b530-4805-8fc9-b314f14a62be}</Project>
|
|
||||||
<Name>NfcC7_DLL</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\RestClient\RestClient.csproj">
|
<ProjectReference Include="..\RestClient\RestClient.csproj">
|
||||||
<Project>{46e3b0e1-209f-4550-b0dd-d7e2c039b3ce}</Project>
|
<Project>{46e3b0e1-209f-4550-b0dd-d7e2c039b3ce}</Project>
|
||||||
<Name>RestClient</Name>
|
<Name>RestClient</Name>
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
|
|||||||
StartTime = DateTime.Now;
|
StartTime = DateTime.Now;
|
||||||
Console.WriteLine($"Start Time Loop: {StartTime.ToString("yyyy-MM-dd HH:mm:ss")}");
|
Console.WriteLine($"Start Time Loop: {StartTime.ToString("yyyy-MM-dd HH:mm:ss")}");
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++)
|
for (int i = 0; i < 100; i++)
|
||||||
{
|
{
|
||||||
cliRunner.AddRunAndCaptureJsonAsync<JsonDataFromPoseidon>(serialPort, SerialPortData.EMeterArg.AllParams);
|
cliRunner.AddRunAndCaptureJsonAsync<JsonDataFromPoseidon>(serialPort, SerialPortData.EMeterArg.AllParams);
|
||||||
}
|
}
|
||||||
|
|||||||
+179
@@ -0,0 +1,179 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.protocolCommons;
|
||||||
|
|
||||||
|
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class IperlHatFrameBuilderTests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void Encode_ViewFactoryId_Command()
|
||||||
|
{
|
||||||
|
byte[] frame = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.ViewFactoryId)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] expected =
|
||||||
|
{
|
||||||
|
Constants.Start, // START
|
||||||
|
Constants.Write, // DIRECTION
|
||||||
|
0x05, // LEN
|
||||||
|
(byte)ProtocolCommand.ViewFactoryId, // COMMAND
|
||||||
|
Constants.End // END
|
||||||
|
};
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, frame);
|
||||||
|
|
||||||
|
string log = IperlHatLogger.DescribeTx(frame);
|
||||||
|
Console.WriteLine(log);
|
||||||
|
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Encode_VERS_Command()
|
||||||
|
{
|
||||||
|
byte[] frame = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.Question)
|
||||||
|
.AddPayload(Constants.Version)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] expected = HexFormatter.HexStringToByteArray("53 57 3F 76 65 72 73 0D");
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, frame);
|
||||||
|
|
||||||
|
string log = IperlHatLogger.DescribeTx(frame);
|
||||||
|
Console.WriteLine(log);
|
||||||
|
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Encode_VERS2_Command()
|
||||||
|
{
|
||||||
|
byte[] frame = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.SetVersionCommand()
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] expected = HexFormatter.HexStringToByteArray("53 57 3F 76 65 72 73 0D");
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, frame);
|
||||||
|
|
||||||
|
string log = IperlHatLogger.DescribeTx(frame);
|
||||||
|
Console.WriteLine(log);
|
||||||
|
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Encode_ViewProgrammableId_Command()
|
||||||
|
{
|
||||||
|
byte[] frame = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.ViewProgrammableId)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] expected = HexFormatter.HexStringToByteArray("53 57 05 03 0D");
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, frame);
|
||||||
|
|
||||||
|
string log = IperlHatLogger.DescribeTx(frame);
|
||||||
|
Console.WriteLine(log);
|
||||||
|
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Encode_ViewState_Command()
|
||||||
|
{
|
||||||
|
byte[] frame = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.ViewState)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] expected = HexFormatter.HexStringToByteArray("53 57 05 19 0D");
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, frame);
|
||||||
|
|
||||||
|
string log = IperlHatLogger.DescribeTx(frame);
|
||||||
|
Console.WriteLine(log);
|
||||||
|
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Encode_SetState_Idle_Command()
|
||||||
|
{
|
||||||
|
byte[] frame = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.SetState)
|
||||||
|
.AddSubCommand(ProtocolStatuses.Idle) // Idle
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] expected = HexFormatter.HexStringToByteArray("53 57 06 1A 01 0D");
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, frame);
|
||||||
|
|
||||||
|
string log = IperlHatLogger.DescribeTx(frame);
|
||||||
|
Console.WriteLine(log);
|
||||||
|
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Encode_SetState_Active_Command()
|
||||||
|
{
|
||||||
|
byte[] frame = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.SetState)
|
||||||
|
.AddSubCommand(ProtocolStatuses.Active) // Active
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] expected = HexFormatter.HexStringToByteArray("53 57 06 1A 02 0D");
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, frame);
|
||||||
|
|
||||||
|
string log = IperlHatLogger.DescribeTx(frame);
|
||||||
|
Console.WriteLine(log);
|
||||||
|
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Encode_SetDiagnosticLEDState_Status4_Command()
|
||||||
|
{
|
||||||
|
// ----------- Arrange -----------
|
||||||
|
byte[] request = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddDeviceCommand(ProtocolDeviceSubCommand.SetDiagnosticLEDState)
|
||||||
|
.AddPayload(DiagnosticLedState.State4)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] expected = HexFormatter.HexStringToByteArray("53 57 07 FD 60 04 0D");
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, request);
|
||||||
|
|
||||||
|
string log = IperlHatLogger.DescribeTx(request);
|
||||||
|
Console.WriteLine(log);
|
||||||
|
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void AddDiagnosticLedState()
|
||||||
|
{
|
||||||
|
// ----------- Arrange -----------
|
||||||
|
byte[] request = new IperlHatFrameBuilder()
|
||||||
|
.AddDiagnosticLedState(DiagnosticLedState.State4)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] expected = HexFormatter.HexStringToByteArray("53 57 07 FD 60 04 0D");
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, request);
|
||||||
|
|
||||||
|
string log = IperlHatLogger.DescribeTx(request);
|
||||||
|
Console.WriteLine(log);
|
||||||
|
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(request));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
using JetBrains.Annotations;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol;
|
||||||
|
|
||||||
|
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[TestSubject(typeof(IperlHatFrameParser))]
|
||||||
|
public class IperlHatFrameParserTest
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void ParseTest_FactoryID()
|
||||||
|
{
|
||||||
|
IperlHatFrameParser parser = new IperlHatFrameParser();
|
||||||
|
byte[] result1 = HexFormatter.HexStringToByteArray("53 52 0F 01 31 30 30 31 30 34 30 35 31 00 0D");
|
||||||
|
IperlHatResponse iperlHatResponse = parser.Parse(result1);
|
||||||
|
|
||||||
|
Assert.IsNotNull(iperlHatResponse);
|
||||||
|
Assert.IsTrue(iperlHatResponse.IsOk);
|
||||||
|
Assert.IsTrue(iperlHatResponse.Payload.Length > 0);
|
||||||
|
Assert.AreEqual("100104051", iperlHatResponse.GetAsciiPayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ParseTest_VERS()
|
||||||
|
{
|
||||||
|
IperlHatFrameParser parser = new IperlHatFrameParser();
|
||||||
|
byte[] versionResult = HexFormatter.HexStringToByteArray("3F 76 65 72 73 3A 20 48 61 72 72 79 20 54 3A 42 38 30 30 2C 20 56 3A 30 36 2E 30 36 2E 30 31 2C 20 46 57 3A 31 39 30 32 31 35 2C 20 37 45 43 45 2C 20 42 31 2E 36 2E 30 31 2C 20 48 57 3A 34 2C 20 53 65 72 69 61 6C 3A 30 0D");
|
||||||
|
IperlHatResponse iperlHatResponse = parser.Parse(versionResult);
|
||||||
|
|
||||||
|
Assert.IsNotNull(iperlHatResponse);
|
||||||
|
Assert.IsTrue(iperlHatResponse.IsOk);
|
||||||
|
Assert.IsTrue(iperlHatResponse.Payload.Length > 0);
|
||||||
|
Assert.AreEqual(Constants.Question, iperlHatResponse.Control);
|
||||||
|
|
||||||
|
Assert.AreEqual("vers: Harry T:B800, V:06.06.01, FW:190215, 7ECE, B1.6.01, HW:4, Serial:0", iperlHatResponse.GetAsciiPayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ParseTest_Response_OK ()
|
||||||
|
{
|
||||||
|
IperlHatFrameParser parser = new IperlHatFrameParser();
|
||||||
|
byte[] versionResult = HexFormatter.HexStringToByteArray("53 52 05 01 0D");
|
||||||
|
IperlHatResponse iperlHatResponse = parser.Parse(versionResult);
|
||||||
|
|
||||||
|
Assert.IsNotNull(iperlHatResponse);
|
||||||
|
Assert.IsTrue(iperlHatResponse.IsOk);
|
||||||
|
Assert.AreEqual(null, iperlHatResponse.GetAsciiPayload());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ParseTest_Response_NOK ()
|
||||||
|
{
|
||||||
|
IperlHatFrameParser parser = new IperlHatFrameParser();
|
||||||
|
byte[] versionResult = HexFormatter.HexStringToByteArray("53 52 05 FD 0D");
|
||||||
|
IperlHatResponse iperlHatResponse = parser.Parse(versionResult);
|
||||||
|
|
||||||
|
Assert.IsNotNull(iperlHatResponse);
|
||||||
|
Assert.IsFalse(iperlHatResponse.IsOk);
|
||||||
|
Assert.AreEqual(null, iperlHatResponse.GetAsciiPayload());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+510
@@ -0,0 +1,510 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Ports;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.protocolCommons;
|
||||||
|
|
||||||
|
|
||||||
|
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class IperlHatIntegrationTests
|
||||||
|
{
|
||||||
|
private const string ComPort = "COM3"; // CHANGE THIS
|
||||||
|
private const int BaudRate = 2400;
|
||||||
|
private const int BaudRateOpto = 38400;
|
||||||
|
private const int ReadTimeoutMs = 2000;
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
[TestCategory("Hardware")]
|
||||||
|
[TestCategory("Serial")]
|
||||||
|
public void Serial_ViewFactoryId_ReadSerialNumber()
|
||||||
|
{
|
||||||
|
// -------- Arrange --------
|
||||||
|
byte[] request = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.ViewFactoryId)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
var parser = new IperlHatFrameParser();
|
||||||
|
|
||||||
|
using (var port = new SerialPort(ComPort, BaudRate, Parity.None, 8, StopBits.One))
|
||||||
|
{
|
||||||
|
port.Handshake = Handshake.None;
|
||||||
|
port.ReadTimeout = 5000;
|
||||||
|
port.Open();
|
||||||
|
|
||||||
|
DateTime end = DateTime.Now.AddSeconds(10);
|
||||||
|
|
||||||
|
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(request));
|
||||||
|
port.Write(request, 0, request.Length);
|
||||||
|
|
||||||
|
Console.WriteLine("Listening for 10 seconds...");
|
||||||
|
byte[] response = null;
|
||||||
|
while (DateTime.Now < end)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response = ReadResponse(port);
|
||||||
|
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (TimeoutException e)
|
||||||
|
{
|
||||||
|
Assert.Fail("Timeout: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IperlHatResponse iperlHatResponse = parser.Parse(response);
|
||||||
|
|
||||||
|
Assert.IsTrue(iperlHatResponse.IsOk);
|
||||||
|
Assert.IsFalse(iperlHatResponse.Payload.Length < 8);
|
||||||
|
|
||||||
|
Console.WriteLine("\nDone.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
[TestCategory("Hardware")]
|
||||||
|
[TestCategory("Serial")]
|
||||||
|
public void Serial_SetStatus_Idle_Active()
|
||||||
|
{
|
||||||
|
|
||||||
|
byte[] requestStatus = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.ViewState)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var parser = new IperlHatFrameParser();
|
||||||
|
|
||||||
|
using (var port = new SerialPort(ComPort, BaudRate, Parity.None, 8, StopBits.One))
|
||||||
|
{
|
||||||
|
port.Handshake = Handshake.None;
|
||||||
|
port.ReadTimeout = 5000;
|
||||||
|
port.Open();
|
||||||
|
|
||||||
|
|
||||||
|
DateTime end = DateTime.Now.AddSeconds(10);
|
||||||
|
|
||||||
|
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(requestStatus));
|
||||||
|
port.Write(requestStatus, 0, requestStatus.Length);
|
||||||
|
|
||||||
|
Console.WriteLine("Listening for 10 seconds...");
|
||||||
|
byte[] resStart = null;
|
||||||
|
while (DateTime.Now < end)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
resStart = ReadResponse(port);
|
||||||
|
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(resStart));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (TimeoutException e)
|
||||||
|
{
|
||||||
|
Assert.Fail("Timeout: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IperlHatResponse iperlHatResponseOld = parser.Parse(resStart);
|
||||||
|
Assert.IsTrue(iperlHatResponseOld.IsOk, "Idle No set!");
|
||||||
|
Console.WriteLine("We start with status: " + HexFormatter.ToHex(iperlHatResponseOld.Payload[0]));
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
// -------- Arrange --------
|
||||||
|
byte[] request = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.SetState)
|
||||||
|
.AddSubCommand(ProtocolStatuses.Idle)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
// -- set idle
|
||||||
|
end = DateTime.Now.AddSeconds(10);
|
||||||
|
|
||||||
|
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(request));
|
||||||
|
port.Write(request, 0, request.Length);
|
||||||
|
|
||||||
|
Console.WriteLine("Listening for 10 seconds...");
|
||||||
|
byte[] response = null;
|
||||||
|
while (DateTime.Now < end)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response = ReadResponse(port);
|
||||||
|
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (TimeoutException e)
|
||||||
|
{
|
||||||
|
Assert.Fail("Timeout: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IperlHatResponse iperlHatResponse = parser.Parse(response);
|
||||||
|
Assert.IsTrue(iperlHatResponse.IsOk, "Idle No set!");
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
request = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.SetState)
|
||||||
|
.AddSubCommand(ProtocolStatuses.Active)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
end = DateTime.Now.AddSeconds(10);
|
||||||
|
|
||||||
|
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(request));
|
||||||
|
port.Write(request, 0, request.Length);
|
||||||
|
|
||||||
|
Console.WriteLine("Listening for 10 seconds...");
|
||||||
|
response = null;
|
||||||
|
while (DateTime.Now < end)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response = ReadResponse(port);
|
||||||
|
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (TimeoutException e)
|
||||||
|
{
|
||||||
|
Assert.Fail("Timeout: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iperlHatResponse = parser.Parse(response);
|
||||||
|
Assert.IsTrue(iperlHatResponse.IsOk, "Idle No set!");
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Console.WriteLine("\nDone.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
[TestCategory("Hardware")]
|
||||||
|
public void Serial_RawSniff()
|
||||||
|
{
|
||||||
|
using (var port = new SerialPort(ComPort, BaudRate, Parity.None, 8, StopBits.One))
|
||||||
|
{
|
||||||
|
port.Handshake = Handshake.None;
|
||||||
|
port.ReadTimeout = 5000;
|
||||||
|
port.Open();
|
||||||
|
|
||||||
|
DateTime end = DateTime.Now.AddSeconds(10);
|
||||||
|
//welcome message
|
||||||
|
byte[] frame = HexFormatter.HexStringToByteArray("53 57 3F 76 65 72 73 0D");
|
||||||
|
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(frame));
|
||||||
|
port.Write(frame, 0, frame.Length);
|
||||||
|
|
||||||
|
Console.WriteLine("Listening for 10 seconds...");
|
||||||
|
while (DateTime.Now < end)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] response = ReadResponse(port);
|
||||||
|
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (TimeoutException e)
|
||||||
|
{
|
||||||
|
Assert.Fail("Timeout: ",e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
end = DateTime.Now.AddSeconds(10);
|
||||||
|
byte[] frameID = HexFormatter.HexStringToByteArray("53 57 05 01 0D");
|
||||||
|
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(frameID));
|
||||||
|
port.Write(frameID, 0, frameID.Length);
|
||||||
|
|
||||||
|
Console.WriteLine("Listening for 10 seconds...");
|
||||||
|
while (DateTime.Now < end)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] response = ReadResponse(port);
|
||||||
|
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (TimeoutException e)
|
||||||
|
{
|
||||||
|
Assert.Fail("Timeout: ",e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("\nDone.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] ReadResponse(SerialPort port)
|
||||||
|
{
|
||||||
|
var result = new List<byte>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
int value = port.ReadByte(); // blocks until byte or timeout
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
throw new IOException("Serial port returned end of stream.");
|
||||||
|
|
||||||
|
byte b = HexFormatter.ToHexByte(value);
|
||||||
|
result.Add(b);
|
||||||
|
|
||||||
|
// stop when CR received
|
||||||
|
if (b == 0x0D)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
catch (TimeoutException ex)
|
||||||
|
{
|
||||||
|
if (result.Count > 0)
|
||||||
|
return result.ToArray();
|
||||||
|
|
||||||
|
throw new TimeoutException("Timeout reading response from serial port.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
[TestCategory("Hardware")]
|
||||||
|
public void OptoCommunicationON_ReadOpto_CommunicatonOFF()
|
||||||
|
{
|
||||||
|
//OPEN COMMUNICATION to Iperl Hat
|
||||||
|
|
||||||
|
var parser = new IperlHatFrameParser();
|
||||||
|
|
||||||
|
using (var port = new SerialPort(ComPort, BaudRate, Parity.None, 8, StopBits.One))
|
||||||
|
{
|
||||||
|
port.Handshake = Handshake.None;
|
||||||
|
port.ReadTimeout = 5000;
|
||||||
|
port.Open();
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// ------ Set active mode ------
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
byte[] requestStatus = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.SetState)
|
||||||
|
.AddSubCommand(ProtocolStatuses.Active)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
DateTime end = DateTime.Now.AddSeconds(10);
|
||||||
|
|
||||||
|
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(requestStatus));
|
||||||
|
port.Write(requestStatus, 0, requestStatus.Length);
|
||||||
|
|
||||||
|
Console.WriteLine("Set active mode - Listening for 10 seconds...");
|
||||||
|
byte[] resStart = null;
|
||||||
|
while (DateTime.Now < end)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
resStart = ReadResponse(port);
|
||||||
|
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(resStart));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (TimeoutException e)
|
||||||
|
{
|
||||||
|
Assert.Fail("Timeout: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IperlHatResponse iperlHatResponseOld = parser.Parse(resStart);
|
||||||
|
Assert.IsTrue(iperlHatResponseOld.IsOk, "Active No set!");
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// ------ Enable Opto data ------
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
// ----------- Arrange -----------
|
||||||
|
byte[] request = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddDeviceCommand(ProtocolDeviceSubCommand.SetDiagnosticLEDState)
|
||||||
|
.AddPayload(DiagnosticLedState.State4)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
end = DateTime.Now.AddSeconds(10);
|
||||||
|
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(request));
|
||||||
|
port.Write(request, 0, request.Length);
|
||||||
|
|
||||||
|
Console.WriteLine("Enable Opto data - Listening for 10 seconds...");
|
||||||
|
byte[] response = null;
|
||||||
|
while (DateTime.Now < end)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response = ReadResponse(port);
|
||||||
|
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (TimeoutException e)
|
||||||
|
{
|
||||||
|
Assert.Fail("Timeout: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IperlHatResponse iperlHatResponse = parser.Parse(response);
|
||||||
|
Assert.IsTrue(iperlHatResponse.IsOk, "Opto data not set!");
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// ------ Test Opto data ------
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
//Now try test opto data
|
||||||
|
Serial_OptoRawSniff();
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// ------ Disable Opto data ------
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
// ----------- Arrange -----------
|
||||||
|
request = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddDeviceCommand(ProtocolDeviceSubCommand.SetDiagnosticLEDState)
|
||||||
|
.AddPayload(DiagnosticLedState.StateOFF)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
end = DateTime.Now.AddSeconds(10);
|
||||||
|
|
||||||
|
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(request));
|
||||||
|
port.Write(request, 0, request.Length);
|
||||||
|
|
||||||
|
Console.WriteLine("Disable Opto data - Listening for 10 seconds...");
|
||||||
|
response = null;
|
||||||
|
while (DateTime.Now < end)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response = ReadResponse(port);
|
||||||
|
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (TimeoutException e)
|
||||||
|
{
|
||||||
|
Assert.Fail("Timeout: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iperlHatResponse = parser.Parse(response);
|
||||||
|
Assert.IsTrue(iperlHatResponse.IsOk, "Disabled opto LED not set!");
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// ------ Set Idle mode ------
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
// ----------- Arrange -----------
|
||||||
|
request = new IperlHatFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.SetState)
|
||||||
|
.AddSubCommand(ProtocolStatuses.Idle)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
end = DateTime.Now.AddSeconds(10);
|
||||||
|
|
||||||
|
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(request));
|
||||||
|
port.Write(request, 0, request.Length);
|
||||||
|
|
||||||
|
Console.WriteLine("Set Idle mode - Listening for 10 seconds...");
|
||||||
|
response = null;
|
||||||
|
while (DateTime.Now < end)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response = ReadResponse(port);
|
||||||
|
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (TimeoutException e)
|
||||||
|
{
|
||||||
|
Assert.Fail("Timeout: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iperlHatResponse = parser.Parse(response);
|
||||||
|
Assert.IsTrue(iperlHatResponse.IsOk, "Idle status not set!");
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// ------ Test finished ------
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
Console.WriteLine("\nDone.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This test work only if Opto data are active
|
||||||
|
/// Use OptoCommunicationON_ReadOpto_CommunicatonOFF() test method
|
||||||
|
/// </summary>
|
||||||
|
[TestMethod]
|
||||||
|
[TestCategory("Hardware")]
|
||||||
|
public void Serial_OptoRawSniff_Standalone()
|
||||||
|
{
|
||||||
|
Serial_OptoRawSniff();
|
||||||
|
}
|
||||||
|
|
||||||
|
//method test connection to optho head
|
||||||
|
private void Serial_OptoRawSniff()
|
||||||
|
{
|
||||||
|
using (var port = new SerialPort("COM4", BaudRateOpto, Parity.None, 8, StopBits.One))
|
||||||
|
{
|
||||||
|
port.Handshake = Handshake.None;
|
||||||
|
port.ReadTimeout = 10000;
|
||||||
|
|
||||||
|
// 🔑 CRLF handling
|
||||||
|
port.NewLine = "\r\n";
|
||||||
|
port.Encoding = Encoding.ASCII; // or UTF8 if needed
|
||||||
|
|
||||||
|
port.Open();
|
||||||
|
|
||||||
|
Console.WriteLine("Listening for 10 seconds...");
|
||||||
|
DateTime end = DateTime.Now.AddSeconds(10);
|
||||||
|
|
||||||
|
var parser = new DiagnosticLedParser(DiagnosticLedState.State4);
|
||||||
|
|
||||||
|
while (DateTime.Now < end)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string line = port.ReadLine(); // string
|
||||||
|
byte[] bytes = port.Encoding.GetBytes(line);
|
||||||
|
|
||||||
|
Console.WriteLine("RX ← " + HexFormatter.ToSerialHex(bytes));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = (DiagnosticLedState4Data)parser.ParseLine(line,false);
|
||||||
|
Console.WriteLine("Parsed: " + data);
|
||||||
|
}catch(Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Failed to parse: " + e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (TimeoutException)
|
||||||
|
{
|
||||||
|
Assert.Fail("Serial read timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("\nDone.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+189
@@ -0,0 +1,189 @@
|
|||||||
|
using JetBrains.Annotations;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed.parserer;
|
||||||
|
|
||||||
|
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[TestSubject(typeof(DiagnosticLedParser))]
|
||||||
|
public class DiagnosticLedParserTest
|
||||||
|
{
|
||||||
|
private static string WithChecksum(string bodyWithoutChecksum)
|
||||||
|
{
|
||||||
|
byte sum = 0;
|
||||||
|
foreach (char c in bodyWithoutChecksum)
|
||||||
|
sum += (byte)c;
|
||||||
|
|
||||||
|
return bodyWithoutChecksum + sum.ToString("X2") + "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Parse_DiagnosticLed_State1()
|
||||||
|
{
|
||||||
|
string body =
|
||||||
|
"FFFF9C\t" + // signed 24-bit ADC = -100
|
||||||
|
"2020\t" + // field strength
|
||||||
|
"FFFA\t" + // raw flow (-6)
|
||||||
|
"0050FC\t" + // raw volume
|
||||||
|
"0054\t"; // capacitor mV
|
||||||
|
|
||||||
|
string line = WithChecksum(body);
|
||||||
|
|
||||||
|
var parser = new DiagnosticLedParser(DiagnosticLedState.State1);
|
||||||
|
var data = (DiagnosticLedState1Data)parser.ParseLine(line);
|
||||||
|
|
||||||
|
Assert.AreEqual(-100, data.Adc24);
|
||||||
|
Assert.AreEqual((ushort)0x2020, data.FieldStrength);
|
||||||
|
Assert.AreEqual((short)-6, data.RawFlow);
|
||||||
|
Assert.AreEqual((uint)0x0050FC, data.RawVolume);
|
||||||
|
Assert.AreEqual((ushort)0x0054, data.CapacitorMv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Parse_DiagnosticLed_State2()
|
||||||
|
{
|
||||||
|
string line =
|
||||||
|
"00004F\t029A\t0000\tFFD3B1\t005C\t3B9AC9B1\t02\t01\t0D\r\n";
|
||||||
|
|
||||||
|
var parser = new DiagnosticLedParser(DiagnosticLedState.State2);
|
||||||
|
var data = (DiagnosticLedState2Data)parser.ParseLine(line);
|
||||||
|
|
||||||
|
Assert.AreEqual(79, data.Adc24);
|
||||||
|
Assert.AreEqual((ushort)666, data.FieldStrength);
|
||||||
|
Assert.AreEqual((short)0, data.RawFlow);
|
||||||
|
Assert.AreEqual(0xFFD3B1u, data.RawVolume);
|
||||||
|
Assert.AreEqual((ushort)92, data.CapacitorMv);
|
||||||
|
Assert.AreEqual(0x3B9AC9B1u, data.LcdVolume);
|
||||||
|
Assert.AreEqual((byte)0x02, data.MeterState);
|
||||||
|
Assert.IsTrue(data.IsLowFlowCutoff);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Parse_DiagnosticLed_State3()
|
||||||
|
{
|
||||||
|
string body =
|
||||||
|
"FFCC09\t2020\tFFFA\t0050FC\t0054\t0B01\t048000\tA7\t";
|
||||||
|
|
||||||
|
string line = WithChecksum(body);
|
||||||
|
|
||||||
|
var parser = new DiagnosticLedParser(DiagnosticLedState.State3);
|
||||||
|
var data = (DiagnosticLedState3Data)parser.ParseLine(line);
|
||||||
|
|
||||||
|
Assert.AreEqual(-13303, data.Adc24);
|
||||||
|
Assert.AreEqual((ushort)0x2020, data.FieldStrength);
|
||||||
|
Assert.AreEqual((short)-6, data.RawFlow);
|
||||||
|
Assert.AreEqual((uint)0x0050FC, data.RawVolume);
|
||||||
|
Assert.AreEqual((ushort)0x0054, data.CapacitorMv);
|
||||||
|
Assert.AreEqual((ushort)0x0B01, data.FieldCalibration);
|
||||||
|
Assert.AreEqual((uint)0x048000, data.AsicTimestamp);
|
||||||
|
Assert.AreEqual((byte)0xA7, data.FieldDriveTimeUs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Parse_DiagnosticLed_State4()
|
||||||
|
{
|
||||||
|
string body =
|
||||||
|
"000ABC\t2020\tFFFA\t0050FC\t0054\t0B01\t048000\tA7\t" +
|
||||||
|
"00001234\t00F0\t00F1\t0100\t0200\t03\t";
|
||||||
|
|
||||||
|
string line = WithChecksum(body);
|
||||||
|
|
||||||
|
var parser = new DiagnosticLedParser(DiagnosticLedState.State4);
|
||||||
|
var data = (DiagnosticLedState4Data)parser.ParseLine(line);
|
||||||
|
|
||||||
|
Assert.AreEqual(2748, data.Adc24);
|
||||||
|
Assert.AreEqual((ushort)0x2020, data.FieldStrength);
|
||||||
|
Assert.AreEqual((short)-6, data.RawFlow);
|
||||||
|
Assert.AreEqual((uint)0x0050FC, data.RawVolume);
|
||||||
|
Assert.AreEqual((ushort)0x0054, data.CapacitorMv);
|
||||||
|
|
||||||
|
Assert.AreEqual((ushort)0x0B01, data.FieldCalibration);
|
||||||
|
Assert.AreEqual((uint)0x048000, data.AsicTimestamp);
|
||||||
|
Assert.AreEqual((byte)0xA7, data.FieldDriveTimeUs);
|
||||||
|
|
||||||
|
Assert.AreEqual(0x00001234, data.MeanFlowRate);
|
||||||
|
Assert.AreEqual((ushort)0x00F0, data.Field1Measurement);
|
||||||
|
Assert.AreEqual((ushort)0x00F1, data.Field2Measurement);
|
||||||
|
Assert.AreEqual((ushort)0x0100, data.IntegratorCalibrationPositive);
|
||||||
|
Assert.AreEqual((ushort)0x0200, data.IntegratorCalibrationNegative);
|
||||||
|
Assert.AreEqual((byte)0x03, data.AsicState);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Parse_DiagnosticLed_State5()
|
||||||
|
{
|
||||||
|
string body =
|
||||||
|
"FFCC09\t2020\tFFFA\t0050FC\t0054\t0B01\t048000\tA7\t" +
|
||||||
|
"00001234\t00F0\t00F1\t0100\t0200\t03\tFFEC\t";
|
||||||
|
|
||||||
|
string line = WithChecksum(body);
|
||||||
|
|
||||||
|
var parser = new DiagnosticLedParser(DiagnosticLedState.State5);
|
||||||
|
var data = (DiagnosticLedState5Data)parser.ParseLine(line);
|
||||||
|
|
||||||
|
Assert.AreEqual((short)-20, data.WaterImpedance);
|
||||||
|
Assert.AreEqual((byte)0x03, data.AsicState);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Parse_DiagnosticLed_State6()
|
||||||
|
{
|
||||||
|
string body =
|
||||||
|
"FFCC09\t2020\tFFFA\t0050FC\t0054\t0B01\t048000\tA7\t" +
|
||||||
|
"00001234\t00F0\t00F1\t0100\t0200\t03\tFFEC\t0010\t" +
|
||||||
|
"02\t" + // pp spike detection
|
||||||
|
"02\t" + // ll pipe status
|
||||||
|
"00000099\t" + // LCD volume
|
||||||
|
"01\t"; // ASIC state1
|
||||||
|
|
||||||
|
|
||||||
|
string line = WithChecksum(body);
|
||||||
|
|
||||||
|
var parser = new DiagnosticLedParser(DiagnosticLedState.State6);
|
||||||
|
var data = (DiagnosticLedState6Data)parser.ParseLine(line);
|
||||||
|
|
||||||
|
Assert.AreEqual((short)-20, data.WaterImpedance);
|
||||||
|
Assert.AreEqual((short)0x0010, data.ElectrodeDeltaMv);
|
||||||
|
Assert.AreEqual((byte)0x02, data.SpikeDetection);
|
||||||
|
Assert.AreEqual((byte)0x02, data.PipeStatus);
|
||||||
|
Assert.AreEqual((uint)0x99, data.LcdVolume);
|
||||||
|
Assert.AreEqual((byte)0x01, data.AsicState1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Parse_DiagnosticLed_State7()
|
||||||
|
{
|
||||||
|
string body =
|
||||||
|
"FFCC09\t2020\tFFFA\t0050FC\t0054\t0B01\t048000\tA7\t" +
|
||||||
|
"00001234\t00F0\t00F1\t0100\t0200\t03\tFFEC\t0010\t" +
|
||||||
|
"02\t" + // pp spike detection
|
||||||
|
"02\t" + // ll pipe status
|
||||||
|
"00000099\t" + // LCD volume
|
||||||
|
"01\t" + // ASIC state1
|
||||||
|
"FFAA10\t" + // raw ADC before offset
|
||||||
|
"000123\t" + // detrended ADC
|
||||||
|
"FFEE\t" + // imaginary water impedance
|
||||||
|
"0011\t" + // electrode voltage noise
|
||||||
|
"03\t"; // ADC offset learning status
|
||||||
|
|
||||||
|
string line = WithChecksum(body);
|
||||||
|
|
||||||
|
var parser = new DiagnosticLedParser(DiagnosticLedState.State7);
|
||||||
|
var data = (DiagnosticLedState7Data)parser.ParseLine(line);
|
||||||
|
|
||||||
|
Assert.AreEqual(-22000, data.RawAdcBeforeOffset);
|
||||||
|
Assert.AreEqual(0x000123, data.DetrendedAdc);
|
||||||
|
Assert.AreEqual((short)-18, data.ImaginaryWaterImpedance);
|
||||||
|
Assert.AreEqual((ushort)0x0011, data.ElectrodeVoltageNoise);
|
||||||
|
Assert.AreEqual((byte)0x03, data.AdcOffsetLearningStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+162
@@ -0,0 +1,162 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger;
|
||||||
|
|
||||||
|
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[TestSubject(typeof(HexFormatter))]
|
||||||
|
public class HexFormatterTest
|
||||||
|
{
|
||||||
|
|
||||||
|
// -----------------------------
|
||||||
|
// ToHex(byte)
|
||||||
|
// -----------------------------
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ToHex_FormatsSingleByte()
|
||||||
|
{
|
||||||
|
var result = HexFormatter.ToHex(0x0D);
|
||||||
|
Assert.AreEqual("0x0D", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------
|
||||||
|
// ToHex(byte[])
|
||||||
|
// -----------------------------
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ToHex_FormatsByteArray()
|
||||||
|
{
|
||||||
|
byte[] data = { 0x01, 0x0D, 0xFF };
|
||||||
|
var result = HexFormatter.ToHex(data);
|
||||||
|
|
||||||
|
Assert.AreEqual("0x01 0x0D 0xFF", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ToHex_EmptyArray_ReturnsEmptyMarker()
|
||||||
|
{
|
||||||
|
var result = HexFormatter.ToHex(Array.Empty<byte>());
|
||||||
|
Assert.AreEqual("<empty>", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ToHex_Null_ReturnsEmptyMarker()
|
||||||
|
{
|
||||||
|
var result = HexFormatter.ToHex(null);
|
||||||
|
Assert.AreEqual("<empty>", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------
|
||||||
|
// ToSerialHex(byte[])
|
||||||
|
// -----------------------------
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ToSerialHex_FormatsCorrectly()
|
||||||
|
{
|
||||||
|
byte[] data = { 0x0D, 0x04, 0x08, 0x01, 0x00, 0x1A };
|
||||||
|
var result = HexFormatter.ToSerialHex(data);
|
||||||
|
|
||||||
|
Assert.AreEqual("0D 04 08 01 00 1A", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ToSerialHex_Empty_ReturnsEmptyString()
|
||||||
|
{
|
||||||
|
var result = HexFormatter.ToSerialHex(Array.Empty<byte>());
|
||||||
|
Assert.AreEqual(string.Empty, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------
|
||||||
|
// ToHexWithAscii(byte)
|
||||||
|
// -----------------------------
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ToHexWithAscii_PrintableAscii()
|
||||||
|
{
|
||||||
|
var result = HexFormatter.ToHexWithAscii(0x41); // 'A'
|
||||||
|
Assert.AreEqual("0x41 ('A')", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ToHexWithAscii_ControlChar()
|
||||||
|
{
|
||||||
|
var result = HexFormatter.ToHexWithAscii(0x0D); // CR
|
||||||
|
Assert.AreEqual("0x0D ('.')", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------
|
||||||
|
// ToSerialHexWithAscii(byte[])
|
||||||
|
// -----------------------------
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ToSerialHexWithAscii_MixedData()
|
||||||
|
{
|
||||||
|
byte[] data = Encoding.ASCII.GetBytes("OK\r\n");
|
||||||
|
var result = HexFormatter.ToSerialHexWithAscii(data);
|
||||||
|
|
||||||
|
Assert.AreEqual("4F 4B 0D 0A | OK..", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------
|
||||||
|
// IntToBytesBE
|
||||||
|
// -----------------------------
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void IntToBytesBE_TwoBytes()
|
||||||
|
{
|
||||||
|
var result = HexFormatter.IntToBytesBE(0x1234, 2);
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(
|
||||||
|
new byte[] { 0x12, 0x34 },
|
||||||
|
result
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------
|
||||||
|
// IntToBytesLE
|
||||||
|
// -----------------------------
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void IntToBytesLE_TwoBytes()
|
||||||
|
{
|
||||||
|
var result = HexFormatter.IntToBytesLE(0x1234, 2);
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(
|
||||||
|
new byte[] { 0x34, 0x12 },
|
||||||
|
result
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------
|
||||||
|
// AsciiToBytes
|
||||||
|
// -----------------------------
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void AsciiToBytes_ConvertsString()
|
||||||
|
{
|
||||||
|
var result = HexFormatter.AsciiToBytes("AB");
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(
|
||||||
|
new byte[] { 0x41, 0x42 },
|
||||||
|
result
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void AsciiToBytes_EmptyString_ReturnsEmpty()
|
||||||
|
{
|
||||||
|
var result = HexFormatter.AsciiToBytes(string.Empty);
|
||||||
|
Assert.AreEqual(0, result.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void AsciiToBytes_Null_ReturnsEmpty()
|
||||||
|
{
|
||||||
|
var result = HexFormatter.AsciiToBytes(null);
|
||||||
|
Assert.AreEqual(0, result.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.led;
|
||||||
|
|
||||||
|
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.led
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[TestSubject(typeof(ShortVariableLedParser))]
|
||||||
|
public class ShortVariableLedParserTest
|
||||||
|
{
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Parse_ValidShortVariableMessage()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string raw = ";12345678,00012345.67;";
|
||||||
|
var message = new TouchReadLedMessage(raw);
|
||||||
|
var parser = new ShortVariableLedParser();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
TouchReadLedData data = parser.Parse(message);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsNotNull(data);
|
||||||
|
Assert.AreEqual(raw, data.Raw);
|
||||||
|
Assert.AreEqual("12345678", data.MeterId);
|
||||||
|
Assert.AreEqual(12345.67m, data.Reading);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
[ExpectedException(typeof(FormatException))]
|
||||||
|
public void Parse_InvalidDecimal_Throws()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string raw = ";12345678,ABCDEF;";
|
||||||
|
var message = new TouchReadLedMessage(raw);
|
||||||
|
var parser = new ShortVariableLedParser();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
parser.Parse(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
using JetBrains.Annotations;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.led;
|
||||||
|
|
||||||
|
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.led
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[TestSubject(typeof(TouchReadLedMessage))]
|
||||||
|
public class TouchReadLedMessageTest
|
||||||
|
{
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Parse_LedMessage_Basic()
|
||||||
|
{
|
||||||
|
string raw = ";12345678,00012345.67;";
|
||||||
|
|
||||||
|
var msg = new TouchReadLedMessage(raw);
|
||||||
|
|
||||||
|
Assert.AreEqual(2, msg.Fields.Length);
|
||||||
|
Assert.AreEqual("12345678", msg.Fields[0]);
|
||||||
|
Assert.AreEqual("00012345.67", msg.Fields[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TouchReadLedData_Parse_Extended()
|
||||||
|
{
|
||||||
|
string raw = ";12345678,ABC123,00012345.67,m3;";
|
||||||
|
|
||||||
|
var msg = new TouchReadLedMessage(raw);
|
||||||
|
|
||||||
|
var data = new TouchReadLedData(raw)
|
||||||
|
{
|
||||||
|
MeterId = msg.Fields[0],
|
||||||
|
CustomerId = msg.Fields[1],
|
||||||
|
Reading = TouchReadLedData.ParseDecimal(msg.Fields[2]),
|
||||||
|
Units = msg.Fields[3]
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.AreEqual("12345678", data.MeterId);
|
||||||
|
Assert.AreEqual("ABC123", data.CustomerId);
|
||||||
|
Assert.AreEqual(12345.67m, data.Reading);
|
||||||
|
Assert.AreEqual("m3", data.Units);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+123
@@ -0,0 +1,123 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO.Ports;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.protocolCommons;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol;
|
||||||
|
|
||||||
|
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class TouchReadBaudRateDetectionTests
|
||||||
|
{
|
||||||
|
private const string ComPort = "COM3"; // COM PORT OF THE ASIC
|
||||||
|
private const int ReadTimeoutMs = 1500;
|
||||||
|
|
||||||
|
private static readonly int[] StandardBaudRates =
|
||||||
|
{
|
||||||
|
115200, 9600//, 10400, 15625, 18432, 19200, 31250, 36864,
|
||||||
|
//38400, 50000, 57600, 62500, 76800,
|
||||||
|
//1200, 2400, 4800, 7812
|
||||||
|
};
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
[TestCategory("Hardware")]
|
||||||
|
[TestCategory("Serial")]
|
||||||
|
public void Detect_BaudRate_By_ViewFactoryId()
|
||||||
|
{
|
||||||
|
byte[] request = new TouchReadFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.Simple)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
var parser = new TouchReadFrameParser();
|
||||||
|
|
||||||
|
foreach (int baud in StandardBaudRates)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"--- Testing baud rate: {baud} ---");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var port = new SerialPort(ComPort, baud, Parity.None, 8, StopBits.One))
|
||||||
|
{
|
||||||
|
port.ReadTimeout = ReadTimeoutMs;
|
||||||
|
port.WriteTimeout = 500;
|
||||||
|
port.Open();
|
||||||
|
|
||||||
|
port.DiscardInBuffer();
|
||||||
|
port.DiscardOutBuffer();
|
||||||
|
|
||||||
|
Console.WriteLine("TX → " + HexFormatter.ToSerialHex(request));
|
||||||
|
port.Write(request, 0, request.Length);
|
||||||
|
|
||||||
|
byte[] response = ReadFullFrame(port);
|
||||||
|
|
||||||
|
Console.WriteLine("RX ← " + HexFormatter.ToSerialHex(response));
|
||||||
|
|
||||||
|
TouchReadResponse decoded = parser.Parse(response);
|
||||||
|
|
||||||
|
if (decoded.IsOk)
|
||||||
|
{
|
||||||
|
string factoryId = decoded.GetAsciiPayload();
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("VALID RESPONSE");
|
||||||
|
Console.WriteLine("Baud rate : " + baud);
|
||||||
|
Console.WriteLine("Factory ID : " + factoryId);
|
||||||
|
Console.WriteLine();
|
||||||
|
|
||||||
|
Assert.IsFalse(string.IsNullOrEmpty(factoryId),
|
||||||
|
"Factory ID is empty");
|
||||||
|
|
||||||
|
return; // SUCCESS → stop scanning
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (TimeoutException)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Timeout");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error: " + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Fail("No valid baud rate detected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ReadFullFrame(SerialPort port)
|
||||||
|
{
|
||||||
|
byte start = (byte)port.ReadByte();
|
||||||
|
if (start != 0x0D)
|
||||||
|
throw new InvalidOperationException("Invalid START byte");
|
||||||
|
|
||||||
|
byte length = (byte)port.ReadByte();
|
||||||
|
|
||||||
|
int remaining = length;
|
||||||
|
byte[] buffer = new byte[2 + remaining];
|
||||||
|
|
||||||
|
buffer[0] = start;
|
||||||
|
buffer[1] = length;
|
||||||
|
|
||||||
|
int offset = 2;
|
||||||
|
while (remaining > 0)
|
||||||
|
{
|
||||||
|
int read = port.Read(buffer, offset, remaining);
|
||||||
|
offset += read;
|
||||||
|
remaining -= read;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ConvertTest()
|
||||||
|
{
|
||||||
|
byte[] input = { 0x53, 0x57, 0x05, 0x01, 0x0D };
|
||||||
|
Console.WriteLine(HexFormatter.ToSerialHex(input));
|
||||||
|
Console.WriteLine(HexFormatter.ToHex(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+166
@@ -0,0 +1,166 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.protocolCommons;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol;
|
||||||
|
|
||||||
|
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[TestSubject(typeof(TouchReadFrameBuilder))]
|
||||||
|
public class TouchReadFrameBuilderTest
|
||||||
|
{
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Encode_ViewFactoryId_Command()
|
||||||
|
{
|
||||||
|
byte[] frame = new TouchReadFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.ViewFactoryId)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] expected =
|
||||||
|
{
|
||||||
|
0x0D, // START
|
||||||
|
0x04, // LEN
|
||||||
|
0x08, // CONTROL (RF)
|
||||||
|
0x01, // COMMAND
|
||||||
|
0x00, // CHECKSUM HI
|
||||||
|
0x1A // CHECKSUM LO
|
||||||
|
};
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, frame);
|
||||||
|
|
||||||
|
string log = TouchReadLogger.DescribeTx(frame);
|
||||||
|
Console.WriteLine(log);
|
||||||
|
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Encode_ViewProgrammableId_Command()
|
||||||
|
{
|
||||||
|
byte[] frame = new TouchReadFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.ViewProgrammableId)
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] expected =
|
||||||
|
{
|
||||||
|
0x0D, // START
|
||||||
|
0x04, // LEN
|
||||||
|
0x08, // CONTROL (RF)
|
||||||
|
0x03, // COMMAND
|
||||||
|
0x00, // CHECKSUM HI
|
||||||
|
0x1C // CHECKSUM LO
|
||||||
|
};
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, frame);
|
||||||
|
|
||||||
|
string log = TouchReadLogger.DescribeTx(frame);
|
||||||
|
Console.WriteLine(log);
|
||||||
|
Console.WriteLine(@"Raw: <{0}>", HexFormatter.ToSerialHex(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Encode_SetState_Idle()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
byte[] frame = new TouchReadFrameBuilder()
|
||||||
|
.RequestResponse(true)
|
||||||
|
.AddCommand(ProtocolCommand.SetState)
|
||||||
|
.AddPayload(new byte[] { 0x01 }) // Idle
|
||||||
|
.BuildBytes();
|
||||||
|
|
||||||
|
byte[] expected =
|
||||||
|
{
|
||||||
|
0x0D, // START
|
||||||
|
0x05, // LEN
|
||||||
|
0x08, // CONTROL (RF)
|
||||||
|
0x1A, // COMMAND (Set State)
|
||||||
|
0x01, // PAYLOAD (Idle)
|
||||||
|
0x00, // CHECKSUM HI
|
||||||
|
0x35 // CHECKSUM LO
|
||||||
|
};
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
CollectionAssert.AreEqual(expected, frame,
|
||||||
|
$"Encoded frame mismatch.\nExpected: {HexFormatter.ToSerialHex(expected)}\nActual: {HexFormatter.ToSerialHex(frame)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
[ExpectedException(typeof(FormatException))]
|
||||||
|
public void Decode_InvalidStart_Throws()
|
||||||
|
{
|
||||||
|
byte[] response =
|
||||||
|
{
|
||||||
|
0x00, // invalid START
|
||||||
|
0x04,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
0x12
|
||||||
|
};
|
||||||
|
|
||||||
|
var parser = new TouchReadFrameParser();
|
||||||
|
|
||||||
|
parser.Parse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void BuildBytes()
|
||||||
|
{
|
||||||
|
// Reserve space for checksum at [0] and [1]
|
||||||
|
var frame = new List<byte>
|
||||||
|
{
|
||||||
|
0x00, // checksum high (placeholder)
|
||||||
|
0x00, // checksum low (placeholder)
|
||||||
|
|
||||||
|
0x05, // length
|
||||||
|
0x01, // command
|
||||||
|
0x0D // start
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate checksum over payload only (skip checksum bytes)
|
||||||
|
ushort checksum = TouchReadFrameBuilder.CalculateChecksum(
|
||||||
|
frame.Skip(2)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Write checksum into first two positions
|
||||||
|
frame[0] = (byte)(checksum >> 8); // high byte
|
||||||
|
frame[1] = (byte)(checksum & 0xFF); // low byte
|
||||||
|
|
||||||
|
Console.WriteLine(HexFormatter.ToHex(frame.ToArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ByteConversion()
|
||||||
|
{
|
||||||
|
byte[] frame = { 0x53, 0x57,0x05, 0x01, 0x0D};
|
||||||
|
Console.WriteLine(@"1: " + HexFormatter.ToHex(frame.ToArray()));
|
||||||
|
|
||||||
|
byte[] payload = { 0x31, 0x30, 0x30, 0x31, 0x30, 0x34, 0x30, 0x35, 0x31, 0x00 };
|
||||||
|
Console.WriteLine(@"Payload: " + HexFormatter.ToSerialHexWithAscii(payload.ToArray()));
|
||||||
|
|
||||||
|
//Connect
|
||||||
|
//2026-02-04 14:06:22.515 TX (8) 53 57 3F 76 65 72 73 0D
|
||||||
|
//2026-02-04 14:06:22.906 RX (74) 3F 76 65 72 73 3A 20 48 61 72 72 79 20 54 3A 42 38 30 30 2C 20 56 3A 30 36 2E 30 36 2E 30 31 2C 20 46 57 3A 31 39 30 32 31 35 2C 20 37 45 43 45 2C 20 42 31 2E 36 2E 30 31 2C 20 48 57 3A 34 2C 20 53 65 72 69 61 6C 3A 30 0D
|
||||||
|
|
||||||
|
string msg = "53 57 3F 76 65 72 73 0D";
|
||||||
|
byte[] activationMsg = HexFormatter.HexStringToByteArray(msg);
|
||||||
|
Console.WriteLine(@"ActivationMsg MSG: " + HexFormatter.ToSerialHexWithAscii(activationMsg.ToArray()));
|
||||||
|
|
||||||
|
string str =
|
||||||
|
"3F 76 65 72 73 3A 20 48 61 72 72 79 20 54 3A 42 38 30 30 2C 20 56 3A 30 36 2E 30 36 2E 30 31 2C 20 46 57 3A 31 39 30 32 31 35 2C 20 37 45 43 45 2C 20 42 31 2E 36 2E 30 31 2C 20 48 57 3A 34 2C 20 53 65 72 69 61 6C 3A 30 0D";
|
||||||
|
byte[] activationMsgRes = HexFormatter.HexStringToByteArray(str);
|
||||||
|
Console.WriteLine(@"ActivationMsg RES: " + HexFormatter.ToSerialHexWithAscii(activationMsgRes.ToArray()));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using JetBrains.Annotations;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.communication;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.implementations;
|
||||||
|
|
||||||
|
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[TestSubject(typeof(OptoHeadTest))]
|
||||||
|
public class OptoHeadTestTest
|
||||||
|
{
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ReadRequest_PCB_Test()
|
||||||
|
{
|
||||||
|
OptoHeadTest optoHeadTest = new OptoHeadTest();
|
||||||
|
|
||||||
|
//TBF.Rig.Generic.IComponentCfg cfg = optoHeadTest.;
|
||||||
|
|
||||||
|
SmartReader iPerlAsicReader = new SmartReader();
|
||||||
|
|
||||||
|
OptoHeadTest.ReadRequest_PCB(iPerlAsicReader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
using JetBrains.Annotations;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using TBF.Rig.RegisterReaders.iPerlASICReader.implementations;
|
||||||
|
|
||||||
|
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.implementations
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[TestSubject(typeof(IPerlASICImplHeadTestCtrl))]
|
||||||
|
public class IPerlASICImplHeadTestCtrlTest
|
||||||
|
{
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CommandTestButtonClick_Operations_ReadPcbCmd()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -103,6 +103,17 @@
|
|||||||
<Compile Include="Rig\Network\Camera\KeyenceIV3G120\CameraTest.cs" />
|
<Compile Include="Rig\Network\Camera\KeyenceIV3G120\CameraTest.cs" />
|
||||||
<Compile Include="Rig\Network\Camera\RoiForFixedStartKeyence\RoiTest.cs" />
|
<Compile Include="Rig\Network\Camera\RoiForFixedStartKeyence\RoiTest.cs" />
|
||||||
<Compile Include="Rig\Output\FileWriters\Enhanced\WriterTest.cs" />
|
<Compile Include="Rig\Output\FileWriters\Enhanced\WriterTest.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\DiagnosticLedParserTest.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\hexLogger\HexFormatterTest.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\IperlHatProtocol\IperlHatFrameBuilderTests.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\IperlHatProtocol\IperlHatFrameParserTest.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\IperlHatProtocol\IperlHatIntegrationTests.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\led\ShortVariableLedParserTest.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\led\TouchReadLedMessageTest.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\wiredProtocol\TouchReadBaudRateDetectionTests.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\wiredProtocol\TouchReadFrameBuilderTest.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\OptoHeadTestTest.cs" />
|
||||||
|
<Compile Include="Rig\RegisterReaders\iPerlASICReader\implementations\IPerlASICImplHeadTestCtrlTest.cs" />
|
||||||
<Compile Include="Rig\RegisterReaders\PoseidonCmdStartStop\CliRunnerTest.cs" />
|
<Compile Include="Rig\RegisterReaders\PoseidonCmdStartStop\CliRunnerTest.cs" />
|
||||||
<Compile Include="Rig\RegisterReaders\PoseidonCmdStartStop\PoseidonReaderTest.cs" />
|
<Compile Include="Rig\RegisterReaders\PoseidonCmdStartStop\PoseidonReaderTest.cs" />
|
||||||
<Compile Include="Rig\RegisterReaders\PoseidonReader\UniHeadTestCtrlTest.cs" />
|
<Compile Include="Rig\RegisterReaders\PoseidonReader\UniHeadTestCtrlTest.cs" />
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
rmdir /s /q AppDiagnostic\bin
|
||||||
|
rmdir /s /q AppDiagnostic\obj
|
||||||
rmdir /s /q Common\bin
|
rmdir /s /q Common\bin
|
||||||
rmdir /s /q Common\obj
|
rmdir /s /q Common\obj
|
||||||
rmdir /s /q Config\bin
|
rmdir /s /q Config\bin
|
||||||
@@ -30,6 +32,10 @@ rmdir /s /q LabelPrinting\bin
|
|||||||
rmdir /s /q LabelPrinting\obj
|
rmdir /s /q LabelPrinting\obj
|
||||||
rmdir /s /q MergeResultsDBs\bin
|
rmdir /s /q MergeResultsDBs\bin
|
||||||
rmdir /s /q MergeResultsDBs\obj
|
rmdir /s /q MergeResultsDBs\obj
|
||||||
|
rmdir /s /q NfcC7_DLL\bin
|
||||||
|
rmdir /s /q NfcC7_DLL\obj
|
||||||
|
rmdir /s /q NfcC7_DLL.Tests\bin
|
||||||
|
rmdir /s /q NfcC7_DLL.Tests\obj
|
||||||
rmdir /s /q OrderManagement\bin\Debug
|
rmdir /s /q OrderManagement\bin\Debug
|
||||||
rmdir /s /q OrderManagement\bin\Release
|
rmdir /s /q OrderManagement\bin\Release
|
||||||
rmdir /s /q OrderManagement\bin\Logs
|
rmdir /s /q OrderManagement\bin\Logs
|
||||||
@@ -58,6 +64,8 @@ rmdir /s /q Statistics\bin
|
|||||||
rmdir /s /q Statistics\obj
|
rmdir /s /q Statistics\obj
|
||||||
rmdir /s /q TBF\bin
|
rmdir /s /q TBF\bin
|
||||||
rmdir /s /q TBF\obj
|
rmdir /s /q TBF\obj
|
||||||
|
rmdir /s /q TBFTests\bin
|
||||||
|
rmdir /s /q TBFTests\obj
|
||||||
rmdir /s /q ToFirstMonitor\bin
|
rmdir /s /q ToFirstMonitor\bin
|
||||||
rmdir /s /q ToFirstMonitor\obj
|
rmdir /s /q ToFirstMonitor\obj
|
||||||
rmdir /s /q ToSecondMonitor\bin
|
rmdir /s /q ToSecondMonitor\bin
|
||||||
|
|||||||
BIN
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,31 @@
|
|||||||
|
This Microsoft .NET Library may incorporate components from the projects listed
|
||||||
|
below. Microsoft licenses these components under the Microsoft .NET Library
|
||||||
|
software license terms. The original copyright notices and the licenses under
|
||||||
|
which Microsoft received such components are set forth below for informational
|
||||||
|
purposes only. Microsoft reserves all rights not expressly granted herein,
|
||||||
|
whether by implication, estoppel or otherwise.
|
||||||
|
|
||||||
|
1. .NET Core (https://github.com/dotnet/core/)
|
||||||
|
|
||||||
|
.NET Core
|
||||||
|
Copyright (c) .NET Foundation and Contributors
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
|
||||||
|
MICROSOFT SOFTWARE LICENSE TERMS
|
||||||
|
|
||||||
|
|
||||||
|
MICROSOFT .NET LIBRARY
|
||||||
|
|
||||||
|
These license terms are an agreement between Microsoft Corporation (or based on where you live, one of its affiliates) and you. Please read them. They apply to the software named above, which includes the media on which you received it, if any. The terms also apply to any Microsoft
|
||||||
|
|
||||||
|
· updates,
|
||||||
|
|
||||||
|
· supplements,
|
||||||
|
|
||||||
|
· Internet-based services, and
|
||||||
|
|
||||||
|
· support services
|
||||||
|
|
||||||
|
for this software, unless other terms accompany those items. If so, those terms apply.
|
||||||
|
|
||||||
|
BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. IF YOU DO NOT ACCEPT THEM, DO NOT USE THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE PERPETUAL RIGHTS BELOW.
|
||||||
|
|
||||||
|
1. INSTALLATION AND USE RIGHTS.
|
||||||
|
|
||||||
|
a. Installation and Use. You may install and use any number of copies of the software to design, develop and test your programs.
|
||||||
|
|
||||||
|
b. Third Party Programs. The software may include third party programs that Microsoft, not the third party, licenses to you under this agreement. Notices, if any, for the third party program are included for your information only.
|
||||||
|
|
||||||
|
2. ADDITIONAL LICENSING REQUIREMENTS AND/OR USE RIGHTS.
|
||||||
|
|
||||||
|
a. DISTRIBUTABLE CODE. The software is comprised of Distributable Code. “Distributable Code” is code that you are permitted to distribute in programs you develop if you comply with the terms below.
|
||||||
|
|
||||||
|
i. Right to Use and Distribute.
|
||||||
|
|
||||||
|
· You may copy and distribute the object code form of the software.
|
||||||
|
|
||||||
|
· Third Party Distribution. You may permit distributors of your programs to copy and distribute the Distributable Code as part of those programs.
|
||||||
|
|
||||||
|
ii. Distribution Requirements. For any Distributable Code you distribute, you must
|
||||||
|
|
||||||
|
· add significant primary functionality to it in your programs;
|
||||||
|
|
||||||
|
· require distributors and external end users to agree to terms that protect it at least as much as this agreement;
|
||||||
|
|
||||||
|
· display your valid copyright notice on your programs; and
|
||||||
|
|
||||||
|
· indemnify, defend, and hold harmless Microsoft from any claims, including attorneys’ fees, related to the distribution or use of your programs.
|
||||||
|
|
||||||
|
iii. Distribution Restrictions. You may not
|
||||||
|
|
||||||
|
· alter any copyright, trademark or patent notice in the Distributable Code;
|
||||||
|
|
||||||
|
· use Microsoft’s trademarks in your programs’ names or in a way that suggests your programs come from or are endorsed by Microsoft;
|
||||||
|
|
||||||
|
· include Distributable Code in malicious, deceptive or unlawful programs; or
|
||||||
|
|
||||||
|
· modify or distribute the source code of any Distributable Code so that any part of it becomes subject to an Excluded License. An Excluded License is one that requires, as a condition of use, modification or distribution, that
|
||||||
|
|
||||||
|
· the code be disclosed or distributed in source code form; or
|
||||||
|
|
||||||
|
· others have the right to modify it.
|
||||||
|
|
||||||
|
3. SCOPE OF LICENSE. The software is licensed, not sold. This agreement only gives you some rights to use the software. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the software that only allow you to use it in certain ways. You may not
|
||||||
|
|
||||||
|
· work around any technical limitations in the software;
|
||||||
|
|
||||||
|
· reverse engineer, decompile or disassemble the software, except and only to the extent that applicable law expressly permits, despite this limitation;
|
||||||
|
|
||||||
|
· publish the software for others to copy;
|
||||||
|
|
||||||
|
· rent, lease or lend the software;
|
||||||
|
|
||||||
|
· transfer the software or this agreement to any third party; or
|
||||||
|
|
||||||
|
· use the software for commercial software hosting services.
|
||||||
|
|
||||||
|
4. BACKUP COPY. You may make one backup copy of the software. You may use it only to reinstall the software.
|
||||||
|
|
||||||
|
5. DOCUMENTATION. Any person that has valid access to your computer or internal network may copy and use the documentation for your internal, reference purposes.
|
||||||
|
|
||||||
|
6. EXPORT RESTRICTIONS. The software is subject to United States export laws and regulations. You must comply with all domestic and international export laws and regulations that apply to the software. These laws include restrictions on destinations, end users and end use. For additional information, see www.microsoft.com/exporting.
|
||||||
|
|
||||||
|
7. SUPPORT SERVICES. Because this software is “as is,” we may not provide support services for it.
|
||||||
|
|
||||||
|
8. ENTIRE AGREEMENT. This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the software and support services.
|
||||||
|
|
||||||
|
9. APPLICABLE LAW.
|
||||||
|
|
||||||
|
a. United States. If you acquired the software in the United States, Washington state law governs the interpretation of this agreement and applies to claims for breach of it, regardless of conflict of laws principles. The laws of the state where you live govern all other claims, including claims under state consumer protection laws, unfair competition laws, and in tort.
|
||||||
|
|
||||||
|
b. Outside the United States. If you acquired the software in any other country, the laws of that country apply.
|
||||||
|
|
||||||
|
10. LEGAL EFFECT. This agreement describes certain legal rights. You may have other rights under the laws of your country. You may also have rights with respect to the party from whom you acquired the software. This agreement does not change your rights under the laws of your country if the laws of your country do not permit it to do so.
|
||||||
|
|
||||||
|
11. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS-IS.” YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR CONDITIONS. YOU MAY HAVE ADDITIONAL CONSUMER RIGHTS OR STATUTORY GUARANTEES UNDER YOUR LOCAL LAWS WHICH THIS AGREEMENT CANNOT CHANGE. TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||||
|
|
||||||
|
FOR AUSTRALIA – YOU HAVE STATUTORY GUARANTEES UNDER THE AUSTRALIAN CONSUMER LAW AND NOTHING IN THESE TERMS IS INTENDED TO AFFECT THOSE RIGHTS.
|
||||||
|
|
||||||
|
12. LIMITATION ON AND EXCLUSION OF REMEDIES AND DAMAGES. YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.
|
||||||
|
|
||||||
|
This limitation applies to
|
||||||
|
|
||||||
|
· anything related to the software, services, content (including code) on third party Internet sites, or third party programs; and
|
||||||
|
|
||||||
|
· claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law.
|
||||||
|
|
||||||
|
It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or other damages.
|
||||||
|
|
||||||
|
Please note: As this software is distributed in Quebec, Canada, some of the clauses in this agreement are provided below in French.
|
||||||
|
|
||||||
|
Remarque : Ce logiciel étant distribué au Québec, Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en français.
|
||||||
|
|
||||||
|
EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel ». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualité marchande, d’adéquation à un usage particulier et d’absence de contrefaçon sont exclues.
|
||||||
|
|
||||||
|
LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et pertes de bénéfices.
|
||||||
|
|
||||||
|
Cette limitation concerne :
|
||||||
|
|
||||||
|
· tout ce qui est relié au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ; et
|
||||||
|
|
||||||
|
· les réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, de négligence ou d’une autre faute dans la limite autorisée par la loi en vigueur.
|
||||||
|
|
||||||
|
Elle s’applique également, même si Microsoft connaissait ou devrait connaître l’éventualité d’un tel dommage. Si votre pays n’autorise pas l’exclusion ou la limitation de responsabilité pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l’exclusion ci-dessus ne s’appliquera pas à votre égard.
|
||||||
|
|
||||||
|
EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous pourriez avoir d’autres droits prévus par les lois de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent les lois de votre pays si celles-ci ne le permettent pas.
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user