You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

649 lines
30 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
{
/// <summary>
/// PLC请求启动校验
/// </summary>
/// <param name="stationInfo"></param>
/// <param name="keyValues"></param>
/// <returns></returns>
public static (bool ok, string val, string msg) StartCheck(StationInfo stationInfo, List<PointKeyValue> 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==nullStationCode={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 支线工位验证主条码
/// <summary>
/// 支线工位验证主条码
/// </summary>
/// <param name="stationCode"></param>
/// <param name="intMachineType"></param>
/// <param name="productCode"></param>
/// <returns></returns>
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<KeyValueVm> dicBranchInfo = new List<KeyValueVm>();
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<string> zzccName = new List<string>() { 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
/// <summary>
/// PLC请求组件条码匹配
/// </summary>
/// <param name="maskCode"></param>
/// <param name="subCodeVms"></param>
/// <returns></returns>
public static (bool ok, string msg) MachCode(T_MaskCode maskCode, List<SubCodeVM> 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");
}
/// <summary>
/// PLC请求指定工位数据
/// </summary>
/// <param name="keyValues"></param>
/// <returns></returns>
public static (bool? ok, string msg) SearchAskData(List<PointKeyValue> 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}");
}
}
/// <summary>
/// 请求注油工位的压缩机总空重
/// </summary>
/// <param name="keyValues"></param>
/// <returns></returns>
public static (bool? ok, string msg) SearchEmptyTotalWeight(List<PointKeyValue> 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}");
}
}
/// <summary>
/// 存本地数据库
/// </summary>
/// <param name="stationCode"></param>
/// <param name="barCode"></param>
/// <returns></returns>
public static (bool ok, string msg) 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!");
}
}
prop.SetValue(result, Convert.ChangeType(keyValItem.Val, prop.PropertyType));
}
}
#endregion
var t_Result = result as T_Result;
t_Result.LineCode = Program.CurrentLineCode;
t_Result.StationCode = stationCode;
//主条码
var M28 = list.FirstOrDefault(m => m.Key == "M28");
//重新读取PLc中的主条码 2023-9-20新增逻辑
var readM28 = PlcHelper.GetPlcVal(M28.DataType, M28.Address);
if (readM28.ok)
{
M28.Val = readM28.val.Replace("\r", "");
LogHelper.WriteLog($"存本地数据库时,获取到的壳体码={M28.Val}");
}
t_Result.ProductSfcCode = M28.Val.Replace("\r", "");
//产品总状态
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!");
}
}
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;
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},";
}
}
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!");
}
else
{
return (true, $"一体机数据上传反馈存库OK!,产品总状态:{t_Result.TotalStatus}");
}
}
catch (Exception ex)
{
LogHelper.WriteLog($"一体机数据上传反馈:{stationCode}工位存库发生异常:{ex.Message}!");
return (false, "一体机数据上传反馈存库NG!");
}
}
else
{
return (false, "一体机数据上传反馈存库NG!");
}
}
/// <summary>
/// 在线时,支线条码作为主条码进行校验
/// </summary>
/// <param name="_stationInfo">工位</param>
/// <param name="code">产品条码</param>
/// <param name="branchSite">站点</param>
/// <param name="branchResource">资源</param>
/// <param name="branchProcedure">工序</param>
/// <param name="branchPara">参数</param>
private static (bool ok, string msg) MatchBranchCode(StationInfo _stationInfo, string code, string branchSite, string[] branchResource, string branchProcedure, string branchPara)
{
List<SubCodeVM> subCodeVms = new List<SubCodeVM>
{
new SubCodeVM { SubCode = code, SortIndex = 1 }
};
var checkSubResult = CheckSubCodesByOnLine(_stationInfo, branchResource, branchSite, branchProcedure, branchPara, subCodeVms);
return (checkSubResult.ok, checkSubResult.msg);
}
/// <summary>
/// 校验组件码
/// </summary>
/// <param name="stationInfo"></param>
/// <param name="statorLines">资源</param>
/// <param name="site">站点</param>
/// <param name="procedure">工序</param>
/// <param name="para">查询参数</param>
/// <param name="subCodeVms">点位信息</param>
/// <returns></returns>
public static (bool ok, string msg) CheckSubCodesByOnLine(StationInfo stationInfo, string[] statorLines, string site, string procedure, string para, List<SubCodeVM> 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");
}
}
}