220 lines
12 KiB
C#
Raw Normal View History

2026-02-01 18:15:03 +08:00
using Infrastructure.Model;
using JinianNet.JNTemplate;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using NLog;
using RIZO.Infrastructure.Helper;
using RIZO.Model.Mes;
using RIZO.Model.MES.product_trace;
using S7.Net;
using SqlSugar.IOC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RIZO.Service.PLCbackTask
{
public class MES_PLC_InterationTask : BackgroundService
{
private static Logger _logger = LogManager.GetCurrentClassLogger();
private SiemensS7Helper s7Helper;
private readonly SqlSugarClient Context;
private readonly PlcAddress _plcAddress;
// 添加一个取消源来控制循环
private CancellationTokenSource _internalCts;
public MES_PLC_InterationTask(IOptions<OptionsSetting> options)
{
Context = DbScoped.SugarScope.CopyNew();
_plcAddress = options.Value.plcAddress;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.Info("PLC Polling Service started");
// 创建内部取消源,用于手动触发停止
_internalCts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken);
using (s7Helper = new SiemensS7Helper(_plcAddress.IP))
{
2026-02-01 19:19:49 +08:00
try
2026-02-01 18:15:03 +08:00
{
2026-02-01 19:19:49 +08:00
while (!stoppingToken.IsCancellationRequested && !_internalCts.Token.IsCancellationRequested)
{
2026-02-01 18:15:03 +08:00
if (!s7Helper.IsConnected)
{
var isConnected = await s7Helper.ConnectAsync();
if (!isConnected)
{
_logger.Error("Failed to connect to PLC.");
2026-02-01 19:19:49 +08:00
break;
2026-02-01 18:15:03 +08:00
}
}
#region
bool? ReadHeartBeat = await s7Helper.ReadBoolAsync(_plcAddress.Read.ReadHeartBeat);//心跳
if (ReadHeartBeat != null && !ReadHeartBeat.Value)
{
Console.WriteLine("plc心跳 死亡");
// 使用内部取消源停止循环而不是直接return
_internalCts.Cancel();
break; // 跳出循环但会继续执行finally块和Dispose
}
//TODO 1. 轮询出站请求
bool? OutStationAsk = await s7Helper.ReadBoolAsync(_plcAddress.Read.OutStationAsk);
if (OutStationAsk != null && OutStationAsk.Value)
{
//TODO : 2.读取业务数据
int WorkStationId = await s7Helper.ReadIntAsync(_plcAddress.Read.WorkStation) ?? 0;//工站
int ProductModelID = await s7Helper.ReadIntAsync(_plcAddress.Read.ProductModelId) ?? 0;//产品型号ID
float temperature = await s7Helper.ReadFloatAsync(_plcAddress.Read.ProductModelId) ?? 0.0f;//温度
float waterPressure = await s7Helper.ReadFloatAsync(_plcAddress.Read.WaterPressure) ?? 0.0f; // 水压默认0.0
float airPressure = await s7Helper.ReadFloatAsync(_plcAddress.Read.AirPressure) ?? 0.0f; // 气压默认0.0
int workTime = await s7Helper.ReadIntAsync(_plcAddress.Read.WorkTime) ?? 0; // 工作时间默认0
// 同时记录到日志
_logger.Info($"业务数据读取完成 - 工站:{WorkStationId}, 产品型号:{ProductModelID}, 温度:{temperature}°C, 水压:{waterPressure}bar, 气压:{airPressure}bar, 工作时间:{workTime}秒");
List<ProductTraceProcessParameters> paramss = new();
// 存入工艺参数表
ProductTraceProcessParameters temperatureParam = new ProductTraceProcessParameters()
{
// 基础信息
ProductSn = WorkStationId.ToString(), // 产品序列号
RoutingCode = "ROUTING_PCB_ASSEMBLY", // 工艺路线代码
OperationCode = WorkStationId.ToString(), // 工序代码
FlowCode = "", // 流程代码
ProductlinebodyCode = "LINE_SMT_01", // 生产线体代码
WorkstationCode = WorkStationId.ToString(), // 工位代码
// 参数信息
ParameterCode = "temperature", // 参数代码
ParameterName = "温度", // 参数名称
PlcPoint = _plcAddress.Read.ProductModelId, // PLC点位
Description = "温度", // 描述
DataType = "float", // 数据类型
Unit = "°C",
ActualValue = (decimal)temperature,
CreatedTime = DateTime.Now, // 创建时间
};
paramss.Add(temperatureParam);
ProductTraceProcessParameters airPressureParm = new ProductTraceProcessParameters()
{
// 基础信息
ProductSn = WorkStationId.ToString(), // 产品序列号
RoutingCode = "ROUTING_PCB_ASSEMBLY", // 工艺路线代码
OperationCode = WorkStationId.ToString(), // 工序代码
FlowCode = "", // 流程代码
ProductlinebodyCode = "LINE_SMT_01", // 生产线体代码
WorkstationCode = WorkStationId.ToString(), // 工位代码
// 参数信息
ParameterCode = "waterPressure", // 参数代码
ParameterName = "气压", // 参数名称
PlcPoint = _plcAddress.Read.WaterPressure, // PLC点位
Description = "气压", // 描述
DataType = "float", // 数据类型
Unit = "N",
ActualValue = (decimal)airPressure,
CreatedTime = DateTime.Now, // 创建时间
};
paramss.Add(airPressureParm);
ProductTraceProcessParameters waterPressureParam = new ProductTraceProcessParameters()
{
// 基础信息
ProductSn = WorkStationId.ToString(), // 产品序列号
RoutingCode = "ROUTING_PCB_ASSEMBLY", // 工艺路线代码
OperationCode = WorkStationId.ToString(), // 工序代码
FlowCode = "", // 流程代码
ProductlinebodyCode = "LINE_SMT_01", // 生产线体代码
WorkstationCode = WorkStationId.ToString(), // 工位代码
// 参数信息
ParameterCode = "waterPressure", // 参数代码
ParameterName = "水压", // 参数名称
PlcPoint = _plcAddress.Read.WaterPressure, // PLC点位
Description = "水压", // 描述
DataType = "float", // 数据类型
Unit = "N",
ActualValue = (decimal)waterPressure,
CreatedTime = DateTime.Now, // 创建时间
};
paramss.Add(waterPressureParam);
ProductTraceProcessParameters workTimeParam = new ProductTraceProcessParameters()
{
// 基础信息
ProductSn = WorkStationId.ToString(), // 产品序列号
RoutingCode = "ROUTING_PCB_ASSEMBLY", // 工艺路线代码
OperationCode = WorkStationId.ToString(), // 工序代码
FlowCode = "", // 流程代码
ProductlinebodyCode = "LINE_SMT_01", // 生产线体代码
WorkstationCode = WorkStationId.ToString(), // 工位代码
// 参数信息
ParameterCode = "waterPressure", // 参数代码
ParameterName = "工作时间", // 参数名称
PlcPoint = _plcAddress.Read.WaterPressure, // PLC点位
Description = "工作时间", // 描述
DataType = "int", // 数据类型
Unit = "秒",
ActualValue = (decimal)workTime,
CreatedTime = DateTime.Now, // 创建时间
};
paramss.Add(workTimeParam);
await Context.Insertable(paramss).ExecuteCommandAsync();
//存入过站记录表
ProductPassStationRecord record = new ProductPassStationRecord()
{
ProductionLifeStage = 1,
PasstationType = 3,
PasstationDescription = "出站完毕",
2026-02-01 19:19:49 +08:00
EffectTime = DateTime.Now,
OutStationTime = DateTime.Now,
ResultCode = 1,
ResultDescription = "OK",
CreatedTime = DateTime.Now
2026-02-01 18:15:03 +08:00
};
// 出站完毕响应
await s7Helper.WriteBoolAsync(_plcAddress.Write.Resp, true);
}
#endregion
// Wait for a defined interval before the next poll
await Task.Delay(1000, stoppingToken);
}
2026-02-01 19:19:49 +08:00
}
catch (Exception ex)
{
_logger.Error(ex, "Fatal error in PLC polling service");
throw;
}
finally
{
_logger.Info("PLC Polling Service stopped");
// 确保资源被正确释放
if (_internalCts != null)
2026-02-01 18:15:03 +08:00
{
2026-02-01 19:19:49 +08:00
_internalCts.Dispose();
_internalCts = null;
2026-02-01 18:15:03 +08:00
}
2026-02-01 19:19:49 +08:00
Console.WriteLine("后台任务关闭!!!!!");
2026-02-01 18:15:03 +08:00
}
}
}
}
}