- restore the Morrisville release version metadata - add end-to-end logs for CLI execution, reader state, parsed results, and UI updates - prevent completed Poseidon reads from being started repeatedly in a cycle - use a fixed CLI directory and reliable working directory
273 lines
8.2 KiB
C#
273 lines
8.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.ComponentModel;
|
|
using System.Reflection;
|
|
using System.Xml.Serialization;
|
|
|
|
namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
|
|
{
|
|
public class SerialPortData
|
|
{
|
|
public const string CliDirectory = @"C:\TBF\Cli";
|
|
|
|
private Boolean? _cliExists;
|
|
public bool CliExists { get {
|
|
if (_cliExists == null || !_cliExists.HasValue)
|
|
{
|
|
_cliExists = File.Exists(SerialPortCmdClientPath);
|
|
}
|
|
return _cliExists.Value;
|
|
} }
|
|
public string SerialPortCmdClientPath
|
|
{
|
|
get
|
|
{
|
|
// The configured value is a file name, not an executable path.
|
|
// Keeping the CLI directory fixed prevents a bench configuration
|
|
// from starting an unintended executable or failing due to a
|
|
// relative path/current-directory change.
|
|
string cliFileName = Path.GetFileName(CmdClientName);
|
|
if (string.IsNullOrWhiteSpace(cliFileName))
|
|
cliFileName = "HalCli.exe";
|
|
|
|
return Path.Combine(CliDirectory, cliFileName);
|
|
}
|
|
}
|
|
public string CmdClientName { get; set; } = "HalCli.exe";
|
|
public string PortName { get; set; }
|
|
// Backward compatibility: old numeric meter type
|
|
public int? OldMeterType { get; set; }
|
|
|
|
// 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"; //Poseidon
|
|
case MeterProduct.Ally:
|
|
return "ally";
|
|
case MeterProduct.IperlPlus:
|
|
return "iperlplus";
|
|
case MeterProduct.IperlLegacy:
|
|
return "iperllegacy";
|
|
default:
|
|
return "74";
|
|
}
|
|
}
|
|
|
|
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,
|
|
|
|
// New macro operations - just waste
|
|
ReadMacro1 = 10,
|
|
ReadMacro2 = 11,
|
|
ReadMacro3 = 12
|
|
}
|
|
|
|
public string DefaultArgSettings(EMeterArg eMeterArg)
|
|
{
|
|
string commonArgs = BuildCommonArgs();
|
|
|
|
switch (eMeterArg)
|
|
{
|
|
case EMeterArg.Calibration:
|
|
return $"{commonArgs} --operation write --parameter Calibration --value 1";
|
|
|
|
case EMeterArg.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 "74"; //return "Poseidon";
|
|
|
|
case MeterProduct.Ally:
|
|
return "ally";
|
|
|
|
case MeterProduct.IperlPlus:
|
|
return "iperlplus";
|
|
|
|
case MeterProduct.IperlLegacy:
|
|
return "iperllegacy";
|
|
|
|
default:
|
|
return "74"; //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,
|
|
int meterType)
|
|
{
|
|
PortName = portName;
|
|
CmdClientName = cmdClientName;
|
|
OldMeterType = meterType;
|
|
}
|
|
}
|
|
|
|
|
|
}
|