416 lines
16 KiB
C#
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
|
|
|
|
|
|
}
|
|
}
|
|
|