diff --git a/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/MagFluxMeter.cs b/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/MagFluxMeter.cs index 70b47356..2bedec84 100644 --- a/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/MagFluxMeter.cs +++ b/Common/Hardware/WaterMeter/MagFlux/MagFluxCore/MagFluxMeter.cs @@ -16,11 +16,9 @@ using Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol; using Xylem.Common.Hardware.WaterMeter.MagFlux.DataPackages.EventArguments; using Xylem.Common.Hardware.WaterMeter.MagFlux.DataPackages.MeasurementRecords; using Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxConfig; -using Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxConfig.Const; using Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts; -using Xylem.Common.Logic.SoftwareAccessHelper; using Xylem.Common.Metrology.Measurements; using Xylem.Common.Metrology.Measurements.Consts; using Xylem.Common.Utils.Logging; @@ -36,50 +34,20 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore /// public class MagFluxMeter : IMeter, IMeterEvents { - #region class handling + #region Variables and Properties /// - /// Ctor - default + /// Enable raw record logging, if set every incoming package will be logged /// - /// - /// - Initial - /// - public MagFluxMeter() - { - SetLogger(); - } - - /// - public void Dispose() - { - throw new NotImplementedException(); - } + private Boolean _enableRawDataLogging; /// - /// Ctor + /// to reduce the IrdA communication in test bench, preparation will be done once (when SkipPreparationForTestBench is true) /// - /// Slot number for test-bench - /// for request Port - /// for streaming Port - /// don´t send CRC error or telegrams with error flag to caller - /// - /// If you have a password for highest access level you need, if you don't want to access the meter - /// (just read led record) than you can leave it null - /// - /// - /// - Initial - /// - public MagFluxMeter(Int32 slot, PortConfig? requestPort, PortConfig? streamingPort, - Boolean ignoreCorruptedData = true, String password = null) + public Boolean SkipPreparationForTestBench { - _logger = NLogHelper.CreateOrGetMultiLogger($"Slot:{slot}", "Slot", "Meter", "MeterBase", "MeterBase"); - SetupMagFluxMeter(slot, requestPort, streamingPort, ignoreCorruptedData, password); + get; set; } - - #endregion - - #region variables and properties - /// /// List of ongoing measurements, base- and calibration-measurements /// @@ -141,7 +109,7 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore { get; private set; } - + /// /// streaming protocol assignment/info /// @@ -251,491 +219,20 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore #endregion - #region events - /// - event EventHandler IMeter.OnProcessStatusChanged - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - event EventHandler IMeterEvents.OnErrorStatusChanged - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - event EventHandler IMeterEvents.OnInitCompleted - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - event EventHandler IMeterEvents.OnMeasurementInitCompleted - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - event EventHandler IMeterEvents.OnMeasurementCompleted - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - event EventHandler IMeterEvents.OnCalibInitCompleted - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - event EventHandler IMeterEvents.OnCalibCompleted - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - event EventHandler IMeterEvents.OnProcessStatusChanged - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - event EventHandler IMeter.OnErrorStatusChanged - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - event EventHandler IMeter.OnInitCompleted - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - event EventHandler IMeter.OnMeasurementInitCompleted - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - event EventHandler IMeter.OnMeasurementCompleted - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - event EventHandler IMeter.OnCalibInitCompleted - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - event EventHandler IMeter.OnCalibCompleted - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - /// - public event EventHandler OnDisposeCompleted; - #endregion - - #region MagFlux handling - /// - /// just internal setup. called on ctor or from vb6 setup function - /// - /// Slot Number for test-bench - /// for RFID/UART/IrDA Port - /// for LED Port - /// don´t send CRC error or telegrams with error flag to caller - /// - /// If you have a password for highest access level you need, if you don't want to access the meter - /// (just read led record) than you can leave it nullS - /// - private void SetupMagFluxMeter(Int32 slot, PortConfig? requestPort, PortConfig? streamingPort, - Boolean ignoreCorruptedData = true, String password = "") - { - Slot = slot; - SetLogger(); - _password = password; - - if (requestPort != null) - { - if (requestPort.Value.Type == "Xylem.Common.Hardware.Interfaces.Ports.SerialPorts.UartSerialPort") - { - var requestIdent = $"Slot:{Slot}, Port:{requestPort.Value.PortName}, Protocol:Request, Type:UART -"; - - RequestProtocol = new RequestProtocol(requestIdent); - TransmitProtocol = new UartTransmitProtocol(requestPort.Value.PortName); - RequestProtocol.SetTransmitProtocol(TransmitProtocol); - - RequestPort = new UartSerialPort(requestIdent, requestPort.Value.GetSerialPort(), - TransmitProtocol.GetTransmitPortSettings()); - } - } - - if (streamingPort != null) - { - var ledTransmit = new LedTransmitProtocol(streamingPort.Value.PortName); - - var streamingIdent = $"Slot:{Slot}/{streamingPort.Value.PortName}-Protocol:LED"; - - StreamingPort = new LedSerialPort(streamingIdent, streamingPort.Value.GetSerialPort(), - ledTransmit.GetTransmitPortSettings()); - StreamingProtocol = new StreamingProtocol(streamingIdent, ignoreCorruptedData); - } - Configuration = new ProcessConfig(ProgramConfig.ConfigFileName); - _logger.Debug($"Slot:{Slot} - Setup done"); - } - - #endregion - - - /// - /// - /// Start Event listening, has to be called after - /// - public void ConnectMeter() - { - if (RequestPort != null && RequestPort.GetPortName() != BaseSerialPort.PortNotAssigned) - { - LinkPortToProtocol(RequestPort, RequestProtocol); - _logger.Trace($"Slot:{Slot} - RequestPort and RequestProtocol linked"); - RequestProtocol.OnRecordIsDecoded += RequestProtocol_ApplyDecodedRecord; - } - if (StreamingPort != null && StreamingPort.GetPortName() != BaseSerialPort.PortNotAssigned) - { - LinkPortToProtocol(StreamingPort, StreamingProtocol); - _logger.Trace($"Slot:{Slot} - StreamingPort and StreamingProtocol linked"); - StreamingProtocol.OnRecordIsDecoded += StreamingProtocol_ApplyDecodedRecord; - } - - _logger.Debug($"Slot:{Slot} - Connected and communication started"); - } - - /// - /// Add a port to working queue - /// - /// On should one once added in runtime - /// - public void LinkPortToProtocol(IPort port, IProtocol protocol) - { - //for streaming mode only - if (port == null) - { - return; - } - - port.OnRawRecordReceived += delegate (Object o, BasePortDataEventArgs rawMsg) - { - protocol.FillDecodingBuffer(rawMsg); - }; - try - { - if (!port.IsOpen()) - { - port.Open(); - } - } - catch (Exception ex) - { - throw new ApplicationException($"Cannot Open Comport. Check TaskManager for other Genesis relevant programs and close them. Also check if the comport is valid! { Environment.NewLine }{ ex.Message}"); - } - - protocol.OnRecordReadyToSend += delegate (Object o, BasePortDataEventArgs dataToSend) - { - var data = (List)dataToSend.GetData(); - port.PortWrite(data.ToArray()); - }; - } - - /// - /// Synchronization of the record for the streaming interface - /// - /// - /// - public void SyncStreamingBuffer(SyncMarkRecord markRecord) - { - if (StreamingPort == null) - { - throw new ApplicationException("Synchronization not possible due to undefined streaming port"); - } - - StreamingPort.SynchronizeReceiveBuffer(markRecord); - } - - private void RequestProtocol_AuthorizationGrant(Object sender, EventArgs e) - { - - _logger.Debug($"Slot:{Slot} - Authorization succeeded"); - - } - /// - public void SetupFromConfigFile(Int32 slot, Boolean ignoreCorruptedData = true) - { - SetupFromConfigFile(slot, ignoreCorruptedData, true, true); - } - - /// - /// Setup water meter from configuration file: - /// -slot, - /// -streaming protocol, - /// -streaming port - /// -request port - /// - /// - /// - /// - /// - /// - public void SetupFromConfigFile(Int32 slot, Boolean ignoreCorruptedData, Boolean useRequest, Boolean useStreaming) - { - - Slot = slot; - SetLogger(); - - - var configFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(MagFlux), ProgramConfig.SerialConfigFileName); - - if (!File.Exists(configFile)) - { - configFile = Path.Combine(ProgramConfig.SerialConfigFileName); - if (!File.Exists(configFile)) - { - throw new ApplicationException($"Configuration file {configFile} not found "); - } - } - var tr = new StreamReader(configFile); - var slotConfigList = JsonConvert.DeserializeObject(tr.ReadToEnd()); - - var slotConfig = slotConfigList.FirstOrDefault(t => t.Slot == slot); - - if (slotConfig == null) - { - throw new ApplicationException($"Slot:{slot} - File " + - $"{ProgramConfig.SerialConfigFileName} does not contain valid configuration"); - } - _logger.Debug($"Slot:{slot} - Configuration loaded"); - if (!useRequest) - { - SetupMagFluxMeter(slot, null, slotConfig.Streaming, ignoreCorruptedData); - } - else if (!useStreaming) - { - SetupMagFluxMeter(slot, slotConfig.Request, null, ignoreCorruptedData); - } - else - { - SetupMagFluxMeter(slot, slotConfig.Request, slotConfig.Streaming, ignoreCorruptedData); - } - } - - /// - public Boolean Logout() - { - return true; - } - - /// - public Boolean Login() - { - return true; - } - - /// - public Boolean Login(String password, Boolean runImmediately = true, Boolean skipReadMeterFwAndAssignRegisters = false) - { - return true; - } - - /// - public void InitMeasurement() - { - throw new NotImplementedException(); - } - - /// - public void StartMeasurement() - { - _listOfIMeasurement = new List - { - new BaseMeasurement(Slot, typeof(MagFluxRecord), IntermediateUpdateTimeS) - }; - - foreach (var measurement in _listOfIMeasurement) - { - measurement.OnActionStateHasChanged += Measurement_ActionStateHasChanged; - } - - _logger.Info($"Slot:{Slot} - Start measurement"); - - ProcessStatus = ProcessState.MeasurementIsActive; - _listOfIMeasurement.ForEach(m => m.MeasurementState = MeasurementStates.IsWaitingForStartData); - SyncStreamingBuffer(SyncMarkRecord.SyncStart); - } - - /// - public void StopMeasurement() - { - _logger.Info($"Slot:{Slot} - Stop measurement"); - ProcessStatus = ProcessState.MeasurementIsDone; - _listOfIMeasurement.ForEach(m => m.MeasurementState = MeasurementStates.IsWaitingForEndData); - SyncStreamingBuffer(SyncMarkRecord.SyncEnd); - } - - private void Measurement_ActionStateHasChanged(Object sender, EventArgs e) - { - SyncStreamingBuffer(SyncMarkRecord.DecodeIntermediate); - } - - /// - public MeasurementResults GetMainMeasurementResult(Double? refVolume, Double? refTimeS, - Boolean intermediateMeasurement = false) - { - throw new NotImplementedException(); - } - - /// - public List GetAllMeasurementResults(Double? refVolume, Double? refTimeS, Boolean intermediateMeasurement = false, - Int32? channel = null) - { - throw new NotImplementedException(); - } - - /// - public MeasurementStates GetMeasurementState(Int32? onlyChannelNr = null) - { - throw new NotImplementedException(); - } - - /// - public Boolean RequestIntermediateMeasurementState(Int32? onlyChannelNr = null) - { - throw new NotImplementedException(); - } - - /// - public void InitCalibration() - { - throw new NotImplementedException(); - } - - /// - public void StartCalibration() - { - throw new NotImplementedException(); - } - - /// - public void StopCalibration() - { - throw new NotImplementedException(); - } - - /// - public MeasurementStates GetCalibrationState() - { - throw new NotImplementedException(); - } - - /// - public void BuildAndCheckCalibFactorsAllChannels(Double refVolumeCm, Double? refTimeS = null, Double reqDeviationPercent = 0, - Double maxCalibFactorTolerancePercent = 0) - { - throw new NotImplementedException(); - } - - /// - public void SetCalibFactorsAllChannels(Boolean justLog = false) - { - throw new NotImplementedException(); - } - - /// - public void SetLcdText(Boolean release, Byte[] textInHex) - { - throw new NotImplementedException(); - } - - /// - public void SetProcessState(DisplayCodes newState, Boolean webRequest = true) - { - throw new NotImplementedException(); - } - - /// - public DisplayCodes GetLastProcessState() - { - throw new NotImplementedException(); - } - - /// - public void WriteLog(String text) - { - throw new NotImplementedException(); - } - - /// - public void LogRawData(Boolean on) - { - throw new NotImplementedException(); - } - - /// - public Boolean CheckStateAfterMeasurement() - { - throw new NotImplementedException(); - } - - /// - public void DisposeMeter() - { - Dispose(); - } - - private void AddData(IMeasurementRecord newRecord) - { - - foreach (var measurement in _listOfIMeasurement) - { - if (measurement.GetType() != newRecord.GetType()) - { - continue; - } - - if (measurement.GetChannel() == newRecord.GetChannel()) - { - measurement.AddData(newRecord); - } - } - - // when every measurement has state IsRunning or every measurement has state IsCompleted, the streaming buffer set to skip decoding - if (_listOfIMeasurement.All(m => m.MeasurementState == MeasurementStates.IsRunning) - || _listOfIMeasurement.All(m => m.MeasurementState == MeasurementStates.IsCompleted)) - { - SyncStreamingBuffer(QualityWatchMode - ? SyncMarkRecord.DecodeIntermediateQuality - : SyncMarkRecord.SkipDecoding); - } - - } - #region Events + event EventHandler IMeter.OnDisposeCompleted + { + add + { + // throw new NotImplementedException(); + } + + remove + { + // throw new NotImplementedException(); + } + } //public event EventHandler HasInformationForCaller; /// @@ -836,6 +333,585 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore OnRequestRecordReceived?.Invoke(sender, (RequestResponseDataEventArgs)e); } } + #endregion + + #region class handling + + /// + /// Ctor - default + /// + /// + /// - Initial + /// + public MagFluxMeter() + { + SetLogger(); + } + + /// + public void Dispose() + { + _logger.Trace($"Slot:{Slot} - Start to dispose"); + + LogRawData(false); + LogManager.Flush(); + //isPart of Logout + //StopKeepSession(); + + //Cancel receive tokens + _keepSessionToken?.Cancel(); + + try + { + Logout(); + } + catch (Exception) + { + // ignored + } + + + //Run thread again to notice CancellationToken has changed + _onSyncKeepSessionThread?.Set(); + + //this timeout counter is being used for dispose only + var timeoutCounter = 100; + if (_keepSessionThread != null) + { + while (_keepSessionThread.ThreadState != ThreadState.Stopped && timeoutCounter > 0) + { + Thread.Sleep(1); + timeoutCounter -= 1; + } + + if (_keepSessionThread.ThreadState != ThreadState.Stopped) + { + //if thread is still running try to abort + // try to avoid abort (takes age to run and is not safe) + _keepSessionThread.Abort(); + } + } + + _keepSessionThread = null; + + RequestPort?.Dispose(); + StreamingPort?.Dispose(); + + RequestProtocol?.Dispose(); + StreamingProtocol?.Dispose(); + _logger.Trace($"Slot:{Slot} - Dispose is finished"); + } + + + /// + /// Ctor + /// + /// Slot number for test-bench + /// for request Port + /// for streaming Port + /// don´t send CRC error or telegrams with error flag to caller + /// + /// If you have a password for highest access level you need, if you don't want to access the meter + /// (just read led record) than you can leave it null + /// + /// + /// - Initial + /// + public MagFluxMeter(Int32 slot, PortConfig? requestPort, PortConfig? streamingPort, + Boolean ignoreCorruptedData = true, String password = null) + { + _logger = NLogHelper.CreateOrGetMultiLogger($"Slot:{slot}", "Slot", "Meter", "MeterBase", "MeterBase"); + SetupMagFluxMeter(slot, requestPort, streamingPort, ignoreCorruptedData, password); + } + + #endregion + + #region MagFlux handling + /// + /// just internal setup. called on ctor or from vb6 setup function + /// + /// Slot Number for test-bench + /// for RFID/UART/IrDA Port + /// for LED Port + /// don´t send CRC error or telegrams with error flag to caller + /// + /// If you have a password for highest access level you need, if you don't want to access the meter + /// (just read led record) than you can leave it nullS + /// + private void SetupMagFluxMeter(Int32 slot, PortConfig? requestPort, PortConfig? streamingPort, + Boolean ignoreCorruptedData = true, String password = "") + { + Slot = slot; + SetLogger(); + _password = password; + + if (requestPort != null) + { + if (requestPort.Value.Type == "Xylem.Common.Hardware.Interfaces.Ports.SerialPorts.UartSerialPort") + { + var requestIdent = $"Slot:{Slot}, Port:{requestPort.Value.PortName}, Protocol:Request, Type:UART -"; + + RequestProtocol = new RequestProtocol(requestIdent); + TransmitProtocol = new UartTransmitProtocol(requestPort.Value.PortName); + RequestProtocol.SetTransmitProtocol(TransmitProtocol); + + RequestPort = new UartSerialPort(requestIdent, requestPort.Value.GetSerialPort(), + TransmitProtocol.GetTransmitPortSettings()); + } + } + + if (streamingPort != null) + { + var ledTransmit = new LedTransmitProtocol(streamingPort.Value.PortName); + + var streamingIdent = $"Slot:{Slot}/{streamingPort.Value.PortName}-Protocol:LED"; + + StreamingPort = new LedSerialPort(streamingIdent, streamingPort.Value.GetSerialPort(), + ledTransmit.GetTransmitPortSettings()); + StreamingProtocol = new StreamingProtocol(streamingIdent, ignoreCorruptedData); + } + Configuration = new ProcessConfig(ProgramConfig.ConfigFileName); + _logger.Debug($"Slot:{Slot} - Setup done"); + } + + /// + /// + /// Start Event listening, has to be called after + /// + public void ConnectMeter() + { + if (RequestPort != null && RequestPort.GetPortName() != BaseSerialPort.PortNotAssigned) + { + LinkPortToProtocol(RequestPort, RequestProtocol); + _logger.Trace($"Slot:{Slot} - RequestPort and RequestProtocol linked"); + RequestProtocol.OnRecordIsDecoded += RequestProtocol_ApplyDecodedRecord; + } + if (StreamingPort != null && StreamingPort.GetPortName() != BaseSerialPort.PortNotAssigned) + { + LinkPortToProtocol(StreamingPort, StreamingProtocol); + _logger.Trace($"Slot:{Slot} - StreamingPort and StreamingProtocol linked"); + StreamingProtocol.OnRecordIsDecoded += StreamingProtocol_ApplyDecodedRecord; + } + + _logger.Debug($"Slot:{Slot} - Connected and communication started"); + } + + /// + /// Add a port to working queue + /// + /// On should one once added in runtime + /// + public void LinkPortToProtocol(IPort port, IProtocol protocol) + { + //for streaming mode only + if (port == null) + { + return; + } + + port.OnRawRecordReceived += delegate (Object o, BasePortDataEventArgs rawMsg) + { + protocol.FillDecodingBuffer(rawMsg); + }; + try + { + if (!port.IsOpen()) + { + port.Open(); + } + } + catch (Exception ex) + { + throw new ApplicationException($"Cannot Open Comport. Check TaskManager for other Genesis relevant programs and close them. Also check if the comport is valid! { Environment.NewLine }{ ex.Message}"); + } + + protocol.OnRecordReadyToSend += delegate (Object o, BasePortDataEventArgs dataToSend) + { + var data = (List)dataToSend.GetData(); + port.PortWrite(data.ToArray()); + }; + } + + /// + /// Synchronization of the record for the streaming interface + /// + /// + /// + public void SyncStreamingBuffer(SyncMarkRecord markRecord) + { + if (StreamingPort == null) + { + throw new ApplicationException("Synchronization not possible due to undefined streaming port"); + } + + StreamingPort.SynchronizeReceiveBuffer(markRecord); + } + + private void RequestProtocol_AuthorizationGrant(Object sender, EventArgs e) + { + + _logger.Debug($"Slot:{Slot} - Authorization succeeded"); + + } + /// + public void SetupFromConfigFile(Int32 slot, Boolean ignoreCorruptedData = true) + { + SetupFromConfigFile(slot, ignoreCorruptedData, true, true); + } + + /// + /// Setup water meter from configuration file: + /// -slot, + /// -streaming protocol, + /// -streaming port + /// -request port + /// + /// + /// + /// + /// + /// + public void SetupFromConfigFile(Int32 slot, Boolean ignoreCorruptedData, Boolean useRequest, Boolean useStreaming) + { + + Slot = slot; + SetLogger(); + + + var configFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(MagFlux), ProgramConfig.SerialConfigFileName); + + if (!File.Exists(configFile)) + { + configFile = Path.Combine(ProgramConfig.SerialConfigFileName); + if (!File.Exists(configFile)) + { + throw new ApplicationException($"Configuration file {configFile} not found "); + } + } + var tr = new StreamReader(configFile); + var slotConfigList = JsonConvert.DeserializeObject(tr.ReadToEnd()); + + var slotConfig = slotConfigList.FirstOrDefault(t => t.Slot == slot); + + if (slotConfig == null) + { + throw new ApplicationException($"Slot:{slot} - File " + + $"{ProgramConfig.SerialConfigFileName} does not contain valid configuration"); + } + _logger.Debug($"Slot:{slot} - Configuration loaded"); + if (!useRequest) + { + SetupMagFluxMeter(slot, null, slotConfig.Streaming, ignoreCorruptedData); + } + else if (!useStreaming) + { + SetupMagFluxMeter(slot, slotConfig.Request, null, ignoreCorruptedData); + } + else + { + SetupMagFluxMeter(slot, slotConfig.Request, slotConfig.Streaming, ignoreCorruptedData); + } + } + + /// + public Boolean Logout() + { + return true; + } + + /// + public Boolean Login() + { + return true; + } + + /// + public Boolean Login(String password, Boolean runImmediately = true, Boolean skipReadMeterFwAndAssignRegisters = false) + { + return true; + } + + /// + public void InitMeasurement() + { + _logger.Info($"Slot:{Slot} - Init measurement"); + PreMeasurement(); + } + + private void PreMeasurement() + { + if (!SkipPreparationForTestBench) + { + SkipPreparationForTestBench = true; + } + else + { + WriteLog($"wait for measurement is starting"); + } + ProcessStatus = ProcessState.WaitForMeasurement; + } + + /// + public void StartMeasurement() + { + _listOfIMeasurement = new List + { + new BaseMeasurement(Slot, typeof(MagFluxRecord), IntermediateUpdateTimeS) + }; + + foreach (var measurement in _listOfIMeasurement) + { + measurement.OnActionStateHasChanged += Measurement_ActionStateHasChanged; + } + + _logger.Info($"Slot:{Slot} - Start measurement"); + + ProcessStatus = ProcessState.MeasurementIsActive; + _listOfIMeasurement.ForEach(m => m.MeasurementState = MeasurementStates.IsWaitingForStartData); + SyncStreamingBuffer(SyncMarkRecord.SyncStart); + } + + /// + public void StopMeasurement() + { + _logger.Info($"Slot:{Slot} - Stop measurement"); + ProcessStatus = ProcessState.MeasurementIsDone; + _listOfIMeasurement.ForEach(m => m.MeasurementState = MeasurementStates.IsWaitingForEndData); + SyncStreamingBuffer(SyncMarkRecord.SyncEnd); + } + + private void Measurement_ActionStateHasChanged(Object sender, EventArgs e) + { + SyncStreamingBuffer(SyncMarkRecord.DecodeIntermediate); + } + + /// + public MeasurementResults GetMainMeasurementResult(Double? refVolume, Double? refTimeS, + Boolean intermediateMeasurement = false) + { + if (!intermediateMeasurement && GetMeasurementState(0) != MeasurementStates.IsCompleted) + { + throw new ApplicationException("Measurement is not completed"); + } + return GetAllMeasurementResults(refVolume, refTimeS, intermediateMeasurement, 0).First(); + } + + /// + public List GetAllMeasurementResults(Double? refVolume, Double? refTimeS, Boolean intermediateMeasurement = false, + Int32? channel = null) + { + if (!intermediateMeasurement && GetMeasurementState(channel) != MeasurementStates.IsCompleted) + { + throw new ApplicationException("Measurement is not completed"); + } + var mainMeasurement = _listOfIMeasurement.FirstOrDefault(m => m.GetType() == typeof(MagFluxRecord)); + + if (mainMeasurement == null) + { + throw new ApplicationException("Can not find an ongoing measurement"); + } + + var results = new List(); + var mainResult = intermediateMeasurement + ? mainMeasurement.GetIntermediateMeasurementResult(refVolume, refTimeS) + : mainMeasurement.GetFinalMeasurementResult(refVolume, refTimeS); + results.Add(mainResult); + _logger.Info($"Slot:{Slot}, Channel:{mainMeasurement.GetChannel()} - MeasuredTime({mainResult.DutTimeS}s), " + + $"MeasuredVolume({mainResult.DutVolumeCm}Qm)"); + + foreach (var otherMeasurement in _listOfIMeasurement.Where(m => m.GetType() != typeof(MagFluxRecord))) + { + try + { + var otherResults = intermediateMeasurement + ? otherMeasurement.GetIntermediateMeasurementResult(refVolume, refTimeS) + : otherMeasurement.GetFinalMeasurementResult(refVolume, refTimeS); + _logger.Info($"Slot:{Slot}, Channel:{otherMeasurement.GetChannel()} - ChannelTime({otherResults.DutTimeS}s), " + + $"ChannelVolume({otherResults.DutVolumeCm}Qm)"); + results.Add(otherResults); + } + catch (Exception ex) + { + _logger.Warn($"Slot:{Slot}, No Results for channel:{otherMeasurement.GetChannel()} Ex: {ex.Message}"); + if (channel == null) + { + throw new ApplicationException($"Can not read result from channel:{otherMeasurement.GetChannel() } Ex: {ex.Message}"); + } + } + } + + return results; + } + + /// + public MeasurementStates GetMeasurementState(Int32? onlyChannelNr = null) + { + _logger.Trace($"Slot:{Slot} - Get measurement state"); + if (!_listOfIMeasurement.Any()) + { + return MeasurementStates.NotStarted; + } + + if (onlyChannelNr.HasValue) + { + var measurement = _listOfIMeasurement.First(f => f.GetChannel() == onlyChannelNr.Value); + return measurement.GetMeasurementState(); + } + return _listOfIMeasurement.Min(m => m.MeasurementState); + } + + /// + public Boolean RequestIntermediateMeasurementState(Int32? onlyChannelNr = null) + { + _logger.Trace($"Slot:{Slot} - Get measurement state"); + if (!_listOfIMeasurement.Any()) + { + return false; + } + Boolean? ret = null; + foreach (var item in _listOfIMeasurement) + { + if (!onlyChannelNr.HasValue || item.GetChannel() == onlyChannelNr.Value) + { + var measurement = _listOfIMeasurement.First(f => onlyChannelNr != null && f.GetChannel() == onlyChannelNr.Value); + if ((measurement.MeasurementState == MeasurementStates.IsRunning + || measurement.MeasurementState == MeasurementStates.IsWaitingForIntermediateData)) + { + measurement.RequestIntermediateRecord(); + if (!ret.HasValue) + { + ret = true; + } + } + else + { + ret = false; + } + } + } + return ret.HasValue ? ret.Value : false; + } + + /// + public void InitCalibration() + { + _logger.Info($"Slot:{Slot} - Init calibration and set calibration values of all channels to default"); + PreMeasurement(); + } + + /// + public void StartCalibration() + { + StartMeasurement(); + } + + /// + public void StopCalibration() + { + StopMeasurement(); + } + + /// + public MeasurementStates GetCalibrationState() + { + return GetMeasurementState(); + } + + /// + public void BuildAndCheckCalibFactorsAllChannels(Double refVolumeCm, Double? refTimeS = null, Double reqDeviationPercent = 0, + Double maxCalibFactorTolerancePercent = 0) + { + throw new NotImplementedException(); + } + + /// + public void SetCalibFactorsAllChannels(Boolean justLog = false) + { + throw new NotImplementedException(); + } + + /// + public void SetLcdText(Boolean release, Byte[] textInHex) + { + throw new NotImplementedException(); + } + + /// + public void SetProcessState(DisplayCodes newState, Boolean webRequest = true) + { + throw new NotImplementedException(); + } + + /// + public DisplayCodes GetLastProcessState() + { + throw new NotImplementedException(); + } + + /// + public void WriteLog(String text) + { + _logger.Info($"Slot:{Slot} - {text}"); + //if (_enableRawDataLogging) + //{ + // if (_loggerRawData == null) + // { + // _loggerRawData = NLogHelper.CreateOrGetMultiLogger( + // StreamingPort.GetPortName(), "", "LedRawData", "TargetLedRawDataBase", "LedRawDataBase"); + + // } + // _loggerRawData.Info($"{text}"); + //} + } + + /// + public void LogRawData(Boolean on) + { + _enableRawDataLogging = on; + if (StreamingPort is LedSerialPort port) + { + port.RecordStreamingRawData = _enableRawDataLogging; + } + } + + /// + public Boolean CheckStateAfterMeasurement() + { + throw new NotImplementedException(); + } + + /// + public void DisposeMeter() + { + Dispose(); + } + + private void AddData(IMeasurementRecord newRecord) + { + + foreach (var measurement in _listOfIMeasurement) + { + if (measurement.GetType() != newRecord.GetType()) + { + continue; + } + + if (measurement.GetChannel() == newRecord.GetChannel()) + { + measurement.AddData(newRecord); + } + } + + // when every measurement has state IsRunning or every measurement has state IsCompleted, the streaming buffer set to skip decoding + if (_listOfIMeasurement.All(m => m.MeasurementState == MeasurementStates.IsRunning) + || _listOfIMeasurement.All(m => m.MeasurementState == MeasurementStates.IsCompleted)) + { + SyncStreamingBuffer(QualityWatchMode + ? SyncMarkRecord.DecodeIntermediateQuality + : SyncMarkRecord.SkipDecoding); + } + + } #endregion #region logging diff --git a/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/RequestProtocol.cs b/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/RequestProtocol.cs index c30892be..231ee51f 100644 --- a/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/RequestProtocol.cs +++ b/Common/Hardware/WaterMeter/MagFlux/Protocols/RequestProtocol/RequestProtocol.cs @@ -24,7 +24,6 @@ namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol _logger = NLogHelper.CreateOrGetMultiLogger(ident, "", "RequestProtocol", "MeterBase", "MeterBase"); } - /// /// public override event EventHandler OnRecordReadyToSend;