using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Newtonsoft.Json; using NLog; using Xylem.Common.CommonCore.Consts; using Xylem.Common.Hardware.Interfaces.Ports.PortCore; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.Consts; using Xylem.Common.Hardware.WaterMeter.Genesis.Registers; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore; using Xylem.Common.Utils.Logging; using static Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.GenesisMeterStreamingQuality; namespace Xylem.Common.Ui.GenesisToolBox { /// /// Streaming quality display /// public partial class FrmStreamingQuality : Form { private GenesisMeterStreamingQuality _currentGenesis; private MeterBatch _meterBatch = new MeterBatch(); private readonly ILogger _logger; private const Int32 SampleRateHz = 16; private Int32 _channels; private const String StrStartLiveCheck = "Start Live Check"; private const String StrStopLiveCheck = "Stop Live Check"; private const String StrStartContinuousCheck = "Start Logging"; private const String StrStopContinuousCheck = "Stop Logging"; private const String StrConnecting = "Connecting"; private const String StrNotConnected = "NOT CONNECTED"; private const String StrPartPcbConnected = "Connected to PCBID:"; private const String StrUpdate = "Update"; private const String StrUnknown = "---"; private Boolean _isLiveUpdate; private Byte[] _readout = new Byte[4]; /// /// Ctor /// public FrmStreamingQuality() { InitializeComponent(); tmrCheck.Tick += TmrCheck_Tick; tmrProgress.Tick += TmrProgress_Tick; _logger = NLogHelper.CreateOrGetLogger("StreamingQuality"); StopLiveUpdate(); StopLoggingUpdate(); lblPcbConnect.Text = StrNotConnected; lblPcbConnect.ForeColor = Color.Red; InitStreamingQualityCheck(); } private void StopLoggingUpdate() { tmrCheck.Enabled = false; btnStartStop.Text = StrStartContinuousCheck; lblLoggingUpdate.Text = @"STOPPED"; lblLoggingUpdate.Visible = true; } private void StopLiveUpdate() { tmrCheck.Enabled = false; btnStartStopLive.Text = StrStartLiveCheck; lblLiveUpdate.Text = @"STOPPED"; lblLiveUpdate.Visible = true; _isLiveUpdate = false; } private void cbComSlot_SelectedIndexChanged(Object sender, EventArgs e) { // switch LED off to safe energy WriteValue(Register.Genesisflow.LedMode, (Byte)LedMode.Off); StopLiveUpdate(); StopLoggingUpdate(); btnStartStop.Text = StrStartContinuousCheck; lblPcbConnect.Text = StrNotConnected; lblPcbConnect.ForeColor = Color.Red; InitStreamingQualityCheck(); } private void FrmStreamingQuality_FormClosing(Object sender, FormClosingEventArgs e) { Dispose(); } private new void Dispose() { // switch LED off to safe energy WriteValue(Register.Genesisflow.LedMode, (Byte)LedMode.Off); _currentGenesis?.DisposeMeter(); _meterBatch?.Dispose(); base.Dispose(); } /// /// - Catch error message on unknown data type and kill meter. /// private void Connect() { Int32 slotNr; lblPcbConnect.Text = StrNotConnected; lblPcbConnect.ForeColor = Color.Red; if (!string.IsNullOrEmpty(cbComSlot.SelectedItem.ToString()) && int.TryParse(cbComSlot.SelectedItem.ToString(), out slotNr)) { try { _currentGenesis?.DisposeMeter(); _currentGenesis = null; ViewProgress(true); _currentGenesis = new GenesisMeterStreamingQuality(); _currentGenesis.SetupFromConfigFile(slotNr); _meterBatch.AddMeter(_currentGenesis); Task.Factory.StartNew(() => { _meterBatch.MetersLogin(); WriteValue(Register.Genesisflow.TriggerIdle, 0); WriteValue(Register.Genesisflow.SampleRate, SampleRateHz); _channels = 4; WriteValue(Register.Genesisflow.LedMode, (Byte)LedMode.FlowTestAndCalibDataAndBendCorrect); if (_currentGenesis.IsLoggedOn) { _currentGenesis.EnableAutoLogon(); Invoke(new Action(() => { lblPcbConnect.Text = StrPartPcbConnected + $@" {_currentGenesis.PcbId}"; lblPcbConnect.ForeColor = Color.Green; EnableCheckButtons(); })); } }).ContinueWith(delegate { ViewProgress(false); }); } catch (Exception ex) { MessageBox.Show(ex.Message, @"FAILED", MessageBoxButtons.OK, MessageBoxIcon.Error); // Dispose meter _meterBatch.RemoveAllMeters(); // If meter is not already assigned to batch as the config reader may fail _currentGenesis?.DisposeMeter(); } } } // write value avoids access if genesis is not assigned and logged in private Boolean WriteValue(String reg, T value) { if (_currentGenesis == null || !_currentGenesis.IsLoggedOn) return false; _currentGenesis.WriteRegister(reg, value, checkRegister: true); return true; } private void btnRawMode_Click(Object sender, EventArgs e) { // stop timer for synchronization tmrCheck.Enabled = false; _currentGenesis.StopStreamingQualityCheck(SampleRateHz * _channels); if (WriteValue(Register.Genesisflow.LedMode, (Byte)LedMode.CalibData)) { _readout = _currentGenesis.ReadRegister(Register.Genesisflow.LedMode); if (null != _readout && _readout[0] == (Byte)LedMode.CalibData) { _channels = 3; } _currentGenesis.StartStreamingQualityCheck(); tmrCheck.Enabled = true; } } private void btnMixMode_Click(Object sender, EventArgs e) { // stop timer for synchronization tmrCheck.Enabled = false; _currentGenesis.StopStreamingQualityCheck(SampleRateHz * _channels); if (WriteValue(Register.Genesisflow.LedMode, (Byte)LedMode.FlowTestAndCalibData)) { _readout = _currentGenesis.ReadRegister(Register.Genesisflow.LedMode); if (null != _readout && _readout[0] == (Byte)LedMode.FlowTestAndCalibData) { _channels = 4; } _currentGenesis.StartStreamingQualityCheck(); tmrCheck.Enabled = true; } } private void btnRawOnly_Click(Object sender, EventArgs e) { // stop timer for synchronization tmrCheck.Enabled = false; _currentGenesis.StopStreamingQualityCheck(SampleRateHz * _channels); if (WriteValue(Register.Genesisflow.LedMode, (Byte)LedMode.FlowTestData)) { _readout = _currentGenesis.ReadRegister(Register.Genesisflow.LedMode); if (null != _readout && _readout[0] == (Byte)LedMode.FlowTestData) { _channels = 1; } _currentGenesis.StartStreamingQualityCheck(); tmrCheck.Enabled = true; } } private void btnStartStop_Click(Object sender, EventArgs e) { // start logging if (btnStartStop.Text == StrStartContinuousCheck) { StopLiveUpdate(); lblLoggingUpdate.Text = StrUpdate; btnStartStop.Text = StrStopContinuousCheck; _logger.Info($"StartCheck for {txtFlowText.Text}"); _currentGenesis.StartStreamingQualityCheck(); tmrCheck.Enabled = true; } // stop logging and display result else { var result = _currentGenesis.StopStreamingQualityCheck(SampleRateHz * _channels); var sb = new StringBuilder(); StopLoggingUpdate(); _logger.Info($"Logging comment: {txtFlowText.Text}"); _logger.Info($"TotalTime={result.TotalTime}"); sb.AppendLine($"TotalTime={result.TotalTime}"); _logger.Info($"ExpectedRecords={result.ExpectedLinesCount}"); sb.AppendLine($"ExpectedRecords={result.ExpectedLinesCount}"); _logger.Info($"ReceivedRecords={result.TotalLinesCount}"); sb.AppendLine($"ReceivedRecords={result.TotalLinesCount}"); _logger.Info($"ValidRecords={result.TotalDecodedCount}"); sb.AppendLine($"ValidRecords={result.TotalDecodedCount}"); _logger.Info($"InvalidRecords={result.TotalTransportErrorCount}"); sb.AppendLine($"InvalidRecords={result.TotalTransportErrorCount}"); _logger.Info($"DifferentMeterErrorCodes={result.ErrorOccurredCounter.Count}"); sb.AppendLine($"DifferentMeterErrorCodes={result.ErrorOccurredCounter.Count}"); foreach (var errorCount in result.ErrorOccurredCounter) { _logger.Info($"MeterErrorCode 0x{errorCount.Key:X4} counted {errorCount.Value} times"); sb.AppendLine($"MeterErrorCode 0x{errorCount.Key:X4} counted {errorCount.Value} times"); } _logger.Info("################################"); MessageBox.Show(sb.ToString()); } } private void btnStartStopLive_Click(Object sender, EventArgs e) { // start live update if (btnStartStopLive.Text == StrStartLiveCheck) { StopLoggingUpdate(); lblLiveUpdate.Text = StrUpdate; btnStartStopLive.Text = StrStopLiveCheck; _currentGenesis.StartStreamingQualityCheck(); tmrCheck.Enabled = true; _isLiveUpdate = true; } // stop live update else { StopLiveUpdate(); } } private void TmrProgress_Tick(Object sender, EventArgs e) { if (barProgress.Value == 100) { barProgress.Value = 0; } barProgress.Value += 1; } private void TmrCheck_Tick(Object sender, EventArgs e) { if (_currentGenesis != null && _currentGenesis.IsRunning) { // stop timer for synchronization tmrCheck.Enabled = false; if (_isLiveUpdate) { lblLiveUpdate.Visible = !lblLiveUpdate.Visible; var result = _currentGenesis.StopStreamingQualityCheck(SampleRateHz * _channels); var percentHit = Math.Round(result.TotalDecodedCount / (Double)result.ExpectedLinesCount * 100.0, 0); if (percentHit > 85.0) { lblHitRate.ForeColor = Color.Green; lblHitRateTxt.ForeColor = Color.Green; } else { lblHitRate.ForeColor = Color.Red; lblHitRateTxt.ForeColor = Color.Red; } lblHitRate.Text = percentHit.ToString(CultureInfo.InvariantCulture); lblExpectedRecords.Text = result.ExpectedLinesCount.ToString(); lblDecodingFailed.Text = result.TotalTransportErrorCount.ToString(); lblDecodingValid.Text = result.TotalDecodedCount.ToString(); lblReceivedRecords.Text = result.TotalLinesCount.ToString(); _currentGenesis.StartStreamingQualityCheck(); } else { lblLoggingUpdate.Visible = !lblLoggingUpdate.Visible; } tmrCheck.Enabled = true; } } private void InitStreamingQualityCheck() { btnStartStopLive.Enabled = false; btnMixMode.Enabled = false; btnStartStop.Enabled = false; btnRawOnly.Enabled = false; btnConnect.Enabled = true; lblHitRate.Text = StrUnknown; lblHitRate.ForeColor = Color.Black; lblHitRateTxt.ForeColor = Color.Black; lblDecodingFailed.Text = StrUnknown; lblExpectedRecords.Text = StrUnknown; lblDecodingValid.Text = StrUnknown; lblReceivedRecords.Text = StrUnknown; } private void EnableCheckButtons() { btnStartStopLive.Enabled = true; btnMixMode.Enabled = true; btnStartStop.Enabled = true; btnRawOnly.Enabled = true; //btnConnect.Enabled = false; } private void ViewProgress(Boolean isActive) { if (isActive) { Invoke(new Action(() => { lblProgress.Text = StrConnecting; barProgress.Value = 0; lblProgress.Visible = true; barProgress.Visible = true; tmrProgress.Enabled = true; lblPcbConnect.Visible = false; })); } else { Invoke(new Action(() => { tmrProgress.Enabled = false; lblProgress.Visible = false; barProgress.Visible = false; lblPcbConnect.Visible = true; })); } } private void btnConnect_Click(Object sender, EventArgs e) { Connect(); } private void btnSetSampleRate_Click(Object sender, EventArgs e) { if (int.TryParse(cobSr.SelectedItem.ToString(), out var intTemp)) { _currentGenesis.WriteRegister(Register.Genesisflow.SampleRate, intTemp); } } private void btnTestAll_Click(Object sender, EventArgs e) { _currentGenesis?.DisposeMeter(); _currentGenesis = null; SlotConfig[] meterConfigList; using (var tr = new StreamReader(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Genesis", ProgramConfig.SerialConfigFileName))) { meterConfigList = JsonConvert.DeserializeObject(tr.ReadToEnd()); } _meterBatch = new MeterBatch(); foreach (var item in meterConfigList) { var meter = new GenesisMeterStreamingQuality(); meter.SetupFromConfigFile(item.Slot); _meterBatch.AddMeter(meter); } _meterBatch.MetersLogin(); Int32 intTemp; if (int.TryParse(cobSr.SelectedItem.ToString(), out intTemp)) { } foreach (var item in _meterBatch.ListOfMeters) { if (item is GenesisMeterStreamingQuality meter) { meter.WriteRegister(Register.Genesisflow.SampleRate, intTemp); meter.WriteRegister(Register.Genesisflow.LedMode, (Byte)LedMode.CalibData); meter.SetLcdText(true, null); } } var start = DateTimeOffset.UtcNow; var taskList = new List(); foreach (var item in _meterBatch.ListOfMeters) { if (item is GenesisMeterStreamingQuality meter) { taskList.Add(new Task(() => { meter.IsRunning = false; meter.StartStreamingQualityCheck(900 * 3); while (meter.IsRunning) { Thread.Sleep(20); } return meter.LastQualityResult; })); } } taskList.ForEach(t => t.Start()); while (!taskList.All(t => t.IsCompleted)) { Thread.Sleep(20); } var ts = DateTimeOffset.UtcNow - start; MessageBox.Show(ts.TotalSeconds.ToString(CultureInfo.InvariantCulture)); } private void btnDispose_Click(Object sender, EventArgs e) { _currentGenesis.CurrentActionText = "StreamingQuality"; } } }