Files
tbf/TBF/Rig/TestMethods/AllyCalibration/AllyCalibrationSeq.cs
T
michal c71fe75446 Ally iPerl initial - reader,test method, unit test
Add AllyReader and AllyCalibration support with tests: Introduce new register readers, calibration methods, and comprehensive unit tests for integration and functionality validation. Update project files accordingly.
2026-08-18 10:01:02 +02:00

260 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading;
using Common;
using Config.Entities;
using Results.Entities;
using TBF.Rig.RegisterReaders.AllyReader;
using TBF.Rig.RegisterReaders.AllyReader.Communication;
using TBF.Rig.Sequences;
using TBF.UiBridge;
namespace TBF.Rig.TestMethods.AllyCalibration
{
public class AllyCalibrationSeq : SequenceBase
{
private const byte InitialMeterMode = 0x09;
private const byte ActiveMeterMode = 0x02;
private const byte DiagnosticLedCalibrationMode = 0xC2;
private const string DisplayVolume = "01134010";
private const byte LcdTimeoutSeconds = 30;
private const ushort OffsetLearningSamples = 1000;
private const ushort OffsetLearningDelaySeconds = 1;
public IList<Event> Execute(
Test test,
int repetitionNr,
TestMethod method,
TestMethodCfg cfg,
TestMethodParams parameters)
{
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted));
TestRslt testResult = BatchRslts.GetTestRslt(test.Name, 0);
if (testResult != null)
testResult.StartTime = DateTime.Now;
List<string> messages = new List<string>();
for (int position = 0; position < BatchRslts.WMPositionsCount; position++)
{
Results.Entities.WaterMeter waterMeter = BatchRslts.Batch.WaterMeters[position];
if (waterMeter == null || waterMeter.Disabled)
continue;
MeterTestRslt meterResult = BatchRslts.GetMeterTestRslt(
test.Name,
position,
CompoundMeterId.Single);
AllyMeterReader reader = sensPath != null &&
sensPath.RegisterReaders != null &&
position < sensPath.RegisterReaders.Length
? sensPath.RegisterReaders[position] as AllyMeterReader
: null;
bool passed;
string resultMessage;
if (reader == null)
{
passed = false;
resultMessage = "ALLY" + (position + 1) + ": ALLY reader is not configured.";
}
else
{
passed = ExecuteWithRetries(reader, cfg, parameters, out resultMessage);
resultMessage = reader.Name + ": " + resultMessage;
}
messages.Add(resultMessage);
if (meterResult != null)
{
meterResult.RegReaderType = (int)RegisterReaderType.DataStream;
meterResult.TestDone = true;
meterResult.Passed = passed;
}
}
if (testResult != null)
{
testResult.EndTime = DateTime.Now;
testResult.TestDone = true;
testResult.Remark = string.Join("; ", messages);
}
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.Completed));
Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, testResult));
allResults.Info(TestResult2CsvLine(test.Name, 0));
return new List<Event> { Event.Done };
}
private static bool ExecuteWithRetries(
AllyMeterReader reader,
TestMethodCfg cfg,
TestMethodParams parameters,
out string resultMessage)
{
Exception lastException = null;
int attempts = Math.Max(1, cfg.MaxAttempts);
for (int attempt = 1; attempt <= attempts; attempt++)
{
try
{
bool passed = ExecuteOnce(reader, cfg, parameters, out resultMessage);
if (!passed)
return false;
if (attempt > 1)
resultMessage += " (attempt " + attempt + ")";
return true;
}
catch (Exception ex)
{
lastException = ex;
if (attempt < attempts && cfg.DelayBetweenAttemptsMs > 0)
Thread.Sleep(cfg.DelayBetweenAttemptsMs);
}
}
resultMessage = lastException == null
? "ALLY command failed."
: "ALLY command failed after " + attempts + " attempts: " + lastException.Message;
return false;
}
private static bool ExecuteOnce(
AllyMeterReader reader,
TestMethodCfg cfg,
TestMethodParams parameters,
out string resultMessage)
{
AllyCalibrationActivity activity;
if (!AllyCalibrationActivityNames.TryParse(parameters.Activity, out activity))
throw new InvalidOperationException("Unknown ALLY calibration activity: " + parameters.Activity);
int timeout = cfg.CommandTimeoutMs;
switch (activity)
{
case AllyCalibrationActivity.ReadSerialNumber:
string serialNumber = reader.ReadSerialNumber(timeout);
if (string.IsNullOrWhiteSpace(serialNumber))
throw new FormatException("ALLY serial number response is empty.");
resultMessage = "SerialNumber=" + serialNumber;
return true;
case AllyCalibrationActivity.ReadVersionAndType:
AllyVersionInfo version = reader.ReadVersionAndType(timeout);
bool deviceTypeOk = string.Equals(
version.DeviceType,
cfg.ExpectedDeviceType,
StringComparison.OrdinalIgnoreCase);
bool firmwareOk = string.IsNullOrWhiteSpace(cfg.ExpectedFirmwareVersion) ||
string.Equals(
version.FirmwareVersion,
cfg.ExpectedFirmwareVersion,
StringComparison.OrdinalIgnoreCase);
resultMessage = "Version=" + version +
", DeviceType=" + (deviceTypeOk ? "OK" : "NOK") +
", Firmware=" + (firmwareOk ? "OK" : "NOK");
return deviceTypeOk && firmwareOk;
case AllyCalibrationActivity.ReadSystemTime:
DateTime systemTime = reader.ReadSystemTimeUtc(timeout);
resultMessage = "SystemTimeUtc=" + systemTime.ToString("O");
return true;
case AllyCalibrationActivity.ReadRebootCount:
byte rebootCount = reader.ReadRebootCount(timeout);
resultMessage = "RebootCount=" + rebootCount;
return rebootCount == 0;
case AllyCalibrationActivity.OpenValve:
reader.OpenValve(timeout);
resultMessage = "Valve=open";
return true;
case AllyCalibrationActivity.DisableSpreadSpectrum:
reader.SetSpreadSpectrum(false, timeout);
resultMessage = "SpreadSpectrum=disabled";
return true;
case AllyCalibrationActivity.SetInitialMeterMode:
reader.SetMeterMode(InitialMeterMode, timeout);
resultMessage = "MeterMode=0x09";
return true;
case AllyCalibrationActivity.TurnDiagnosticLedOn:
reader.SetDiagnosticLed(DiagnosticLedCalibrationMode, timeout);
resultMessage = "DiagnosticLED=0xC2";
return true;
case AllyCalibrationActivity.ResetCalibrationFactor:
double resetFactor = reader.ResetCalibrationFactor(timeout);
resultMessage = "ResetCalibrationFactor=" + resetFactor.ToString("F2") + "%";
return true;
case AllyCalibrationActivity.ReadCalibrationFactor:
double currentFactor = reader.ReadCalibrationFactor(timeout);
bool factorMatches = !reader.ExpectedCalibrationFactorPercent.HasValue ||
Math.Abs(currentFactor - reader.ExpectedCalibrationFactorPercent.Value) <= 0.05D;
resultMessage = "CalibrationFactor=" + currentFactor.ToString("F3") + "%";
return factorMatches;
case AllyCalibrationActivity.SetCalibrationMagneticTamperProfile:
reader.SetMagneticTamperProfile(AllyMagneticTamperProfile.Calibration, timeout);
resultMessage = "MagneticTamperProfile=calibration";
return true;
case AllyCalibrationActivity.TurnDiagnosticLedOff:
reader.SetDiagnosticLed(0x00, timeout);
resultMessage = "DiagnosticLED=off";
return true;
case AllyCalibrationActivity.SetActiveMeterMode:
reader.SetMeterMode(ActiveMeterMode, timeout);
resultMessage = "MeterMode=active";
return true;
case AllyCalibrationActivity.EnableSpreadSpectrum:
reader.SetSpreadSpectrum(true, timeout);
resultMessage = "SpreadSpectrum=enabled";
return true;
case AllyCalibrationActivity.SetDefaultMagneticTamperProfile:
reader.SetMagneticTamperProfile(AllyMagneticTamperProfile.FirmwareDefaults, timeout);
resultMessage = "MagneticTamperProfile=firmware defaults";
return true;
case AllyCalibrationActivity.WriteCalibrationFactor:
reader.SetCalibrationFactor(parameters.CalibrationFactorPercent, timeout);
resultMessage = "CalibrationFactorWritten=" +
parameters.CalibrationFactorPercent.ToString("F3") + "%";
return true;
case AllyCalibrationActivity.WriteDisplayVolume:
reader.SetDisplayVolume(DisplayVolume, timeout);
resultMessage = "DisplayVolume=" + DisplayVolume;
return true;
case AllyCalibrationActivity.SetLcdTimeout:
reader.SetLcdTimeout(LcdTimeoutSeconds, timeout);
resultMessage = "LcdTimeout=30s";
return true;
case AllyCalibrationActivity.StartOffsetLearning:
reader.StartOffsetLearning(
OffsetLearningSamples,
OffsetLearningDelaySeconds,
timeout);
resultMessage = "OffsetLearning=1000 samples, 1s delay";
return true;
default:
throw new InvalidOperationException("Unsupported ALLY calibration activity.");
}
}
}
}