Add GetDescription utility and enhance PoseidonCmdStartStop with refined serial port configuration, new macros, and improved test coverage. Clean up old dependencies and update warning levels. Bump AssemblyVersion to 3.9.2201.1.

This commit is contained in:
Michal Buzik 2026-06-26 10:33:41 +02:00
parent 2b9a207342
commit 5ea88265b9
16 changed files with 747 additions and 121 deletions

View File

@ -6,6 +6,10 @@
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<WarningLevel>0</WarningLevel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />

45
TBF.sln
View File

@ -106,13 +106,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LabelPrinting", "LabelPrint
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TBFTests", "TBFTests\TBFTests.csproj", "{77EB589F-C670-4489-AAD6-2A3C02061FD1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppDiagnostic", "AppDiagnostic\AppDiagnostic.csproj", "{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}"
ProjectSection(ProjectDependencies) = postProject
{8F942729-F454-4C99-BA6C-746962065AE3} = {8F942729-F454-4C99-BA6C-746962065AE3}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedComponents", "SharedComponents\SharedComponents.csproj", "{8F942729-F454-4C99-BA6C-746962065AE3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sensus.iPerl.RfidCom", "..\iPerlHead\Sensus.iPerl.RfidCom\Sensus.iPerl.RfidCom.csproj", "{A3E14180-7F00-42E5-94A9-8DB62EAD6EE8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sensus.iPerl.TestConsole", "..\iPerlHead\Sensus.iPerl.TestConsole\Sensus.iPerl.TestConsole.csproj", "{5025ED8B-A94F-4E58-8BE0-68481B061609}"
@ -121,8 +114,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NfcS5_DLL", "..\NfcS5_DLL\N
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NfcC7_DLL", "NfcC7_DLL\NfcC7_DLL.csproj", "{53E75979-B530-4805-8FC9-B314F14A62BE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NfcC7_DLL.Tests", "NfcC7_DLL.Tests\NfcC7_DLL.Tests.csproj", "{715605C5-568B-48D6-9C09-2DC5F2E81F66}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -483,30 +474,6 @@ Global
{77EB589F-C670-4489-AAD6-2A3C02061FD1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{77EB589F-C670-4489-AAD6-2A3C02061FD1}.Release|x86.ActiveCfg = Release|Any CPU
{77EB589F-C670-4489-AAD6-2A3C02061FD1}.Release|x86.Build.0 = Release|Any CPU
{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|x86.ActiveCfg = Debug|Any CPU
{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Debug|x86.Build.0 = Debug|Any CPU
{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|Any CPU.Build.0 = Release|Any CPU
{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|x86.ActiveCfg = Release|Any CPU
{FA9ABAD1-7184-4295-ADE8-D44F2E3DE6B2}.Release|x86.Build.0 = Release|Any CPU
{8F942729-F454-4C99-BA6C-746962065AE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8F942729-F454-4C99-BA6C-746962065AE3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8F942729-F454-4C99-BA6C-746962065AE3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{8F942729-F454-4C99-BA6C-746962065AE3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{8F942729-F454-4C99-BA6C-746962065AE3}.Debug|x86.ActiveCfg = Debug|Any CPU
{8F942729-F454-4C99-BA6C-746962065AE3}.Debug|x86.Build.0 = Debug|Any CPU
{8F942729-F454-4C99-BA6C-746962065AE3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8F942729-F454-4C99-BA6C-746962065AE3}.Release|Any CPU.Build.0 = Release|Any CPU
{8F942729-F454-4C99-BA6C-746962065AE3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{8F942729-F454-4C99-BA6C-746962065AE3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{8F942729-F454-4C99-BA6C-746962065AE3}.Release|x86.ActiveCfg = Release|Any CPU
{8F942729-F454-4C99-BA6C-746962065AE3}.Release|x86.Build.0 = Release|Any CPU
{A3E14180-7F00-42E5-94A9-8DB62EAD6EE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A3E14180-7F00-42E5-94A9-8DB62EAD6EE8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A3E14180-7F00-42E5-94A9-8DB62EAD6EE8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -555,18 +522,6 @@ Global
{53E75979-B530-4805-8FC9-B314F14A62BE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{53E75979-B530-4805-8FC9-B314F14A62BE}.Release|x86.ActiveCfg = Release|Any CPU
{53E75979-B530-4805-8FC9-B314F14A62BE}.Release|x86.Build.0 = Release|Any CPU
{715605C5-568B-48D6-9C09-2DC5F2E81F66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{715605C5-568B-48D6-9C09-2DC5F2E81F66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{715605C5-568B-48D6-9C09-2DC5F2E81F66}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{715605C5-568B-48D6-9C09-2DC5F2E81F66}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{715605C5-568B-48D6-9C09-2DC5F2E81F66}.Debug|x86.ActiveCfg = Debug|Any CPU
{715605C5-568B-48D6-9C09-2DC5F2E81F66}.Debug|x86.Build.0 = Debug|Any CPU
{715605C5-568B-48D6-9C09-2DC5F2E81F66}.Release|Any CPU.ActiveCfg = Release|Any CPU
{715605C5-568B-48D6-9C09-2DC5F2E81F66}.Release|Any CPU.Build.0 = Release|Any CPU
{715605C5-568B-48D6-9C09-2DC5F2E81F66}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{715605C5-568B-48D6-9C09-2DC5F2E81F66}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{715605C5-568B-48D6-9C09-2DC5F2E81F66}.Release|x86.ActiveCfg = Release|Any CPU
{715605C5-568B-48D6-9C09-2DC5F2E81F66}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
[assembly: AssemblyVersion("3.9.2200.1")]
[assembly: AssemblyFileVersion("3.9.2200.1")]
[assembly: AssemblyVersion("3.9.2201.1")]
[assembly: AssemblyFileVersion("3.9.2201.1")]

View File

@ -17,8 +17,7 @@ using TBF.Boxes;
using TBF.Rig.GenericDevices;
using TBF.Rig.Sequences;
using TBF.UiBridge;
using AppDiagnostic;
using SharedComponents;
namespace TBF.Rig.ControlBoard.Uni
{

View File

@ -0,0 +1,27 @@
using System;
using System.ComponentModel;
using System.Reflection;
namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
{
public static class GetDescription
{
public static string ToDescription(this Enum en)
{
Type type = en.GetType();
MemberInfo[] memInfo = type.GetMember(en.ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(
typeof(DescriptionAttribute),
false);
if (attrs != null && attrs.Length > 0)
return ((DescriptionAttribute)attrs[0]).Description;
}
return en.ToString();
}
}
}

View File

@ -1,22 +1,53 @@
namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
{
public class JsonDataFromPoseidon
{
public bool? NfcTagDetected { get; set; }
public int? ProductType { get; set; }
public string ProductTypeVersion { get; set; }
public bool NfcTagDetected { get; set; }
public bool ReadingComplete { get; set; }
public string DeviceId { get; set; }
public string ProductType { get; set; }
public string ProductTypeVersion { get; set; }
public string CliVersion { get; set; }
public string Reading { get; set; }
public string Reading_Totalizer { get; set; }
public string Reading_Digits { get; set; }
public string Reading_Shift { get; set; }
public string Reading_Resolution { get; set; }
public object Reading_Totalizer { get; set; }
public object Reading_FlowRate { get; set; }
public object Reading_FlowDirection { get; set; }
public object Reading_Digits { get; set; }
public object Reading_Shift { get; set; }
public object Reading_Resolution { get; set; }
public string Reading_Units { get; set; }
public string Reading_FlowDirection { get; set; }
public string Reading_FlowRate { get; set; }
public string MeterState { get; set; }
public string CalibrationFactor { get; set; }
public bool? ReadingComplete { get; set; }
public string OpticalDataMode { get; set; }
public string BuildInformation { get; set; }
public string ManufactureDate { get; set; }
public string MeterSize { get; set; }
public string FactoryId { get; set; }
public string CustomerText { get; set; }
public string TestTotalizer { get; set; }
public string FlowUnits { get; set; }
public string ReadingUnits { get; set; }
public string SpreadSpectrumParameters { get; set; }
public string SpreadSpect_DisableSpreadSpectrum { get; set; }
public string SpreadSpect_AlwaysUseFullRateBags { get; set; }
public string SpreadSpect_PowerUp { get; set; }
public string SpreadSpect_HighNoise { get; set; }
public string SpreadSpect_EmptyPipe { get; set; }
public string SpreadSpect_BadAdc { get; set; }
public string SpreadSpect_InitLearningCompleteCount { get; set; }
public string SpreadSpect_MinOffsetLearningSampleCount { get; set; }
public string SpreadSpect_AdcShiftUpdateInterval { get; set; }
public string SpreadSpect_MaxPreviousAdcAge { get; set; }
public string SpreadSpect_AdcOffsetLearningGuard { get; set; }
public string SpreadSpect_DisplacementCorrectionCount { get; set; }
}
}

View File

@ -3,10 +3,12 @@
///
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.ComponentModel;
using System.Xml.Serialization;
using Common;
using TBF.Rig.Generic;
using System.Linq;
using System.Reflection;
using Common;
namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
{
@ -22,7 +24,22 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
///
public int ComPortNr;
public string CliFileName;
public int MeterType;
[XmlIgnore]
public SerialPortData.MeterProduct MeterType = SerialPortData.MeterProduct.Poseidon;
[XmlElement("MeterProduct")]
public string MeterProductXml
{
get { return SerialPortData.MeterToString(MeterType); }
set { MeterType = SerialPortData.StringToMeter(value); }
}
public SerialPortData.HatType HatType = SerialPortData.HatType.Mth;
public int TimeOut = 30;
public string MainMacro = SerialPortData.MacroTypes.readall.ToDescription();
/// <summary> Procedure parameters </summary>
@ -31,14 +48,68 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
public override IParamsProvider GetRuntimeProcParamsProvider() { return ProcParams; }
public override IParamsProvider CreateProcParamsProvider() { return new PoseidonProcParams(true); }
public static bool TryParseMeter(
string description,
out SerialPortData.MeterProduct meter)
{
var found = Enum.GetValues(typeof(SerialPortData.MeterProduct))
.Cast<SerialPortData.MeterProduct>()
.FirstOrDefault(e =>
string.Equals(
e.GetType()
.GetField(e.ToString())
.GetCustomAttribute<DescriptionAttribute>()
?.Description,
description,
StringComparison.OrdinalIgnoreCase));
if (!Equals(found, default(SerialPortData.MeterProduct)) ||
string.Equals(description, "Poseidon", StringComparison.OrdinalIgnoreCase))
{
meter = found;
return true;
}
meter = default;
return false;
}
public static bool TryParseMacro(
string description,
out string macro)
{
var found = Enum.GetValues(typeof(SerialPortData.MacroTypes))
.Cast<SerialPortData.MacroTypes>()
.FirstOrDefault(e =>
string.Equals(
e.GetType()
.GetField(e.ToString())
.GetCustomAttribute<DescriptionAttribute>()
?.Description,
description,
StringComparison.OrdinalIgnoreCase));
if (!Equals(found, default(SerialPortData.MacroTypes)) ||
string.Equals(description, "readall", StringComparison.OrdinalIgnoreCase))
{
macro = found.ToDescription();
return true;
}
macro = default;
return false;
}
string[] paramNames = new string[]
{
"Serial port number", /// 0
"CLI program name", /// 1
"Meter Type", /// 2
"Hat Type", /// 3
"TimeOut [s]", /// 4
"Main Macro" /// 5
};
public string ParamName(int i) { return paramNames[i]; }
public int ParamsCount() { return paramNames.Length; }
@ -51,8 +122,27 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
case 1:
return new string[] { "HatCLI.exe"};
case 2:
return new string[] { "74" };
return new string[] {
SerialPortData.MeterProduct.Poseidon.ToDescription() ,
SerialPortData.MeterProduct.Ally.ToDescription(),
SerialPortData.MeterProduct.IperlPlus.ToDescription(),
SerialPortData.MeterProduct.IperlLegacy.ToDescription()
};
case 3:
return new string[]
{
SerialPortData.HatType.Mth.ToDescription(),
SerialPortData.HatType.Harry.ToDescription()
};
case 4:
return new string[] { "30", "60", "90"};
case 5:
string macro0 = SerialPortData.MacroTypes.readall.ToDescription();
string macro1 = SerialPortData.MacroTypes.macro1.ToDescription();
string macro2 = SerialPortData.MacroTypes.macro2.ToDescription();
string macro3 = SerialPortData.MacroTypes.macro3.ToDescription();
return new string[] { macro0, macro1, macro2, macro3 };
default:
return null;
}
@ -60,12 +150,15 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new Configs.ParamsProvider.ComponentCfgCtrl(this, null); }
public void InitializeAll()
{
ComPortNr = 3;
CliFileName = "HatCLI.exe";
MeterType = 74;
CliFileName = "HatCLI.exe";
MeterType = SerialPortData.MeterProduct.Poseidon;
HatType = SerialPortData.HatType.Mth;
TimeOut = 30;
MainMacro = SerialPortData.MacroTypes.readall.ToDescription();
}
public bool ValidateParam(int i, string strValue, out string message)
@ -83,8 +176,17 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
if(System.Text.RegularExpressions.Regex.IsMatch(strValue, @"^[a-zA-Z0-9_-]+\.exe$")) return true; //validate exe file name
break;
case 2:
if (TryParseMeter(strValue, out var meter)) return true;
break;
case 3:
if (TryParseHatType(strValue, out var hatType)) return true;
break;
case 4:
if (int.TryParse(strValue, out idummy) && idummy > 0) return true;
break;
case 5:
if (TryParseMacro(strValue, out string macroType)) return true;
break;
default:
message = "Invalid index";
return false;
@ -100,11 +202,38 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
{
case 0: ComPortNr = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 1: CliFileName = str; return CfgUpdateFlags.RestartRqrd;
case 2: MeterType = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 2: TryParseMeter(str, out MeterType); return CfgUpdateFlags.RestartRqrd;
case 3: TryParseHatType(str, out HatType); return CfgUpdateFlags.RestartRqrd;
case 4: TimeOut = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 5: MainMacro = str; return CfgUpdateFlags.RestartRqrd;
default: return CfgUpdateFlags.None;
}
}
public static bool TryParseHatType(string description, out SerialPortData.HatType hatType)
{
var found = Enum.GetValues(typeof(SerialPortData.HatType))
.Cast<SerialPortData.HatType>()
.FirstOrDefault(e =>
string.Equals(
e.GetType()
.GetField(e.ToString())
.GetCustomAttribute<DescriptionAttribute>()
?.Description,
description,
StringComparison.OrdinalIgnoreCase));
if (!Equals(found, default(SerialPortData.HatType)) ||
string.Equals(description, "Mth", StringComparison.OrdinalIgnoreCase))
{
hatType = found;
return true;
}
hatType = default;
return false;
}
public bool UpdateEmbeddedDbEntity()
{
return true; /// =OK, do nothing
@ -139,9 +268,12 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
case 0: return ComPortNr.ToString();
case 1: return CliFileName;
case 2: return MeterType.ToString();
case 3: return HatType.ToString();
case 4: return TimeOut.ToString();
case 5: return MainMacro;
default:
return string.Format("{0}: Com{1}, CliName =`{2}`, MeterType = {3}",
Name, ComPortNr, CliFileName, MeterType);
return string.Format("{0}: Com{1}, CliName =`{2}`, MeterType = {3}, HatType = {4}, TimeOut = {5}",
Name, ComPortNr, CliFileName, MeterType, HatType, TimeOut);
}
}
@ -150,6 +282,9 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
prms.ComPortNr = this.ComPortNr;
prms.CliFileName = this.CliFileName;
prms.MeterType = this.MeterType;
prms.HatType = this.HatType;
prms.TimeOut = this.TimeOut;
prms.MainMacro = this.MainMacro;
prms.ProcParams = this.ProcParams;
}
}

View File

@ -282,7 +282,11 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
/// Prepare serial port
serialPort = new SerialPortData(string.Format("COM{0}", registerReaderCfg.ComPortNr),
registerReaderCfg.CliFileName,
registerReaderCfg.MeterType);
registerReaderCfg.MeterType, //registerReaderCfg.MeterType, //MeterProduct.Poseidon
registerReaderCfg.HatType,//HatType.Mth
registerReaderCfg.TimeOut, //timeoutSeconds
registerReaderCfg.MainMacro
);
//TODO BUMI prepare serial port - for us do nothing

View File

@ -1,5 +1,8 @@
using System;
using System.IO;
using System.ComponentModel;
using System.Reflection;
using System.Xml.Serialization;
namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
{
@ -22,30 +25,228 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
}
public string CmdClientName { get; set; } = "HalCli.exe";
public string PortName { get; set; }
public int MeterType { get; set; }
// Backward compatibility: old numeric meter type
public int? OldMeterType { get; set; }
public enum EMeterArg {
// New v2.0 parameters
public HatType Hat { get; set; } = HatType.Mth;
public int TimeoutSeconds { get; set; } = 10;
public string Macro { get; set; } = "readall";
[XmlIgnore]
public MeterProduct Meter { get; set; } = MeterProduct.Poseidon;
[XmlElement("MeterProduct")]
public string MeterXml
{
get { return MeterToString(Meter); }
set { Meter = StringToMeter(value); }
}
public static string MeterToString(MeterProduct meter)
{
switch (meter)
{
case MeterProduct.Poseidon:
return "Poseidon";
case MeterProduct.Ally:
return "ally";
case MeterProduct.IperlPlus:
return "iperlplus";
case MeterProduct.IperlLegacy:
return "iperllegacy";
default:
return "Poseidon";
}
}
public static MeterProduct StringToMeter(string value)
{
if (string.IsNullOrWhiteSpace(value))
return MeterProduct.Poseidon;
// old numeric values: 74, 7889, etc.
if (int.TryParse(value, out _))
return MeterProduct.Poseidon;
if (string.Equals(value, "cTouchRead", StringComparison.OrdinalIgnoreCase))
return MeterProduct.Poseidon;
if (string.Equals(value, "Poseidon", StringComparison.OrdinalIgnoreCase))
return MeterProduct.Poseidon;
if (string.Equals(value, "ally", StringComparison.OrdinalIgnoreCase))
return MeterProduct.Ally;
if (string.Equals(value, "iperlplus", StringComparison.OrdinalIgnoreCase))
return MeterProduct.IperlPlus;
if (string.Equals(value, "iperllegacy", StringComparison.OrdinalIgnoreCase))
return MeterProduct.IperlLegacy;
return MeterProduct.Poseidon;
}
public static bool TryParseMeter(
string description,
out SerialPortData.MeterProduct meter)
{
foreach (SerialPortData.MeterProduct value in
Enum.GetValues(typeof(SerialPortData.MeterProduct)))
{
var attr = value.GetType()
.GetField(value.ToString())
.GetCustomAttribute<DescriptionAttribute>();
if (string.Equals(attr?.Description, description, StringComparison.OrdinalIgnoreCase) ||
string.Equals(value.ToString(), description, StringComparison.OrdinalIgnoreCase))
{
meter = value;
return true;
}
}
meter = SerialPortData.MeterProduct.Poseidon;
return false;
}
public enum MacroTypes
{
[Description("readall")]
readall = 0,
[Description("readmacro1")]
macro1 = 1,
[Description("readmacro2")]
macro2 = 2,
[Description("readmacro3")]
macro3 = 3
}
public enum HatType
{
[Description("Mth")]
Mth = 0,
[Description("Harry")]
Harry = 1
}
public enum MeterProduct
{
[Description("Poseidon")]
[XmlEnum("74")]
Poseidon = 74,
[Description("ally")]
[XmlEnum("ally")]
Ally = 75,
[Description("iperlplus")]
[XmlEnum("iperlplus")]
IperlPlus = 76,
[Description("iperllegacy")]
[XmlEnum("iperllegacy")]
IperlLegacy = 77
}
public enum EMeterArg
{
Calibration = 0,
AllParams = 2,
DeviceId = 3,
}
EMeterArg _eMeterArg = EMeterArg.AllParams;
// New macro operations - just waste
ReadMacro1 = 10,
ReadMacro2 = 11,
ReadMacro3 = 12
}
public string DefaultArgSettings(EMeterArg eMeterArg)
public string DefaultArgSettings(EMeterArg eMeterArg)
{
string commonArgs = BuildCommonArgs();
switch (eMeterArg)
{
case EMeterArg.Calibration:
return $"-p {PortName} -m {MeterType} --operation write --parameter Calibration --value 1";
case EMeterArg.AllParams:
return $"-p {PortName} -m {MeterType} --operation readall";
return $"{commonArgs} --operation write --parameter Calibration --value 1";
case EMeterArg.DeviceId:
return $"-p {PortName} -m {MeterType} --operation read --parameter DeviceId";
return $"{commonArgs} --operation read --parameter DeviceId";
case EMeterArg.AllParams:
case EMeterArg.ReadMacro1:
case EMeterArg.ReadMacro2:
case EMeterArg.ReadMacro3:
return $"{commonArgs} --operation {Macro}";
default:
return "";
}
}
private string BuildCommonArgs()
{
return $"-p {PortName} " +
$"-m {GetMeterArgument()} " +
$"--hat {GetHatArgument()} " +
$"--timeout {TimeoutSeconds}";
}
private string GetMeterArgument()
{
// Old compatibility mode
if (OldMeterType.HasValue)
return OldMeterType.Value.ToString();
switch (Meter)
{
case MeterProduct.Poseidon:
return "Poseidon";
case MeterProduct.Ally:
return "ally";
case MeterProduct.IperlPlus:
return "iperlplus";
case MeterProduct.IperlLegacy:
return "iperllegacy";
default:
return "Poseidon";
}
}
private string GetHatArgument()
{
switch (Hat)
{
case HatType.Harry:
return "harry";
case HatType.Mth:
default:
return "mth";
}
}
// New constructor for v2.0
public SerialPortData(
string portName,
string cmdClientName,
MeterProduct meter = MeterProduct.Poseidon,
HatType hat = HatType.Mth,
int timeoutSeconds = 10,
string macro = "readall")
{
PortName = portName;
CmdClientName = cmdClientName;
Meter = meter;
Hat = hat;
TimeoutSeconds = timeoutSeconds;
Macro = macro;
}
// Old constructor kept for backward compatibility
public SerialPortData(
string portName,
string cmdClientName,
@ -53,7 +254,9 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
{
PortName = portName;
CmdClientName = cmdClientName;
MeterType = meterType;
OldMeterType = meterType;
}
}
}

View File

@ -18,7 +18,6 @@ using TBF.Rig.Network.RestAPI;
using TBF.Rig.Network.RestAPI.facade;
using TBF.Rig.Output.Printers.GroupPrinting.Single;
using TBF.UiBridge;
using SharedComponents;
using System.Text;
using TBF.Rig.RegisterReaders.CommonRR.IPerl;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
@ -1548,7 +1547,7 @@ namespace TBF.Rig.Sequences
}
// ✍️ Uloženie do vlastného logu
LiveLogCache.Instance.AddLog(logBuilder.ToString());
//LiveLogCache.Instance.AddLog(logBuilder.ToString());
Bridge.OnError(this, "Chyba pri aktualizácii výsledkov v MySQL.");
goto error;

View File

@ -10,7 +10,7 @@ using SchematicDrawing;
using TBF.Rig.ControlBoard.Uni;
using TBF.Boxes;
using TBF.Resources;
using AppDiagnostic;
namespace TBF.Rig.Uni.FlowMeter
{

View File

@ -7,7 +7,6 @@ using log4net;
using SchematicDrawing;
using TBF.Rig.ControlBoard.Uni;
using TBF.Boxes;
using SharedComponents;
namespace TBF.Rig.Uni.RegValveLowRegulTimeSaturation
{

View File

@ -63,6 +63,7 @@
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;CAMERA;LANG_PL;IPERL;</DefineConstants>
<DebugType>full</DebugType>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
@ -74,6 +75,7 @@
<DefineConstants>TRACE;CAMERA;LANG_PL;IPERL;</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
@ -1324,6 +1326,7 @@
<Compile Include="Rig\RegisterReaders\PoseidonCmdStartStop\CliTaskInfo.cs" />
<Compile Include="Rig\RegisterReaders\PoseidonCmdStartStop\CliTaskState.cs" />
<Compile Include="Rig\RegisterReaders\PoseidonCmdStartStop\Factory.cs" />
<Compile Include="Rig\RegisterReaders\PoseidonCmdStartStop\GetDescription.cs" />
<Compile Include="Rig\RegisterReaders\PoseidonCmdStartStop\JsonDataFromPoseidon.cs" />
<Compile Include="Rig\RegisterReaders\PoseidonCmdStartStop\PoseidonCfg.cs" />
<Compile Include="Rig\RegisterReaders\PoseidonCmdStartStop\PoseidonProcParams.cs" />
@ -3970,10 +3973,6 @@
<Project>{5954d496-caab-4f7a-bde2-bdc8f47dab19}</Project>
<Name>NfcS5_DLL</Name>
</ProjectReference>
<ProjectReference Include="..\AppDiagnostic\AppDiagnostic.csproj">
<Project>{fa9abad1-7184-4295-ade8-d44f2e3de6b2}</Project>
<Name>AppDiagnostic</Name>
</ProjectReference>
<ProjectReference Include="..\Common\Common.csproj">
<Project>{c8939821-ba5c-4988-a3d0-bf53b74865c7}</Project>
<Name>Common</Name>
@ -4014,10 +4013,6 @@
<Project>{0f79ca69-9dbc-41f3-a6fc-5a2937365343}</Project>
<Name>SchematicDrawing</Name>
</ProjectReference>
<ProjectReference Include="..\SharedComponents\SharedComponents.csproj">
<Project>{8f942729-f454-4c99-ba6c-746962065ae3}</Project>
<Name>SharedComponents</Name>
</ProjectReference>
<ProjectReference Include="..\SharedDatabase\SharedDatabase.csproj">
<Project>{211b5e3f-9996-48a7-abde-c878dd2d71c2}</Project>
<Name>SharedDatabase</Name>
@ -4035,4 +4030,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

View File

@ -13,13 +13,9 @@ using Common;
using Config.Entities;
using Dirichlet.Numerics;
using SchematicDrawing;
using SharedDatabase;
using TBF.Resources;
using TBF.UiBridge;
using TBF.UI.Shared;
using AppDiagnostic;
using SharedComponents;
using System.Diagnostics;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
namespace TBF.UI
@ -1164,8 +1160,8 @@ namespace TBF.UI
ILog loger = LogManager.GetLogger("logCache");
log.Debug("ahoj, ideme");*/
LiveLogCache.Instance.AddLog("=== Live diagnostic entry ===");
DiagApi liveDiagApi = new DiagApi();
//LiveLogCache.Instance.AddLog("=== Live diagnostic entry ===");
//DiagApi liveDiagApi = new DiagApi();
/*try
{

View File

@ -17,6 +17,7 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
{
string allOutput = " {\n \"DeviceId\": \"1000000267\"\n}\n";
CliRunner cliRunner = new CliRunner(false);
string json = cliRunner.ExtractJson(allOutput);
Assert.IsFalse(string.IsNullOrEmpty(json));
@ -25,8 +26,10 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
[TestMethod]
public void ExtractJson_Test2()
{
string allOutput = "{\n \"NfcTagDetected\": true,\n \"ProductType\": 74,\n \"ProductTypeVersion\": \"B1.0.13\",\n \"DeviceId\": \"1000000267\",\n \"Reading\": \"0003292.1\",\n \"Reading_Totalizer\": \"000329218\",\n \"Reading_Digits\": \"8\",\n \"Reading_Shift\": \"-1\",\n \"Reading_Resolution\": \"-2\",\n \"Reading_Units\": \"2\",\n \"Reading_FlowDirection\": \"3\",\n \"Reading_FlowRate\": \"0\",\n \"CalibrationFactor\": \"3197\",\n \"ReadingComplete\": true,\n \"MeterState\": \"0x02\",\n \"OpticalDataMode\": \"0x00\",\n \"SpreadSpectrumParameters\": \"Disabled: 0xTrue\",\n \"BuildInformation\": \"\"\n}\n";
string allOutput =
"{\n \"NfcTagDetected\": true,\n \"ProductType\": 74,\n \"ProductTypeVersion\": \"B1.0.13\",\n \"DeviceId\": \"1000000267\",\n \"Reading\": \"0003292.1\",\n \"Reading_Totalizer\": \"000329218\",\n \"Reading_Digits\": \"8\",\n \"Reading_Shift\": \"-1\",\n \"Reading_Resolution\": \"-2\",\n \"Reading_Units\": \"2\",\n \"Reading_FlowDirection\": \"3\",\n \"Reading_FlowRate\": \"0\",\n \"CalibrationFactor\": \"3197\",\n \"ReadingComplete\": true,\n \"MeterState\": \"0x02\",\n \"OpticalDataMode\": \"0x00\",\n \"SpreadSpectrumParameters\": \"Disabled: 0xTrue\",\n \"BuildInformation\": \"\"\n}\n";
CliRunner cliRunner = new CliRunner(false);
string json = cliRunner.ExtractJson(allOutput);
Assert.IsFalse(string.IsNullOrEmpty(json));
@ -35,7 +38,8 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
[TestMethod]
public void TryJsonStringDeserialize_Test()
{
string allOutput = "{\n \"NfcTagDetected\": true,\n \"ProductType\": 74,\n \"ProductTypeVersion\": \"B1.0.13\",\n \"DeviceId\": \"1000000267\",\n \"Reading\": \"0003292.1\",\n \"Reading_Totalizer\": \"000329218\",\n \"Reading_Digits\": \"8\",\n \"Reading_Shift\": \"-1\",\n \"Reading_Resolution\": \"-2\",\n \"Reading_Units\": \"2\",\n \"Reading_FlowDirection\": \"3\",\n \"Reading_FlowRate\": \"0\",\n \"CalibrationFactor\": \"3197\",\n \"ReadingComplete\": true,\n \"MeterState\": \"0x02\",\n \"OpticalDataMode\": \"0x00\",\n \"SpreadSpectrumParameters\": \"Disabled: 0xTrue\",\n \"BuildInformation\": \"\"\n}\n";
string allOutput =
"{\n \"NfcTagDetected\": true,\n \"ProductType\": 74,\n \"ProductTypeVersion\": \"B1.0.13\",\n \"DeviceId\": \"1000000267\",\n \"Reading\": \"0003292.1\",\n \"Reading_Totalizer\": \"000329218\",\n \"Reading_Digits\": \"8\",\n \"Reading_Shift\": \"-1\",\n \"Reading_Resolution\": \"-2\",\n \"Reading_Units\": \"2\",\n \"Reading_FlowDirection\": \"3\",\n \"Reading_FlowRate\": \"0\",\n \"CalibrationFactor\": \"3197\",\n \"ReadingComplete\": true,\n \"MeterState\": \"0x02\",\n \"OpticalDataMode\": \"0x00\",\n \"SpreadSpectrumParameters\": \"Disabled: 0xTrue\",\n \"BuildInformation\": \"\"\n}\n";
CliRunner cliRunner = new CliRunner(false);
string json = cliRunner.ExtractJson(allOutput);
@ -48,13 +52,115 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
Assert.AreEqual("0003292.1", dto.Reading);
Assert.AreEqual("000329218", dto.Reading_Totalizer);
Assert.AreEqual(true, dto.NfcTagDetected);
Assert.AreEqual(74, dto.ProductType);
Assert.AreEqual("74", dto.ProductType);
}
[TestMethod]
public void SerialPortData_NewDefaults_ShouldUsePoseidonMthTimeout10()
{
SerialPortData serialPort = new SerialPortData(
"COM3",
"HalCli.exe",
SerialPortData.MeterProduct.Poseidon);
string args = serialPort.DefaultArgSettings(SerialPortData.EMeterArg.AllParams);
Assert.AreEqual(
"-p COM3 -m Poseidon --hat mth --timeout 10 --operation readall",
args);
}
[TestMethod]
public void SerialPortData_HarryHat_ShouldUseHarry()
{
SerialPortData serialPort = new SerialPortData(
"COM3",
"HalCli.exe",
SerialPortData.MeterProduct.Poseidon,
SerialPortData.HatType.Harry,
30);
string args = serialPort.DefaultArgSettings(SerialPortData.EMeterArg.DeviceId);
Assert.AreEqual(
"-p COM3 -m Poseidon --hat harry --timeout 30 --operation read --parameter DeviceId",
args);
}
[TestMethod]
public void SerialPortData_OldConstructor_ShouldKeepOldMeterType()
{
SerialPortData serialPort = new SerialPortData("COM3", "HalCli.exe", 74);
string args = serialPort.DefaultArgSettings(SerialPortData.EMeterArg.AllParams);
Assert.AreEqual(
"-p COM3 -m 74 --hat mth --timeout 10 --operation readall",
args);
}
[TestMethod]
public void SerialPortData_NewMeterTypes_ShouldGenerateCorrectMeterNames()
{
var testCases = new[]
{
new { Meter = SerialPortData.MeterProduct.Poseidon, Expected = "Poseidon" },
new { Meter = SerialPortData.MeterProduct.Ally, Expected = "ally" },
new { Meter = SerialPortData.MeterProduct.IperlPlus, Expected = "iperlplus" },
new { Meter = SerialPortData.MeterProduct.IperlLegacy, Expected = "iperllegacy" }
};
foreach (var testCase in testCases)
{
SerialPortData serialPort = new SerialPortData(
"COM3",
"HalCli.exe",
testCase.Meter);
string args = serialPort.DefaultArgSettings(SerialPortData.EMeterArg.AllParams);
StringAssert.Contains(args, $"-m {testCase.Expected}");
}
}
[TestMethod]
public void SerialPortData_ReadMacros_ShouldGenerateCorrectOperations()
{
SerialPortData serialPort = new SerialPortData(
"COM3",
"HalCli.exe",
SerialPortData.MeterProduct.Poseidon);
serialPort.Macro = "readmacro1";
Assert.AreEqual(
"-p COM3 -m Poseidon --hat mth --timeout 10 --operation readmacro1",
serialPort.DefaultArgSettings(SerialPortData.EMeterArg.ReadMacro1));
serialPort.Macro = "readmacro2";
Assert.AreEqual(
"-p COM3 -m Poseidon --hat mth --timeout 10 --operation readmacro2",
serialPort.DefaultArgSettings(SerialPortData.EMeterArg.ReadMacro2));
serialPort.Macro = "readmacro3";
Assert.AreEqual(
"-p COM3 -m Poseidon --hat mth --timeout 10 --operation readmacro3",
serialPort.DefaultArgSettings(SerialPortData.EMeterArg.ReadMacro3));
serialPort.Macro = "xxx";
Assert.AreEqual(
"-p COM3 -m Poseidon --hat mth --timeout 10 --operation xxx",
serialPort.DefaultArgSettings(SerialPortData.EMeterArg.AllParams));
}
[TestMethod]
public void RunMultipleTimesTestProgram_CheckParalelWork()
{
SerialPortData serialPort = new SerialPortData("COM3", "cmdSleepTest.exe", 74);
SerialPortData serialPort = new SerialPortData(
"COM3",
"cmdSleepTest.exe",
SerialPortData.MeterProduct.Poseidon,
SerialPortData.HatType.Mth,
10);
if (!System.IO.File.Exists(serialPort.SerialPortCmdClientPath))
{
@ -92,9 +198,11 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
Console.WriteLine($"End Time Loop: {endTime:yyyy-MM-dd HH:mm:ss}");
TimeSpan delta = endTime - startTime;
Console.WriteLine(
$"Delta Time One process {oneEndTime.Hours:D2}:{oneEndTime.Minutes:D2}:{oneEndTime.Seconds:D2}.{oneEndTime.Milliseconds:D3} " +
$"vs Loop: {delta.Hours:D2}:{delta.Minutes:D2}:{delta.Seconds:D2}.{delta.Milliseconds:D3}");
Console.WriteLine($"Total tasks: {cliRunner.TaskPool.Count}");
foreach (CliTaskInfo taskInfo in cliRunner.TaskPool)
@ -108,12 +216,15 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
Assert.IsNotNull(task, "Expected Task<JsonDataFromPoseidon>.");
JsonDataFromPoseidon jsonDataFromPoseidon = task.Result;
Console.WriteLine($"Result: {jsonDataFromPoseidon?.DeviceId}");
Assert.IsNotNull(jsonDataFromPoseidon);
}
else
{
Assert.Fail($"Task did not complete successfully. State={taskInfo.State}, Status={taskInfo.Task.Status}");
Assert.Fail(
$"Task did not complete successfully. State={taskInfo.State}, Status={taskInfo.Task.Status}");
}
}
@ -123,7 +234,12 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
[TestMethod]
public async Task RunMultipleTimesTestProgram_CheckParalelWorkCumulative()
{
SerialPortData serialPort = new SerialPortData("COM3", "cmdSleepTest.exe", 74);
SerialPortData serialPort = new SerialPortData(
"COM3",
"cmdSleepTest.exe",
SerialPortData.MeterProduct.Poseidon,
SerialPortData.HatType.Mth,
10);
if (!System.IO.File.Exists(serialPort.SerialPortCmdClientPath))
{
@ -179,9 +295,11 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
Console.WriteLine($"End Time Loop: {endTime:yyyy-MM-dd HH:mm:ss}");
TimeSpan delta = endTime - startTime;
Console.WriteLine(
$"Delta Time One process {oneEndTime.Hours:D2}:{oneEndTime.Minutes:D2}:{oneEndTime.Seconds:D2}.{oneEndTime.Milliseconds:D3} " +
$"vs Loop: {delta.Hours:D2}:{delta.Minutes:D2}:{delta.Seconds:D2}.{delta.Milliseconds:D3}");
Console.WriteLine($"Total tasks: {cliRunnerList.Sum(runner => runner.TaskPool.Count)}");
for (int iCliRunner = 0; iCliRunner < cliRunnerList.Count; iCliRunner++)
@ -199,7 +317,9 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
Assert.IsNotNull(task, "Expected Task<JsonDataFromPoseidon>.");
JsonDataFromPoseidon jsonDataFromPoseidon = task.Result;
results += $" ID: {jsonDataFromPoseidon?.DeviceId}";
Assert.IsNotNull(jsonDataFromPoseidon);
}
else
@ -214,5 +334,115 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
Assert.IsTrue((cliRunnerList.Count * oneEndTime.Ticks) > delta.Ticks);
}
[TestMethod]
public void TryJsonStringDeserialize_ReadMacro1_Test()
{
string allOutput = @"{
""DeviceId"": ""1000000176"",
""MeterState"": ""MB012501A177"",
""CalibrationFactor"": ""3250"",
""Reading_Units"": ""0"",
""Reading_Totalizer"": 0,
""Reading_FlowRate"": 0,
""Reading_FlowDirection"": 0,
""Reading_Digits"": 0,
""Reading_Shift"": 0,
""Reading_Resolution"": 0,
""OpticalDataMode"": ""199"",
""MeterSize"": ""3"",
""ManufactureDate"": ""2026/04/20 00:56:00"",
""ProductType"": ""74"",
""ProductTypeVersion"": ""B1.0.29"",
""CliVersion"": ""2.0.0.0"",
""ReadingComplete"": true,
""NfcTagDetected"": true
}";
CliRunner cliRunner = new CliRunner(false);
string json = cliRunner.ExtractJson(allOutput);
bool ok = cliRunner.TryJsonStringDeserialize<JsonDataFromPoseidon>(json, out var dto);
Assert.IsTrue(ok);
Assert.IsNotNull(dto);
Assert.AreEqual("1000000176", dto.DeviceId);
Assert.AreEqual("MB012501A177", dto.MeterState);
Assert.AreEqual("3250", dto.CalibrationFactor);
Assert.AreEqual("199", dto.OpticalDataMode);
Assert.AreEqual("3", dto.MeterSize);
Assert.AreEqual("74", dto.ProductType);
Assert.AreEqual("2.0.0.0", dto.CliVersion);
Assert.IsTrue(dto.ReadingComplete);
Assert.IsTrue(dto.NfcTagDetected);
}
[TestMethod]
public void TryJsonStringDeserialize_ReadMacro2_Test()
{
string allOutput = @"{
""DeviceId"": ""1000000176"",
""Reading_Units"": ""0"",
""Reading_Totalizer"": 0,
""Reading_FlowRate"": 0,
""Reading_FlowDirection"": 0,
""Reading_Digits"": 0,
""Reading_Shift"": 0,
""Reading_Resolution"": 0,
""ProductType"": ""74"",
""ProductTypeVersion"": ""B1.0.29"",
""CliVersion"": ""2.0.0.0"",
""ReadingComplete"": true,
""NfcTagDetected"": true
}";
CliRunner cliRunner = new CliRunner(false);
string json = cliRunner.ExtractJson(allOutput);
bool ok = cliRunner.TryJsonStringDeserialize<JsonDataFromPoseidon>(json, out var dto);
Assert.IsTrue(ok);
Assert.IsNotNull(dto);
Assert.AreEqual("1000000176", dto.DeviceId);
Assert.AreEqual("0", dto.Reading_Units);
Assert.AreEqual("74", dto.ProductType);
Assert.AreEqual("B1.0.29", dto.ProductTypeVersion);
Assert.AreEqual("2.0.0.0", dto.CliVersion);
Assert.IsTrue(dto.ReadingComplete);
Assert.IsTrue(dto.NfcTagDetected);
}
[TestMethod]
public void TryJsonStringDeserialize_ReadMacro3_Test()
{
string allOutput = @"{
""DeviceId"": ""1000000176"",
""Reading_Units"": ""0"",
""Reading_Totalizer"": 0,
""Reading_FlowRate"": 0,
""Reading_FlowDirection"": 0,
""Reading_Digits"": 0,
""Reading_Shift"": 0,
""Reading_Resolution"": 0,
""CliVersion"": ""2.0.0.0"",
""ReadingComplete"": true,
""NfcTagDetected"": true
}";
CliRunner cliRunner = new CliRunner(false);
string json = cliRunner.ExtractJson(allOutput);
bool ok = cliRunner.TryJsonStringDeserialize<JsonDataFromPoseidon>(json, out var dto);
Assert.IsTrue(ok);
Assert.IsNotNull(dto);
Assert.AreEqual("1000000176", dto.DeviceId);
Assert.AreEqual("0", dto.Reading_Units);
Assert.AreEqual("2.0.0.0", dto.CliVersion);
Assert.IsTrue(dto.ReadingComplete);
Assert.IsTrue(dto.NfcTagDetected);
}
}
}

View File

@ -1,4 +1,3 @@
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
@ -12,10 +11,20 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
[TestSubject(typeof(CliRunner))]
public class CliRunnerTimeoutTest
{
private static SerialPortData CreateDefaultSerialPortData()
{
return new SerialPortData(
"COM3",
"cmdSleepTest.exe",
SerialPortData.MeterProduct.Poseidon,
SerialPortData.HatType.Mth,
30,
TBF.Rig.RegisterReaders.PoseidonCmdStartStop.GetDescription.ToDescription(SerialPortData.MacroTypes.readall));
}
private static string GetCmdSleepTestPath()
{
var serialPort = new SerialPortData("COM3", "cmdSleepTest.exe", 74);
return serialPort.SerialPortCmdClientPath;
return CreateDefaultSerialPortData().SerialPortCmdClientPath;
}
private static void EnsureExeExists(string exePath)
@ -28,6 +37,33 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
}
}
[TestMethod]
public void SerialPortData_ForTimeoutTests_ShouldUseVersion2Defaults()
{
SerialPortData serialPort = CreateDefaultSerialPortData();
string args = serialPort.DefaultArgSettings(SerialPortData.EMeterArg.AllParams);
Assert.AreEqual(
"-p COM3 -m Poseidon --hat mth --timeout 30 --operation readall",
args);
}
[TestMethod]
public void SerialPortData_ForTimeoutTests_ShouldStillSupportOldMeterType()
{
SerialPortData serialPort = new SerialPortData(
"COM3",
"cmdSleepTest.exe",
74);
string args = serialPort.DefaultArgSettings(SerialPortData.EMeterArg.AllParams);
Assert.AreEqual(
"-p COM3 -m 74 --hat mth --timeout 10 --operation readall",
args);
}
[TestMethod]
public async Task Timeout_ShouldBeDetected_ForLongRunningTask()
{
@ -85,7 +121,7 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
}
catch
{
// let assertions inspect states
// Let assertions inspect states.
}
cliRunner.RefreshTaskStates();
@ -101,6 +137,7 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
Assert.IsTrue(taskInfo.UseResult, "Completed task should remain usable.");
var task = taskInfo.Task as Task<JsonDataFromPoseidon>;
Assert.IsNotNull(task);
Assert.AreEqual(TaskStatus.RanToCompletion, task.Status);
Assert.IsNotNull(task.Result);
@ -123,7 +160,9 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
cliRunner.RefreshTaskStates();
Assert.AreEqual(2, cliRunner.TaskPool.Count);
Assert.AreEqual(1, cliRunner.TaskPool.Count(t => t.State == CliTaskState.Completed),
Assert.AreEqual(
1,
cliRunner.TaskPool.Count(t => t.State == CliTaskState.Completed),
"Exactly one fast task should be completed before timeout handling.");
cliRunner.CancelUndoneTasksAsTimedOut();
@ -136,6 +175,7 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
Assert.IsFalse(timedOutTask.UseResult);
var completed = doneTask.Task as Task<JsonDataFromPoseidon>;
Assert.IsNotNull(completed);
Assert.AreEqual(TaskStatus.RanToCompletion, completed.Status);
Assert.IsNotNull(completed.Result);
@ -153,12 +193,15 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
await Task.Delay(150);
Assert.IsFalse(cliRunner.AreTasksDone(), "Task should still be running before timeout cancellation.");
Assert.IsFalse(
cliRunner.AreTasksDone(),
"Task should still be running before timeout cancellation.");
cliRunner.CancelUndoneTasksAsTimedOut();
cliRunner.RefreshTaskStates();
Assert.IsTrue(cliRunner.AreTasksDone(),
Assert.IsTrue(
cliRunner.AreTasksDone(),
"After timed out tasks are marked, runner should report no running tasks.");
}
@ -193,7 +236,9 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
for (int i = 0; i < 5; i++)
{
cliRunner.AddRunAndCaptureJsonAsync<JsonDataFromPoseidon>(exePath, "sleep=5000");
cliRunner.AddRunAndCaptureJsonAsync<JsonDataFromPoseidon>(
exePath,
"sleep=5000");
}
await Task.Delay(200);
@ -214,7 +259,9 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
var cliRunner = new CliRunner(false);
cliRunner.AddRunAndCaptureJsonAsync<JsonDataFromPoseidon>(exePath, "sleep=50 invalidjson=true");
cliRunner.AddRunAndCaptureJsonAsync<JsonDataFromPoseidon>(
exePath,
"sleep=50 invalidjson=true");
try
{
@ -222,6 +269,7 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
}
catch
{
// Let assertions inspect states.
}
cliRunner.RefreshTaskStates();
@ -229,19 +277,20 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
Assert.AreEqual(1, cliRunner.TaskPool.Count);
var taskInfo = cliRunner.TaskPool.Single();
Assert.AreEqual(CliTaskState.Completed, taskInfo.State);
var task = taskInfo.Task as Task<JsonDataFromPoseidon>;
Assert.IsNotNull(task);
Assert.AreEqual(TaskStatus.RanToCompletion, task.Status);
// depending on your TryJsonStringDeserialize fallback,
// result may be null or an empty/default object
// so avoid asserting UseResult=false here
// instead assert no valid device id
// Depending on TryJsonStringDeserialize fallback,
// result may be null or an empty/default object.
if (task.Result != null)
{
Assert.IsTrue(string.IsNullOrEmpty(task.Result.DeviceId),
Assert.IsTrue(
string.IsNullOrEmpty(task.Result.DeviceId),
"Invalid JSON should not produce a valid DeviceId.");
}
}