tbf/TBF/Rig/TestMethods/GenesisCommunication/GenesisHead/GenesisHead.cs

659 lines
20 KiB
C#

using Config.Entities;
using log4net;
///
/// Copyright (c) 2015-2018 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using TBF.Rig.Generic;
using TBF.Rig.GenericDevices;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Metrology.Measurements;
using Xylem.Common.Metrology.Measurements.Consts;
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
using Common;
using System.IO.Ports;
namespace TBF.Rig.TestMethods.GenesisCommunication.GenesisHead
{
public static class GenesisHeadBatch
{
public static Dictionary<string, List<MeasurementResults>> MeterIdDetailResults = new Dictionary<string, List<MeasurementResults>>();
private static readonly ILog log = LogManager.GetLogger(typeof(GenesisHeadBatch));
public static readonly Lazy<MeterBatch> BatchHolder = new Lazy<MeterBatch>(() =>
{
return new MeterBatch();
});
internal static bool Start(IRegReader[] registerReaders, string[] lastSNTexts)
{
try
{
MeterIdDetailResults = new Dictionary<string, List<MeasurementResults>>();
int index = 0;
var ret = false;
foreach (var rr in registerReaders)
{
if (rr is TestMethods.GenesisCommunication.GenesisHead.GenesisHead)
{
if (!string.IsNullOrEmpty(lastSNTexts[index]))
{
var myGenesis = ((TestMethods.GenesisCommunication.GenesisHead.GenesisHead)rr).SetUp();
myGenesis.SerialNumber = lastSNTexts[index];
ret = true;
}
}
index = index + 1;
}
return ret;
}
catch (Exception ex)
{
log.Fatal(ex.Message, ex);
return false;
}
}
}
/// <summary>
/// This component = instance of this class is a placeholder for a combined main watermeter
/// </summary>
public class GenesisHead : ComponentBase, IDevice, GenericDevices./*IRegisterReader*/IRegReader, IOperation
{
public List<MeasurementResults> DetailedResults { get; set; }
private static readonly ILog log = LogManager.GetLogger(typeof(GenesisHead));
public override string ToString() { return string.Format("Genesis({0})", Cfg.ToString(1)); }
public RegisterReaderType RegisterReaderType { get { return RegisterReaderType.DataStream; } }
private readonly GenesisHeadCfg genesisHeadCfg;
public int SlotNr { get { return genesisHeadCfg.SlotNr; } }
public int OptoComPortNr { get { return genesisHeadCfg.OptoComPortNr; } }
public int HeadComPortNr { get { return genesisHeadCfg.HeadComPortNr; } }
public double PulsesPerLtr { get { return 1000.0; } }
public double LtrsPerPulse { get { return 1 / PulsesPerLtr; } }
public string QuantityUnits { get; set; }
public int Position { get; }//...MF
double IRegReader.PulsesPerLtr { get; set; }
// Adding the missing static method to resolve the error. ...MF
public static void ResetStaticProperties()
{
// Add logic to reset static properties here, if applicable.
// If no static properties exist, this method can remain empty.
}
#if ORACLE_DB
public int WMType_ID { get { return iperlHeadCfg.ProcParams.WMType_ID; } } /// Required by Oracle DB
public int WMType_Rev { get { return iperlHeadCfg.ProcParams.WMType_Rev; } } /// Required by Oracle DB
#endif
public float CalibTarget { get { return (ushort)genesisHeadCfg.ProcParams.CalibTarget; } }
public ushort FactorLimitLo { get { return (ushort)genesisHeadCfg.ProcParams.FactorLimitLo; } }
public ushort FactorLimitHi { get { return (ushort)genesisHeadCfg.ProcParams.FactorLimitHi; } }
/// Properties set by the Begin and the End form
//todo rd implement
public string SerialNr;
public string EndState
{
get { return endState; }
set { endState = value; }
}
private string endState;
public string BeginState
{
get { return beginState; }
set { beginState = value; }
}
private string beginState;
public bool Disabled
{
get { return disabled; }
set { disabled = value; }
}
private bool disabled;
public bool CommFailed
{
get { return commFailed; }
set { commFailed = value; }
}
private bool commFailed;
public int ResultCode
{
get { return resultCode; }
}
private int resultCode;
/// <summary> ConfigStruct of the water meter obtained or updated by iPerlCommunication </summary>
public ConfigStruct ConfigStruct
{
get { return configStruct; }
set { configStruct = value; }
}
private ConfigStruct configStruct;
/// <summary> CalibrationStruct of the water meter obtained or updated by iPerlCommunication </summary>
public CalibrationStruct CalibrationStruct
{
get { return calibrationStruct; }
set { calibrationStruct = value; }
}
private CalibrationStruct calibrationStruct;
public ushort OrigCalibFactor;
public ushort CalibFactor { get { return (CalibrationStruct != null) ? CalibrationStruct.Calibration : (ushort)0; } }
public double Q2ErrWOCorrection;
public bool Q2CorrectionDone;
public double Q2Correction;
public int Q2CorrRFlow;
public int Q2CorrLFlow;
public double Diff2Hz8Hz;
public bool Hz2CorrectionDone;
public int Hz2Correction;
public string FWVersion { get { return (CalibrationStruct != null) ? CalibrationStruct.FWVersionStr() : string.Empty; } }
/// <summary> Result of the last test used to calculate Q2 correction factors, etc </summary>
public Results.Entities.MeterTestRslt LastTestResult2;
public Results.Entities.MeterTestRslt LastTestResult;
public double NominalTestFlowLph; /// in liter per hour
///
/// Required for IRegisterReader interface
///
public int WMPulses { get { return wmPulses; } }
public int WMRefPulses { get { return wmRefPulses; } }
public double WMVolume { get { return wmVolume; } }
public double BeginWMState { get { return beginWMState; } }
public double EndWMState { get { return endWMState; } }
public double WMTestTime { get { return wmTestTime; } }
private double beginWMState;
private double endWMState;
private double wmVolume;
private int wmPulses;
private int wmRefPulses;
private double wmTestTime;
/// <summary> Name set by the test, to be used as a part of the opto-data log file name </summary>
public string TestName;
/// <summary> Name set by the test, to be used as a part of the opto-data log file name </summary>
public string BenchName;
///
/// Volume of water from the opto telegram
///
private Int64 lastVolumeRaw; /// Last read raw volume
private double volumeLtr; ///
private double volumeLtr0;
///
/// Timestamp from the opto telegram
///
private double timestampSec;
private double timestampSec0;
public bool NoSamples { get { return (timestampSecEnd - timestampSecStart) < float.Epsilon; } }
public double TimestampSecStart { get { return timestampSecStart; } }
public double TimestampSecEnd { get { return timestampSecEnd; } }
private double timestampSecStart;
private double timestampSecEnd;
public GenesisHead()
{
}
public GenesisHead(Generic.IComponentCfg cfg)
: base(cfg)
{
ClearData();
genesisHeadCfg = cfg as GenesisHeadCfg;
log.Debug(this.ToString());
}
private GenesisMeter myGenesis = null;
public GenesisMeter SetUp()
{
try
{
Log("Call SetUp()");
if (myGenesis != null)
{
myGenesis.DisposeMeter();
}
//add for gen
myGenesis = new GenesisMeter();
//myGenesis.SetupFromConfigFile(SlotNr);
//myGenesis.SetLogger(); - private, but called into basic constructor!
myGenesis.SetupGenesisMeter(
SlotNr,
new Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig.PortConfig()
{
Type = "Xylem.Common.Hardware.Interfaces.Ports.SerialPorts.IrdaSerialPort",
PortName =$"COM{HeadComPortNr}"
},
new Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig.PortConfig()
{
Type = "",
PortName = $"COM{OptoComPortNr}"
}
);
Log("Add Meter to batch");
GenesisHeadBatch.BatchHolder.Value.AddMeter(myGenesis);
Log("Log Raw Data");
myGenesis.LogRawData(true);
return myGenesis;
}
catch (Exception e)
{
if (myGenesis != null)
{
Log(e.Message);
}
throw e;
}
}
/// <summary>
/// Clear data related to a specific water meter
/// </summary>
public void ClearData()
{
DetailedResults = new List<MeasurementResults>();
resultCode = 0;
disabled = false;
commFailed = false;
endState = string.Empty;
beginState = string.Empty;
configStruct = null;
calibrationStruct = null;
LastTestResult = null;
NominalTestFlowLph = 0;
OrigCalibFactor = 0;
Q2ErrWOCorrection = 0;
Q2CorrectionDone = false;
Q2CorrRFlow = 0;
}
public override void Initialize()
{
ClearData();
if (DebugLevel == DebugMode.Normal)
{
}
}
public void RunDeviceBefore()
{
////todo: RD- Login??
//if (DebugLevel == DebugMode.Normal)
//{
// if (myGenesis != null)
// {
// Log("TBF RunDeviceBefore");
// }
// else
// {
// //throw new Exception("No meter was bound!");
// }
//}
//else if (DebugLevel == DebugMode.FailureDuringOperation)
//{
//}
}
public void RunDeviceAfter() { }
public void StopDevice()
{
try
{
if (DebugLevel == DebugMode.Normal && myGenesis != null)
{
myGenesis.DisposeMeter();
GenesisHeadBatch.BatchHolder.Value.RemoveMeter(myGenesis);
}
}
catch
{
}
}
public void StopDevice2() { }
/// <summary>
/// Events: Event.ReadRegisterDone, Event.Error
/// </summary>
/// <returns>ReadWaterMeter instance reference casted to IOperaton</returns>
public IOperation ReadRegisterOp()
{
return this;
}
/// <summary>
/// Clear data/counters related to a specific tests
/// </summary>
public void Clear()
{
resultCode = 0;
sampleNr = 0;
volumeLtr = 0;
volumeLtr0 = 0;
timestampSec = 0;
timestampSec0 = 0;
ReadPulses();
}
public void TestCompleted()
{
/// TODO: Implement
}
private int sampleNr; /// This is to determine when the test start sample should be taken
private bool StoreStartPackage = false;
private bool StoreEndPackage = false;
private bool Enable = false;
public bool IsCalibration = false;
/// <summary>Start this operation</summary>
public void Start()
{
}
public void StartRead(string TestName, int batchNr, int repetitionNr)
{
StoreStartPackage = false;
StoreEndPackage = false;
//Start mesurement
if (DebugLevel == DebugMode.Normal)
{
if (myGenesis != null)
{
IsCalibration = false;
Log($"TBF Start Measurement {TestName}");
myGenesis.CurrentActionText = $"Batch{batchNr}_Rep{repetitionNr}";
if (TestName.ToLower().Contains("calib"))
{
IsCalibration = true;
//myGenesis.Login();
myGenesis.StartCalibration();
}
else if (TestName.ToLower().Contains("login"))
{
//myGenesis.Login();
myGenesis.InitMeasurement();
}
else
{
DetailedResults = new List<MeasurementResults>();
myGenesis.StartMeasurement();
}
StoreStartPackage = true;
}
}
}
public void Log(string text)
{
log.Debug(text);
if (DebugLevel == DebugMode.Normal)
{
if (myGenesis != null)
{
myGenesis.WriteLog(text);
}
}
}
/// <summary>Run this operation</summary>
/// <returns>eventDone</returns>
public Event Run()
{
if (DebugLevel == DebugMode.Normal)
{
if (myGenesis != null)
{
try
{
//var results = myGenesis.GetIntermediateMeasurementResult();
//readOutResults(results);
}
catch (Exception)
{
}
}
}
return Event.ReadRegisterDone;
}
public double RefVolume = 0.0;
public void Stop()
{
//Stop(null);
if (DebugLevel == DebugMode.Normal && myGenesis != null)
{
if (IsCalibration)
{
myGenesis.StopCalibration();
}
else
{
myGenesis.StopMeasurement();
}
}
}
/// <summary>Stop this operation</summary>
public void Stop(Double? testTimeS = null, double? refVol = null)
{
if (DebugLevel == DebugMode.Normal && myGenesis != null)
{
Log($"TBF Stop Measurement {IsCalibration} {testTimeS} {refVol }");
if (IsCalibration)
{
//myGenesis.StopCalibration();
int retryCounter = 400;
while (myGenesis.GetCalibrationState() != MeasurementStates.IsCompleted)
{
if (retryCounter < 0)
{
break;
}
Thread.Sleep(10);
retryCounter = retryCounter - 1;
}
try
{
var results = myGenesis.GetMainMeasurementResult(refVol, testTimeS, false);
readOutResults(results, testTimeS);
if (refVol.HasValue && refVol.Value != 0.0)
{
myGenesis.BuildAndCheckCalibFactorsAllChannels(refVol.Value / 1000, testTimeS, Q2ErrWOCorrection, 0.0/*, (int?)null*/);
myGenesis.SetCalibFactorsAllChannels(false);
}
}
catch (Exception ex)
{
MarkAsError();
Log("Error while Stop Calib " + ex.Message);
if (ex.InnerException != null)
{
Log("Inner Error:" + ex.InnerException.Message);
}
}
}
else
{
int retryCounter = 4000;
//myGenesis.StopMeasurement();
try
{
while (myGenesis.GetMeasurementState() != MeasurementStates.IsCompleted)
{
if (retryCounter < 0)
{
break;
}
Thread.Sleep(10);
retryCounter = retryCounter - 1;
}
try
{
if (refVol.HasValue && testTimeS.HasValue)
{
Log("GetMainMeasurementResult V" + refVol.ToString() + " and S" + testTimeS.Value);
}
else
{
Log("GetMainMeasurementResult empty");
}
DetailedResults = myGenesis.GetAllMeasurementResults(refVol, testTimeS);
foreach (var item in DetailedResults)
{
Log("Detail Measurement Channel =" + item.Channel + "; CorrectedDutVolumeCm= " + item.CorrectedDutVolumeCm + "; DeviationDutToRefPer= " + item.DeviationDutToRefPer);
}
readOutResults(DetailedResults.First(), testTimeS);
}
catch (Exception ex)
{
MarkAsError();
Log("Error while Stop Measurement " + ex.Message);
}
}
catch (Exception ex)
{
MarkAsError();
Log("Error while GetMeasurementState " + ex.Message);
}
}
StoreEndPackage = true;
}
}
private void readOutResults(MeasurementResults results, double? testTimeS)
{
volumeLtr = results.CorrectedDutVolumeCm * 1000;
timestampSec = results.DutStopRecord.GetTimeS();
if (testTimeS.HasValue)
{
wmTestTime = testTimeS.Value;
}
else
{
wmTestTime = results.DutTimeS;
}
wmVolume = results.CorrectedDutVolumeCm * 1000;
Log("DutFlowRateCmPh" + results.DutFlowRateCmPh.ToString());
Log("CorrectedDutVolumeCm=" + results.CorrectedDutVolumeCm.ToString());
Log("DutVolumeCm=" + results.DutVolumeCm.ToString());
ReadPulses();
}
private void MarkAsError()
{
volumeLtr = 0;
timestampSec = 0;
wmTestTime = 0;
wmVolume = 0;
ReadPulses();
}
private void ReadPulses()
{
beginWMState = volumeLtr0;
endWMState = volumeLtr;
wmPulses = (int)(wmVolume * (double)PulsesPerLtr + 0.5);
wmRefPulses = StateMachine.ControlBoardMain.RefPulses;//EtPulses(0);//...MF
}
private bool optoSerialPortParsingEnabled;
}
}