using HslCommunication.Profinet.GE; using Microsoft.Extensions.Logging; using SlnMesnac.Common; using SlnMesnac.Config; using SlnMesnac.Model.domain; using SlnMesnac.Plc; using SlnMesnac.Repository.service; using SlnMesnac.Repository.service.Impl; using SlnMesnac.TouchSocket; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Security.Cryptography.Xml; using System.ServiceModel.Channels; using System.Threading; using System.Threading.Tasks; using TouchSocket.Core; namespace SlnMesnac.Business { public class LogoBusiness { private TcpServer tcpServer = null; private ILogger logger; private PlcAbsractFactory plc = null; private DebugConfig config = DebugConfig.Instance; private IBaseMaterialService baseMaterialService; private ILogoIdentifyService logoIdentifyService; private ILogoConfigService logoConfigService; public PaddleOCRSharp.PaddleOCREngine engine = null; private GunHelper gunHelper = GunHelper.Instance; private static LogoBusiness instance; // 存放照片路径 public static string PicturePath = System.Environment.CurrentDirectory + "/picture/"; /// /// 存储海康相机识别结果 /// private static bool HikCameraResult = false; #region 委托定义 刷新界面扫描信息 public delegate void RefreshBoxInfo(string boxCode, string boxTime, string model, byte[] imageData, bool isSuccess); public static event RefreshBoxInfo? RefreshBoxInfoEvent; public delegate void RefreshMessage(string message, bool isWarning = false); public static event RefreshMessage? RefreshMessageEvent; #endregion private LogoBusiness(ILogger logger,ILogoConfigService logoConfigService, IBaseMaterialService baseMaterialService,ILogoIdentifyService logoIdentifyService,PlcPool _plcPool,TcpServer _tcpServer) { this.logger = logger; tcpServer = _tcpServer; TcpServer.RefreshMaterialCodeStrEvent += BarCodeHandler; TcpServer.CameraResultEvent += ReceiveCameraResult; this.baseMaterialService = baseMaterialService; this.logoIdentifyService = logoIdentifyService; this.logoConfigService = logoConfigService; gunHelper.InstanceSerialPort(); plc = _plcPool.GetPlcByKey("plc"); BarCodeHandler("2741001000021E680369",""); } private void ReceiveCameraResult(string result) { logger.LogInformation($"相机返回结果:{result}"); } public static LogoBusiness GetInstance(ILogger logger,ILogoConfigService logoConfigService,IBaseMaterialService baseMaterialService, ILogoIdentifyService ocrVerfiyService, PlcPool _plcPool, TcpServer _tcpServer) { if (instance == null) { instance = new LogoBusiness(logger,logoConfigService,baseMaterialService, ocrVerfiyService, _plcPool,_tcpServer); } return instance; } /// /// 条码触发相机拍照校验 /// /// /// public async void BarCodeHandler(string materialCodeStr, string ip) { // 传入照片 byte[] ImageData = null; try { #region 初始操作:复位海康上次结果,删除海康上次保存文件 HikCameraResult = false; FileHelper.DeleteAllPictures(config.CameraFilePath); #endregion bool judge = FoamtJudge(materialCodeStr); if (!judge) { WarningAndStop($"箱体码{materialCodeStr}格式不正确,停线报警!"); return; } logger.LogInformation($"扫描到箱体码:{materialCodeStr}"); // 1.触发相机拍照 tcpServer.SendCommand(config.CameraIP, "Execute"); //2.根据箱体码查询型号,根据型号判断是否需要校验LOGO ProductModel mode = logoConfigService.GetMaterialTypeByBarCode(materialCodeStr); LogoConfig logoConfig = logoConfigService.GetByMaterialType(mode.MaterialCode); // 海康校验结果 bool hikFlag = false; if (logoConfig.IsChecked == 1) { // 需要校验 // 2.等待接收海康结果 hikFlag = await JudgeIsSuccessAsync(); if (hikFlag) { //校验成功放行 RefreshMessageEvent?.Invoke("Logo识别成功,下发放行"); logger.LogInformation($"箱体码:{materialCodeStr},Logo识别成功,下发放行"); } else { //校验失败禁止放行 WarningAndStop($"Logo识别失败,禁止放行"); } } else { // 不需要校验 hikFlag = true; RefreshMessageEvent?.Invoke("Logo无需识别,下发放行"); logger.LogInformation($"箱体码:{materialCodeStr},Logo无需识别,下发放行"); } #region 更新数据库 LogoIdentify record = new LogoIdentify(); record.ProductCode = materialCodeStr; record.MaterialType = logoConfig.MaterialType; record.MaterialName = logoConfig.MaterialName; record.isChecked = logoConfig.IsChecked; record.Result = hikFlag ? 1 : 0; record.RecordTime = DateTime.Now; logoIdentifyService.InsertRecord(record); #endregion ImageData = FileHelper.FindPhoto(config.CameraFilePath); if(ImageData != null) { FileHelper.SaveImage(ImageData, materialCodeStr + ".jpg", PicturePath); // 刷新界面、刷新图片,照片按照日期存储本地 RefreshBoxInfoEvent?.Invoke(materialCodeStr, DateTime.Now.ToString(), logoConfig.MaterialName, ImageData, hikFlag); } else { WarningAndStop($"读取相机保存照片文件夹失败,请检查文件夹:{config.CameraFilePath}是否存在"); } } catch (Exception ex) { WarningAndStop($"BarCodeHandler异常,识别Logo失败,原因:{ex.Message},箱体条码:{materialCodeStr}"); } } /// /// 判断Logo校验是否成功 /// /// public async Task JudgeIsSuccessAsync() { bool result = false; // 设置计时器 Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); //至多等待2.5s海康的校验结果 result = await Task.Run(() => { while (true) { if (HikCameraResult == true) { return true; } // 检查是否超过两秒 if (stopwatch.ElapsedMilliseconds > 2500) { return false; } Thread.Sleep(100); } }); return result; } /// /// 箱体码格式校验 /// /// /// private bool FoamtJudge(string code) { if (!string.IsNullOrEmpty(code)) { if(code.Length == 20) { return true; } } return false; } /// /// 截取两个逗号之间的字符串 /// /// /// static string GetSubstringBetweenCommas(string input) { if (input == null) return null; // 找到第一个逗号的位置 int firstCommaIndex = input.IndexOf(','); if (firstCommaIndex != -1) { // 找到第二个逗号的位置 int secondCommaIndex = input.IndexOf(',', firstCommaIndex + 1); if (secondCommaIndex != -1) { // 使用Substring截取第一个逗号和第二个逗号之间的字符 return input.Substring(firstCommaIndex + 1, secondCommaIndex - firstCommaIndex - 1); } else { return null; } } else { return null; } } #region PLC交互部分 //M100停止点位 public void Pass() { try { if (plc != null && plc.IsConnected) { plc.writeInt32ByAddress("DB22.DBW2", 8); Task.Run(() => { // 设置计时器 Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); while (true) { if (plc.readInt32ByAddress("DB22.DBW2") == 0) { logger.LogInformation("PLC复位成功,启动线体"); RefreshMessageEvent?.Invoke("PLC复位成功,启动线体", true); } // 检查是否超过两秒 if (stopwatch.ElapsedMilliseconds > 3000) { logger.LogError("PLC复位超时"); RefreshMessageEvent?.Invoke("PLC复位超时", true); break; } Thread.Sleep(100); } }); } else { logger.LogError("PLC未连接,请检查连接"); RefreshMessageEvent?.Invoke("PLC未连接,请检查连接", true); } // 声光电报警复位 gunHelper.SendData("OK"); } catch (Exception ex) { logger.LogError($"下发PLC复位方法Pass()异常:{ex.Message}"); } } public void Stop() { try { if (plc != null && plc.IsConnected) { plc.writeInt32ByAddress("DB22.DBW2", 9); Task.Run(() => { // 设置计时器 Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); while (true) { if (plc.readInt32ByAddress("DB22.DBW2") == 1) { logger.LogInformation("PLC复位成功,启动线体"); RefreshMessageEvent?.Invoke("PLC复位成功,启动线体", true); } // 检查是否超过两秒 if (stopwatch.ElapsedMilliseconds > 3000) { logger.LogError("PLC复位超时"); RefreshMessageEvent?.Invoke("PLC复位超时", true); break; } Thread.Sleep(100); } }); } // 声光电报警 gunHelper.SendData("NG"); } catch (Exception ex) { logger.LogError($"下发PLC报警方法Stop()异常:{ex.Message}"); } } #endregion #region 记录日志,刷新界面及下发PLC报警 public void WarningAndStop(string message) { logger.LogError(message); RefreshMessageEvent?.Invoke(message, true); Stop(); } #endregion } }