using Newtonsoft.Json; using NLog; using System; using System.Collections.Generic; using System.Net; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Xylem.Common.CommonCore.Configuration; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore; using Xylem.Common.Logic.SoftwareAccessHelper; using Xylem.Common.Utils.Logging; namespace XylemCommonUiLegacyGenCtl { [Guid("34DE1F5F-BC96-4A28-9ED3-87C1A3E00920"), ComVisible(true), ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(ICtlAutoDetect))] public partial class ctlAutoDetect : UserControl, ICtlAutoDetect { public delegate void OnSearchCompletedDelegate(); private event OnSearchCompletedDelegate OnSearchCompleted; private CancellationTokenSource Stop = new CancellationTokenSource(); private Exception[] exs; private int[] slots; private MeterBatch batch = new MeterBatch(); private string[] slotStatus; private string[] slotSerialNumbers; private ILogger _logger; private bool isDone = false; public bool IsDone() { return isDone; } public ctlAutoDetect() { _logger = NLogHelper.CreateOrGetMultiLogger("ctlBatch", "", "Batch", "", ""); _logger.Info($"start construct ctlAutoDetect"); InitializeComponent(); } public event EventHandler ErrorOnSlot; public string GetErrorText(int Slot) { throw new NotImplementedException(); } public string GetSerialNumber(int Slot) { var slotIndex = getSlotIndex(Slot); if (slotIndex == -1 || slotSerialNumbers.Length <= slotIndex || slotSerialNumbers[slotIndex] == null) { _logger.Info($"GetSerialNumber for slot {Slot} return Empty"); return string.Empty; } _logger.Info($"GetSerialNumber for slot {Slot} return {slotSerialNumbers[slotIndex]}"); return slotSerialNumbers[slotIndex]; } public void Init(int Slots) { _logger.Info($"Init {Slots} Slots"); slots = new Int32[Slots]; for (int i = 0; i < Slots; i++) { slots[i] = i + 1; } } private Task searchTask = null; public void Start() { if (searchTask == null || searchTask.IsCompleted) { Stop = new CancellationTokenSource(); isDone = false; Invoke(new Action(() => { btnSearch.Enabled = false; btnTake.Enabled = false; })); searchTask = new Task(() => { search(Stop.Token); }, Stop.Token); searchTask.Start(); } else { isDone = true; } } private void UpdateUi() { var dgvData = new List(); foreach (var slot in slots) { var sr = slotStatus[getSlotIndex(slot)]; var ex = exs[getSlotIndex(slot)]; if (string.IsNullOrEmpty(sr)) { sr = "None"; } if (ex != null) { sr = $"{sr}[error]"; } dgvData.Add(new Object[] { slot, sr }); } Invoke(new Action(() => { dgvDetect.Rows.Clear(); foreach (var data in dgvData) { dgvDetect.Rows.Add(data); } })); } private void btnSearch_Click(object sender, EventArgs e) { Start(); } private int getSlotIndex(int Slot) { int r = 0; foreach (var searchForSlot in slots) { if (Slot == searchForSlot) { return r; } r = r + 1; } return -1; } private void search(CancellationToken cancellation) { _logger.Info($"start search"); if (slots == null) { _logger.Info($"search was not initialized"); throw new ApplicationException("Not Init"); } exs = new Exception[slots.Length]; slotStatus = new String[slots.Length]; slotSerialNumbers = new String[slots.Length]; var allSearchTask = new List(); if (batch != null) { batch.Dispose(); } batch = new MeterBatch(); var sClone = slots.Clone(); foreach (var searchSlot in slots) { try { if (cancellation.IsCancellationRequested) { return; } var newTryMeter = new GenesisMeter(); _logger.Info($"Try to setup meter at slot {searchSlot}"); newTryMeter.SetupFromConfigFile(searchSlot); batch.AddMeter(newTryMeter); } catch (Exception e) { slotStatus[getSlotIndex(searchSlot)] = "None"; exs[getSlotIndex(searchSlot)] = e; _logger.Error(e, $"failed to setup slot setup task at slot {searchSlot}"); } } UpdateUi(); foreach (var meterslot in batch.ListOfMeters) { if (meterslot is GenesisMeter searchSlot) { try { var t = new Task(() => { try { if (cancellation.IsCancellationRequested) { return; } SearchPcbId(searchSlot, searchSlot.Slot, cancellation); } catch (Exception e) { _logger.Error(e, $"failed to setup meter at slot {searchSlot.Slot}"); slotStatus[getSlotIndex(searchSlot.Slot)] = "None"; exs[getSlotIndex(searchSlot.Slot)] = e; } }); allSearchTask.Add(t); } catch (Exception e) { slotStatus[getSlotIndex(searchSlot.Slot)] = "None"; exs[getSlotIndex(searchSlot.Slot)] = e; _logger.Error(e, $"failed to start slot setup task at slot {searchSlot.Slot}"); } } } allSearchTask.ForEach(t => t.Start()); Task.WaitAll(allSearchTask.ToArray()); UpdateUi(); batch.Dispose(); batch = null; _logger.Info($"Batch is disposed"); Invoke(new Action(() => { btnSearch.Enabled = true; btnTake.Enabled = true; })); } private string GetPcbMapping(string pcbID) { if (string.IsNullOrEmpty(pcbID)) { return ""; } var url = $"{ServiceUrls.MarriageServiceUrl()}GetSerialNumberAndOrderNumber?PcbId={pcbID}"; try { var requestResponse = LocalWebRequest.GetRequest(url, 2000); if (!string.IsNullOrEmpty(requestResponse)) { var a = JsonConvert.DeserializeObject(requestResponse); return a[0]; } else { return ""; } } catch (Exception ex) { if (ex is WebException) { //MessageBox.Show($"Error on Store: {Environment.NewLine} { ((WebException)ex).Message}"); } _logger.Error(ex, $"failed to get pcb mapping for pcbid {pcbID}"); return ""; //MessageBox.Show(ex.Message); } } private void SearchPcbId(GenesisMeter newTryMeter, int slot, CancellationToken cancellation) { try { if (cancellation.IsCancellationRequested) { return; } var firstPcbID = newTryMeter.GetPcbId(); if (cancellation.IsCancellationRequested) { return; } if (!string.IsNullOrEmpty(firstPcbID)) { slotStatus[getSlotIndex(slot)] = $"detect {firstPcbID}"; var sr = GetPcbMapping(firstPcbID); if (!string.IsNullOrEmpty(sr)) { slotStatus[getSlotIndex(slot)] = $"found meter {sr}"; slotSerialNumbers[getSlotIndex(slot)] = sr; } else { slotStatus[getSlotIndex(slot)] = $"no mapping found for PCBId {firstPcbID}"; } } } catch (Exception e) { _logger.Error(e, $"failed to search pcbid at slot {slot}"); exs[getSlotIndex(slot)] = e; } finally { batch?.RemoveMeter(newTryMeter); } } public void Kill() { batch?.RemoveAllMeters(); batch.Dispose(); Dispose(); } private void btnTake_Click(object sender, EventArgs e) { if (searchTask.Status == TaskStatus.Running || searchTask.Status == TaskStatus.WaitingToRun) { Stop.Cancel(); searchTask.Wait(); } searchTask.Dispose(); isDone = true; OnSearchCompleted?.Invoke(); //internalSerialNumberFound?.Invoke(); batch?.Dispose(); btnTake.Enabled = false; } private void dgvDetect_CellContentClick(object sender, DataGridViewCellEventArgs e) { } private void ctlAutoDetect_Load(object sender, EventArgs e) { } } }