diff --git a/TBF/Rig/RegisterReaders/GenesisRegReader/communication/Utils/ISerialDriver.cs b/TBF/Rig/RegisterReaders/GenesisRegReader/communication/Utils/ISerialDriver.cs index cc07bcf90..3d4245c27 100644 --- a/TBF/Rig/RegisterReaders/GenesisRegReader/communication/Utils/ISerialDriver.cs +++ b/TBF/Rig/RegisterReaders/GenesisRegReader/communication/Utils/ISerialDriver.cs @@ -5,8 +5,9 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication.Utils { public interface ISerialDriver : IDisposable { - bool IsOpen(); - bool Open(); + bool IsOpen { get; } + void Open(); + void Close(); void CloseConnection(); void DiscardInBuffer(); diff --git a/TBF/Rig/RegisterReaders/GenesisRegReader/communication/Utils/SerialDriver.cs b/TBF/Rig/RegisterReaders/GenesisRegReader/communication/Utils/SerialDriver.cs index 4f450c91f..add5c6b79 100644 --- a/TBF/Rig/RegisterReaders/GenesisRegReader/communication/Utils/SerialDriver.cs +++ b/TBF/Rig/RegisterReaders/GenesisRegReader/communication/Utils/SerialDriver.cs @@ -68,9 +68,9 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication.Utils _discardOutBufferOnOpen = discardOutBufferOnOpen; } - public bool Open() + public void Open() { - return OpenConnection( + OpenConnection( _portName, _baudRate, _dataBits, @@ -188,6 +188,11 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication.Utils } } + public void Close() + { + CloseConnection(); + } + public void CloseConnection() { if (_serialPort != null) @@ -200,7 +205,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication.Utils } } - public bool IsOpen() => _serialPort?.IsOpen == true; + public bool IsOpen => _serialPort?.IsOpen == true; public void DiscardInBuffer() { @@ -216,7 +221,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication.Utils public string ReadExisting() { - if (!IsOpen()) + if (!IsOpen) throw new InvalidOperationException("Serial port not open"); return _serialPort.ReadExisting(); @@ -230,7 +235,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication.Utils public string ReadLine() { - if (!IsOpen()) + if (!IsOpen) throw new InvalidOperationException("Serial port not open"); return _serialPort.ReadLine(); @@ -238,7 +243,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication.Utils public string ReadLine(int timeoutMs) { - if (!IsOpen()) + if (!IsOpen) throw new InvalidOperationException("Serial port not open"); int originalTimeout = _serialPort.ReadTimeout; @@ -256,7 +261,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication.Utils public bool SendMessage(byte[] sendDataBytes, int length, int readTimeout = 1000, int writeTimeout = 1000) { - if (!IsOpen()) return false; + if (!IsOpen) return false; if (sendDataBytes == null || sendDataBytes.Length == 0) return true; try @@ -275,7 +280,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication.Utils public byte[] SendAndWait(byte[] data, int timeoutMs) { - if (!IsOpen()) + if (!IsOpen) throw new InvalidOperationException("Serial port not open"); try diff --git a/TBF/Rig/RegisterReaders/GenesisRegReader/communication/Utils/SerialDriverBuilder.cs b/TBF/Rig/RegisterReaders/GenesisRegReader/communication/Utils/SerialDriverBuilder.cs index 85f2b498a..4661c4a9e 100644 --- a/TBF/Rig/RegisterReaders/GenesisRegReader/communication/Utils/SerialDriverBuilder.cs +++ b/TBF/Rig/RegisterReaders/GenesisRegReader/communication/Utils/SerialDriverBuilder.cs @@ -175,7 +175,8 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication.Utils public SerialDriver BuildAndOpen() { var driver = Build(); - if (!driver.Open()) + driver.Open(); + if (!driver.IsOpen) { throw new InvalidOperationException(driver.ErrorMessage); } diff --git a/TBF/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReader.cs b/TBF/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReader.cs index 444d97fcb..b12e37615 100644 --- a/TBF/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReader.cs +++ b/TBF/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReader.cs @@ -962,13 +962,13 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations private double CalculateTimeByChannels() { - double[] timestampSec = new double[iChanelsCount]; + double[] timeDelta = new double[iChanelsCount]; for (int iChanel = 0; iChanel < iChanelsCount; iChanel++) { - timestampSec[iChanel] = timestampSec[iChanel] - timestampSec0[iChanel]; + timeDelta[iChanel] = this.timestampSec[iChanel] - this.timestampSec0[iChanel]; } - - return Average(timestampSec); + + return Average(timeDelta); } private double CalculateVolumeByChannels() @@ -976,7 +976,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations double[] volumeDelta = new double[iChanelsCount]; for (int iChanel = 0; iChanel < iChanelsCount; iChanel++) { - volumeDelta[iChanel] = volumeLtr[iChanel] - volumeLtr0[iChanel]; + volumeDelta[iChanel] = this.volumeLtr[iChanel] - this.volumeLtr0[iChanel]; } return Average(volumeDelta); @@ -1008,7 +1008,8 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations if (_serialFactory != null) { optoSerialPort = _serialFactory(); - if (!optoSerialPort.Open()) + optoSerialPort.Open(); + if (!optoSerialPort.IsOpen) throw new InvalidOperationException("Failed to open injected serial driver."); } else @@ -1045,7 +1046,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations { if (optoSerialPort != null) { - optoSerialPort.CloseConnection(); + optoSerialPort.Close(); optoSerialPort = null; log.FatalFormat($"{Name} OptoPort closed: {this}"); } @@ -1076,7 +1077,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations endTelegramIdx3 = 0; TestEndTelegramIx = 0; - if (optoSerialPort != null && optoSerialPort.IsOpen()) optoSerialPort.DiscardInBuffer(); + if (optoSerialPort != null && optoSerialPort.IsOpen) optoSerialPort.DiscardInBuffer(); if (flowDirectionDetection != null) flowDirectionDetection.ClearFifo(); /// Clear FIFO for flow direction detection @@ -1853,10 +1854,10 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations public async Task DataEntry_EndVolumeAsync() { - if (optoSerialPort == null || !optoSerialPort.IsOpen()) + if (optoSerialPort == null || !optoSerialPort.IsOpen) { StartDataStreamProcessing(); - if (optoSerialPort == null || !optoSerialPort.IsOpen()) + if (optoSerialPort == null || !optoSerialPort.IsOpen) { log.Error($"optoSerialPort COM: {this.OptoComPortNr} is not open - DataEntry_EndVolumeAsync()"); return Double.NaN; @@ -1900,7 +1901,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations log.Debug($"Try get End Volume! COM: {this.OptoComPortNr}, Volume: {volumeLtr}"); - if (optoSerialPort != null && optoSerialPort.IsOpen()) CloseOptoSerialPort(); + if (optoSerialPort != null && optoSerialPort.IsOpen) CloseOptoSerialPort(); if (!Double.IsNaN(volumeLtr[channel0])) { @@ -1975,7 +1976,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations } log.Debug($"Try get Start Volume! COM: {this.OptoComPortNr}, Volume: {volumeLtr0}"); - if (optoSerialPort != null && optoSerialPort.IsOpen()) CloseOptoSerialPort(); + if (optoSerialPort != null && optoSerialPort.IsOpen) CloseOptoSerialPort(); if (!Double.IsNaN(volumeLtr0[channel0])) { diff --git a/TBFTests/Rig/RegisterReaders/GenesisRegReader/implementations/FakeSerialDriver.cs b/TBFTests/Rig/RegisterReaders/GenesisRegReader/implementations/FakeSerialDriver.cs index d745532de..f8b9eaba0 100644 --- a/TBFTests/Rig/RegisterReaders/GenesisRegReader/implementations/FakeSerialDriver.cs +++ b/TBFTests/Rig/RegisterReaders/GenesisRegReader/implementations/FakeSerialDriver.cs @@ -24,13 +24,17 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations public void EnqueueLine(string line) => _lines.Enqueue(line); - public bool IsOpen() => _isOpen; + public bool IsOpen => _isOpen; - public bool Open() + public void Open() { OpenCalls++; _isOpen = true; - return true; + } + + public void Close() + { + CloseConnection(); } public void CloseConnection() diff --git a/TBFTests/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReaderTest.cs b/TBFTests/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReaderTest.cs index c7db3a5c0..d525145e7 100644 --- a/TBFTests/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReaderTest.cs +++ b/TBFTests/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReaderTest.cs @@ -6,34 +6,18 @@ using TBF.Rig; using TBF.Rig.RegisterReaders.GenesisRegReader; using TBF.Rig.RegisterReaders.GenesisRegReader.implementations; - namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations { [TestClass] [TestSubject(typeof(GenesisSmartReader))] public class GenesisSmartReaderTest { - + private const int ChannelCount = 3; private static GenesisCfg CreateCfg() { Factory factory = new Factory(); - return new GenesisCfg(factory); - // { - // OptoComPortNr = 7, - // RfidComPortNr = 8, - // MuxBoardNr = 1, - // Group = 1, - // CommunicationInterface = CommunicationInterface.RFID, - // ProcParams = new ProcParams - // { - // CalibTarget = 0, - // FactorLimitLo = 0, - // FactorLimitHi = 65535, - // Counting = Counting.Arbitrary - // } - // }; } private static void SetPrivateField(object target, string fieldName, object value) @@ -54,6 +38,21 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations return (T)field.GetValue(target); } + private static void InitializeThreeChannelState(GenesisSmartReader reader) + { + SetPrivateField(reader, "volumeRawExtLast", new double[ChannelCount]); + SetPrivateField(reader, "timestampExtLast", new double[ChannelCount]); + + SetPrivateField(reader, "lastVolumeRaw", new double[ChannelCount]); + SetPrivateField(reader, "lastTimestamp", new double[ChannelCount]); + + SetPrivateField(reader, "volumeLtr", new[] { 0.0, 0.0, 0.0 }); + SetPrivateField(reader, "volumeLtr0", new[] { 0.0, 0.0, 0.0 }); + + SetPrivateField(reader, "timestampSec", new[] { 0.0, 0.0, 0.0 }); + SetPrivateField(reader, "timestampSec0", new[] { 0.0, 0.0, 0.0 }); + } + [TestMethod] public void Start_ShouldOpenPort_AndEnableProcessing() { @@ -62,8 +61,8 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations reader.Initialize(); reader.Start(); - - Assert.IsTrue(fake.IsOpen()); + + Assert.IsTrue(fake.IsOpen); Assert.IsTrue(fake.OpenCalls >= 1); Assert.AreEqual(1, fake.DiscardInCalls); } @@ -77,11 +76,11 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations reader.Initialize(); reader.Start(); - Assert.IsTrue(fake.IsOpen()); + Assert.IsTrue(fake.IsOpen); reader.Stop(); - Assert.IsFalse(fake.IsOpen()); + Assert.IsFalse(fake.IsOpen); Assert.AreEqual(2, fake.CloseCalls); } @@ -96,11 +95,7 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations SetPrivateField(reader, "currentTelegramIx", 12); SetPrivateField(reader, "timeFromStart", 7); - // prevent ReadPulses() from crashing if needed - SetPrivateField(reader, "volumeLtr", 0.0); - SetPrivateField(reader, "volumeLtr0", 0.0); - SetPrivateField(reader, "timestampSec", 0.0); - SetPrivateField(reader, "timestampSec0", 0.0); + InitializeThreeChannelState(reader); var ev = reader.Run(); @@ -115,17 +110,13 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations var reader = new GenesisSmartReader(CreateCfg(), () => fake); reader.Initialize(); + InitializeThreeChannelState(reader); - // Important if these arrays are not initialized elsewhere - SetPrivateField(reader, "volumeRawExtLast", new double[3]); - SetPrivateField(reader, "timestampExtLast", new double[3]); - - // valid sample line for your protocol - var line = "FFFFFE\t51EA\t0000\t65324E\t0087\tF6319DFF\t86"; + var line = "@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331"; reader.optoSerialPort = fake; fake.Open(); - + reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave); int optoDataCount = GetPrivateField(reader, "optoDataCount"); @@ -145,19 +136,69 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations reader.Initialize(); reader.optoSerialPort = fake; - - SetPrivateField(reader, "volumeRawExtLast", new double[3]); - SetPrivateField(reader, "timestampExtLast", new double[3]); + InitializeThreeChannelState(reader); reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave); var volumeRawExtLast = GetPrivateField(reader, "volumeRawExtLast"); var timestampExtLast = GetPrivateField(reader, "timestampExtLast"); - Assert.IsTrue( - volumeRawExtLast[expectedChannelIndex] != 0 || - timestampExtLast[expectedChannelIndex] != 0, - $"Channel {expectedChannelIndex} was not updated"); + for (int i = 0; i < ChannelCount; i++) + { + if (i == expectedChannelIndex) + { + Assert.IsTrue( + volumeRawExtLast[i] != 0 || timestampExtLast[i] != 0, + $"Channel {i} was expected to be updated, but it was not."); + } + else + { + Assert.AreEqual(0.0, volumeRawExtLast[i], $"Unexpected volume update in channel {i}"); + Assert.AreEqual(0.0, timestampExtLast[i], $"Unexpected timestamp update in channel {i}"); + } + } + } + + [TestMethod] + public void Run_WhenChannel0IsAverageModeMinus2_ShouldReadUsingAllThreeChannels() + { + var fake = new FakeSerialDriver(); + var reader = new GenesisSmartReader(CreateCfg(), () => fake); + + reader.Initialize(); + reader.Start(); + + SetPrivateField(reader, "channel0", -2); + SetPrivateField(reader, "volumeLtr0", new[] { 10.0, 20.0, 30.0 }); + SetPrivateField(reader, "volumeLtr", new[] { 13.0, 24.0, 35.0 }); + SetPrivateField(reader, "timestampSec0", new[] { 100.0, 100.0, 100.0 }); + SetPrivateField(reader, "timestampSec", new[] { 110.0, 112.0, 114.0 }); + + var ev = reader.Run(); + + Assert.AreEqual(Event.ReadRegisterDone, ev); + Assert.AreEqual(4.0, reader.WMVolume, 1E-6); // average of (3, 4, 5) + Assert.AreEqual(4000, reader.WMPulses); + } + + [TestMethod] + public void ProcessOptoLine_FirstValidTelegram_ShouldSetCurrentTelegramIndex() + { + var fake = new FakeSerialDriver(); + fake.Open(); + + var reader = new GenesisSmartReader(CreateCfg(), () => fake); + reader.Initialize(); + + reader.optoSerialPort = fake; + InitializeThreeChannelState(reader); + + var line = "@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD"; + + reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave); + + int currentTelegramIx = GetPrivateField(reader, "currentTelegramIx"); + Assert.AreEqual(0, currentTelegramIx); } } } \ No newline at end of file