Files
2026-04-04 17:25:15 +08:00

172 lines
7.4 KiB
C#
Raw Permalink 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 Modbus.Net;
using DataReturnDef = Modbus.Net.DataReturnDef<string, double>;
using MultipleMachinesJobScheduler = Modbus.Net.MultipleMachinesJobScheduler<Modbus.Net.IMachineMethodDatas, string, double>;
namespace MachineJob.Service
{
/// <summary>
/// MachineJob 后台工作服务
/// 使用 Quartz 调度器定期从多个设备读取数据并写入
/// </summary>
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
// 1. 编码方式(已注释)
// 手动配置地址单元列表
//List<AddressUnit> _addresses = new List<AddressUnit>
//{
// new AddressUnit() { Area = "4X", Address = 1, DataType = typeof(short), Id = "1", Name = "Test1" },
// ...
//};
//List<AddressUnit> _addresses2 = new List<AddressUnit>
//{
// new AddressUnit() { Area = "DB1", Address = 0, DataType = typeof(short), Id = "1", Name = "Test1" },
// ...
//};
// 创建 Modbus 和 Siemens 机器实例
//IMachine<string> machine = new ModbusMachine<string, string>("ModbusMachine1", ModbusType.Tcp, null, _addresses, true, 1, 2, Endian.BigEndianLsb);
//IMachine<string> machine2 = new SiemensMachine<string, string>("SiemensMachine1", SiemensType.Tcp, null, SiemensMachineModel.S7_1200, _addresses2, true, 1, 2);
//var machines = new List<IMachine<string>> { machine, machine2 };
// 2. 从配置文件读取机器配置
// 使用 MachineReader 从 appsettings.json 读取机器配置
var machines = MachineReader.ReadMachines();
// 3. 使用 MachineJobScheduler已注释
// 为每个机器创建独立的调度器
//foreach (var machine in machines)
//{
// var scheduler = await MachineJobSchedulerCreator<IMachineMethodDatas, string, double>.CreateScheduler(machine.Id, -1, 10);
// var job = scheduler.From(machine.Id + ".From", machine, MachineDataType.Name).Result.Query(machine.Id + ".ConsoleQuery", QueryConsole).Result.To(machine.Id + ".To", machine).Result.Deal(machine.Id + ".Deal", OnSuccess, OnFailure).Result;
// await job.Run();
//}
// 4. 使用 MultipleMachinesJobScheduler已注释
// 使用多机器调度器,带时间间隔
//return Task.Run(() => MultipleMachinesJobScheduler.RunScheduler(machines, async (machine, scheduler) =>
//{
// await scheduler.From(machine.Id + ".From", machine, MachineDataType.Name).Result.Query(machine.Id + ".ConsoleQuery", QueryConsole).Result.To(machine.Id + ".To", machine).Result.Deal(machine.Id + ".Deal", OnSuccess, OnFailure).Result.Run();
//}, -1, 10));
// 5. 使用固定时间,立即调度 Job
// 当前使用的方式:立即执行,无时间间隔
return Task.Run(() => MultipleMachinesJobScheduler.RunScheduler(machines, async (machine, scheduler) =>
{
// 配置作业链From -> Query -> To -> Deal
// From: 从机器读取数据
// Query: 查询处理QueryConsole
// To: 写入数据到机器
// Deal: 处理结果OnSuccess/OnFailure
await scheduler.From(machine.Id + ".From", machine, MachineDataType.Name).Result.Query(machine.Id + ".ConsoleQuery", QueryConsole).Result.To(machine.Id + ".To", machine).Result.Deal(machine.Id + ".Deal", OnSuccess, OnFailure).Result.Run();
}, -1, 0));
}
public override Task StopAsync(CancellationToken cancellationToken)
{
// 停止所有作业调度
return Task.Run(() => MultipleMachinesJobScheduler.CancelJob());
}
/// <summary>
/// 成功回调
/// 记录机器设置成功的日志
/// </summary>
public Task OnSuccess(string machineId)
{
_logger.LogInformation("Machine {0} set success", machineId);
return Task.CompletedTask;
}
/// <summary>
/// 失败回调
/// 记录机器设置失败的日志
/// </summary>
public Task OnFailure(string machineId, int errorCode, string errorMsg)
{
_logger.LogError("Machine {0} set failure: {1}", machineId, errorMsg);
return Task.CompletedTask;
}
/// <summary>
/// 查询处理函数
/// 处理从设备读取的数据,可以写入数据库或生成随机数据
/// </summary>
private Dictionary<string, double>? QueryConsole(DataReturnDef dataReturnDef)
{
var values = dataReturnDef.ReturnValues.Datas;
// 如果读取成功
if (dataReturnDef.ReturnValues.IsSuccess == true)
{
// 记录日志
foreach (var value in values)
{
_logger.LogDebug(dataReturnDef.MachineId + " " + value.Key + " " + value.Value.DeviceValue);
}
/*
// 写入数据库(已注释)
try
{
using (var context = new DatabaseWriteContext())
{
context.DatabaseWrites?.Add(new DatabaseWriteEntity
{
Value1 = values["Test1"].DeviceValue,
Value2 = values["Test2"].DeviceValue,
Value3 = values["Test3"].DeviceValue,
Value4 = values["Test4"].DeviceValue,
Value5 = values["Test5"].DeviceValue,
Value6 = values["Test6"].DeviceValue,
Value7 = values["Test7"].DeviceValue,
Value8 = values["Test8"].DeviceValue,
Value9 = values["Test9"].DeviceValue,
Value10 = values["Test10"].DeviceValue,
UpdateTime = DateTime.Now,
});
context.SaveChanges();
}
}
catch
{
// 忽略异常
}
*/
// 生成随机数据用于写入
Random r = new Random();
foreach (var value in values)
{
value.Value.DeviceValue = r.Next(65536) - 32768;
}
// 将读取的值转换为写入格式
return values.MapGetValuesToSetValues();
}
// 如果读取结果为 null未知状态
else if (dataReturnDef.ReturnValues.IsSuccess == null)
{
// 生成随机数据
Random r = new Random();
Dictionary<string, double> ans = new Dictionary<string, double>();
for (int i = 0; i < 10; i++)
{
ans["Test" + (i + 1)] = r.Next(65536) - 32768;
}
return ans;
}