234 lines
9.4 KiB
C#
234 lines
9.4 KiB
C#
using MDM.Model.Plant;
|
|
using MDM.Model.Process;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using NLog;
|
|
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.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace RIZO.Service.PLCBackground.Stations
|
|
{
|
|
public class PlcIntoStationService_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 PlcIntoStationService_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 intoStationAsk = await _plcService.ReadAsync<int>("DB1001.DBW2000");
|
|
if (intoStationAsk == 1)
|
|
{
|
|
// 处理进站请求
|
|
_logger.Info("Processing into 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 ASKintoStation = new ProductPassStationRecord
|
|
{
|
|
ProductSN = productSN,
|
|
WorkstationCode = WorkstationCode,
|
|
Routingcode = processOperations.First().FkRoutingCode,
|
|
OperationCode = WorkstationCode,
|
|
ProductionLifeStage = 1, // 1表示生产中
|
|
PasstationType = 0, // 0表示入站请求
|
|
PasstationDescription = "入站请求ASK",
|
|
EffectTime = DateTime.Now,
|
|
CreatedTime = DateTime.Now,
|
|
|
|
};
|
|
await Context.Insertable(ASKintoStation).ExecuteCommandAsync();
|
|
|
|
//判断该产品是否允许进站
|
|
|
|
EntryPermissionResult result = await checkEntryPermission(productModel, productSN, WorkstationCode, processOperations);
|
|
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>
|
|
/// <param name="productModel">产品型号</param>
|
|
/// <param name="productSN">产品SN</param>
|
|
/// <returns></returns>
|
|
private async Task<EntryPermissionResult> checkEntryPermission(string productModel, string productSN, string workstationCode, List<ProcessOperation> processOperations)
|
|
{
|
|
|
|
EntryPermissionResult result = EntryPermissionResult.UnkownException;
|
|
|
|
|
|
//2上工位无记录
|
|
|
|
//ProcessOperation LastOperation = processOperations.Where(operation => operation.OperationSeq < processOperations.Where(it => it.OperationCode == workstationCode).Select(it => it.OperationSeq).First()).OrderByDescending(operation => operation.OperationSeq).First();
|
|
int LastOperationSeq = processOperations.Where(operation => operation.OperationCode == workstationCode).Select(operation => operation.LastOperationSeq ?? -1).First();
|
|
ProcessOperation LastOperation = processOperations.Where(it => it.OperationSeq == LastOperationSeq).First();
|
|
bool isExistLastOperationRecord = await DbScoped.SugarScope.CopyNew().Queryable<ProductPassStationRecord>()
|
|
.Where(it => it.ProductSN == productSN)
|
|
.Where(it => it.OperationCode == LastOperation.OperationCode)
|
|
.AnyAsync();
|
|
if (!isExistLastOperationRecord)
|
|
{
|
|
return EntryPermissionResult.NoRecordAtPreviousStation;
|
|
}
|
|
|
|
// 3 上工位NG 入站或者出站结果 NG
|
|
bool isExistLastOperationNG = await Context.Queryable<ProductPassStationRecord>()
|
|
.Where(it => it.ProductSN == productSN)
|
|
.Where(it => it.OperationCode == LastOperation.OperationCode)
|
|
.Where(it => it.PasstationType == 2 || it.PasstationType == 4)
|
|
.Where(it => it.ResultCode != 1)
|
|
.AnyAsync();
|
|
if (!isExistLastOperationNG)
|
|
{
|
|
result = EntryPermissionResult.PreviousStationNG;
|
|
goto InsertPassrecord;
|
|
}
|
|
|
|
|
|
// 4 扫码产品型号错误
|
|
bool isExistproductSN = await Context.Queryable<ProductLifecycle>()
|
|
.Where(it => it.ProductSN == productSN).AnyAsync();
|
|
|
|
|
|
bool isExistproductSNProducting = await Context.Queryable<ProductLifecycle>()
|
|
.Where(it => it.ProductSN == productSN && (it.ProductCurrentStatus != 1 && it.ProductCurrentStatus != 3)).AnyAsync();
|
|
if (!isExistproductSN || !isExistproductSNProducting)
|
|
{
|
|
result = EntryPermissionResult.ProductModelError;
|
|
goto InsertPassrecord;
|
|
}
|
|
//6时间超出规定无法生产
|
|
|
|
//OK 准许进站
|
|
result = EntryPermissionResult.AllowIntoStation;
|
|
goto InsertPassrecord;
|
|
InsertPassrecord:
|
|
//插入入站请求Resp过站记录
|
|
ProductPassStationRecord RespintoStation = new ProductPassStationRecord
|
|
{
|
|
ProductSN = productSN,
|
|
WorkstationCode = WorkstationCode,
|
|
Routingcode = processOperations.First().FkRoutingCode,
|
|
OperationCode = WorkstationCode,
|
|
ProductionLifeStage = 1, // 1表示生产中
|
|
PasstationType = 1, // 入站完毕
|
|
PasstationDescription = "入站完毕Resp",
|
|
EffectTime = DateTime.Now,
|
|
InStationTime = DateTime.Now,
|
|
ResultCode = (int)result,
|
|
ResultDescription = result.ToString(),
|
|
CreatedTime = DateTime.Now,
|
|
|
|
};
|
|
await Context.Insertable(RespintoStation).ExecuteCommandAsync();
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
/// <summary>
|
|
/// 入站校验结果
|
|
/// </summary>
|
|
enum EntryPermissionResult
|
|
{
|
|
//1之前工位数据正常
|
|
AllowIntoStation = 1,
|
|
// 2上工位无记录
|
|
NoRecordAtPreviousStation = 2,
|
|
// 3上工位NG
|
|
PreviousStationNG = 3,
|
|
// 4扫码产品型号错误
|
|
ProductModelError = 4,
|
|
//5本工位NG
|
|
CurrentStationNG = 5,
|
|
//6时间超出规定无法生产
|
|
TimeExceeded = 6,
|
|
//7固化时间未到规定时间
|
|
CuringTimeNotReached = 7,
|
|
// 8未找到时间属性
|
|
TimeAttributeNotFound = 8,
|
|
// 10条码为空
|
|
BarcodeEmpty = 10,
|
|
//0之前工位数据异常
|
|
PreviousStationDataAbnormal = 0,
|
|
//11 未知异常
|
|
UnkownException = 11
|
|
}
|
|
}
|
|
|