2026-01-26 20:41:41 +08:00

190 lines
7.1 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.MES.product_trace;
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 PlcPollingService_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;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.Info("PLC Polling Service started");
// 使用工厂方法创建服务实例
using (_plcService = new PlcConntectHepler(_ipAddress, _cpuType))
{
// 获取当前的工序/工站
WorkstationCode = await DbScoped.SugarScope.CopyNew().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");
//判断该产品是否允许进站
EntryPermissionResult result = await checkEntryPermission(productModel, productSN, WorkstationCode);
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 = await DbScoped.SugarScope.CopyNew().Queryable<ProcessRouting>().LeftJoin<ProcessOperation>((r, o) => r.RoutingCode == o.FkRoutingCode)
.Where((r, o) => r.FkProductMaterialCode == productModel && r.Status == 1)
.Select((r, o) => o).ToListAsync();
//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 DbScoped.SugarScope.CopyNew().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)
{
return EntryPermissionResult.PreviousStationNG;
}
// 4 扫码产品型号错误
bool isExistproductSN = await DbScoped.SugarScope.CopyNew().Queryable<ProductLifecycle>()
.Where(it => it.ProductSN == productSN).AnyAsync();
bool isExistproductSNProducting = await DbScoped.SugarScope.CopyNew().Queryable<ProductLifecycle>()
.Where(it => it.ProductSN == productSN && (it.ProductCurrentStatus != 1 && it.ProductCurrentStatus != 3)).AnyAsync();
if (!isExistproductSN || !isExistproductSNProducting)
{
return EntryPermissionResult.ProductModelError;
}
//6时间超出规定无法生产
//查询上一站标准时间
return EntryPermissionResult.UnkownException;
}
}
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
}
}