using System; using System.Collections.Generic; using System.Data; using System.Drawing; using System.Globalization; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Xylem.Common.Hardware.WaterMeter.MagFlux.DataPackages.DataTypes; using Xylem.Common.Hardware.WaterMeter.MagFlux.DataPackages.EventArguments; using Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore; using Xylem.Common.Utils.ProcessExec.EventArguments; namespace Xylem.Common.Ui.MagFluxToolBox { /// /// Test form for MagFlux operation /// public partial class FrmTest : Form { #region Variables const String headerRef = @"Ref FlowRate [m³/h]"; const String headerDut = @"DUT FlowRate [m³/h]"; /// /// Reference to list of calibration points in cubic meters per hour. /// private List _calibPointsCmPerH; private DataTable _dataTableCalibPoints; private readonly MeterBatch _meterBatch = new MeterBatch(); private MagFluxMeter _magFluxMeter; private const String StrConnecting = "Connecting to PCB"; private const String StrNotConnected = "NOT CONNECTED"; private const String StrOverallProcess = "Overall Process"; private String _lastState; private Int32 _lastSingleProgress; private DateTimeOffset _startTime; private Boolean _resetTimeMeasurement; private readonly Boolean _updateGui = true; private Boolean _tryConnectPcb; // external update remarks form // private readonly FrmHistory _frmHistory = new FrmHistory(); private readonly Version _version; // marker for initial connection to update information just needed once private Boolean _initialConnect; // status information private static readonly Color ColorDefault = Color.Black; private static readonly Color ColorSuccess = Color.Green; private static readonly Color ColorProcessFailed = Color.Red; //private static readonly Color ColorOngoingProcess = Color.Blue; //private static readonly Color ColorUnknownStatus = Color.Gray; //private const String SuccessSign = @"✔"; //private const String FailedSign = @"✘"; private const String StrSeparator = "-----------------------------------------------------" + "-----------------------------------------------------"; #endregion #region FormControls /// /// Ctor FW update /// public FrmTest() { InitializeComponent(); var cultureInfo = new CultureInfo("en-GB"); Thread.CurrentThread.CurrentUICulture = cultureInfo; Thread.CurrentThread.CurrentCulture = cultureInfo; _version = Assembly.GetExecutingAssembly().GetName().Version; } /// /// Clear data table and set genesis to not connected /// private void Init() { ProcessViewControl(false); _magFluxMeter?.StopStreamingCatcher(); lblSensorNo.Text = StrNotConnected; lblSensorNo.ForeColor = Color.Red; lblWaitingForMeterResponse.Visible = false; btnConnect.Enabled = true; SetControlDownloadsLocked(); _initialConnect = true; tbxUniqueId.Text = ""; tbxSensorNo.Text = ""; tbxFwVersion.Text = ""; tbxFwBuildDate.Text = ""; tbxFwGitHash.Text = ""; tbxMeterSize.Text = ""; tbxFlowRate.Text = ""; tbxStatus.Text = ""; tbxVolume.Text = ""; tbxRevVolume.Text = ""; } private void FrmTest_Load(Object sender, EventArgs e) { var version = Assembly.GetExecutingAssembly().GetName().Version; lblFwUpdateInfo.Text = $@"Version: {version.Major}.{version.Minor}.{version.Build}"; _resetTimeMeasurement = true; Init(); LogText($"MagFluxToolBox: {_version.Major}.{_version.Minor}.{_version.Build}"); LogText(StrSeparator); } private void FrmTest_FormClosing(Object sender, FormClosingEventArgs e) { if (_magFluxMeter != null) { _magFluxMeter.OnStreamingRecordDecoded -= StreamingCatcher_OnStreamingRecordDecoded; _magFluxMeter.Logout(); _magFluxMeter.StopStreamingCatcher(); } _meterBatch?.RemoveAllMeters(); _meterBatch?.Dispose(); Dispose(); } private void cbComSlot_SelectedIndexChanged(Object sender, EventArgs e) { _resetTimeMeasurement = true; Init(); } #endregion #region ------------------------------------------ Data Grid Calibration -------------------------------------- /// /// Edit calibrations and fill the data back to calibration data field /// /// /// - Initial. /// private void gridViewCalib_CellEndEdit(Object sender, DataGridViewCellEventArgs e) { try { if (e.ColumnIndex < 0 || e.RowIndex < 0 || _dataTableCalibPoints == null || _calibPointsCmPerH == null || _calibPointsCmPerH.Count < e.RowIndex) { return; } var array = _calibPointsCmPerH.ToArray(); var index = e.RowIndex; _calibPointsCmPerH.Clear(); var cellContent = gridViewCalib.Rows[e.RowIndex].Cells[e.ColumnIndex].Value; if (gridViewCalib.Columns[e.ColumnIndex].Name == headerRef) array[index].refFlowRate = (Single)cellContent; if (gridViewCalib.Columns[e.ColumnIndex].Name == headerDut) array[index].dutFlowRate = (Single)cellContent; var ordered = array.OrderBy(x => x.refFlowRate); foreach (var a in ordered) { _calibPointsCmPerH.Add(a); } FillDataGridWithCalibInfos(); } catch (Exception) { // ignored } } /// /// Build data grid for calibrations /// /// /// - Initial. /// private void FillDataGridWithCalibInfos() { if (_calibPointsCmPerH == null) return; _dataTableCalibPoints?.Dispose(); _dataTableCalibPoints = new DataTable(); _dataTableCalibPoints.Columns.Add(headerRef, typeof(Single)); _dataTableCalibPoints.Columns.Add(headerDut, typeof(Single)); try { foreach (var cb in _calibPointsCmPerH) { var row = _dataTableCalibPoints.NewRow(); row[headerRef] = cb.refFlowRate; row[headerDut] = cb.dutFlowRate; _dataTableCalibPoints.Rows.Add(row); } gridViewCalib.DataSource = _dataTableCalibPoints; foreach (DataGridViewColumn column in gridViewCalib.Columns) { column.SortMode = DataGridViewColumnSortMode.NotSortable; } } catch (Exception) { //not implemented } } #endregion --------------------------------------- Data Grid Calibration -------------------------------------- #region ActivationControls private void SetControlDownloadsLocked() { btnConnect.Enabled = true; btnAbortCalibration.Enabled = false; btnPrepareCalibration.Enabled = false; btnReadCalibration.Enabled = false; btnWriteCalibration.Enabled = false; } private void SetControlsDownloadIsOngoing() { btnConnect.Enabled = false; btnAbortCalibration.Enabled = false; btnPrepareCalibration.Enabled = false; btnReadCalibration.Enabled = false; btnWriteCalibration.Enabled = false; } private void SetControlsDownloadIsFinished() { btnConnect.Enabled = true; btnAbortCalibration.Enabled = false; btnPrepareCalibration.Enabled = true; btnReadCalibration.Enabled = true; btnWriteCalibration.Enabled = true; } private void SetControlsDownloadEnabled() { btnConnect.Enabled = true; btnAbortCalibration.Enabled = false; btnPrepareCalibration.Enabled = true; btnReadCalibration.Enabled = true; btnWriteCalibration.Enabled = true; } #endregion #region BoardControls /// /// Cyclic execution of catcher on incoming events. /// /// /// private void StreamingCatcher_OnStreamingRecordDecoded(Object sender, MagFluxFlowDataEventArgs e) { Invoke(new Action(() => { tbxVolume.Text = $@"{e.NewData.VolumeCm:F3}"; tbxRevVolume.Text = $@"{e.NewData.RevVolumeCm:F3}"; tbxFlowRate.Text = $@"{e.NewData.FlowRateCmPh:F3}"; tbxStatus.Text = $@"0x{e.NewData.StatusBits:X8}"; })); } private void Connect() { try { Init(); if (string.IsNullOrEmpty(cbComSlot.SelectedItem.ToString()) || !int.TryParse(cbComSlot.SelectedItem.ToString(), out var slotNr)) { return; } //lblOverall.Text = @"Establish data base connection.."; Task.Factory.StartNew(() => { ViewProgressPcb(true); _magFluxMeter?.DisposeMeter(); //dispose old meter _meterBatch.RemoveAllMeters(); _magFluxMeter = null; Thread.Sleep(200); //assign new meter and assign meter to FW update file if this exists _magFluxMeter = new MagFluxMeter(); _magFluxMeter.SetupFromConfigFile(slotNr); _meterBatch.AddMeter(_magFluxMeter); _magFluxMeter.Configuration.UseRegisterWatchService = false; _magFluxMeter.Configuration.UseMinMaxCheck = false; _magFluxMeter.OnStreamingRecordDecoded += StreamingCatcher_OnStreamingRecordDecoded; _meterBatch.MetersLogin(); Invoke(new Action(() => { if (_magFluxMeter != null && _magFluxMeter.IsLoggedOn) { lblSensorNo.Text = ""; tbxUniqueId.Text = _magFluxMeter.UniqueId; tbxSensorNo.Text = _magFluxMeter.PcbId; tbxFwVersion.Text = _magFluxMeter.FwVersion; tbxFwBuildDate.Text = _magFluxMeter.FwBuildDate; tbxFwGitHash.Text = _magFluxMeter.FwGitHash; tbxMeterSize.Text = _magFluxMeter.MeterSizeMm.ToString(); lblSensorNo.ForeColor = Color.Green; CheckUpdateEnabled(); _magFluxMeter.StartStreamingCatcher(); _magFluxMeter.Logout(); LogInstalledMeterFw(); } })); }).ContinueWith(delegate { ViewProgressPcb(false); }); } catch (Exception ex) { MessageBox.Show(ex.Message); LogErrorText(ex.Message); } } #endregion #region ProcessControls private void ViewProgressPcb(Boolean isActive) { if (_updateGui) { if (isActive) { Invoke(new Action(() => { _tryConnectPcb = true; ProcessViewControl(true); lblActualProcess.Text = StrConnecting; lblOverall.Text = StrOverallProcess; })); } else { Invoke(new Action(() => { _tryConnectPcb = false; ProcessViewControl(false); })); } } } /// /// View all process bars and labels /// private void ProcessViewControl(Boolean view) { if (view) { lblActualProcess.Visible = true; lblOverall.Visible = true; barOverallProgressUpdate.Visible = true; barSingleProgressUpdate.Visible = true; _lastState = ""; tmrProgressUpdate.Enabled = true; } else { lblActualProcess.Visible = false; lblOverall.Visible = false; barOverallProgressUpdate.Visible = false; barSingleProgressUpdate.Visible = false; tmrProgressUpdate.Enabled = false; _lastState = ""; lblWaitingForMeterResponse.Visible = false; lblActualProcess.Text = ""; lblOverall.Text = ""; } //common actions and settings lblActualProcess.Update(); lblOverall.Update(); barOverallProgressUpdate.Value = 0; barOverallProgressUpdate.Update(); barSingleProgressUpdate.Value = 0; barSingleProgressUpdate.Update(); Update(); } private void StartStopDownload(Boolean isActive) { if (isActive) { Invoke(new Action(() => { ProcessViewControl(true); tmrProgressUpdate.Enabled = true; })); } else { Invoke(new Action(() => { ProcessViewControl(false); SetControlsDownloadIsFinished(); //// update the display of the meter size, LUT CRC and region //tbxMeterFw.Text = _magFluxMeter.FwVersion; //tbxMeterMeterSize.Text = _magFluxMeter.MeterSizeMm; //tbxMeterLutCrc.Text = _magFluxMeter.LutCrc; //tbxRegion.Text = _magFluxMeter.Region; //if (!_lutFileSuccessfulWritten) //{ // lblLutFileLoadedInfo.ForeColor = Color.Red; // lblLutFileLoadedInfo.Text = StrUpdateErrorMessage; // var txt = StrUpdateErrorMessage; // if (!string.IsNullOrEmpty(_meterLutUpdate?.ErrorMessage)) // { // txt += "\n"; // txt += _meterLutUpdate?.ErrorMessage; // } // LogErrorText(txt); // MessageBoxShow(txt, @"FAILED", // MessageBoxButtons.OK, MessageBoxIcon.Error); //} //else //{ // LogSuccessText(StrUpdateSuccessMessage); // MessageBoxShow(StrUpdateSuccessMessage, @"SUCCESS", // MessageBoxButtons.OK, MessageBoxIcon.Information); //} })); } } /// /// Display installed meter FW. /// /// /// - Init. /// private void LogInstalledMeterFw() { //if (_magFluxMeter == null) // return; //LogText(StrSeparator); //LogText($"PCB ID: {_magFluxMeter.PcbId}"); //LogText($"Core Version: {GenesisMeter.BuildFwVersionString(_magFluxMeter.CoreRevision)}"); //LogText(""); //LogText("Installed Applications:"); //foreach (var app in _magFluxMeter.MeterAppListVersion) //{ // var versionString = app.IsInstalled ? $"V: {app.StrVersion} - CRC: 0x{app.Crc:X4}" : // "App NOT Installed"; // LogText($"AppId: 0x{app.AppId:X2} - {versionString} - " + $"AppName: {app.AppName}"); // if (app.IsInstalled) // { // var appVersion = new CordonelAppVersion(app.AppId, app.StrVersion); // // Copy metrology update permission // if (app.AppName == MeterFwUpdateCapability.MetrologyName && // _magFluxMeter.MetrologyUpgradePermission != MeterFwUpdateCapability.MetrologyUpgradePermitted) // { // appVersion.IsUpdateable = false; // } // } //} //LogText(StrSeparator); } /// /// Output exclusively to user update remarks text window. /// /// /// - Color added. /// private void LogText(String txtHistory) { InfoWindowColoredText(txtHistory, ColorDefault); } /// /// Output exclusively to user update remarks text window. /// private void LogErrorText(String txtHistory) { InfoWindowColoredText(txtHistory, ColorProcessFailed); } /// /// Output exclusively to user update remarks text window. /// private void LogSuccessText(String txtHistory) { InfoWindowColoredText(txtHistory, ColorSuccess); } /// /// Output exclusively to user update remarks text window. /// private void InfoWindowColoredText(String txtHistory, Color color) { //if (_frmHistory?.rtbHistory == null) // return; //Invoke(new Action(() => //{ // _frmHistory.rtbHistory.SuspendLayout(); // _frmHistory.rtbHistory.SelectionStart = _frmHistory.rtbHistory.Text.Length; // _frmHistory.rtbHistory.SelectionLength = 0; // _frmHistory.rtbHistory.SelectionColor = color; // _frmHistory.rtbHistory.AppendText($"{txtHistory}{Environment.NewLine}"); // _frmHistory.rtbHistory.SelectionColor = _frmHistory.rtbHistory.ForeColor; // _frmHistory.rtbHistory.ScrollToCaret(); // _frmHistory.rtbHistory.ResumeLayout(); //})); } #endregion #region Checks private void CheckUpdateEnabled() { //this check has been placed here to force display update if (_magFluxMeter != null) { SetControlsDownloadEnabled(); return; } SetControlDownloadsLocked(); } #endregion #region Events /// /// Process update event for displaying messages in history window /// /// /// /// /// - Initial /// public virtual void ProcessUpdate_Event(Object sender, ProcessExecEventArgs e) { LogText(e.OverallProcessMessage); } #endregion #region TimerControls private void tmrProgressUpdate_Tick(Object sender, EventArgs e) { //cbxManualControl.Visible = true; if (_tryConnectPcb) { barOverallProgressUpdate.Value = barOverallProgressUpdate.Value + 1 > 100 ? 0 : barOverallProgressUpdate.Value + 1; barSingleProgressUpdate.Value = barSingleProgressUpdate.Value + 4 > 100 ? 0 : barSingleProgressUpdate.Value + 4; lblOverall.Text = StrOverallProcess; } else { //lblOverall.Text = _meterLutUpdate?.GetLutUpdateStateOperation(); //lblActualProcess.Text = _meterLutUpdate?.GetActualOperation(); //var overallProgress = (Int32)(_meterLutUpdate?.OverallProcessCtrPercent ?? 0); //if (overallProgress < 0) // overallProgress = 0; //barOverallProgressUpdate.Value = overallProgress > 100 ? 100 : overallProgress; //barOverallProgressUpdate.Update(); //var singleProgress = (Int32)(_meterLutUpdate?.SingleFileProcessCtrPercent ?? 0); //if (_meterLutUpdate?.GetActualOperation() != _lastState) //{ // _lastState = _meterLutUpdate?.GetActualOperation(); // lblWaitingForMeterResponse.Visible = false; //} //else //{ // //if the communication gets frozen // lblWaitingForMeterResponse.Visible = _lastSingleProgress == singleProgress; //} //barSingleProgressUpdate.Value = singleProgress > 100 ? 100 : singleProgress; //_lastSingleProgress = singleProgress; //barSingleProgressUpdate.Update(); } SetTimeDisplay(); Update(); } private void SetTimeDisplay() { var time = DateTimeOffset.UtcNow; var timeSpan = time - _startTime; lblUpdateTime.Text = $@"{(UInt32)timeSpan.TotalMinutes}:{timeSpan.Seconds:00}"; } #endregion #region Buttons private void btnPrepareCalibration_Click(Object sender, EventArgs e) { SetControlsDownloadIsOngoing(); _magFluxMeter?.InitCalibration(); btnAbortCalibration.Enabled = true; btnReadCalibration_Click(this, null); SetControlsDownloadIsFinished(); } private void btnReadCalibration_Click(Object sender, EventArgs e) { SetControlsDownloadIsOngoing(); _magFluxMeter?.ReadCalibration(out _calibPointsCmPerH); if (_calibPointsCmPerH == null) return; _dataTableCalibPoints?.Clear(); FillDataGridWithCalibInfos(); SetControlsDownloadIsFinished(); } private void btnWriteCalibration_Click(Object sender, EventArgs e) { SetControlsDownloadIsOngoing(); if (_calibPointsCmPerH == null) return; _magFluxMeter?.WriteCalibration(_calibPointsCmPerH); btnReadCalibration_Click(this, null); } private void btnAbortCalibration_Click(Object sender, EventArgs e) { _magFluxMeter?.StopCalibration(); } private void btnConnect_Click(Object sender, EventArgs e) { if (_resetTimeMeasurement) { _startTime = DateTimeOffset.UtcNow; _resetTimeMeasurement = false; } Connect(); } /// /// Download calibration to MagFlux /// /// /// private void btnDownloadCalibration_Click(Object sender, EventArgs e) { if (_magFluxMeter == null) { return; } SetControlsDownloadIsOngoing(); StartStopDownload(true); _startTime = DateTimeOffset.UtcNow; _resetTimeMeasurement = false; } #endregion #region ExternalCalls /// /// /// public MsgEventArgs LastMsgEvent; /// public class MsgEventArgs : EventArgs { /// /// Text to display /// public String Text; /// /// Headline /// public String Caption; /// /// Buttons /// public MessageBoxButtons Buttons; /// /// Icon /// public MessageBoxIcon Icon; } /// /// Message pop up event handler /// public event EventHandler OnMsgPopUp; private void MessageBoxShow(String text, String caption, MessageBoxButtons buttons, MessageBoxIcon icon) { if (_updateGui) { MessageBox.Show(text, caption, buttons, icon); } else { LastMsgEvent = new MsgEventArgs() { Text = text, Caption = caption, Buttons = buttons, Icon = icon }; OnMsgPopUp?.Invoke(this, LastMsgEvent); } } #endregion } }