using Modbus.Net; using DataReturnDef = Modbus.Net.DataReturnDef; using MultipleMachinesJobScheduler = Modbus.Net.MultipleMachinesJobScheduler; namespace MachineJob.Service { /// /// MachineJob 后台工作服务 /// 使用 Quartz 调度器定期从多个设备读取数据并写入 /// public class Worker : BackgroundService { private readonly ILogger _logger; public Worker(ILogger logger) { _logger = logger; } protected override Task ExecuteAsync(CancellationToken stoppingToken) { // 1. 编码方式(已注释) // 手动配置地址单元列表 //List _addresses = new List //{ // new AddressUnit() { Area = "4X", Address = 1, DataType = typeof(short), Id = "1", Name = "Test1" }, // ... //}; //List _addresses2 = new List //{ // new AddressUnit() { Area = "DB1", Address = 0, DataType = typeof(short), Id = "1", Name = "Test1" }, // ... //}; // 创建 Modbus 和 Siemens 机器实例 //IMachine machine = new ModbusMachine("ModbusMachine1", ModbusType.Tcp, null, _addresses, true, 1, 2, Endian.BigEndianLsb); //IMachine machine2 = new SiemensMachine("SiemensMachine1", SiemensType.Tcp, null, SiemensMachineModel.S7_1200, _addresses2, true, 1, 2); //var machines = new List> { machine, machine2 }; // 2. 从配置文件读取机器配置 // 使用 MachineReader 从 appsettings.json 读取机器配置 var machines = MachineReader.ReadMachines(); // 3. 使用 MachineJobScheduler(已注释) // 为每个机器创建独立的调度器 //foreach (var machine in machines) //{ // var scheduler = await MachineJobSchedulerCreator.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()); } /// /// 成功回调 /// 记录机器设置成功的日志 /// public Task OnSuccess(string machineId) { _logger.LogInformation("Machine {0} set success", machineId); return Task.CompletedTask; } /// /// 失败回调 /// 记录机器设置失败的日志 /// public Task OnFailure(string machineId, int errorCode, string errorMsg) { _logger.LogError("Machine {0} set failure: {1}", machineId, errorMsg); return Task.CompletedTask; } /// /// 查询处理函数 /// 处理从设备读取的数据,可以写入数据库或生成随机数据 /// private Dictionary? 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 ans = new Dictionary(); for (int i = 0; i < 10; i++) { ans["Test" + (i + 1)] = r.Next(65536) - 32768; } return ans; }