2026-02-01 19:19:49 +08:00

220 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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))
{
try
{
while (!stoppingToken.IsCancellationRequested && !_internalCts.Token.IsCancellationRequested)
{
if (!s7Helper.IsConnected)
{
var isConnected = await s7Helper.ConnectAsync();
if (!isConnected)
{
_logger.Error("Failed to connect to PLC.");
break;
}
}
#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 = "出站完毕",
EffectTime = DateTime.Now,
OutStationTime = DateTime.Now,
ResultCode = 1,
ResultDescription = "OK",
CreatedTime = DateTime.Now
};
// 出站完毕响应
await s7Helper.WriteBoolAsync(_plcAddress.Write.Resp, true);
}
#endregion
// Wait for a defined interval before the next poll
await Task.Delay(1000, stoppingToken);
}
}
catch (Exception ex)
{
_logger.Error(ex, "Fatal error in PLC polling service");
throw;
}
finally
{
_logger.Info("PLC Polling Service stopped");
// 确保资源被正确释放
if (_internalCts != null)
{
_internalCts.Dispose();
_internalCts = null;
}
Console.WriteLine("后台任务关闭!!!!!");
}
}
}
}
}