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");
}
}
}