365 lines
11 KiB
C#
365 lines
11 KiB
C#
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<Object[]>();
|
|
|
|
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<Task>();
|
|
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<string[]>(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)
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|