235 lines
9.1 KiB
C#
235 lines
9.1 KiB
C#
///
|
|
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
|
///
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel.Composition;
|
|
using System.ComponentModel.Composition.Hosting;
|
|
using System.Xml.Serialization;
|
|
using log4net;
|
|
using Config.Entities;
|
|
using DataStreamInterface;
|
|
using TBF.BenchControl;
|
|
using TBF.BenchControl.Generic;
|
|
using TBF.BenchControl.RegisterReaders.DataStream;
|
|
|
|
namespace TBF.BenchControl.RegisterReaders.DataStream.Reader
|
|
{
|
|
/// <summary>
|
|
/// Holds information identifying the test bench.
|
|
/// </summary>
|
|
public class Reader : ComponentBase, IOperation, GenericDevices.IRegReaderDatastream
|
|
{
|
|
private static readonly ILog log = LogManager.GetLogger(typeof(Reader));
|
|
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
|
|
|
|
MefImport.MefImport mefImport;
|
|
Int64 minSamplesCount { get { return mefImport.MinSamplesCount; } }
|
|
|
|
///
|
|
/// IRegReader interface part 1
|
|
///
|
|
readonly ReaderCfg myCfg;
|
|
public RegisterReaderType RegisterReaderType { get { return RegisterReaderType.DataStream; } }
|
|
public int Position { get { return (myCfg != null) ? myCfg.Position : 1; } }
|
|
public double PulsesPerLtr { get { return 1.0; } }
|
|
public double LtrsPerPulse { get { return 1.0; } }
|
|
|
|
string waterMeterID;
|
|
Int64 storedFramesCount;
|
|
Int64 startIx;
|
|
Int64 endIx;
|
|
Dictionary<Int64, DataFrame> samplesDict;
|
|
DataStreamInterface.Unit timeUnit;
|
|
DataStreamInterface.Unit volumeUnit;
|
|
|
|
|
|
public Reader() { }
|
|
|
|
public Reader(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
|
: base(cfg)
|
|
{
|
|
myCfg = cfg as ReaderCfg;
|
|
|
|
mefImport = TbfComponents.FindComponent(cfg.ParentName, components) as MefImport.MefImport;
|
|
if (mefImport == null) throw new Exception("Cannot find " + Name + " parent");
|
|
}
|
|
|
|
public override void Initialize()
|
|
{
|
|
samplesDict = new Dictionary<Int64, DataFrame>();
|
|
|
|
if (DebugLevel == DebugMode.Normal)
|
|
{
|
|
if (Position < 1 || Position > Math.Min(TBF.Data.WMsCount, mefImport.DataStreamIFace.GetMetersCount()))
|
|
{
|
|
throw new ArgumentException("Position is out of range");
|
|
}
|
|
|
|
log.FatalFormat("{0} initialized: {1}", Name, this);
|
|
}
|
|
else
|
|
{
|
|
log.FatalFormat("{0} simulated: {1}", Name, this);
|
|
}
|
|
}
|
|
|
|
|
|
///
|
|
/// IRegReader interface part 2
|
|
///
|
|
int wmPulses;
|
|
int wmRefPulses;
|
|
double wmVolume;
|
|
double beginWMState;
|
|
double endWMState;
|
|
///
|
|
public int WMPulses { get { return wmPulses; } } /// Counted pulses of the water meter
|
|
public int WMRefPulses { get { return wmRefPulses; } } /// 'Gated' reference pulses of the water meters
|
|
public double WMVolume { get { return wmVolume; } } /// Counted volume of the water meter
|
|
public double BeginWMState { get { return beginWMState; } } /// Test begin state of the water meter
|
|
public double EndWMState { get { return endWMState; } } /// Test end state of the water meter
|
|
|
|
|
|
/// To be used at the beginning of a test
|
|
public void Clear()
|
|
{
|
|
storedFramesCount = 0;
|
|
startIx = -1;
|
|
endIx = -1;
|
|
beginWMState = 0;
|
|
endWMState = 0;
|
|
wmVolume = 0;
|
|
wmPulses = 0;
|
|
wmRefPulses = 0;
|
|
samplesDict.Clear();
|
|
timeUnit = DataStreamInterface.Unit.s;
|
|
volumeUnit = DataStreamInterface.Unit.l;
|
|
}
|
|
|
|
/// To be used when the test is completed ...
|
|
public void TestCompleted()
|
|
{
|
|
mefImport.DataStreamIFace.CloseConnection(Position - 1);
|
|
}
|
|
|
|
public IOperation ReadRegisterOp()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
///
|
|
/// IOperation interface
|
|
///
|
|
public void Start()
|
|
{
|
|
Clear();
|
|
|
|
if (TBF.BenchControl.Sequences.ProcessData.BatchRslts.Batch.WaterMeters.Count >= Position &&
|
|
TBF.BenchControl.Sequences.ProcessData.BatchRslts.Batch.WaterMeters[Position - 1] != null &&
|
|
!TBF.BenchControl.Sequences.ProcessData.BatchRslts.Batch.WaterMeters[Position - 1].Disabled)
|
|
{
|
|
timeUnit = mefImport.DataStreamIFace.GetTimeUnits();
|
|
volumeUnit = mefImport.DataStreamIFace.GetVolumeUnits();
|
|
log.DebugFormat("timeUnit = {0}, volumeUnit = {1}", timeUnit, volumeUnit);
|
|
|
|
bool started = mefImport.StartMeasurement(Position - 1);
|
|
log.DebugFormat("{0} : DataStreamIFace.StartMeasurement({1}) in Start() returned {2}", Name, Position - 1, started);
|
|
}
|
|
}
|
|
|
|
public Event Run()
|
|
{
|
|
log.DebugFormat("Run() name={0} position={1}", Name, Position - 1);
|
|
return Event.ReadRegisterDone;
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
|
|
if (TBF.BenchControl.Sequences.ProcessData.BatchRslts.Batch.WaterMeters.Count >= Position &&
|
|
TBF.BenchControl.Sequences.ProcessData.BatchRslts.Batch.WaterMeters[Position - 1] != null &&
|
|
!TBF.BenchControl.Sequences.ProcessData.BatchRslts.Batch.WaterMeters[Position - 1].Disabled)
|
|
{
|
|
bool stopped = mefImport.StopMeasurement(Position - 1, out storedFramesCount);
|
|
log.DebugFormat("{0} : DataStreamIFace.StopMeasurement({1}) in Stop() returned {2}, storedFramesCount = {3}", Name, Position - 1, stopped, storedFramesCount);
|
|
|
|
if (storedFramesCount >= minSamplesCount)
|
|
{
|
|
startIx = storedFramesCount / minSamplesCount;
|
|
endIx = (storedFramesCount * (minSamplesCount - 1) / minSamplesCount) - 1;
|
|
|
|
beginWMState = VolumeLtrStart;
|
|
endWMState = VolumeLtrEnd;
|
|
wmVolume = Math.Abs(VolumeLtrEnd - VolumeLtrStart);
|
|
wmPulses = (int)Math.Round(wmVolume * PulsesPerLtr);
|
|
wmRefPulses = StateMachine.ControlBoard.EtPulses(0);
|
|
log.DebugFormat("Stop() ... Position={0}, wmVolume={1}, wmPulses={2}, wmRefPulses={3}", Position, wmVolume, wmPulses, wmRefPulses);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// ... for more accurate WMPulses, WMRefPulses calculation
|
|
|
|
|
|
///
|
|
/// IRegReaderDatastream interface
|
|
///
|
|
public bool NoSamples { get { return storedFramesCount < minSamplesCount || startIx < 0 || endIx < 0; } }
|
|
public double VolumeLtrStart { get { return (startIx >= 0) ? GetVolumeFromSamples(startIx) : 0; } }
|
|
public double VolumeLtrEnd { get { return (endIx >= 0) ? GetVolumeFromSamples(endIx) : 0; } }
|
|
public double TimestampSecStart { get { return (startIx >= 0) ? GetTimeFromSamples(startIx) : 0; } }
|
|
public double TimestampSecEnd { get { return (endIx >= 0) ? GetTimeFromSamples(endIx) : 0; } }
|
|
|
|
double GetTimeFromSamples(Int64 ix)
|
|
{
|
|
DataFrame oneFrame;
|
|
DataFrame[] frames;
|
|
|
|
if (samplesDict.TryGetValue(ix, out oneFrame))
|
|
{
|
|
double time = DataStreamInterface.Units.ConvertFrom(timeUnit, oneFrame.Time);
|
|
log.DebugFormat("GetTimeFromSamples({0}) returns {1} ... value from dictionary", ix, time);
|
|
return time;
|
|
}
|
|
else if ((frames = mefImport.DataStreamIFace.GetFrames(Position - 1, ix, 1)).Length == 1)
|
|
{
|
|
samplesDict.Add(ix, frames[0]);
|
|
double time = DataStreamInterface.Units.ConvertFrom(timeUnit, frames[0].Time);
|
|
log.DebugFormat("GetTimeFromSamples({0}) returns {1} ... value obtained by DataStreamIFace.GetFrames({2}, {0}, 1)", ix, time, Position - 1);
|
|
return time;
|
|
}
|
|
else
|
|
{
|
|
log.DebugFormat("GetTimeFromSamples({0}) returns 0", ix);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
double GetVolumeFromSamples(Int64 ix)
|
|
{
|
|
DataFrame oneFrame;
|
|
DataFrame[] frames;
|
|
|
|
if (samplesDict.TryGetValue(ix, out oneFrame))
|
|
{
|
|
double volume = DataStreamInterface.Units.ConvertFrom(volumeUnit, oneFrame.Volume);
|
|
log.DebugFormat("GetVolumeFromSamples({0}) returns {1} ... value from dictionary", ix, volume);
|
|
return volume;
|
|
}
|
|
else if ((frames = mefImport.DataStreamIFace.GetFrames(Position - 1, ix, 1)).Length == 1)
|
|
{
|
|
samplesDict.Add(ix, frames[0]);
|
|
double volume = DataStreamInterface.Units.ConvertFrom(volumeUnit, frames[0].Volume);
|
|
log.DebugFormat("GetVolumeFromSamples({0}) returns {1} ... value obtained by DataStreamIFace.GetFrames({2}, {0}, 1)", ix, volume, Position - 1);
|
|
return volume;
|
|
}
|
|
else
|
|
{
|
|
log.DebugFormat("GetVolumeFromSamples({0}) returns 0", ix);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|