using System; using NLog; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using Newtonsoft.Json; using Xylem.Common.CommonCore.Consts; using Xylem.Common.Hardware.Interfaces.Ports.PortCore; using Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments; using Xylem.Common.Hardware.Interfaces.Ports.SerialPorts; using Xylem.Common.Hardware.Interfaces.Protocols.ProtocolCore; using Xylem.Common.Hardware.Interfaces.Protocols.ProtocolCore.EventArguments; using Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol; using Xylem.Common.Hardware.WaterMeter.MagFlux.DataPackages.DataTypes; using Xylem.Common.Hardware.WaterMeter.MagFlux.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.Protocols.RequestProtocol; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts; using Xylem.Common.Metrology.Measurements; using Xylem.Common.Metrology.Measurements.Consts; using Xylem.Common.Utils.Logging; using XYLEM.Device; namespace Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore { /// /// /// MagFlux meter is the core class for the MJK MagFlux water meter. /// One meter always is always linked to two port, one for communication and one for LED streaming. /// public class MagFluxMeter : IMeter, IMeterEvents { #region Variables and Properties /// /// Mark the streaming catcher as active /// private Boolean _streamingCatcherIsActive; /// /// Enable raw record logging, if set every incoming package will be logged /// private Boolean _enableRawDataLogging; /// /// to reduce the IrdA communication in test bench, preparation will be done once (when SkipPreparationForTestBench is true) /// public Boolean SkipPreparationForTestBench { get; set; } /// /// List of ongoing measurements, base- and calibration-measurements /// private List _listOfIMeasurement = new List(); /// /// Quality watch mode can be used to decode intermediate records and check /// for actual quality of the measurements. /// public Boolean QualityWatchMode; /// /// Represent FW version /// public String FwVersion { get; private set; } = "?"; /// /// Represent meter size in mm /// public Int32 MeterSizeMm { get; private set; } /// /// Represent FW version /// public String FwBuildDate { get; private set; } = "?"; /// /// Represent FW GIT hash /// public String FwGitHash { get; private set; } = "?"; /// /// Represent pcb serial number /// public String PcbId { get; private set; } /// /// Represent unique id /// public String UniqueId { get; private set; } private String _currentActionText = ""; /// /// Hold the current process name e.g. FlowTest, Preadjustment for logging /// public String CurrentActionText { get => _currentActionText; set { _currentActionText = value; SetLogger(); } } ///// ///// Add on ctor a password and it will be used for login in if no other password is set ///// //private String _password; /// /// request port assignment/info /// private IPort RequestPort { get; set; } /// /// request protocol assignment/info /// private RequestProtocol RequestProtocol; /// /// streaming port assignment/info /// private IPort StreamingPort { get; set; } /// /// streaming protocol assignment/info /// private StreamingProtocol StreamingProtocol; /// public String SerialNumber { get; set; } /// /// do not use it to set ProcessStatus /// if you want to change ProcessStatus of this genesis use /// is just store for some routines /// private ProcessState _myProcessStatus; /// /// if state is change /// /// will be invoked. /// on some states other events will be invoke as well public ProcessState ProcessStatus { get => _myProcessStatus; private set { if (_myProcessStatus == value) { return; } _myProcessStatus = value; Invoker(OnProcessStatusChanged); switch (value) { case ProcessState.InitIsActive: Invoker(OnInitCompleted); break; case ProcessState.MeasurementIsActive: Invoker(OnMeasurementInitCompleted); break; case ProcessState.MeasurementIsDone: Invoker(OnMeasurementCompleted); break; case ProcessState.CalibrationIsActive: Invoker(OnCalibInitCompleted); break; case ProcessState.CalibrationIsDone: Invoker(OnCalibCompleted); break; case ProcessState.QRefDone: case ProcessState.WaitForQRef: case ProcessState.WaitForCalibration: case ProcessState.WaitForMeasurement: case ProcessState.IsNotInit: //no extra event needed break; default: throw new OverflowException("MagFlux measurement unknown process status"); } } } public Boolean IsLoggedOn { private set; get; } /// public ErrorState ErrorStatus { private set; get; } = ErrorState.None; /// public Int32 Slot { get; set; } /// public Int32 IntermediateUpdateTimeS { get; set; } = CommunicationConfig.MeasurementUpdateTimeS; /// /// Process configuration /// public ProcessConfig Configuration = new ProcessConfig(); /// /// Transmit protocol access for underlie objects to change response timeout /// private ITransmitProtocol TransmitProtocol; //initially do not signal event private readonly AutoResetEvent _onSyncKeepSessionThread = new AutoResetEvent(false); private Thread _keepSessionThread; private readonly CancellationTokenSource _keepSessionToken = new CancellationTokenSource(); private ILogger _logger; #endregion #region Events event EventHandler IMeter.OnDisposeCompleted { add { // throw new NotImplementedException(); } remove { // throw new NotImplementedException(); } } //public event EventHandler HasInformationForCaller; /// public event EventHandler OnCalibCompleted; /// public event EventHandler OnErrorStatusChanged; /// public event EventHandler OnProcessStatusChanged; /// public event EventHandler OnCalibInitCompleted; /// public event EventHandler OnInitCompleted; /// public event EventHandler OnMeasurementInitCompleted; /// public event EventHandler OnMeasurementCompleted; /// /// Response received after request for record /// public event EventHandler OnRequestRecordReceived; /// /// Streaming record is decoded /// public event EventHandler OnStreamingRecordDecoded; ///// ///// call this if session is expired and you need an re-authorization ///// //public EventHandler AuthorizationRequired; /// /// A helper to invoke events only if someone is listening, otherwise nothing will happen /// /// Event handler to call /// Sender (can be null) /// Event arguments (can be null) private void Invoker(EventHandler handler, Object sender = null, EventArgs e = null) { if (handler != null) { if (sender == null) { sender = this; } if (e == null) { e = new EventArgs(); } handler.Invoke(sender, e); } // ReSharper disable once RedundantIfElseBlock else { //nobody is listening } } /// /// Track all incoming led record packages (Calibration and Flow) /// /// /// /// I should be /// otherwise this method does nothing /// private void StreamingProtocol_ApplyDecodedRecord(Object sender, BaseDataEventArgs e) { var result = e.GetEventData(); if (result is IMeasurementRecord) { if (result is MagFluxRecord) { if (!((MagFluxRecord)result).IsValid) { return; } } AddData(((IMeasurementRecord)result)); } } /// /// tracking request record processing /// /// /// private void RequestProtocol_ApplyDecodedRecord(Object sender, BaseDataEventArgs e) { if (e is RequestResponseDataEventArgs) { OnRequestRecordReceived?.Invoke(sender, (RequestResponseDataEventArgs)e); } } /// /// Kick off the streaming catcher. /// public void StartStreamingCatcher() { if (_streamingCatcherIsActive) { return; } if (!(StreamingPort is LedSerialPort)) { throw new ApplicationException("No valid streaming port"); } SyncStreamingBuffer(SyncMarkRecord.DecodeEveryPackage); StreamingProtocol.OnRecordIsDecoded += StreamingCatcher_OnRawRecordReceived; LogRawData(true); _streamingCatcherIsActive = true; } /// /// Cyclic execution of catcher on incoming events. /// /// /// private void StreamingCatcher_OnRawRecordReceived(Object sender, BaseDataEventArgs e) { OnStreamingRecordDecoded?.Invoke(this, (MagFluxFlowDataEventArgs)e); } /// /// Stop the streaming catcher. /// /// public void StopStreamingCatcher() { if (StreamingPort == null || !(StreamingPort is LedSerialPort)) { throw new ApplicationException("No valid streaming port"); } LogRawData(false); StreamingProtocol.OnRecordIsDecoded -= StreamingCatcher_OnRawRecordReceived; SyncStreamingBuffer(SyncMarkRecord.SkipDecoding); _streamingCatcherIsActive = false; } #endregion #region class handling /// /// Ctor - default /// /// /// - Initial /// public MagFluxMeter() { } /// public void Dispose() { _logger.Trace($"Slot:{Slot} - Start to dispose"); StreamingProtocol.OnRecordIsDecoded -= StreamingProtocol_ApplyDecodedRecord; RequestProtocol.OnRecordIsDecoded -= RequestProtocol_ApplyDecodedRecord; 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; //_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); // request port is needed to assign the port name from file, else it is not used // as the IMagFluxRequestProtocol implements the port handling and communication RequestPort = new UartSerialPort(requestIdent, requestPort.Value.GetSerialPort(), TransmitProtocol.GetTransmitPortSettings()); } } if (streamingPort != null) { var ledTransmit = new LedTransmitProtocol(streamingPort.Value.PortName); var streamingIdent = $"Slot:{Slot}, Port:{streamingPort.Value.PortName}, Protocol:LED"; StreamingPort = new LedSerialPort(streamingIdent, streamingPort.Value.GetSerialPort(), ledTransmit.GetTransmitPortSettings()); StreamingProtocol = new StreamingProtocol(streamingIdent, ignoreCorruptedData); } Configuration = new ProcessConfig(ProgramConfig.ConfigFileName); SetLogger(); _logger.Debug($"Slot:{Slot} - Setup done"); } /// /// /// Start Event listening, has to be called after /// public void ConnectMeter() { if (RequestPort != null && RequestPort.GetPortName() != BaseSerialPort.PortNotAssigned) { if (RequestProtocol.Connect(RequestPort.GetPortName())) { _logger.Trace($"Slot:{Slot} - RequestPort and RequestProtocol linked"); RequestProtocol.OnRecordIsDecoded += RequestProtocol_ApplyDecodedRecord; RequestProtocol.CloseConnection(); } else { _logger.Trace($"Slot:{Slot} - RequestPort Connection failed"); } } 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 /// private static 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 /// /// /// private 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); } /// /// Copy list of flow results to and kick off the /// writing of calibrations to MagFlux. /// /// List of flow results public void WriteCalibrationTestBench(List results) { if (RequestProtocol == null) return; var calibrationsCmPerH = new List(); var calibrationCmPerH = new Calibration(); foreach (var result in results) { calibrationCmPerH.refFlowRate = (Single)result.MeasuredRefFlowQmPerH; calibrationCmPerH.dutFlowRate = (Single)result.MeasuredDutFlowQmPerH; calibrationsCmPerH.Add(calibrationCmPerH); } RequestProtocol.SetCalibrationPoints(calibrationsCmPerH); } /// void IMeter.SetupFromConfigFile(Int32 slot, Boolean ignoreCorruptedData, Boolean useRequest, Boolean useStreaming) { SetupFromConfigFile(slot, ignoreCorruptedData); } /// /// Setup water meter from configuration file: /// -slot, /// -streaming protocol, /// -streaming port /// -request port /// /// /// /// /// /// private void SetupFromConfigFile(Int32 slot, Boolean ignoreCorruptedData, Boolean useRequest, Boolean useStreaming) { Slot = slot; 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"); } 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); } SetLogger(); _logger.Debug($"Slot:{slot} - Configuration loaded"); } /// public Boolean Logout() { RequestProtocol.CloseConnection(); IsLoggedOn = false; return true; } /// /// /// - Unique Id introduced, /// - Sensor Serial number mapped as PcbId. /// public Boolean Login() { if (!RequestProtocol.Connect(RequestPort.GetPortName())) return IsLoggedOn; IsLoggedOn = true; if (RequestProtocol.GetFirmwareVersion(out var fwVersion)) { FwVersion = fwVersion; } if (RequestProtocol.GetFwBuildDate(out var fwBuildDate)) { FwBuildDate = fwBuildDate; } if (RequestProtocol.GetMeterSizeMm(out var meterSizeMm)) { MeterSizeMm = meterSizeMm; } if (RequestProtocol.GetFwGitHash(out var gitHash)) { FwGitHash = gitHash; } if (RequestProtocol.GetUniqueId(out var uniqueId)) { UniqueId = uniqueId; } // The PcbId will be named as SensorSerialNo by MJK if (RequestProtocol.GetPcbId(out var pcbId)) { PcbId = pcbId; } StreamingProtocol?.SetDecodingMask(pcbId, uniqueId); return IsLoggedOn; } /// 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 on measurement start"); } 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 String GetPcbId(Int32 expectedLength = 12) { if (!string.IsNullOrEmpty(PcbId) && !string.Equals("?", PcbId)) { return PcbId; } var pcbId = PcbId; RequestProtocol?.GetPcbId(out pcbId); PcbId = pcbId; return pcbId; } /// /// Write calibration values to MagFlux /// public void WriteCalibration(List calibrationsCmPerH) { _logger.Info($"Slot:{Slot} - Write calibration values to MagFlux"); RequestProtocol?.SetCalibrationPoints(calibrationsCmPerH); } /// /// Read calibration values to MagFlux /// public void ReadCalibration(out List calibrationsCmPerH) { calibrationsCmPerH = null; _logger.Info($"Slot:{Slot} - Read calibration values from MagFlux"); RequestProtocol?.GetCalibrationPoints(out calibrationsCmPerH); } /// public void InitCalibration() { _logger.Info($"Slot:{Slot} - Init calibration and set calibration values of all channels to default"); if (RequestProtocol == null) return; if (RequestProtocol.PrepareDeviceForCalibration()) PreMeasurement(); } /// public void StartCalibration() { StartMeasurement(); } /// public void StopCalibration() { StopMeasurement(); RequestProtocol?.AbortDeviceForCalibration(); } /// 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 private void SetLogger() { if (_logger != null) { LogManager.Flush(); } // the id is a combination of UniqueId stored in PcbId and SensorSN (SensorId) var id = !string.IsNullOrEmpty(PcbId) ? $"PCBID{PcbId}" : "?"; id += !string.IsNullOrEmpty(SerialNumber) ? $"_SN{SerialNumber}" : "?"; var fileName = $"MagFluxRawData_Slot_{Slot}"; if (string.IsNullOrEmpty(CurrentActionText)) { _logger = NLogHelper.CreateOrGetMultiLogger($"Slot:{Slot}", $"", "Meter", "MeterBase", "MeterBase"); if (RequestProtocol != null) { var pathName = NLogHelper.GetPath(_logger); var path = Path.GetDirectoryName(pathName); RequestProtocol.SetLogLocation(path, fileName); } } else { _logger = NLogHelper.CreateOrGetMultiLogger($"Slot:{Slot}_{id}_{CurrentActionText}", "Slot", "Meter", "MeterBase", "MeterBase"); if (RequestProtocol != null) { var pathName = NLogHelper.GetPath(_logger); var path = Path.GetDirectoryName(pathName); RequestProtocol.SetLogLocation(path, fileName); } //TODO check with roland if (StreamingPort is LedSerialPort) { var streamingIdent = $"LedRawData_Slot_{Slot}_{id}_{CurrentActionText}"; ((LedSerialPort)StreamingPort).Ident = streamingIdent; ((LedSerialPort)StreamingPort).RefreshLogger(); if (!string.IsNullOrEmpty(SerialNumber) && CurrentActionText.Contains("PG")) { //var pathMain = NLogHelper.GetPath(_logger); //var pathRaw = NLogHelper.GetPath(((LedSerialPort)StreamingPort).GetRawLogger()); //var basePath = Path.GetDirectoryName(pathMain); //var testRunString = CurrentActionText.Replace("PG", ""); //var lastChat = pathMain.LastIndexOf('\\'); //pathMain = pathMain.Substring(lastChat + 1); //pathRaw = Path.GetFileName(pathRaw); //var tmpUrl = $"http://10.49.40.25/MeterProcessState/api/TestBench/SetMeterLogPathInfo?SerialNumber={SerialNumber}&TestRunId={testRunString}&BasePath={basePath}&MainLogName={pathMain}&LEDName={pathRaw}"; //_logger.Debug($"Request Url: { tmpUrl}"); ////ToDO: Update to service URl //LocalWebRequest.GetRequest(tmpUrl); } } } } #endregion } }