From a3ee28408be44edfd64be59cdbe63a7d8455ef8f Mon Sep 17 00:00:00 2001 From: MysticBoy Date: Sat, 3 Sep 2022 19:02:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96modbus=E9=87=87=E9=9B=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Jobs/ModbusMasterJob.cs | 101 +++++++++++++++++++++++++++++-------- Jobs/ModbusSchedulerJob.cs | 6 ++- 2 files changed, 86 insertions(+), 21 deletions(-) diff --git a/Jobs/ModbusMasterJob.cs b/Jobs/ModbusMasterJob.cs index 3e4f23f..e299416 100644 --- a/Jobs/ModbusMasterJob.cs +++ b/Jobs/ModbusMasterJob.cs @@ -8,6 +8,9 @@ using Newtonsoft.Json.Linq; using Quartz; using System.IO.Ports; using System.Web; +using System.Numerics; +using System.Collections.Specialized; + namespace IoTSharp.Gateways.Jobs { @@ -36,10 +39,11 @@ namespace IoTSharp.Gateways.Jobs { var slave_id = new Guid( context.Trigger.JobDataMap.GetString("slave_id")); var slave_name = context.Trigger.JobDataMap.GetString("slave_name"); - _logger = _factory.CreateLogger($"{nameof(ModbusMasterJob)}_{slave_name}"); + var slave = await _dbContext.ModbusSlaves.FirstOrDefaultAsync(m=>m.Id== slave_id); if (slave != null) { + _logger = _factory.CreateLogger($"Slaver:{slave_name}({slave.Slave})"); /// DTU: dtu://dev.ttyS0/?BaudRate=115200 /// DTU: dtu://COM1:115200 /// TCP: tcp://www.host.com:602 @@ -79,27 +83,35 @@ namespace IoTSharp.Gateways.Jobs var points = _dbContext.PointMappings.Include(p => p.Owner).Where(p => p.Owner == slave).ToList(); foreach (var point in points) { - switch (point.FunCode) + try { - case FunCode.ReadCoils: - var _coils = await client.ReadCoils(point.SlaveCode, point.Address, point.Length, stoppingToken); - await UploadCoils(slave, point, _coils); - break; - case FunCode.ReadDiscreteInputs: - await UploadDiscreteInputs(slave, client, point, stoppingToken); - break; + switch (point.FunCode) + { + case FunCode.ReadCoils: + var _coils = await client.ReadCoils(point.SlaveCode, point.Address, point.Length, stoppingToken); + await UploadCoils(slave, point, _coils); + break; + case FunCode.ReadDiscreteInputs: + await UploadDiscreteInputs(slave, client, point, stoppingToken); + break; - case FunCode.ReadMultipleHoldingRegisters: - var _registers = await client.ReadHoldingRegisters(point.SlaveCode, point.Address, point.Length, stoppingToken); - await UploadRegisters(slave, point, _registers); - break; + case FunCode.ReadMultipleHoldingRegisters: + var _registers = await client.ReadHoldingRegisters(point.SlaveCode, point.Address, point.Length, stoppingToken); + await UploadRegisters(slave, point, _registers); + break; - case FunCode.ReadInputRegisters: - var _input_registers = await client.ReadInputRegisters(point.SlaveCode, point.Address, point.Length, stoppingToken); - await UploadRegisters(slave, point, _input_registers); - break; - default: - break; + case FunCode.ReadInputRegisters: + var _input_registers = await client.ReadInputRegisters(point.SlaveCode, point.Address, point.Length, stoppingToken); + await UploadRegisters(slave, point, _input_registers); + break; + default: + break; + } + _logger.LogInformation($"从{slave.Slave}执行{point.FunCode} 将地址{point.Address}的长度{point.Length}的数据存储到名称{point.DataName}类型{point.DataType}完成。 "); + } + catch (Exception ex) + { + _logger.LogWarning($"从{slave.Slave}执行{point.FunCode} 将地址{point.Address}的长度{point.Length}的数据存储到名称{point.DataName}类型{point.DataType}时遇到错误{ex.Message}。"); } } } @@ -172,8 +184,11 @@ namespace IoTSharp.Gateways.Jobs break; case DataType.DateTime: - break; + break; + case DataType.Boolean: + await UploadData(slave, point, RegistersToBitVector32(_registers)); + break; default: _logger.LogWarning($"多寄存器读取方式不支持类型{point.DataType}"); break; @@ -221,6 +236,19 @@ namespace IoTSharp.Gateways.Jobs var uint64 = BitConverter.ToDouble(buff); return uint64; } + private static BitVector32 RegistersToBitVector32(List _registers) + { + BitVector32 vector32=new BitVector32 (0); + if (_registers.Count == 1)//16位 + { + vector32= new BitVector32( BitConverter.ToInt32(new byte[] { _registers[0].HiByte, _registers[0].LoByte,0,0 })); + } + else if (_registers.Count == 2)//32位 + { + vector32 = new BitVector32(BitConverter.ToInt32(new byte[] { _registers[0].HiByte, _registers[0].LoByte, _registers[1].HiByte, _registers[1].LoByte })); + } + return vector32; + } private async Task UploadData(ModbusSlave slave, PointMapping point, T? value) { @@ -246,6 +274,39 @@ namespace IoTSharp.Gateways.Jobs } } + private async Task UploadData(ModbusSlave slave, PointMapping point, BitVector32 value) + { + Dictionary lst = new Dictionary(); + var _format = point.DateTimeFormat ?? $"{point.DataName}_unknow1:8;{point.DataName}_unknow2:8"; + _format.Split(';').ToList().ForEach(s => + { + var sk = s.Split(':'); + lst.Add(sk[0], short.Parse(sk[1])); + }); + var objx = value.ToDictionary(lst); + JObject jo = new() + { + { point.DataName, new JValue(value.Data) } + }; + objx.Keys.ToList().ForEach(s => + { + jo.Add(s, objx[s]); + }); + switch (point.DataCatalog) + { + case DataCatalog.AttributeData: + await _client.UploadAttributeAsync(slave.DeviceName, jo); + break; + + case DataCatalog.TelemetryData: + await _client.UploadTelemetryDataAsync(slave.DeviceName, jo); + break; + + default: + break; + } + } + private IModbusClient? CreateModbusSlave(ModbusSlave slave) { var url = slave.Slave; diff --git a/Jobs/ModbusSchedulerJob.cs b/Jobs/ModbusSchedulerJob.cs index 2e033a7..3289c08 100644 --- a/Jobs/ModbusSchedulerJob.cs +++ b/Jobs/ModbusSchedulerJob.cs @@ -31,7 +31,9 @@ namespace IoTSharp.Gateways.Jobs job = JobBuilder.Create() .WithIdentity(nameof( ModbusMasterJob)) + .StoreDurably() .Build(); + await _scheduler.AddJob(job,true, context.CancellationToken); } else { @@ -39,6 +41,7 @@ namespace IoTSharp.Gateways.Jobs } var triggers = await _scheduler.GetTriggersOfJob(_modbuskeys, context.CancellationToken); var slaves = _dbContext.ModbusSlaves.ToList(); + var tgs = new List(); foreach (var slave in slaves) { @@ -49,11 +52,12 @@ namespace IoTSharp.Gateways.Jobs { var trg = TriggerBuilder.Create() .WithIdentity(slaveid) + .ForJob(job) .UsingJobData("slave_id",slaveid) .UsingJobData("slave_name", slave.DeviceName) .WithSimpleSchedule(x => x.WithIntervalInSeconds(interval).RepeatForever()).StartNow() .Build(); - await _scheduler.ScheduleJob(job, trg, context.CancellationToken); + await _scheduler.ScheduleJob(trg,context.CancellationToken); } } _logger.LogInformation($"{_scheduler.IsStarted}");