/// /// Copyright (c) 2021-2022 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using log4net; using Common; using Config.Entities; using SchematicDrawing; using TBF.Resources; using TBF.Rig.Sequences; using TBF.UiBridge; namespace TBF.UI.Process { public partial class ProcessTabPageCtrl : UserControl { static readonly ILog log = LogManager.GetLogger(typeof(ProcessTabPageCtrl)); enum Column { Nr, Error, Volume, Pulses, RefPulses, SerialNr, Count } MetersKind currentMetersKind; public ProcessTabPageCtrl() { InitializeComponent(); InitializeDrawing(); Bridge.ProcedureSelectedHandler += delegate(object sender, ProcedureSelectedEventArgs args) { try { if (InvokeRequired) Invoke(new EventHandler(OnProcedureSelected), sender, args); else OnProcedureSelected(sender, args); } catch (Exception e) { log.ErrorFormat("ProcessTabPageCtrl.OnProcedureSelected() failed: {0}", e.Message); } }; Bridge.TestSelectedHandler += delegate(object sender, TestSelectedEventArgs args) { try { if (InvokeRequired) Invoke(new EventHandler(OnTestSelected), sender, args); else OnTestSelected(sender, args); } catch (Exception e) { log.ErrorFormat("ProcessTabPageCtrl.OnTestSelected() failed: {0}", e.Message); } }; Bridge.ProcessDataHandler += delegate(object sender, ProcessDataEventArgs args) { try { if (InvokeRequired) Invoke(new EventHandler(OnProcessDataChanged), sender, args); else OnProcessDataChanged(sender, args); } catch (Exception e) { log.ErrorFormat("ProcessTabPageCtrl.OnProcessDataChanged() failed: {0}", e.Message); } }; Bridge.TestCompletedHandler += delegate(object sender, TestCompletedEventArgs args) { try { if (InvokeRequired) Invoke(new EventHandler(OnTestCompleted), sender, args); else OnTestCompleted(sender, args); } catch (Exception e) { log.ErrorFormat("ProcessTabPageCtrl.OnTestCompleted() failed: {0}", e.Message); } }; Bridge.ProcedureCompletedHandler += delegate(object sender, ProcedureCompletedEventArgs args) { try { if (InvokeRequired) Invoke(new EventHandler(OnProcedureCompleted), sender, args); else OnProcedureCompleted(sender, args); } catch (Exception e) { log.ErrorFormat("ProcessTabPageCtrl.OnProcedureCompleted() failed: {0}", e.Message); } }; } void InitializeDrawing() { /// /// Initialize hydraulical schematic drawing /// processDrawingCtrl.SupressRedraws = true; /// var scale = new TBF.Rig.MettlerToledo.Standard.BalanceCfg(new TBF.Rig.MettlerToledo.Standard.BalanceFactory()) { Id = 2, Name = "WT", Shape = Shape.Scale, X = 640, Y = 150, Sz = Sz.M, Orient = Orient.R, Flip = false, LblX = 16, LblY = 40, LblOrient = Orient.R, MsrdX = 16, MsrdY = 64, MsrdOrient = Orient.R, MsrdFormat = "{0:F3}", MsrdUnit = Common.Unit.kg, }; var diverter = new TBF.Rig.Uni.Diverter.DiverterCfg(new TBF.Rig.Uni.Diverter.Factory()) { Id = 3, Name = "Div", DivNr1 = 1, BitNr = 0, Inverted = false, Shape = Shape.Div, X = 610, Y = 90, Sz = Sz.L, Orient = Orient.R, Flip = false, LblX = 50, LblY = -8, LblOrient = Orient.R, }; var regValve = new TBF.Rig.Uni.RegValve.RegValveCfg("VR", new TBF.Rig.Uni.RegValve.Factory()) { Id = 4, Shape = Shape.RegV, X = 450, Y = 140, Sz = Sz.L, Orient = Orient.Up, Flip = true, LblX = 46, LblY = 0, LblOrient = Orient.R, SetpX = 46, SetpY = 22, SetpOrient = Orient.R, }; var flowmeter = new TBF.Rig.Uni.FlowMeter.FlowMeterCfg(new TBF.Rig.Uni.FlowMeter.Factory(), "I") { Id = 5, MsrdFormat = "{0:F3} m2/h", MsrdUnit = Common.Unit.m3ph, Shape = Shape.FlowM, X = 450, Y = 210, Sz = Sz.L, Orient = Orient.Up, Flip = true, LblX = 46, LblY = 0, LblOrient = Orient.R, MsrdX = 46, MsrdY = 22, MsrdOrient = Orient.R, }; var startValve = new TBF.Rig.BuiltIn.Valve.ValveCfg(new TBF.Rig.BuiltIn.Valve.ValveFactory()) { Id = 6, Name = "VI", BitNr = 0, Inverted = false, Shape = Shape.Valve, X = 450, Y = 280, Sz = Sz.L, Orient = Orient.Up, Flip = false, LblX = 48, LblY = 9, LblOrient = Orient.R, }; var wm1 = new TBF.Rig.WaterMeters.WaterMeter.WaterMeterCfg(new TBF.Rig.WaterMeters.WaterMeter.WaterMeterFactory()) { Id = 7, Name = "WM1", Shape = Shape.WaterM, X = 120, Y = 360, Sz = Sz.L, Orient = Orient.R, Flip = false, LblX = 0, LblY = -24, LblOrient = Orient.R, }; var wm2 = new TBF.Rig.WaterMeters.WaterMeter.WaterMeterCfg(new TBF.Rig.WaterMeters.WaterMeter.WaterMeterFactory()) { Id = 8, Name = "WM2", Shape = Shape.WaterM, X = 180, Y = 360, Sz = Sz.L, Orient = Orient.R, Flip = false, LblX = 0, LblY = -24, LblOrient = Orient.R, }; var wm3 = new TBF.Rig.WaterMeters.WaterMeter.WaterMeterCfg(new TBF.Rig.WaterMeters.WaterMeter.WaterMeterFactory()) { Id = 9, Name = "WM3", Shape = Shape.WaterM, X = 310, Y = 360, Sz = Sz.L, Orient = Orient.R, Flip = false, LblX = 0, LblY = -24, LblOrient = Orient.R, }; var pump = new TBF.Rig.Modbus.PumpFM.DanfossVLT.PumpCfg(new TBF.Rig.Modbus.PumpFM.DanfossVLT.Factory()) { Id = 10, Name = "P", BitNr = 0, Inverted = false, Shape = Shape.PumpFM, X = 450, Y = 480, Sz = Sz.L, Orient = Orient.L, Flip = false, LblX = 0, LblY = -46, LblOrient = Orient.R, SetpX = 0, SetpY = -24, SetpOrient = Orient.R, SetpFormat = "{0:F0} %", SetpUnit = Common.Unit.Pct, }; var tank = new TBF.Rig.Various.Drawing.Tank.Configuration("Tank", new TBF.Rig.Various.Drawing.Tank.Factory()) { Id = 11, Shape = Shape.Tank, X = 570, Y = 410, Sz = Sz.L, Orient = Orient.R, Flip = false, LblX = 33, LblY = 22, LblOrient = Orient.R, }; var drainValve = new TBF.Rig.BuiltIn.Valve.ValveCfg(new TBF.Rig.BuiltIn.Valve.ValveFactory()) { Id = 16, Name = "VB", BitNr = 0, Inverted = false, Shape = Shape.Valve, X = 660, Y = 270, Sz = Sz.M, Orient = Orient.Dn, Flip = false, LblX = 40, LblY = 5, LblOrient = Orient.R, }; var j1 = new TBF.Rig.Various.Drawing.Junction.Configuration("J1", new TBF.Rig.Various.Drawing.Junction.Factory()) { Id = 17, Shape = Shape.Junction, X = 50, Y = 490, Sz = Sz.L, }; var j2 = new TBF.Rig.Various.Drawing.Junction.Configuration("J2", new TBF.Rig.Various.Drawing.Junction.Factory()) { Id = 18, Shape = Shape.Junction, X = 50, Y = 370, Sz = Sz.L, }; var j3 = new TBF.Rig.Various.Drawing.Junction.Configuration("J3", new TBF.Rig.Various.Drawing.Junction.Factory()) { Id = 19, Shape = Shape.Junction, X = 460, Y = 370, Sz = Sz.L, }; var j4 = new TBF.Rig.Various.Drawing.Junction.Configuration("J4", new TBF.Rig.Various.Drawing.Junction.Factory()) { Id = 20, Shape = Shape.Junction, X = 460, Y = 80, Sz = Sz.L, }; var j5 = new TBF.Rig.Various.Drawing.Junction.Configuration("J5", new TBF.Rig.Various.Drawing.Junction.Factory()) { Id = 21, Shape = Shape.Junction, X = 630, Y = 40, Sz = Sz.L, }; var j6 = new TBF.Rig.Various.Drawing.Junction.Configuration("J6", new TBF.Rig.Various.Drawing.Junction.Factory()) { Id = 22, Shape = Shape.Junction, X = 680, Y = 390, Sz = Sz.None, }; var j7 = new TBF.Rig.Various.Drawing.Junction.Configuration("J7", new TBF.Rig.Various.Drawing.Junction.Factory()) { Id = 23, Shape = Shape.Junction, X = 620, Y = 390, Sz = Sz.None, }; var t_in = new TBF.Rig.Modbus.TempMeter.Groch.TempMeterCfg(new TBF.Rig.Modbus.TempMeter.Groch.Factory()) { Id = 25, Name = "T in", MsrdFormat = "{0:F1} °C", MsrdUnit = Common.Unit.C, MsrdValLimLo = 5, MsrdValLimHi = 95, Shape = Shape.TempM, X = 50, Y = 320, Sz = Sz.M, Orient = Orient.R, Flip = false, LblX = 0, LblY = 2, LblOrient = Orient.R, MsrdX = 0, MsrdY = 24, MsrdOrient = Orient.R, }; var t_out = new TBF.Rig.Modbus.TempMeter.Groch.TempMeterCfg(new TBF.Rig.Modbus.TempMeter.Groch.Factory()) { Id = 26, Name = "T out", MsrdFormat = "{0:F1} °C", MsrdUnit = Common.Unit.C, MsrdValLimLo = 5, MsrdValLimHi = 95, Shape = Shape.TempM, X = 370, Y = 320, Sz = Sz.M, Orient = Orient.R, Flip = false, LblX = 0, LblY = 2, LblOrient = Orient.R, MsrdX = 0, MsrdY = 24, MsrdOrient = Orient.R, }; var t_div = new TBF.Rig.Modbus.TempMeter.Groch.TempMeterCfg(new TBF.Rig.Modbus.TempMeter.Groch.Factory()) { Id = 27, Name = "T div", MsrdFormat = "{0:F1} °C", MsrdUnit = Common.Unit.C, MsrdValLimLo = 5, MsrdValLimHi = 95, Shape = Shape.TempM, X = 660, Y = 30, Sz = Sz.M, Orient = Orient.R, Flip = false, LblX = 0, LblY = 0, LblOrient = Orient.R, MsrdX = 0, MsrdY = 22, MsrdOrient = Orient.R, }; var pr_up = new TBF.Rig.Modbus.PressureMeter.Meret.PressureMeterCfg(new TBF.Rig.Modbus.PressureMeter.Meret.Factory()) { Id = 28, Name = "Pr up", MsrdFormat = "{0:F2} bar", MsrdUnit = Common.Unit.bar, MsrdValLimLo = -0.1, MsrdValLimHi = 25, Shape = Shape.PressM, X = 50, Y = 270, Sz = Sz.M, Orient = Orient.R, Flip = false, LblX = 0, LblY = 0, LblOrient = Orient.R, MsrdX = 0, MsrdY = 22, MsrdOrient = Orient.R, }; var pr_dn = new TBF.Rig.Modbus.PressureMeter.Meret.PressureMeterCfg(new TBF.Rig.Modbus.PressureMeter.Meret.Factory()) { Id = 29, Name = "Pr dn", MsrdFormat = "{0:F2} bar", MsrdUnit = Common.Unit.bar, MsrdValLimLo = -0.1, MsrdValLimHi = 25, Shape = Shape.PressM, X = 370, Y = 270, Sz = Sz.M, Orient = Orient.R, Flip = false, LblX = 0, LblY = 0, LblOrient = Orient.R, MsrdX = 0, MsrdY = 22, MsrdOrient = Orient.R, }; processDrawingCtrl.AddItem(scale); processDrawingCtrl.AddItem(diverter); processDrawingCtrl.AddItem(regValve); processDrawingCtrl.AddItem(flowmeter); processDrawingCtrl.AddItem(startValve); processDrawingCtrl.AddItem(wm1); processDrawingCtrl.AddItem(wm2); processDrawingCtrl.AddItem(wm3); processDrawingCtrl.AddItem(pump); processDrawingCtrl.AddItem(tank); processDrawingCtrl.AddItem(drainValve); processDrawingCtrl.AddItem(j1); processDrawingCtrl.AddItem(j2); processDrawingCtrl.AddItem(j3); processDrawingCtrl.AddItem(j4); processDrawingCtrl.AddItem(j5); processDrawingCtrl.AddItem(j6); processDrawingCtrl.AddItem(j7); processDrawingCtrl.AddItem(t_in); processDrawingCtrl.AddItem(t_out); processDrawingCtrl.AddItem(t_div); processDrawingCtrl.AddItem(pr_up); processDrawingCtrl.AddItem(pr_dn); processDrawingCtrl.PipesS = new string[0]; processDrawingCtrl.PipesM = new string[0]; processDrawingCtrl.PipesL = new string[] { "11~0~10~0", "10~1~17~0", "17~0~18~0", "18~0~7~0", "7~1~8~0", "8~1~9~0", "9~1~19~0", "19~0~6~0", "6~1~5~0", "5~1~4~0", "4~1~20~0", "20~0~21~0", "21~0~3~0", "2~0~16~0", "16~1~22~0", "3~1~23~0" }; processDrawingCtrl.PipesXL = new string[0]; processDrawingCtrl.Route = 0; processDrawingCtrl.SupressRedraws = false; /// Invokes Dijkstra algoritm } public void Settings2UI() { TBF.LocalSettings ls = Program.LocalSettings; /// Splitter distances splitContainer1.SplitterDistance = ls.ProcessSplitDist1; splitContainer2.SplitterDistance = ls.ProcessSplitDist2; /// ListViewEx columns processListViewEx.Columns.Add(Strings.Nr, (ls.ProcessColumnCount > 0) ? ls.ProcessColumnWidths[0] : 30 * MainWnd.Dpi / Constants.Dpi100pct); processListViewEx.Columns.Add(Strings.Error, (ls.ProcessColumnCount > 1) ? ls.ProcessColumnWidths[1] : 50 * MainWnd.Dpi / Constants.Dpi100pct); processListViewEx.Columns.Add(Strings.Volume, (ls.ProcessColumnCount > 2) ? ls.ProcessColumnWidths[2] : 50 * MainWnd.Dpi / Constants.Dpi100pct); processListViewEx.Columns.Add(Strings.Pulses, (ls.ProcessColumnCount > 3) ? ls.ProcessColumnWidths[3] : 60 * MainWnd.Dpi / Constants.Dpi100pct); processListViewEx.Columns.Add(Strings.Ref_pulses, (ls.ProcessColumnCount > 4) ? ls.ProcessColumnWidths[4] : 75 * MainWnd.Dpi / Constants.Dpi100pct); processListViewEx.Columns.Add(Strings.SerialNr, (ls.ProcessColumnCount > 5) ? ls.ProcessColumnWidths[5] : 100 * MainWnd.Dpi / Constants.Dpi100pct); } /// /// Save UI settings to Program.LocalSettings and save them to a file. /// UI settings are: /// MainWnd size and location and splitter distances. /// public void UI2Settings() { LocalSettings ls = Program.LocalSettings; bool anyChange = splitContainer1.SplitterDistance != ls.ProcessSplitDist1 || splitContainer2.SplitterDistance != ls.ProcessSplitDist2; if (anyChange) { ls.ProcessSplitDist1 = splitContainer1.SplitterDistance; ls.ProcessSplitDist2 = splitContainer2.SplitterDistance; } /// Compare list view column widths with the saved ones if (processListViewEx.Columns.Count != ls.ProcessColumnCount) { ls.ProcessColumnWidths = new int[processListViewEx.Columns.Count]; for (int i = 0; i < ls.ProcessColumnCount; i++) { ls.ProcessColumnWidths[i] = processListViewEx.Columns[i].Width; } anyChange = true; } else { for (int i = 0; i < ls.ProcessColumnCount; i++) { if (processListViewEx.Columns[i].Width != ls.ProcessColumnWidths[i]) { ls.ProcessColumnWidths[i] = processListViewEx.Columns[i].Width; anyChange = true; } } } if (anyChange) ls.Save(); } void OnProcedureSelected(object sender, ProcedureSelectedEventArgs args) { currentMetersKind = args.Procedure.MetersKind; Invalidate(); } void OnTestSelected(object sender, TestSelectedEventArgs args) { } void OnProcessDataChanged(object sender, ProcessDataEventArgs args) { if (ProcessData.RegisterReaders == null || ProcessData.BatchRslts == null || ProcessData.BatchRslts.Batch == null || ProcessData.BatchRslts.Batch.WaterMeters == null) { return; } int wmsCount = Math.Min(ProcessData.RegisterReaders.Length, ProcessData.BatchRslts.Batch.WaterMeters.Count); if (processListViewEx.Items.Count != wmsCount) { /// Invoked only when the number of water meters or register readers changes processListViewEx.Items.Clear(); for (int i = 0; i < wmsCount; i++) { var lvi = new ListViewItem((i+1).ToString()); /// Column 0 for (Column c = (Column)1; c < Column.Count; c++) /// Column 1 .. Column.Count-1 { lvi.SubItems.Add("."); } lvi.Tag = ProcessData.BatchRslts.Batch.WaterMeters[i]; processListViewEx.Items.Add(lvi); } } TBF.Rig.ControlBoard.IControlBoard cBrd = TBF.Rig.StateMachine.ControlBoard; if (cBrd != null && cBrd.Devices != null && cBrd.Devices.FlowMeter != null) { double refVolume = cBrd.RefPulses * cBrd.Devices.FlowMeter.LtrPerPulse; for (int i = 0; i < wmsCount; i++) { var rr = ProcessData.RegisterReaders[i]; var lvi = processListViewEx.Items[i]; if (rr != null && Math.Abs(rr.WMVolume) > float.Epsilon && refVolume > float.Epsilon) { /// Update a list view item lvi.SubItems[(int)Column.Error].Text = Formulas.ErrorFromVolumes(rr.WMVolume, refVolume).ToString("F1"); lvi.SubItems[(int)Column.Volume].Text = rr.WMVolume.ToString("F1"); lvi.SubItems[(int)Column.Pulses].Text = rr.WMPulses.ToString(); lvi.SubItems[(int)Column.RefPulses].Text = rr.WMRefPulses.ToString(); } else { lvi.SubItems[(int)Column.Error].Text = string.Empty; lvi.SubItems[(int)Column.Volume].Text = string.Empty; lvi.SubItems[(int)Column.Pulses].Text = string.Empty; lvi.SubItems[(int)Column.RefPulses].Text = string.Empty; } if (rr is TBF.Rig.RegisterReaders.S640Stream.S640Stream) { lvi.SubItems[(int)Column.SerialNr].Text = (rr as TBF.Rig.RegisterReaders.S640Stream.S640Stream).PcbNumber.ToString(); } } } } void OnTestCompleted(object sender, TestCompletedEventArgs args) { if (args.TestRslt == null || ProcessData.RegisterReaders == null || ProcessData.BatchRslts == null || ProcessData.BatchRslts.Batch == null || ProcessData.BatchRslts.Batch.WaterMeters == null) { return; } int wmsCount = Math.Min(ProcessData.RegisterReaders.Length, ProcessData.BatchRslts.Batch.WaterMeters.Count); if (processListViewEx.Items.Count != wmsCount) { /// Invoked only when the number of water meters or register readers changes processListViewEx.Items.Clear(); for (int i = 0; i < wmsCount; i++) { var lvi = new ListViewItem((i + 1).ToString()); /// Column 0 for (Column c = (Column)1; c < Column.Count; c++) /// Column 1 .. Column.Count-1 { lvi.SubItems.Add("."); } lvi.Tag = ProcessData.BatchRslts.Batch.WaterMeters[i]; processListViewEx.Items.Add(lvi); } } if (args.TestRslt != null) { for (int i = 0; i < wmsCount; i++) { var wm = processListViewEx.Items[i].Tag as Results.Entities.WaterMeter; if (wm != null && !wm.Disabled) { Results.Entities.MeterTestRslt mtr = wm.MeterTestRslts.FirstOrDefault(x => x.TestRslt == args.TestRslt); if (mtr != null) { var lvi = processListViewEx.Items[i]; /// Update a list view item lvi.SubItems[(int)Column.Error].Text = mtr.Error.ToString("F1"); lvi.SubItems[(int)Column.Volume].Text = mtr.VolumeMeter.ToString("F1"); lvi.SubItems[(int)Column.Pulses].Text = mtr.PulsesMeter.ToString(); lvi.SubItems[(int)Column.RefPulses].Text = mtr.PulsesMaster.ToString(); lvi.SubItems[(int)Column.SerialNr].Text = mtr.SerialNr(); } } } } } void OnProcedureCompleted(object sender, ProcedureCompletedEventArgs args) { } private void ProcessTabPageCtrl_Paint(object sender, PaintEventArgs e) { System.Drawing.Graphics formGraphics = this.CreateGraphics(); } } }