/// /// 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 { /// /// Holds information identifying the test bench. /// 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 samplesDict; DataStreamInterface.Unit timeUnit; DataStreamInterface.Unit volumeUnit; public Reader() { } public Reader(Generic.IComponentCfg cfg, IList 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(); 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; } } } }