common/Ui/GenesisToolBox/FrmStreamingQuality.cs
2026-04-23 17:50:07 +02:00

505 lines
18 KiB
C#

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
{
/// <summary>
/// Streaming quality display
/// </summary>
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];
/// <summary>
/// Ctor
/// </summary>
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();
}
/// <remarks date="2025-Oct-02" author="Thomas Wiedebusch">
/// - Catch error message on unknown data type and kill meter.
/// </remarks>
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<T>(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<SlotConfig[]>(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<Task>();
foreach (var item in _meterBatch.ListOfMeters)
{
if (item is GenesisMeterStreamingQuality meter)
{
taskList.Add(new Task<QualityResult>(() =>
{
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";
}
}
}