Valeo_Line_MES_backend/RIZO.Service/PLCBackground/Stations/PlcOutStationService_OP07_01.cs
2026-01-27 15:16:56 +08:00

416 lines
16 KiB
C#

using MDM.Model.Plant;
using MDM.Model.Process;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog;
using NPOI.SS.Formula.Functions;
using RIZO.Model.Mes;
using RIZO.Model.MES.product_trace;
using RIZO.Repository;
using RIZO.Service.PLC;
using S7.Net;
using SqlSugar.IOC;
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace RIZO.Service.PLCBackground.Stations
{
/// <summary>
/// OP07_01 出站
/// </summary>
public class PlcOutStationService_OP07_01 : BackgroundService
{
private static Logger _logger = LogManager.GetCurrentClassLogger();
private PlcConntectHepler _plcService;
private readonly TimeSpan _pollingInterval = TimeSpan.FromSeconds(5);
private readonly string _ipAddress = "192.168.10.222";
private readonly CpuType _cpuType = CpuType.S71500;
private string WorkstationCode;
private readonly SqlSugarClient Context;
public PlcOutStationService_OP07_01()
{
Context = DbScoped.SugarScope.CopyNew();
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.Info("PLC Polling Service started");
// 使用工厂方法创建服务实例
using (_plcService = new PlcConntectHepler(_ipAddress, _cpuType))
{
// 获取当前的工序/工站
WorkstationCode = await Context.Queryable<PlantWorkstation>().Where(it => it.PlcIP == _ipAddress)
.Select(it => it.WorkstationCode).FirstAsync();
while (!stoppingToken.IsCancellationRequested)
{
try
{
//心跳检测
await _plcService.WriteAsync("DB1010.DBW0", 1);
// 轮询出站站请求信号/工位保存查询请求
int outStationAsk = await _plcService.ReadAsync<int>("DB1001.DBW2002");
if (outStationAsk == 1)
{
// 处理进站请求
_logger.Info("Processing out station request...");
//获取产品SN码
string productModel = await _plcService.ReadStringAsync("DB1001.DBB1000");
string productSN = await _plcService.ReadStringAsync("DB1001.DBB1054");
// 获取工单
//获取工艺路线工序
List<ProcessOperation> processOperations = await Context.Queryable<ProcessRouting>().LeftJoin<ProcessOperation>((r, o) => r.RoutingCode == o.FkRoutingCode)
.Where((r, o) => r.FkProductMaterialCode == productModel && r.Status == 1)
.Select((r, o) => o).ToListAsync();
//判断改产品是正常件还是返工件
//插入出站请求ASK过站记录
ProductPassStationRecord ASKoutStation = new ProductPassStationRecord
{
ProductSN = productSN,
WorkstationCode = WorkstationCode,
Routingcode = processOperations.First().FkRoutingCode,
OperationCode = WorkstationCode,
ProductionLifeStage = 1, // 1表示生产中
PasstationType = 2, // 0表示出站请求
PasstationDescription = "出站请求ASK",
EffectTime = DateTime.Now,
CreatedTime = DateTime.Now,
};
await Context.Insertable(ASKoutStation).ExecuteCommandAsync();
//上传工艺参数
bool CheckOutstationResult = await UploadProcessParameters(productSN, processOperations.First().FkRoutingCode, WorkstationCode);
//判断该产品是否允许出站
OutPermissionResult result = await checkOutPermission(productModel, productSN, WorkstationCode, processOperations, CheckOutstationResult);
await _plcService.WriteAsync("DB1010.DBW2000", (int)result);
}
await Task.Delay(_pollingInterval, stoppingToken);
}
catch (OperationCanceledException)
{
_logger.Info("PLC Polling Service is stopping");
break;
}
catch (Exception ex)
{
_logger.Error(ex, "PLC polling error");
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
}
}
}
_logger.Info("PLC Polling Service stopped");
}
/// <summary>
/// 保存工艺参数上传
/// </summary>
/// <returns></returns>
private async Task<bool> UploadProcessParameters(string productSN, string RoutingCode, string OperationCode)
{
bool result = true;
List<ProductProcessParameters> productProcessParameters = new List<ProductProcessParameters>();
//实际产量
ProductProcessParameters ActualProductParameter = new ProductProcessParameters
{
ProductSN = productSN,
RoutingCode = RoutingCode,
OperationCode = OperationCode,
ProductlinebodyCode = "line3",
WorkstationCode = OperationCode,
ParameterCode = "actual_product",
ParameterName = "实际产量",
PlcPoint = "DB1001.DBW1104",
Description = OperationCode + "工序的" + "实际产量",
DataType = "int",
Unit = "个",
ActualValue = (await _plcService.ReadAsync<int>("DB1001.DBW1104")).ToString(),
CreatedTime = DateTime.Now,
};
productProcessParameters.Add(ActualProductParameter);
//合格数量
ProductProcessParameters QualifiedProductParameter = new ProductProcessParameters
{
ProductSN = productSN,
RoutingCode = RoutingCode,
OperationCode = OperationCode,
ProductlinebodyCode = "line3",
WorkstationCode = OperationCode,
ParameterCode = "actual_product",
ParameterName = "合格数量",
PlcPoint = "DB1001.DBW1108",
Description = OperationCode + "工序的" + "合格数量",
DataType = "int",
Unit = "个",
ActualValue = (await _plcService.ReadAsync<int>("DB1001.DBW1108")).ToString(),
CreatedTime = DateTime.Now,
};
productProcessParameters.Add(QualifiedProductParameter);
//失败数量
ProductProcessParameters FailureProductParameter = new ProductProcessParameters
{
ProductSN = productSN,
RoutingCode = RoutingCode,
OperationCode = OperationCode,
ProductlinebodyCode = "line3",
WorkstationCode = OperationCode,
ParameterCode = "actual_product",
ParameterName = "失败数量",
PlcPoint = "DB1001.DBW1112",
Description = OperationCode + "工序的" + "失败数量",
DataType = "int",
Unit = "个",
ActualValue = (await _plcService.ReadAsync<int>("DB1001.DBW1112")).ToString(),
CreatedTime = DateTime.Now,
};
productProcessParameters.Add(FailureProductParameter);
//SN_1
ProductProcessParameters SN_1Parameter = new ProductProcessParameters
{
ProductSN = productSN,
RoutingCode = RoutingCode,
OperationCode = OperationCode,
ProductlinebodyCode = "line3",
WorkstationCode = OperationCode,
ParameterCode = "SN_1",
ParameterName = "SN_1",
PlcPoint = "DB1001.DBW1112",
Description = OperationCode + "工序的" + "SN_1",
DataType = "string",
Unit = "个",
ActualValue = await _plcService.ReadStringAsync("DB1001.DBW1112"),
CreatedTime = DateTime.Now,
};
productProcessParameters.Add(SN_1Parameter);
//SN_2
ProductProcessParameters SN_2Parameter = new ProductProcessParameters
{
ProductSN = productSN,
RoutingCode = RoutingCode,
OperationCode = OperationCode,
ProductlinebodyCode = "line3",
WorkstationCode = OperationCode,
ParameterCode = "SN_1",
ParameterName = "SN_1",
PlcPoint = "DB1001.DBW2134",
Description = OperationCode + "工序的" + "SN_2",
DataType = "string",
Unit = "个",
ActualValue = await _plcService.ReadStringAsync("DB1001.DBW2134"),
CreatedTime = DateTime.Now,
};
productProcessParameters.Add(SN_2Parameter);
//相机结果
int CameraResult = await _plcService.ReadAsync<int>("DB1001.DBW2164");
if (CameraResult == 1)
{
result = true;
}
if (CameraResult == 2)
{
result = false;
}
ProductProcessParameters CameraParameter = new ProductProcessParameters
{
ProductSN = productSN,
RoutingCode = RoutingCode,
OperationCode = OperationCode,
ProductlinebodyCode = "line3",
WorkstationCode = OperationCode,
ParameterCode = "CameraResult",
ParameterName = "CameraResult",
PlcPoint = "DB1001.DBW2164",
Description = OperationCode + "工序的" + "相机结果 1 OK 2 NG",
DataType = "int",
Unit = "个",
ActualValue = CameraResult.ToString(),
ExpectValue = "1",
Result = result ? 1 : 0,
CreatedTime = DateTime.Now,
};
productProcessParameters.Add(CameraParameter);
//站位结果
int StationPosition = await _plcService.ReadAsync<int>("DB1001.DBW2166");
if (StationPosition == 1)
{
result = true;
}
if (StationPosition == 2)
{
result = false;
}
ProductProcessParameters StationPositionParameter = new ProductProcessParameters
{
ProductSN = productSN,
RoutingCode = RoutingCode,
OperationCode = OperationCode,
ProductlinebodyCode = "line3",
WorkstationCode = OperationCode,
ParameterCode = "StationPosition",
ParameterName = "StationPosition",
PlcPoint = "DB1001.DBW2166",
Description = OperationCode + "工序的" + "站位结果 1 OK 2 NG",
DataType = "int",
Unit = "个",
ActualValue = StationPosition.ToString(),
ExpectValue = "1",
Result = result ? 1 : 0,
CreatedTime = DateTime.Now,
};
productProcessParameters.Add(StationPositionParameter);
//节拍时间 real类型
ProductProcessParameters BeatParameter = new ProductProcessParameters
{
ProductSN = productSN,
RoutingCode = RoutingCode,
OperationCode = OperationCode,
ProductlinebodyCode = "line3",
WorkstationCode = OperationCode,
ParameterCode = "beat",
ParameterName = "节拍时间",
PlcPoint = "DB1001.DBD2168",
Description = OperationCode + "工序的" + "节拍时间",
DataType = "float",
Unit = "s",
ActualValue = (await _plcService.ReadAsync<float>("DB1001.DBD2168")).ToString(),
CreatedTime = DateTime.Now,
};
productProcessParameters.Add(BeatParameter);
await Context.Insertable(productProcessParameters).ExecuteCommandAsync();
return result;
}
/// <summary>
/// 校验是否可以出站
/// </summary>
/// <param name="productModel">产品型号</param>
/// <param name="productSN">产品SN</param>
/// <returns></returns>
private async Task<OutPermissionResult> checkOutPermission(string productModel, string productSN, string workstationCode, List<ProcessOperation> processOperations, bool CheckOutstationResult)
{
OutPermissionResult result = OutPermissionResult.UnkownException;
if (!CheckOutstationResult)
{
result = OutPermissionResult.ProcessParameterNG;
goto InsertPassrecord;
}
//OK 准许进站
result = OutPermissionResult.OK;
goto InsertPassrecord;
InsertPassrecord:
//插入出站请求Resp 过站记录
ProductPassStationRecord RespintoStation = new ProductPassStationRecord
{
ProductSN = productSN,
WorkstationCode = WorkstationCode,
Routingcode = processOperations.First().FkRoutingCode,
OperationCode = WorkstationCode,
ProductionLifeStage = 1, // 1表示生产中
PasstationType = 3, // 出站完毕
PasstationDescription = "出站完毕Resp",
EffectTime = DateTime.Now,
OutStationTime = DateTime.Now,
ResultCode = (int)result,
ResultDescription = result.ToString(),
CreatedTime = DateTime.Now,
};
await Context.Insertable(RespintoStation).ExecuteCommandAsync();
return result;
}
}
/// <summary>
/// 出站校验结果
/// </summary>
public enum OutPermissionResult
{
/// <summary>
/// 1 OK - 成功
/// </summary>
OK = 1,
/// <summary>
/// 2 产品时间属性增加失败
/// </summary>
ProductTimeAttributeAddFailed = 2,
/// <summary>
/// 3 产品条码合并失败
/// </summary>
ProductBarcodeMergeFailed = 3,
/// <summary>
/// 4 产品结果上传次数超出
/// </summary>
ProductUploadCountExceeded = 4,
/// <summary>
/// 5 时间属性移除失败
/// </summary>
TimeAttributeRemoveFailed = 5,
/// <summary>
/// 6 数据保存失败
/// </summary>
DataSaveFailed = 6,
/// <summary>
/// 10 上传条码为空
/// </summary>
UploadBarcodeEmpty = 10,
/// <summary>
/// 11 未知异常
/// </summary>
UnkownException = 11,
/// <summary>
/// 工艺参数NG
/// </summary>
ProcessParameterNG = 12
}
}