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.TestResult.Lixun; using Plugin.TestResult.Model; using Plugin.TestResult.Util; using Plugin.TestResult_WPF.Model; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO.Ports; using System.Windows; using System.Windows.Input; namespace Plugin.TestResult_WPF { 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; } } /// /// Scanner.xaml 的交互逻辑 /// public partial class Scanner : WindowX { private string _title; public string title { get { return _title; } set => Set(ref _title, value); } public event EventHandler FinishBarcode; public event EventHandler ComplateClick; private static Dictionary snrCache = new Dictionary(); 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) { ViewControl.Logger.Error("Open Scanner Window Error.", ex); MsgBoxHelper.Error(this, $"{ex.Message}"); } } /// /// 设置扫码枪 /// private void InitScanner() { string comStr = ""; if (serialPort != null) return; string section = this.Tag.ToString(); ScannerConfig common = ScannerConfig.ReadFromIni(ViewControl.SannerIniFile, "Config"); string portName = IniFileHelper.ReadIniData(section, "PortName", "", ViewControl.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) { ViewControl.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 { this.targetCellInfo = ScannerParser.GetCellInfoByCode(this.model, this.columns, this.rows, barcode); if (!TestResultView.nameTables.ContainsKey(targetCellInfo.OvenName)) { MsgBoxHelper2.Error($"老化炉 [{targetCellInfo.OvenName}] 不存在,请检查配置"); return; } positionText.Text = barcode; //positionText.Focus(); //snrText.Text = ""; snrText.Focus(); } catch (Exception ex) { ViewControl.Logger.Error("Parse Position Code Error.", ex); MsgBoxHelper2.Error($"穴位号 [{barcode}] 解析失败: {ex.Message}"); } } }); } catch (Exception ex) { ViewControl.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("EnableMes", false); if (ParamSetting.CustomerCode == "LIXUN" && EnableMes) { var table = TestResultView.tables[this.ovenIndex]; string currentPn = table.CbProduct.Text; /// 检查格式 if (!SNValidator.ValidateSN(currentPn, snr, out string msg)) { TestResultView.tables[this.ovenIndex].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)) { TestResultView.tables[this.ovenIndex].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) { TestResultView.tables[this.ovenIndex].GetSingleCell(targetCellInfo.Index).LightRed(true, out _); MsgBoxHelper2.Error($"当前测试料号为 [{currentPn}],扫码产品料号为 [{pn}] 不允许测试"); snrText.Text = string.Empty; snrText.Focus(); return; } } else { TestResultView.tables[this.ovenIndex].GetSingleCell(targetCellInfo.Index).LightRed(true, out _); MsgBoxHelper2.Error($"检查产品条码异常:{msg}"); snrText.Text = string.Empty; snrText.Focus(); return; } /// 检查工序 if (PNUtil.CheckIn(ViewControl.Logger, ParamSetting.MesAddress, stationName, snr, out bool needCheckIn, out msg)) { if (needCheckIn != true) { TestResultView.tables[this.ovenIndex].GetSingleCell(targetCellInfo.Index).LightRed(true, out _); MsgBoxHelper2.Error($"条码[{snr}]工序不在本站:{msg}"); snrText.Text = string.Empty; snrText.Focus(); return; } } else { TestResultView.tables[this.ovenIndex].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) { ViewControl.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) { ViewControl.Logger.Error("Con_Click Failed.", ex); ToastHelper.Warning(this, ex.Message); } }); } /// /// 原来的完成扫描逻辑 /// /// /// //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 oven = TestResultView.nameTables[targetCellInfo.OvenName]; if (oven.cells.Length < targetCellInfo.Index + 1) { MsgBoxHelper2.Error($"穴位下标 [{targetCellInfo.Index}] 超出索引"); positionText.Text = string.Empty; positionText.Focus(); targetCellInfo = null; return; } snrText.Focus(); } catch (Exception ex) { positionText.Text = string.Empty; positionText.Focus(); ViewControl.Logger.Error("Parse Position Code Error.", ex); MsgBoxHelper2.Error($"穴位号 [{barcode}] 解析失败: {ex.Message}"); } } }); } } } }