using HMI.Core.Manager;
|
using HMI.Core.Setting;
|
using HMI.Core.Util;
|
using HMI.UI.Util;
|
using HMI.Util;
|
using Panuon.WPF.UI;
|
using Plugin.BurnIn.Model;
|
using Plugin.BurnIn.Util;
|
using System.ComponentModel;
|
using System.IO.Ports;
|
using System.Windows;
|
using System.Windows.Input;
|
|
namespace Plugin.BurnIn
|
{
|
public class BarcodeEventArg
|
{
|
public string name { get; private set; }
|
public string positionCode { get; private set; }
|
public string snrCode { get; private set; }
|
public CellInfo lastInfo { get; private set; }
|
|
public BarcodeEventArg(string name, string positionCode, string snrCode, CellInfo lastInfo)
|
{
|
this.name = name;
|
this.positionCode = positionCode;
|
this.snrCode = snrCode;
|
this.lastInfo = lastInfo;
|
}
|
}
|
|
/// <summary>
|
/// Scanner.xaml 的交互逻辑
|
/// </summary>
|
public partial class Scanner : WindowX
|
{
|
private string _title;
|
|
public string title
|
{
|
get { return _title; }
|
set => Set(ref _title, value);
|
}
|
|
public event EventHandler<BarcodeEventArg> FinishBarcode;
|
public event EventHandler<RoutedEventArgs> ComplateClick;
|
|
private static Dictionary<string, CellInfo> snrCache = new Dictionary<string, CellInfo>();
|
SerialPort serialPort;
|
|
private string model;
|
private int columns;
|
private int rows;
|
private int ovenIndex;
|
private CellInfo targetCellInfo;
|
public Scanner(int index, string title, string model, int columns, int rows)
|
{
|
this.ovenIndex = index;
|
this.title = title;
|
this.model = model;
|
this.columns = columns;
|
this.rows = rows;
|
this.DataContext = this;
|
InitializeComponent();
|
Loaded += Scanner_Loaded;
|
}
|
|
private void Scanner_Loaded(object sender, RoutedEventArgs e)
|
{
|
try
|
{
|
InitScanner();
|
Loaded -= Scanner_Loaded;
|
}
|
catch (Exception ex)
|
{
|
BurnInUI.Logger.Error("Open Scanner Window Error.", ex);
|
MsgBoxHelper.Error(this, $"{ex.Message}");
|
}
|
}
|
|
/// <summary>
|
/// 设置扫码枪
|
/// </summary>
|
private void InitScanner()
|
{
|
string comStr = "";
|
if (serialPort != null) return;
|
|
string section = this.Tag.ToString();
|
ScannerConfig common = ScannerConfig.ReadFromIni(BurnInUI.SannerIniFile, "Config");
|
|
string portName = IniFileHelper.ReadIniData(section, "PortName", "", BurnInUI.SannerIniFile);
|
if (string.IsNullOrEmpty(portName))
|
{
|
if (section.StartsWith("A"))
|
{
|
portName = "COM1";
|
}
|
else
|
{
|
portName = "COM2";
|
}
|
}
|
common.PortName = portName;
|
|
|
// 配置串口
|
serialPort = new SerialPort
|
{
|
PortName = common.PortName,
|
BaudRate = common.BaudRate,
|
Parity = Parity.None,
|
DataBits = common.DataBits,
|
StopBits = common.StopBits,
|
Handshake = Handshake.None,
|
DtrEnable = common.DtrEnable,
|
RtsEnable = common.RtsEnable
|
//ReadTimeout = 500,
|
//WriteTimeout = 500,
|
//ReciveBufferSize=4096
|
};
|
|
try
|
{
|
// 打开串口
|
serialPort.Open();
|
// 注册接收数据事件
|
serialPort.DataReceived += SerialPort_DataReceived;
|
}
|
catch (Exception ex)
|
{
|
BurnInUI.Logger.Error("Init Scan Gun Failed.", ex);
|
MsgBoxHelper.Error(this, $"{this.lang("Tr.InitGunFailed")}: {ex.StackTrace}");
|
}
|
}
|
|
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
{
|
try
|
{
|
SerialPort sp = (SerialPort)sender;
|
string barcode = ReadDataFrom(sp).Trim();
|
|
//string barcode =
|
Dispatcher.Invoke(() =>
|
{
|
if (snrText.IsFocused)
|
{
|
snrText.Text = barcode;
|
Con_Click(null, null);
|
}
|
else
|
{
|
try
|
{
|
var targetCellInfo = ScannerParser.GetCellInfoByCode(this.model, this.columns, this.rows, barcode);
|
if (!TestResultView.nameTables.ContainsKey(targetCellInfo.OvenName))
|
{
|
MsgBoxHelper2.Error($"老化炉 [{targetCellInfo.OvenName}] 不存在,请检查配置");
|
return;
|
}
|
var sourceTable = TestResultView.tables[this.ovenIndex];
|
if (sourceTable.title != targetCellInfo.OvenName)
|
{
|
MsgBoxHelper2.Error($"请切换至 [{targetCellInfo.OvenName}] 区扫码,当前为 [{sourceTable.title}] 区!");
|
return;
|
}
|
|
var oven = TestResultView.nameTables[targetCellInfo.OvenName];
|
if (oven.cells.Length < targetCellInfo.Index + 1)
|
{
|
MsgBoxHelper2.Error($"穴位号 [{barcode}] 超出索引 {targetCellInfo.Index}");
|
return;
|
}
|
|
this.targetCellInfo = targetCellInfo;
|
positionText.Text = barcode;
|
//positionText.Focus();
|
//snrText.Text = "";
|
snrText.Focus();
|
}
|
catch (Exception ex)
|
{
|
BurnInUI.Logger.Error("Parse Position Code Error.", ex);
|
MsgBoxHelper2.Error($"穴位号 [{barcode}] 解析失败: {ex.Message}");
|
}
|
}
|
});
|
}
|
catch (Exception ex)
|
{
|
BurnInUI.Logger.Error("Get Scan Gun Data Failed.", ex);
|
MessageBox.Show($"{this.lang("Tr.GetGunData")}: {ex.StackTrace}");
|
}
|
}
|
|
public static void InsertNewCode(string snr, CellInfo info)
|
{
|
snrCache[snr] = info;
|
}
|
|
public static void RemoveSNR(string snr)
|
{
|
snrCache.Remove(snr);
|
}
|
|
private void SendCode(string tag, string position, string snr)
|
{
|
if (snrCache.ContainsKey(snr))
|
{
|
string oldPosition = snrCache[snr].OriginCode;
|
if (MsgBoxHelper2.WarnChoose($"条码[{snr}]已放置于[{oldPosition}]中,是否清除?") == MessageBoxResult.OK)
|
{
|
try
|
{
|
FinishBarcode.Invoke(this, new BarcodeEventArg(tag, position, null, snrCache[snr]));
|
snrCache.Remove(snr);
|
FinishBarcode.Invoke(this, new BarcodeEventArg(tag, position, snr, null));
|
}
|
catch (Exception ex)
|
{
|
ToastHelper.Error(ex.Message);
|
}
|
}
|
}
|
else
|
{
|
FinishBarcode.Invoke(this, new BarcodeEventArg(tag, position, snr, null));
|
}
|
}
|
|
private void Con_Click(object sender, RoutedEventArgs e)
|
{
|
Dispatcher.Invoke(() =>
|
{
|
string position = positionText.Text, snr = snrText.Text;
|
try
|
{
|
var EnableMes = ParameterManager.GetCommonParameterByName<bool>("EnableMes", false);
|
if (ParamSetting.CustomerCode == "LIXUN" && EnableMes)
|
{
|
var table = TestResultView.nameTables[targetCellInfo.OvenName];
|
// TestResultView.tables[this.ovenIndex]
|
string currentPn = table.CbProduct.Text;
|
|
/// 检查格式
|
if (!SNValidator.ValidateSN(currentPn, snr, out string msg))
|
{
|
table.GetSingleCell(targetCellInfo.Index).LightRed(true, out _);
|
MsgBoxHelper2.Error($"检查产品条码异常:{msg}");
|
snrText.Text = string.Empty;
|
snrText.Focus();
|
return;
|
}
|
|
/// 获取站名
|
string stationName = ProductManager.GetParameterByProductAndName(currentPn, "MES站位")?.Value;
|
if (string.IsNullOrEmpty(stationName))
|
{
|
table.GetSingleCell(targetCellInfo.Index).LightRed(true, out _);
|
MsgBoxHelper2.Error($"检查产品条码异常,当前产品[{currentPn}]未设置参数MES站位");
|
snrText.Text = string.Empty;
|
snrText.Focus();
|
return;
|
}
|
|
/// 检查PN
|
if (PNUtil.GetPN(ParamSetting.MesAddress, stationName, snr, out string pn, out msg))
|
{
|
|
if (pn != currentPn)
|
{
|
table.GetSingleCell(targetCellInfo.Index).LightRed(true, out _);
|
MsgBoxHelper2.Error($"当前测试料号为 [{currentPn}],扫码产品料号为 [{pn}] 不允许测试");
|
snrText.Text = string.Empty;
|
snrText.Focus();
|
return;
|
}
|
}
|
else
|
{
|
table.GetSingleCell(targetCellInfo.Index).LightRed(true, out _);
|
MsgBoxHelper2.Error($"检查产品条码异常:{msg}");
|
snrText.Text = string.Empty;
|
snrText.Focus();
|
return;
|
}
|
|
/// 检查工序
|
if (PNUtil.CheckIn(BurnInUI.Logger, ParamSetting.MesAddress, stationName, snr, out bool needCheckIn, out msg))
|
{
|
if (needCheckIn != true)
|
{
|
table.GetSingleCell(targetCellInfo.Index).LightRed(true, out _);
|
MsgBoxHelper2.Error($"条码[{snr}]工序不在本站:{msg}");
|
snrText.Text = string.Empty;
|
snrText.Focus();
|
return;
|
}
|
}
|
else
|
{
|
table.GetSingleCell(targetCellInfo.Index).LightRed(true, out _);
|
MsgBoxHelper2.Error($"条码[{snr}]CheckIn失败:{msg}");
|
snrText.Text = string.Empty;
|
snrText.Focus();
|
return;
|
}
|
}
|
//var _ = ScannerParser.GetCellInfoByCode(this.model, this.columns, this.rows, snr);
|
//ToastHelper.Warning(this, "产品码格式异常");
|
//snrText.Text = string.Empty;
|
//snrText.Focus();
|
//return;
|
}
|
catch (Exception ex)
|
{
|
BurnInUI.Logger.Error("Scanner Check Error.", ex);
|
MsgBoxHelper2.Error($"扫码检查异常:{ex.Message}");
|
return;
|
}
|
|
if (string.IsNullOrEmpty(position) || string.IsNullOrEmpty(snr))
|
{
|
ToastHelper.Warning(this, this.lang("Tr.PleaseInputSnrs"));
|
return;
|
}
|
try
|
{
|
SendCode(Tag.ToString(), position, snr);
|
positionText.Text = "";
|
snrText.Text = "";
|
positionText.Focus();
|
}
|
catch (Exception ex)
|
{
|
BurnInUI.Logger.Error("Con_Click Failed.", ex);
|
ToastHelper.Warning(this, ex.Message);
|
}
|
});
|
}
|
|
/// <summary>
|
/// 原来的完成扫描逻辑
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
//private void Ok_Click(object sender, RoutedEventArgs e)
|
//{
|
// string position = positionText.Text, snr = snrText.Text;
|
// if (string.IsNullOrEmpty(position) || string.IsNullOrEmpty(snr))
|
// {
|
// ToastHelper.Warning(this, this.lang("Tr.PleaseInputSnrs"));
|
// return;
|
// }
|
// try
|
// {
|
// SendCode(Tag.ToString(), position, snr);
|
// this.Close();
|
// }
|
// catch (Exception ex)
|
// {
|
// ViewControl.Logger.Error("Con_Click Failed.", ex);
|
// ToastHelper.Warning(this, ex.Message);
|
// }
|
//}
|
|
private void Ok_Click(object sender, RoutedEventArgs e)
|
{
|
ComplateClick?.Invoke(this, e);
|
this.Close();
|
}
|
|
private string ReadDataFrom(SerialPort sp)
|
{
|
string barcode = "";
|
while (sp.BytesToRead > 0)
|
{
|
byte[] buffer = new byte[sp.BytesToRead];
|
sp.Read(buffer, 0, buffer.Length);
|
barcode += System.Text.Encoding.ASCII.GetString(buffer);
|
System.Threading.Thread.Sleep(50);
|
}
|
return barcode;
|
}
|
|
private void Window_Closing(object sender, CancelEventArgs e)
|
{
|
try
|
{
|
targetCellInfo = null;
|
serialPort.Dispose();
|
serialPort = null;
|
}
|
catch (Exception ex)
|
{
|
}
|
}
|
|
private void TextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
|
{
|
if (e.Key == Key.Enter)
|
{
|
//string barcode =
|
Dispatcher.Invoke(() =>
|
{
|
if (snrText.IsFocused)
|
{
|
Con_Click(null, null);
|
}
|
else
|
{
|
//if (ParamSetting.CustomerCode != "LIXUN")
|
//{
|
// snrText.Focus();
|
// return;
|
//}
|
string barcode = positionText.Text;
|
try
|
{
|
targetCellInfo = ScannerParser.GetCellInfoByCode(this.model, this.columns, this.rows, barcode);
|
if (!TestResultView.nameTables.ContainsKey(targetCellInfo.OvenName))
|
{
|
MsgBoxHelper2.Error($"老化炉 [{targetCellInfo.OvenName}] 不存在,请检查配置");
|
positionText.Text = string.Empty;
|
positionText.Focus();
|
targetCellInfo = null;
|
return;
|
}
|
|
var sourceTable = TestResultView.tables[this.ovenIndex];
|
if (sourceTable.title != targetCellInfo.OvenName)
|
{
|
MsgBoxHelper2.Error($"请切换至 [{targetCellInfo.OvenName}] 区扫码,当前为 [{sourceTable.title}] 区!");
|
positionText.Text = string.Empty;
|
positionText.Focus();
|
targetCellInfo = null;
|
return;
|
}
|
|
var oven = TestResultView.nameTables[targetCellInfo.OvenName];
|
if (oven.cells.Length < targetCellInfo.Index + 1)
|
{
|
MsgBoxHelper2.Error($"穴位号 [{barcode}] 超出索引 {targetCellInfo.Index}");
|
positionText.Text = string.Empty;
|
positionText.Focus();
|
targetCellInfo = null;
|
return;
|
}
|
snrText.Focus();
|
}
|
catch (Exception ex)
|
{
|
positionText.Text = string.Empty;
|
positionText.Focus();
|
BurnInUI.Logger.Error("Parse Position Code Error.", ex);
|
MsgBoxHelper2.Error($"穴位号 [{barcode}] 解析失败: {ex.Message}");
|
}
|
}
|
});
|
}
|
}
|
}
|
}
|