using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using GenesisCordonelInterface.API; using static GenesisCordonelInterface.API.PublicModels; namespace GenesisCordonelInterface.UI.Debug { public partial class MeterBatchConfigPanel : UserControl { private readonly InterfaceOutsideToGCI api; private bool isRefreshing; private List comPorts = new List(); public MeterBatchConfigPanel(InterfaceOutsideToGCI api) { this.api = api; InitializeComponent(); RefreshComPorts(); InitializeGridColumns(); api.MeterBatchStatusChanged += Api_MeterBatchStatusChanged; UpdateGrid(api.GetMeterBatchDebugStatuses()); } #region INIT // ---------------------------------------------------- private void InitializeGridColumns() { grid.Columns.Clear(); grid.Columns.Add("Slot", "Slot"); grid.Columns.Add(new DataGridViewCheckBoxColumn { Name = "Selected", HeaderText = "Selected" }); grid.Columns.Add("PcbId", "PcbId"); grid.Columns.Add(new DataGridViewCheckBoxColumn { Name = "IsLoggedOn", HeaderText = "IsLoggedOn" }); grid.Columns.Add(CreateComPortColumn("RequestPort", "RequestPort")); grid.Columns.Add(CreateComPortColumn("StreamingPort", "StreamingPort")); grid.Columns.Add(CreateButtonColumn("DetectRequest", "DetectRequest", "...")); grid.Columns.Add(CreateButtonColumn("DetectStreaming", "DetectStreaming", "...")); grid.Columns.Add("FwVersion", "FwVersion"); grid.Columns.Add("InterfaceVersion", "InterfaceVersion"); foreach (DataGridViewColumn col in grid.Columns) { col.ReadOnly = col.Name != "Selected" && col.Name != "RequestPort" && col.Name != "StreamingPort" && col.Name != "DetectRequest" && col.Name != "DetectStreaming"; } EnableDoubleBuffering(grid); } private DataGridViewComboBoxColumn CreateComPortColumn(string name, string headerText) { return new DataGridViewComboBoxColumn { Name = name, HeaderText = headerText, DataSource = new List(comPorts), FlatStyle = FlatStyle.Flat, DisplayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton }; } private DataGridViewButtonColumn CreateButtonColumn(string name, string headerText, string text) { return new DataGridViewButtonColumn { Name = name, HeaderText = headerText, Text = text, UseColumnTextForButtonValue = true }; } private void RefreshComPorts() { comPorts = SerialPort.GetPortNames() .OrderBy(NaturalComPortOrder) .ToList(); if (!comPorts.Contains("")) comPorts.Insert(0, ""); } // ---------------------------------------------------- #endregion #region REFRESH EVENT DRIVEN // ---------------------------------------------------- private void Api_MeterBatchStatusChanged( List data) { if (IsDisposed) return; if (InvokeRequired) { BeginInvoke(new Action(() => UpdateGrid(data))); return; } UpdateGrid(data); } private void UpdateGrid(List data) { isRefreshing = true; foreach (var meter in data) { EnsurePortValueExists(meter.RequestPort); EnsurePortValueExists(meter.StreamingPort); var row = FindOrCreateRow(meter.Slot); Set(row, "Slot", meter.Slot); Set(row, "Selected", meter.Selected); Set(row, "PcbId", meter.PcbId); Set(row, "IsLoggedOn", meter.IsLoggedOn); Set(row, "RequestPort", meter.RequestPort); Set(row, "StreamingPort", meter.StreamingPort); Set(row, "FwVersion", meter.FwVersion); Set(row, "InterfaceVersion", meter.InterfaceVersion); } isRefreshing = false; } // ---------------------------------------------------- #endregion #region COM PORT HELPERS // ---------------------------------------------------- private void UpdateComPortColumnItems(string columnName) { var col = grid.Columns[columnName] as DataGridViewComboBoxColumn; if (col == null) return; col.DataSource = null; col.DataSource = new List(comPorts); } private void EnsurePortValueExists(string port) { if (string.IsNullOrWhiteSpace(port)) return; if (comPorts.Contains(port)) return; comPorts.Add(port); comPorts = comPorts.OrderBy(NaturalComPortOrder).ToList(); if (!comPorts.Contains("")) comPorts.Insert(0, ""); UpdateComPortColumnItems("RequestPort"); UpdateComPortColumnItems("StreamingPort"); } private static int NaturalComPortOrder(string port) { if (string.IsNullOrWhiteSpace(port)) return 0; string number = new string(port.Where(char.IsDigit).ToArray()); int parsed; if (int.TryParse(number, out parsed)) return parsed; return int.MaxValue; } // ---------------------------------------------------- #endregion #region GRID HELPERS // ---------------------------------------------------- private DataGridViewRow FindOrCreateRow(int slot) { foreach (DataGridViewRow row in grid.Rows) { if (row.Cells["Slot"].Value != null && Convert.ToInt32(row.Cells["Slot"].Value) == slot) { return row; } } int idx = grid.Rows.Add(); var newRow = grid.Rows[idx]; newRow.Cells["Slot"].Value = slot; return newRow; } private void Set(DataGridViewRow row, string col, object value) { if (!grid.Columns.Contains(col)) return; if (value == null) value = ""; var cell = row.Cells[col]; if (!Equals(cell.Value, value)) cell.Value = value; } // ---------------------------------------------------- #endregion #region USER EDIT // ---------------------------------------------------- private void grid_CurrentCellDirtyStateChanged(object sender, EventArgs e) { if (grid.IsCurrentCellDirty) grid.CommitEdit(DataGridViewDataErrorContexts.Commit); } private void grid_CellValueChanged(object sender, DataGridViewCellEventArgs e) { if (isRefreshing) return; if (e.RowIndex < 0) return; string columnName = grid.Columns[e.ColumnIndex].Name; if (columnName != "Selected" && columnName != "RequestPort" && columnName != "StreamingPort") return; int slot = Convert.ToInt32(grid.Rows[e.RowIndex].Cells["Slot"].Value); if (columnName == "Selected") { bool selected = Convert.ToBoolean(grid.Rows[e.RowIndex].Cells["Selected"].Value); api.SetSlotSelected(slot, selected); return; } string port = Convert.ToString(grid.Rows[e.RowIndex].Cells[columnName].Value); if (columnName == "RequestPort") { //api.SetSlotRequestPort(slot, port); return; } if (columnName == "StreamingPort") { //api.SetSlotStreamingPort(slot, port); return; } } private async void grid_CellContentClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex < 0) return; string columnName = grid.Columns[e.ColumnIndex].Name; if (columnName != "DetectRequest" && columnName != "DetectStreaming") return; int slot = Convert.ToInt32(grid.Rows[e.RowIndex].Cells["Slot"].Value); if (columnName == "DetectRequest") { await DetectRequestPortAsync(slot); return; } if (columnName == "DetectStreaming") { await DetectStreamingPortAsync(slot); return; } } private async Task DetectRequestPortAsync(int slot) { try { grid.Enabled = false; await api.DetectRequestPortAsync(slot); api.RaiseMeterBatchStatusChanged(); } finally { grid.Enabled = true; } } private async Task DetectStreamingPortAsync(int slot) { try { grid.Enabled = false; await api.DetectStreamingPortAsync(slot); api.RaiseMeterBatchStatusChanged(); } finally { grid.Enabled = true; } } private void grid_DataError(object sender, DataGridViewDataErrorEventArgs e) { e.ThrowException = false; } // ---------------------------------------------------- #endregion #region PERFORMANCE // ---------------------------------------------------- private void EnableDoubleBuffering(DataGridView dgv) { typeof(DataGridView) .GetProperty( "DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic) ?.SetValue(dgv, true, null); } // ---------------------------------------------------- #endregion public void AddEmptySlotRow() { int nextSlot = 1; var existing = grid.Rows .Cast() .Where(r => r.Cells["Slot"].Value != null) .Select(r => Convert.ToInt32(r.Cells["Slot"].Value)) .ToList(); if (existing.Count > 0) nextSlot = existing.Max() + 1; int idx = grid.Rows.Add(); var row = grid.Rows[idx]; row.Cells["Slot"].Value = nextSlot; row.Cells["Selected"].Value = true; row.Cells["RequestPort"].Value = ""; row.Cells["StreamingPort"].Value = ""; } public List GetGridData() { var list = new List(); foreach (DataGridViewRow row in grid.Rows) { if (row.Cells["Slot"].Value == null) continue; list.Add(new MeterBatchDebugStatus { Slot = Convert.ToInt32(row.Cells["Slot"].Value), Selected = Convert.ToBoolean(row.Cells["Selected"].Value), RequestPort = Convert.ToString(row.Cells["RequestPort"].Value), StreamingPort = Convert.ToString(row.Cells["StreamingPort"].Value) }); } return list; } } }