using Newtonsoft.Json; using SqlSugar; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using ZJ_BYD.Common; using ZJ_BYD.DB; using ZJ_BYD.Enums; using ZJ_BYD.Model; using ZJ_BYD.Untils; using ZJ_BYD.ViewModel; namespace ZJ_BYD { public class CheckCode { /// /// PLC请求启动校验 /// /// /// /// public static (bool ok, string val, string msg) StartCheck(StationInfo stationInfo, List keyValues) { string msg; string productCode = string.Empty; #region 本地校验主条码 //机种信息 var M14 = keyValues.FirstOrDefault(m => m.Key == "M14"); if (string.IsNullOrWhiteSpace(M14.Val)) { msg = $"{stationInfo.StationName}请求启动时机种({M14.Val})异常!"; return (false, "3", msg); } var mskCode = Program.t_MaskCodes.First(m => m.StationCode == stationInfo.StationCode && m.SortIndex == int.Parse(M14.Val)); if (mskCode == null) { msg = $"一体机启动反馈:StartCheck方法中mskCode==null,StationCode={stationInfo.StationCode},SortIndex={M14.Val}"; return (false, "3", msg); } //主条码 var M28 = keyValues.FirstOrDefault(m => m.Key == "M28"); //重新读取主条码 var M28Result = PlcHelper.GetPlcVal(M28.DataType, M28.Address); if (M28Result.ok) { M28.Val = M28Result.val.Replace("\r", ""); } if (string.IsNullOrWhiteSpace(M28.Val) || M28.Val.ToLower() == "error") { msg = $"{stationInfo.StationName}请求启动时主条码({M28.Val})异常!"; return (false, "3", msg); } productCode = M28.Val.Replace("\r", ""); //如果打印铭牌工位 if (stationInfo.IsShowPrintBtn) { //打印铭牌工位以标签码作为主条码 var (ok_1, resultBarcode, num, msg_1) = PrintHelper.PrintByHttp_2(stationInfo.StationCode, mskCode); Program.PrintBarCode = resultBarcode; Program.SerialNum = num; } var makResult = MskCodeHelper.CheckCodeByMakCode(stationInfo.StationCode, productCode, M14.Val); if (!makResult) { msg = $"{stationInfo.StationName}请求启动时反馈:NG(机种下的条码错误,主条码:{productCode})!"; return (false, "3", msg); } #endregion //离线模式 if (!Program.SysMode) { /*本地查询上工位数据*/ if (stationInfo.IsSearchLastStation) { //获取上工位结果表的字段 var list = AheadParaHelper.QueryAheadVM(stationInfo.StationCode, stationInfo.Category).ToList(); if (list.Count > 0) { var sqlField = ""; var colCount = 0; foreach (var item in list) { if (!string.IsNullOrWhiteSpace(item.ResultColName)) { sqlField += $"{item.ResultColName},"; colCount++; } } if (!string.IsNullOrWhiteSpace(sqlField)) { sqlField = sqlField.TrimEnd(','); var db = DBHelper.GetConnStrByIp(stationInfo.DatabaseIp); var sql = $"select {sqlField} from t_result where stationcode=@stationcode and productsfccode=@productsfccode order by createdtime desc LIMIT 1"; var sqlParams = new SugarParameter[] { new SugarParameter("@stationcode",list.FirstOrDefault()?.LastStationCode), new SugarParameter("@productsfccode",productCode) }; var dt = db.Ado.GetDataTable(sql, sqlParams); if (dt.Rows.Count <= 0) { msg = $"请求启动时反馈:NG({stationInfo.StationName}工位的上工位无数据)!"; return (false, "3", msg); } else { var fieldArr = sqlField.Split(','); for (int i = 0; i < fieldArr.Length; i++) { var val = dt.Rows[0][i].ToString(); //列为空则返回NG if (string.IsNullOrWhiteSpace(val)) { msg = $"请求启动时反馈:NG({stationInfo.StationName}工位的上工位{fieldArr[i]}字段存在数据缺失)!"; return (false, "3", msg); } //列为NG或者UNDEFINED则返回NG else if (val.ToUpper() == "NG" || val.ToUpper() == "UNDEFINED") { msg = $"请求启动时反馈:NG({stationInfo.StationName}工位的上工位{fieldArr[i]}字段状态=NG)!"; return (false, "3", msg); } } } } } } } else//在线模式 { /*如果是铭牌打印工位*/ if (stationInfo.IsShowPrintBtn) { productCode = Program.PrintBarCode; } //主线 if (!stationInfo.IsBranch) { var startMsg = ""; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); //调用MES的Start接口 var mesResult = RequestMes.Start(mskCode.Site, productCode, mskCode.Resource, mskCode.Procedure, CurrentUser.UserName); stopwatch.Stop(); startMsg = $"请求启动时反馈:调用start接口成功,主条码:{productCode},耗时:{stopwatch.ElapsedMilliseconds}"; LogHelper.WriteLog(startMsg); if (mesResult.ok == false) { LogHelper.WriteLog(mesResult.msg); return (false, "2", mesResult.msg); } //在线模式只要非首工位均需要调用MES接口查询上工位数据 if (!stationInfo.IsShowOrderBtn) { var aheadParas = AheadParaHelper.QueryAheadVM(stationInfo.StationCode, stationInfo.Category).Select(m => m.PointCode).ToList(); if (aheadParas.Count > 0) { stopwatch.Restart(); mesResult = RequestMes.GetIntegratedData("查询上工位数据", mskCode.Site, productCode, mskCode.LastStationResource, mskCode.LastStationProcedure, CurrentUser.UserName, aheadParas); stopwatch.Stop(); startMsg += $",调用上工位接口成功,耗时:{stopwatch.ElapsedMilliseconds}"; LogHelper.WriteLog($"请求启动时反馈:调用上工位接口成功,耗时:{stopwatch.ElapsedMilliseconds}"); if (mesResult.ok == false) { LogHelper.WriteLog(mesResult.msg); return (false, "2", mesResult.msg); } } } return (true, "1", startMsg); } else//支线工位 { var checkResult = ZZCC_M28(stationInfo.StationCode, int.Parse(M14.Val), productCode); msg = checkResult.msg; if (!checkResult.ok) { LogHelper.WriteLog(checkResult.msg); return (false, "2", checkResult.msg); } } } msg = $"请求启动时反馈:PASS(工位:{stationInfo.StationName},主条码:{productCode})"; LogHelper.WriteLog(msg); return (true, "1", msg); } #region 支线工位验证主条码 /// /// 支线工位验证主条码 /// /// /// /// /// private static (bool ok, string msg) ZZCC_M28(string stationCode, int intMachineType, string productCode) { try { var mskCode = Program.t_MaskCodes.FirstOrDefault(m => m.StationCode == stationCode && m.SortIndex == intMachineType); if (mskCode == null) { return (false, $"{DateTime.Now:HH:mm:ss}>>>>>匹配反馈:NG(未查询到掩码表数据,工位:{stationCode},机型={intMachineType})"); } Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); //是否启用支线查询-2023-7-10新增逻辑 if (mskCode.IsUseStator) { var branchInfo = BranchInfoHelper.GetBranchInfoByStationCodeAndProductSfcCode(stationCode, mskCode.ProductSfcCode); if (branchInfo == null) { return (false, $"{DateTime.Now:HH:mm:ss}>>>>>查询支线信息反馈:NG(未查询到支线配置信息,工位:{stationCode},机壳条码:{mskCode.ProductSfcCode})"); } List dicBranchInfo = new List(); string[] resources = null; string[] procedures = null; if (!string.IsNullOrWhiteSpace(branchInfo.BranchResource)) { if (branchInfo.BranchResource.Contains(",")) { resources = branchInfo.BranchResource.Split(','); } else { resources = new string[1]; resources[0] = branchInfo.BranchResource; } } if (!string.IsNullOrWhiteSpace(branchInfo.BranchProcedure)) { if (branchInfo.BranchProcedure.Contains(",")) { procedures = branchInfo.BranchProcedure.Split(','); } else { procedures = new string[1]; procedures[0] = branchInfo.BranchProcedure; } } if (resources.Length != procedures.Length) { return (false, $"{DateTime.Now:HH:mm:ss}>>>>>{stationCode}工位支线资源和工序配置错误,NG!"); } for (int i = 0; i < resources.Length; i++) { dicBranchInfo.Add(new KeyValueVm { Key = resources[i], Value = procedures[i] }); } //验证转子支线数据 List zzccName = new List() { branchInfo.BranchPara }; for (int i = 0; i < dicBranchInfo.Count; i++) { stopwatch.Restart(); var info = RequestMes.GetIntegratedData("查询支线数据", mskCode.Site, productCode, dicBranchInfo[i].Key, dicBranchInfo[i].Value, CurrentUser.UserName, zzccName); stopwatch.Stop(); if (info.ok) { return (true, $"{DateTime.Now:HH:mm:ss}>>>>>{stationCode}工位验证支线数据成功,PASS,耗时:{stopwatch.ElapsedMilliseconds}"); } else { continue; } } return (false, ""); } else { return (true, "未启用支线查询!"); } } catch (Exception ex) { var errMsg = ex == null ? "未知异常" : ex.Message; return (false, $"ZZCC_M28方法出发异常:{errMsg},请联系管理员!"); } } #endregion /// /// PLC请求组件条码匹配 /// /// /// /// public static (bool ok, string msg) MachCode(T_MaskCode maskCode, List subCodeVms) { string msg; var (checkSubCodeResult, checkmsg) = MskCodeHelper.CheckSubCode(maskCode, subCodeVms); if (!checkSubCodeResult) { msg = $"{maskCode.StationCode}组件条码({checkmsg})本地匹配反馈:NG(机种下的条码错误,机种:{maskCode.SortIndex})"; LogHelper.WriteLog(msg); return (false, msg); } return (true, $"组件条码:{JsonConvert.SerializeObject(subCodeVms)}本地匹配反馈:PASS!"); } /// /// PLC请求指定工位数据 /// /// /// public static (bool? ok, string msg) SearchAskData(List keyValues) { //PLC请求指定工位数据 var M25 = keyValues.FirstOrDefault(m => m.Key == "M25"); if (M25 == null) { return (false, "请求指定工位数据时,M25点位未配置!"); } if (string.IsNullOrWhiteSpace(M25.Val) || M25.Val == "0") { var M25Result = PlcHelper.GetPlcVal(M25.DataType, M25.Address); if (M25Result.ok) { M25.Val = M25Result.val; } } if (!string.IsNullOrWhiteSpace(M25.Val) && M25.Val != "0") { var strVal = M25.Val; var stationIndex = strVal.Substring(0, 2); var beginAddress = strVal.Substring(2, 2); var len = strVal.Substring(strVal.Length - 1); var responseData = keyValues.Where(m => m.IsResponseData).OrderBy(m => m.SortIndex).ToList(); if (responseData.Count <= 0) { return (false, "请求指定工位数据时,未找到反馈数据点位!"); } var M28 = keyValues.FirstOrDefault(m => m.Key == "M28"); if (string.IsNullOrEmpty(M28.Val)) { return (false, "请求指定工位数据时,壳体条码为空!"); } var dt = PlcPointHelper.GetStationData(stationIndex, beginAddress, len, M28.Val); if (dt == null || dt.Rows.Count <= 0) { return (false, "请求指定工位数据NG,指定工位结果表数据为空!"); } var resultData = ""; for (int i = 0; i < responseData.Count; i++) { var val = dt.Rows[0][i] == null ? "0" : (string.IsNullOrWhiteSpace(dt.Rows[0][i].ToString()) ? "0" : dt.Rows[0][i].ToString()); Program.siemensS7Net.Write(responseData[i].Address, float.Parse(val)); resultData += val + ","; if ((i + 1) == int.Parse(len)) { break; } } return (true, $"请求指定工位数据OK,反馈结果已写入PLC,值={resultData}!"); } else { return (null, $"M25值异常:{M25.Val}"); } } /// /// 请求注油工位的压缩机总空重 /// /// /// public static (bool? ok, string msg) SearchEmptyTotalWeight(List keyValues, out float emptyTotalWeight) { emptyTotalWeight = 0; //PLC请求指定工位数据 var M25 = keyValues.FirstOrDefault(m => m.Key == "M25"); if (M25 == null) { return (false, "请求指定工位数据时,M25点位未配置!"); } if (string.IsNullOrWhiteSpace(M25.Val) || M25.Val == "0") { var M25Result = PlcHelper.GetPlcVal(M25.DataType, M25.Address); if (M25Result.ok) { M25.Val = M25Result.val; } } if (!string.IsNullOrWhiteSpace(M25.Val) && M25.Val != "0") { var strVal = M25.Val; var stationIndex = strVal.Substring(0, 2); var beginAddress = strVal.Substring(2, 2); var len = strVal.Substring(strVal.Length - 1); var responseData = keyValues.Where(m => m.IsResponseData).OrderBy(m => m.SortIndex).ToList(); if (responseData.Count <= 0) { return (false, "请求指定工位数据时,未找到反馈数据点位!"); } var M28 = keyValues.FirstOrDefault(m => m.Key == "M28"); var dt = PlcPointHelper.GetStationData(stationIndex, beginAddress, len, M28.Val); if (dt == null || dt.Rows.Count <= 0) { return (false, "请求指定工位数据NG,指定工位结果表数据为空!"); } var val = dt.Rows[0][0] == null ? "0" : (string.IsNullOrWhiteSpace(dt.Rows[0][0].ToString()) ? "0" : dt.Rows[0][0].ToString()); emptyTotalWeight = float.Parse(val); return (true, $"请求指定工位数据Ok,值={val}!"); } else { return (null, $"M25值异常:{M25.Val}"); } } /// /// 存本地数据库 /// /// /// /// public static (bool ok, string msg, T_Result _Result) SaveDb(string stationCode, string barCode) { if (Program.type == null) { LogHelper.WriteLog($"{stationCode}工位,存库时重新初始化了Program.type!"); //获取类型 Program.type = typeof(T_Result); Program.properties = Program.type.GetProperties(); } //创建对象 var result = Activator.CreateInstance(Program.type); var list = Program.PointKeyValues.Where(m => m.StationCode == stationCode).ToList(); var saveDbList = Program.PointKeyValues.Where(m => m.StationCode == stationCode && m.IsSaveDb).ToList(); //机种 var M14 = list.FirstOrDefault(m => m.Key == "M14"); var station = Program.stationInfos.FirstOrDefault(m => m.StationCode == stationCode && m.MachineTypeIndex.ToString() == M14?.Val); if (list.Count > 0) { try { #region 版本二 foreach (var keyValItem in saveDbList) { if (keyValItem.Val == "0" || keyValItem.Val == "0.000") { //重新读取一遍 var plcResult = PlcHelper.GetPlcVal(keyValItem.DataType, keyValItem.Address); if (plcResult.ok) { keyValItem.Val = plcResult.val; } else { LogHelper.WriteLog($"重新读取PLC点位失败:{keyValItem.Address}值={keyValItem.Val}"); } } var prop = Program.properties.FirstOrDefault(m => m.Name == keyValItem.FieldCode); if (prop != null && !string.IsNullOrWhiteSpace(keyValItem.Val)) { if (keyValItem.IsTestItem && keyValItem.KeyDesc.Contains("状态")) { var valItem = keyValItem.Val; if (valItem.Contains(".")) { valItem = valItem.Substring(0, valItem.LastIndexOf(".")); } var intVal = Convert.ToInt32(valItem); var enumVal = EnumHelper.GetEnumByValue(typeof(StatusEnum), intVal); keyValItem.Val = EnumHelper.GetEnumDescription(enumVal); if (keyValItem.Val != "OK" && keyValItem.Val != "NG") { return (false, $"一体机数据上传反馈:{keyValItem.KeyDesc}异常={keyValItem.Val},存库NG!", null); } } prop.SetValue(result, Convert.ChangeType(keyValItem.Val, prop.PropertyType)); } } #endregion var t_Result = result as T_Result; t_Result.LineCode = Program.CurrentLineCode.Replace("\x00", ""); t_Result.StationCode = stationCode; //主条码 var M28 = list.FirstOrDefault(m => m.Key == "M28"); //重新读取PLc中的主条码 2023-9-20新增逻辑 var readM28 = PlcHelper.GetPlcVal(M28.DataType, M28.Address,M28.Length); if (readM28.ok) { M28.Val = readM28.val.Replace("\r", ""); LogHelper.WriteLog($"存本地数据库时,获取到的壳体码={M28.Val}"); } t_Result.ProductSfcCode = M28.Val.Replace("\r", "").Replace("\x00", ""); //产品总状态 var M5 = list.FirstOrDefault(m => m.Key == "M5"); if (M5 != null && (M5.Val == "undefined" || M5.Val == "UNDEFINED" || M5.Val == "0.000")) { var m5Result = PlcHelper.GetPlcVal(M5.DataType, M5.Address); LogHelper.WriteLog($"存本地数据库时重新读取产品总状态:{m5Result.val}"); if (m5Result.ok) { M5.Val = m5Result.val; if (M5.Val.Contains(".")) { M5.Val = M5.Val.Substring(0, M5.Val.LastIndexOf(".")); } var intVal = Convert.ToInt32(M5.Val); var enumVal = EnumHelper.GetEnumByValue(typeof(StatusEnum), intVal); M5.Val = EnumHelper.GetEnumDescription(enumVal); if (M5.Val != "OK" && M5.Val != "NG") { return (false, $"一体机数据上传反馈:产品状态异常={M5.Val},存库NG!", t_Result); } } else { LogHelper.WriteLog($"存本地数据库时,读取M5点位:{M5.Address},值时失败"); } } t_Result.TotalStatus = M5?.Val; if (station != null) { t_Result.MesSite = station.Site; t_Result.MesResource = station.Resource; t_Result.MesSequence = station.Procedure; t_Result.Category = station.Category; } t_Result.TestFileName = Program.testfilename; t_Result.BarCode = barCode.Replace("\x00", ""); t_Result.ProgramVersion = Program.programversion; t_Result.LoginUser = CurrentUser.UserName; t_Result.SysMode = Program.SysMode; t_Result.CreatedTime = DateTime.Now; //组件条码,M100是定子码的点位编号 var subs = list.Where(m => m.IsSub && m.Key != "M100").OrderBy(m => m.SortIndex).ToList(); if (subs.Count > 0) { var strSubCode = ""; for (int i = 0; i < subs.Count; i++) { if (!string.IsNullOrWhiteSpace(subs[i].Val)) { strSubCode += $"{subs[i].Val.Replace("\x00", "")},"; } } t_Result.BulkParts = strSubCode.TrimEnd(','); } if (Program.SysMode) { t_Result.IsUploaded = true; t_Result.UploadMsg = "上传成功"; } var addResult = ResultHelper.AddResult(t_Result); if (addResult <= 0) { LogHelper.WriteLog($"{stationCode}工位,新增结果失败:{JsonConvert.SerializeObject(t_Result)}"); return (false, "一体机数据上传反馈:存库NG!", t_Result); } else { return (true, $"一体机数据上传反馈:存库OK!,产品总状态:{t_Result.TotalStatus}", t_Result); } } catch (Exception ex) { LogHelper.WriteLog($"一体机数据上传反馈:{stationCode}工位存库发生异常:{ex.Message}!"); return (false, "一体机数据上传反馈:存库NG!",null); } } else { return (false, "一体机数据上传反馈:存库NG!", null); } } /// /// 在线时,支线条码作为主条码进行校验 /// /// 工位 /// 产品条码 /// 站点 /// 资源 /// 工序 /// 参数 private static (bool ok, string msg) MatchBranchCode(StationInfo _stationInfo, string code, string branchSite, string[] branchResource, string branchProcedure, string branchPara) { List subCodeVms = new List { new SubCodeVM { SubCode = code, SortIndex = 1 } }; var checkSubResult = CheckSubCodesByOnLine(_stationInfo, branchResource, branchSite, branchProcedure, branchPara, subCodeVms); return (checkSubResult.ok, checkSubResult.msg); } /// /// 校验组件码 /// /// /// 资源 /// 站点 /// 工序 /// 查询参数 /// 点位信息 /// public static (bool ok, string msg) CheckSubCodesByOnLine(StationInfo stationInfo, string[] statorLines, string site, string procedure, string para, List subCodeVms) { if (subCodeVms.Count <= 0) { LogHelper.WriteLog($"{stationInfo.StationName}请求条码匹配时校验未通过!"); return (false, "一体机条码匹配反馈:NG(未获取到条码)"); } //循环条码 for (int i = 0; i < subCodeVms.Count; i++) { if (statorLines != null && statorLines.Length > 0) { //执行结果状态 bool isCheck = false; //循环支线资源 for (int j = 0; j < statorLines.Length; j++) { var info = RequestMes.CheckSubCodeByMes(site, statorLines[j], procedure, subCodeVms[i].SubCode, para, CurrentUser.UserName); if (info.ok) { isCheck = info.ok; break; } } if (!isCheck) { return (false, $"MESS匹配条码反馈:{subCodeVms[i].SubCode}校验结果:NG"); } } } return (true, "MESS匹配条码反馈:OK"); } } }