From 61b6c6c5e206136ff1a493c093f0520d52360382 Mon Sep 17 00:00:00 2001 From: luosheng Date: Sun, 16 Jul 2023 20:57:48 +0800 Subject: [PATCH 01/15] HJ212 Implementation --- Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs | 97 +++++++++++++ Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs | 130 ++++++++++++++++++ .../Modbus.Net.HJ212/HJ212ProtocolLinker.cs | 24 ++++ .../HJ212ProtocolLinkerBytesExtend.cs | 42 ++++++ Modbus.Net/Modbus.Net.HJ212/HJ212Utility.cs | 61 ++++++++ .../Modbus.Net.HJ212/Modbus.Net.HJ212.csproj | 39 ++++++ Modbus.Net/Modbus.Net.HJ212/README.md | 7 + Modbus.Net/Modbus.Net.sln | 10 ++ 8 files changed, 410 insertions(+) create mode 100644 Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs create mode 100644 Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs create mode 100644 Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinker.cs create mode 100644 Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinkerBytesExtend.cs create mode 100644 Modbus.Net/Modbus.Net.HJ212/HJ212Utility.cs create mode 100644 Modbus.Net/Modbus.Net.HJ212/Modbus.Net.HJ212.csproj create mode 100644 Modbus.Net/Modbus.Net.HJ212/README.md diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs new file mode 100644 index 0000000..45600f1 --- /dev/null +++ b/Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs @@ -0,0 +1,97 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Modbus.Net.HJ212 +{ + public class HJ212Machine : BaseMachine where TKey : IEquatable + where TUnitKey : IEquatable + { + private static readonly ILogger> logger = LogProvider.CreateLogger>(); + + private readonly int _maxErrorCount = 3; + + protected string ST { get; } + + protected string CN { get; } + + protected string PW { get; } + + protected string MN { get; } + + private int ErrorCount { get; set; } + + /// + /// 构造函数 + /// + /// 设备的ID号 + /// 连接地址 + /// 需要读写的地址 + public HJ212Machine(TKey id, string connectionString, string st, string cn, string pw, string mn) + : base(id, null, true) + { + BaseUtility = new HJ212Utility(connectionString); + ST = st; + CN = cn; + PW = pw; + MN = mn; + } + + public override async Task> SetDatasAsync(MachineDataType setDataType, Dictionary values) + { + try + { + //检测并连接设备 + if (!BaseUtility.IsConnected) + await BaseUtility.ConnectAsync(); + //如果设备无法连接,终止 + if (!BaseUtility.IsConnected) return new ReturnStruct() + { + Datas = false, + IsSuccess = false, + ErrorCode = -1, + ErrorMsg = "Connection Error" + }; + + //遍历每个要设置的值 + Dictionary formatValues = new Dictionary(); + foreach (var value in values) + { + //根据设置类型找到对应的地址描述 + formatValues.Add(value.Key, value.Value.ToString()); + } + var sendValues = new List>() { formatValues }; + //写入数据 + await + BaseUtility.GetUtilityMethods().SetDatasAsync("0", new object[] { ST, CN, PW, MN, sendValues, DateTime.Now }); + + //如果不保持连接,断开连接 + if (!KeepConnect) + BaseUtility.Disconnect(); + } + catch (Exception e) + { + ErrorCount++; + logger.LogError(e, $"BaseMachine -> SetDatas, Id:{Id} Connection:{ConnectionToken} error. ErrorCount {ErrorCount}."); + + if (ErrorCount >= _maxErrorCount) + Disconnect(); + return new ReturnStruct() + { + Datas = false, + IsSuccess = false, + ErrorCode = -100, + ErrorMsg = "Unknown Exception" + }; + } + return new ReturnStruct() + { + Datas = true, + IsSuccess = true, + ErrorCode = 0, + ErrorMsg = "" + }; + } + } +} diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs new file mode 100644 index 0000000..4ce6be3 --- /dev/null +++ b/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace Modbus.Net.HJ212 +{ + /// + /// HJ212协议 + /// + public class HJ212Protocol : BaseProtocol + { + /// + /// 构造函数 + /// + public HJ212Protocol(string connectionToken) + : base(0, 0, Endian.BigEndianLsb) + { + ProtocolLinker = new HJ212ProtocolLinker(connectionToken); + } + + /// + /// 连接 + /// + /// 是否连接成功 + public override async Task ConnectAsync() + { + return await ProtocolLinker.ConnectAsync(); + } + } + + #region 写数据 + /// + /// 写数据协议 + /// + public class WriteRequestHJ212Protocol : ProtocolUnit + { + /// + /// 从对象的参数数组格式化 + /// + /// 非结构化的输入数据 + /// 格式化后的字节流 + public override byte[] Format(IInputStruct message) + { + var r_message = (WriteRequestHJ212InputStruct)message; + string formatMessage = "##0633"; + formatMessage += "QN=" + r_message.QN + ";"; + formatMessage += "ST=" + r_message.ST + ";"; + formatMessage += "CN=" + r_message.CN + ";"; + formatMessage += "PW=" + r_message.PW + ";"; + formatMessage += "MN=" + r_message.MN + ";"; + formatMessage += "CP=&&"; + formatMessage += "DateTime=" + r_message.Datetime.ToString("yyyyMMddHHmmss") + ";"; + foreach (var record in r_message.CP) + { + foreach (var data in record) + { + formatMessage += data.Key + "=" + data.Value + ","; + } + formatMessage = formatMessage[..^1]; + formatMessage += ";"; + } + formatMessage = formatMessage[..^1]; + formatMessage += "&&"; + return Encoding.ASCII.GetBytes(formatMessage); + } + + /// + /// 把仪器返回的内容填充到输出结构中 + /// + /// 返回数据的字节流 + /// 转换标记位 + /// 结构化的输出数据 + public override IOutputStruct Unformat(byte[] messageBytes, ref int pos) + { + return new WriteRequestHJ212OutputStruct(Encoding.ASCII.GetString(messageBytes)); + } + } + + /// + /// 写数据输入 + /// + public class WriteRequestHJ212InputStruct : IInputStruct + { + public WriteRequestHJ212InputStruct(string st, string cn, string pw, string mn, List> cp, DateTime datetime) + { + ST = st; + CN = cn; + PW = pw; + MN = mn; + CP = cp; + Datetime = datetime; + } + + public string QN => "20170101000926706"; + + public string ST { get; } + + public string CN { get; } + + public string PW { get; } + + public string MN { get; } + + public List> CP { get; } + + public DateTime Datetime { get; } + } + + /// + /// 写数据输出 + /// + public class WriteRequestHJ212OutputStruct : IOutputStruct + { + /// + /// 构造函数 + /// + /// 读取的数据 + public WriteRequestHJ212OutputStruct(string value) + { + GetValue = value; + } + + /// + /// 读取的地址 + /// + public string GetValue { get; private set; } + } + #endregion +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinker.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinker.cs new file mode 100644 index 0000000..51b0932 --- /dev/null +++ b/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinker.cs @@ -0,0 +1,24 @@ +namespace Modbus.Net.HJ212 +{ + /// + /// HJ212协议连接器 + /// + public class HJ212ProtocolLinker : ProtocolLinker + { + public HJ212ProtocolLinker(string connectionToken) + { + BaseConnector = new TcpConnector(connectionToken, 443); + ((IConnectorWithController)BaseConnector).AddController(new FifoController(1000)); + } + + /// + /// 检查接收的数据是否正确 + /// + /// 接收协议的内容 + /// 协议是否是正确的 + public override bool? CheckRight(byte[] content) + { + return true; + } + } +} \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinkerBytesExtend.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinkerBytesExtend.cs new file mode 100644 index 0000000..d07317f --- /dev/null +++ b/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinkerBytesExtend.cs @@ -0,0 +1,42 @@ +using System; +using System.Text; + +namespace Modbus.Net.HJ212 +{ + /// + /// Rtu协议字节伸缩 + /// + public class HJ212ProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend + { + /// + /// 协议扩展,协议内容发送前调用 + /// + /// 扩展前的原始协议内容 + /// 扩展后的协议内容 + public byte[] BytesExtend(byte[] content) + { + var crc = new byte[2]; + //Modbus/Rtu协议扩张,增加CRC校验 + var newFormat = new byte[content.Length + 4]; + Crc16.GetInstance().GetCRC(content, ref crc); + Array.Copy(content, 0, newFormat, 0, content.Length); + string crcString = BitConverter.ToString(crc).Replace("-", string.Empty); + var crcCalc = Encoding.ASCII.GetBytes(crcString); + Array.Copy(crcCalc, 0, newFormat, newFormat.Length - 4, 4); + return newFormat; + } + + /// + /// 协议收缩,协议内容接收后调用 + /// + /// 收缩前的完整协议内容 + /// 收缩后的协议内容 + public byte[] BytesDecact(byte[] content) + { + //Modbus/Rtu协议收缩,抛弃后面2个字节的内容 + var newContent = new byte[content.Length - 2]; + Array.Copy(content, 0, newContent, 0, newContent.Length); + return newContent; + } + } +} diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212Utility.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212Utility.cs new file mode 100644 index 0000000..fd047b1 --- /dev/null +++ b/Modbus.Net/Modbus.Net.HJ212/HJ212Utility.cs @@ -0,0 +1,61 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Modbus.Net.HJ212 +{ + public class HJ212Utility : BaseUtility, PipeUnit> + { + private static readonly ILogger logger = LogProvider.CreateLogger(); + + public HJ212Utility(string connectionString) : base(0, 0) + { + ConnectionString = connectionString; + Wrapper = new HJ212Protocol(connectionString); + } + + public override Endian Endian => throw new NotImplementedException(); + + public override Task> GetDatasAsync(string startAddress, int getByteCount) + { + throw new NotImplementedException(); + } + + public override void SetConnectionType(int connectionType) + { + throw new NotImplementedException(); + } + + public override async Task> SetDatasAsync(string startAddress, object[] setContents) + { + try + { + var writeRequestHJ212InputStruct = + new WriteRequestHJ212InputStruct((string)setContents[0], (string)setContents[1], (string)setContents[2], (string)setContents[3], (List>)setContents[4], (DateTime)setContents[5]); + var writeRequestOpcOutputStruct = + await + Wrapper.SendReceiveAsync(Wrapper[typeof(WriteRequestHJ212Protocol)], + writeRequestHJ212InputStruct); + return new ReturnStruct + { + Datas = writeRequestOpcOutputStruct?.GetValue != null, + IsSuccess = writeRequestOpcOutputStruct?.GetValue != null, + ErrorCode = 0, + ErrorMsg = null, + }; + } + catch (Exception e) + { + logger.LogError(e, $"OpcUtility -> SetDatas: {ConnectionString} error: {e.Message}"); + return new ReturnStruct + { + Datas = false, + IsSuccess = false, + ErrorCode = -100, + ErrorMsg = e.Message + }; + } + } + } +} diff --git a/Modbus.Net/Modbus.Net.HJ212/Modbus.Net.HJ212.csproj b/Modbus.Net/Modbus.Net.HJ212/Modbus.Net.HJ212.csproj new file mode 100644 index 0000000..1b05333 --- /dev/null +++ b/Modbus.Net/Modbus.Net.HJ212/Modbus.Net.HJ212.csproj @@ -0,0 +1,39 @@ + + + + net6.0 + 10.0 + Modbus.Net.HJ212 + Modbus.Net.HJ212 + Modbus.Net.HJ212 + 1.4.2 + Chris L.(Luo Sheng) + Hangzhou Delian Science Technology Co.,Ltd. + Modbus.Net.HJ212 + Modbus.Net Modbus Implementation + Copyright 2023 Hangzhou Delian Science Technology Co.,Ltd. + https://github.com/parallelbgls/Modbus.Net/tree/master/Modbus.Net/Modbus.Net.HJ212 + https://github.com/parallelbgls/Modbus.Net + git + hardware communicate protocol modbus Delian + False + True + True + True + MIT + README.md + snupkg + + + + bin\Debug\Modbus.Net.HJ212.xml + + + + + + + + + + \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.HJ212/README.md b/Modbus.Net/Modbus.Net.HJ212/README.md new file mode 100644 index 0000000..b9b4c3d --- /dev/null +++ b/Modbus.Net/Modbus.Net.HJ212/README.md @@ -0,0 +1,7 @@ +Modbus.Net.HJ212 +=================== +[![NuGet](https://img.shields.io/nuget/v/Modbus.Net.HJ212.svg)](https://www.nuget.org/packages/Modbus.Net.HJ212/) + +HJ212 Implementation of Modbus.Net + +Doc has been moved to wiki. diff --git a/Modbus.Net/Modbus.Net.sln b/Modbus.Net/Modbus.Net.sln index 92c3165..77327bc 100644 --- a/Modbus.Net/Modbus.Net.sln +++ b/Modbus.Net/Modbus.Net.sln @@ -45,6 +45,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Technosoftware.DaAeHdaClien EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Technosoftware.DaAeHdaClient.Com", "..\Technosoftware\DaAeHdaClient.Com\Technosoftware.DaAeHdaClient.Com.csproj", "{ACAF0A16-FC51-4369-BFA8-484FF20707D7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Modbus.Net.HJ212", "Modbus.Net.HJ212\Modbus.Net.HJ212.csproj", "{057644EF-1407-4C2B-808A-AEF0F2979EA8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -181,6 +183,14 @@ Global {ACAF0A16-FC51-4369-BFA8-484FF20707D7}.Release|Any CPU.Build.0 = Release|Any CPU {ACAF0A16-FC51-4369-BFA8-484FF20707D7}.Release|x64.ActiveCfg = Release|x64 {ACAF0A16-FC51-4369-BFA8-484FF20707D7}.Release|x64.Build.0 = Release|x64 + {057644EF-1407-4C2B-808A-AEF0F2979EA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {057644EF-1407-4C2B-808A-AEF0F2979EA8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {057644EF-1407-4C2B-808A-AEF0F2979EA8}.Debug|x64.ActiveCfg = Debug|Any CPU + {057644EF-1407-4C2B-808A-AEF0F2979EA8}.Debug|x64.Build.0 = Debug|Any CPU + {057644EF-1407-4C2B-808A-AEF0F2979EA8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {057644EF-1407-4C2B-808A-AEF0F2979EA8}.Release|Any CPU.Build.0 = Release|Any CPU + {057644EF-1407-4C2B-808A-AEF0F2979EA8}.Release|x64.ActiveCfg = Release|Any CPU + {057644EF-1407-4C2B-808A-AEF0F2979EA8}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 90642d6c2e01c0c73fa56c23a4c7e88c612b14f7 Mon Sep 17 00:00:00 2001 From: luosheng Date: Sun, 16 Jul 2023 20:59:12 +0800 Subject: [PATCH 02/15] Fix --- Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs index 45600f1..48e0353 100644 --- a/Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs +++ b/Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs @@ -38,6 +38,11 @@ namespace Modbus.Net.HJ212 MN = mn; } + public override Task>>> GetDatasAsync(MachineDataType getDataType) + { + throw new NotImplementedException(); + } + public override async Task> SetDatasAsync(MachineDataType setDataType, Dictionary values) { try From d2f0bff752cc4ef6155a439287e6efb827c0e133 Mon Sep 17 00:00:00 2001 From: luosheng Date: Sun, 16 Jul 2023 21:30:13 +0800 Subject: [PATCH 03/15] Fix --- Modbus.Net/Modbus.Net/Connector/ComConnector.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Modbus.Net/Modbus.Net/Connector/ComConnector.cs b/Modbus.Net/Modbus.Net/Connector/ComConnector.cs index 43900ce..a2a84af 100644 --- a/Modbus.Net/Modbus.Net/Connector/ComConnector.cs +++ b/Modbus.Net/Modbus.Net/Connector/ComConnector.cs @@ -289,7 +289,6 @@ namespace Modbus.Net SerialPort.Dispose(); logger.LogInformation("Com interface {Com} Disposed", _com); Controller.SendStop(); - Controllers.Remove(_com); Connectors[_com] = null; Connectors.Remove(_com); ReceiveMsgThreadStop(); From 04006aaf14aebd79bc68ece3d0e7b491b710a36b Mon Sep 17 00:00:00 2001 From: luosheng Date: Mon, 17 Jul 2023 06:58:43 +0800 Subject: [PATCH 04/15] Fix --- Samples/MachineJob/MachineJob.csproj | 1 + Samples/MachineJob/Program.cs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Samples/MachineJob/MachineJob.csproj b/Samples/MachineJob/MachineJob.csproj index 2b490b0..cf66102 100644 --- a/Samples/MachineJob/MachineJob.csproj +++ b/Samples/MachineJob/MachineJob.csproj @@ -19,6 +19,7 @@ + diff --git a/Samples/MachineJob/Program.cs b/Samples/MachineJob/Program.cs index 8ee1307..059cccd 100644 --- a/Samples/MachineJob/Program.cs +++ b/Samples/MachineJob/Program.cs @@ -16,7 +16,9 @@ IHost host = Host.CreateDefaultBuilder(args).UseWindowsService() Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(configuration) + .Enrich.FromLogContext() .WriteTo.Console() + .WriteTo.File("Log\\log..txt", Serilog.Events.LogEventLevel.Error, shared: true, rollingInterval: RollingInterval.Day) .CreateLogger(); var loggerFactory = new LoggerFactory().AddSerilog(Log.Logger); From 6a1acf545451367a97e1d205c09fa78889e1c0bc Mon Sep 17 00:00:00 2001 From: luosheng Date: Mon, 17 Jul 2023 17:05:07 +0800 Subject: [PATCH 05/15] Code optimization and controller enchancement --- ...torWithControllerByteArrayCodeGenerator.cs | 158 ++++++++++++ .../Modbus.Net.CodeGenerator.csproj | 14 ++ .../Modbus.Net.HJ212/HJ212Controller.cs | 10 + Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs | 1 - Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs | 4 +- .../Modbus.Net.HJ212/HJ212ProtocolLinker.cs | 6 +- .../ModbusAsciiInTcpProtocolLinker.cs | 15 -- .../ModbusAsciiInUdpProtocolLinker.cs | 16 -- .../ModbusAsciiProtocolLinker.cs | 16 -- .../Modbus.Net.Modbus/ModbusController.cs | 238 ++++++++++++++++++ .../ModbusRtuInTcpProtocolLinker.cs | 17 +- .../ModbusRtuInUdpProtocolLinker.cs | 17 +- .../ModbusRtuProtocolLinker.cs | 19 +- .../ModbusTcpMatchDirectlySendController.cs | 41 --- .../ModbusTcpProtocolLinker.cs | 11 +- .../ModbusUdpProtocolLinker.cs | 11 +- .../Modbus.Net.Siemens/SiemensController.cs | 53 ++++ .../SiemensPpiProtocolLinker.cs | 17 -- .../SiemensTcpProtocolLinker.cs | 8 - Modbus.Net/Modbus.Net.sln | 23 +- .../Modbus.Net/Connector/BaseConnector.cs | 94 +------ .../Connector/EventHandlerConnector.cs | 95 +------ .../Modbus.Net/Helper/ControllerHelper.cs | 41 +++ .../Modbus.Net/Linker/ComProtocolLinker.cs | 1 + .../Modbus.Net/Linker/TcpProtocolLinker.cs | 1 + .../Modbus.Net/Linker/UdpProtocolLinker.cs | 1 + Modbus.Net/Modbus.Net/Modbus.Net.csproj | 8 +- .../DatabaseWriteEntityCodeGenerator.cs | 33 +++ .../MachineJob.CodeGenerator.csproj | 15 ++ Samples/MachineJob/DatabaseWrite.cs | 13 +- Samples/MachineJob/MachineJob.csproj | 3 + 31 files changed, 613 insertions(+), 387 deletions(-) create mode 100644 Modbus.Net/Modbus.Net.CodeGenerator/ConnectorWithControllerByteArrayCodeGenerator.cs create mode 100644 Modbus.Net/Modbus.Net.CodeGenerator/Modbus.Net.CodeGenerator.csproj create mode 100644 Modbus.Net/Modbus.Net.HJ212/HJ212Controller.cs create mode 100644 Modbus.Net/Modbus.Net.Modbus/ModbusController.cs delete mode 100644 Modbus.Net/Modbus.Net.Modbus/ModbusTcpMatchDirectlySendController.cs create mode 100644 Modbus.Net/Modbus.Net.Siemens/SiemensController.cs create mode 100644 Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs create mode 100644 Samples/MachineJob.CodeGenerator/DatabaseWriteEntityCodeGenerator.cs create mode 100644 Samples/MachineJob.CodeGenerator/MachineJob.CodeGenerator.csproj diff --git a/Modbus.Net/Modbus.Net.CodeGenerator/ConnectorWithControllerByteArrayCodeGenerator.cs b/Modbus.Net/Modbus.Net.CodeGenerator/ConnectorWithControllerByteArrayCodeGenerator.cs new file mode 100644 index 0000000..74dcb4f --- /dev/null +++ b/Modbus.Net/Modbus.Net.CodeGenerator/ConnectorWithControllerByteArrayCodeGenerator.cs @@ -0,0 +1,158 @@ +using Microsoft.CodeAnalysis; +using System.Text; + +namespace Modbus.Net.CodeGenerator +{ + [Generator] + public class BaseConnectorCodeGenerator : ISourceGenerator + { + public void Execute(GeneratorExecutionContext context) + { + var source = $@" +using Microsoft.Extensions.Logging; +using Nito.AsyncEx; +using System; +using System.Threading.Tasks; + +namespace Modbus.Net +{{ + public abstract partial class BaseConnector : BaseConnector + {{ +" ++ ConnectorWithControllerByteArrayCodeContent.Code("BaseConnector") ++ $@" + }} +}}"; + context.AddSource("BaseConnectorContent.g.cs", source); + } + + public void Initialize(GeneratorInitializationContext context) + { + + } + } + + [Generator] + public class EventHandlerConnectorCodeGenerator : ISourceGenerator + { + public void Execute(GeneratorExecutionContext context) + { + var source = $@" +using Microsoft.Extensions.Logging; +using Nito.AsyncEx; +using System; +using System.Threading.Tasks; + +namespace Modbus.Net +{{ + public abstract partial class EventHandlerConnector : EventHandlerConnector + {{ +" ++ ConnectorWithControllerByteArrayCodeContent.Code("EventHandlerConnector") ++ $@" + }} +}}"; + context.AddSource("EventHandlerConnectorContent.g.cs", source); + } + + public void Initialize(GeneratorInitializationContext context) + { + + } + } + + public static class ConnectorWithControllerByteArrayCodeContent + { + public static string Code(string className) + { + return new StringBuilder(@" + /// + /// 发送锁 + /// + protected abstract AsyncLock Lock { get; } + + /// + /// 是否为全双工 + /// + public bool IsFullDuplex { get; } + + /// + /// 发送超时时间 + /// + protected abstract int TimeoutTime { get; set; } + + /// + /// 构造器 + /// + /// 发送超时时间 + /// 是否为全双工 + protected {%0}(int timeoutTime = 10000, bool isFullDuplex = false) + { + IsFullDuplex = isFullDuplex; + if (timeoutTime < -1) timeoutTime = -1; + TimeoutTime = timeoutTime; + } + + /// + public override async Task SendMsgAsync(byte[] message) + { + var ans = await SendMsgInner(message); + if (ans == null) return new byte[0]; + return ans.ReceiveMessage; + } + + /// + /// 发送内部 + /// + /// 发送的信息 + /// 是否为重发消息 + /// 发送信息的定义 + protected async Task SendMsgInner(byte[] message, bool repeat = false) + { + IDisposable asyncLock = null; + try + { + if (!Controller.IsSending) + { + Controller.SendStart(); + } + var messageSendingdef = Controller.AddMessage(message); + if (messageSendingdef != null) + { + if (!IsFullDuplex) + { + asyncLock = await Lock.LockAsync(); + } + var success = messageSendingdef.SendMutex.WaitOne(TimeoutTime); + if (success) + { + await SendMsgWithoutConfirm(message); + success = messageSendingdef.ReceiveMutex.WaitOne(TimeoutTime); + if (success) + { + if (!repeat && messageSendingdef.ReceiveMessage == null) + { + asyncLock?.Dispose(); + return await SendMsgInner(message, true); + } + return messageSendingdef; + } + } + Controller.ForceRemoveWaitingMessage(messageSendingdef); + } + logger.LogInformation(""Message is waiting in {0}. Cancel!"", ConnectionToken); + return null; + } + catch (Exception e) + { + logger.LogError(e, ""Connector {0} Send Error."", ConnectionToken); + return null; + } + finally + { + asyncLock?.Dispose(); + } + }").Replace("{%0}", className).ToString(); + } + } +} diff --git a/Modbus.Net/Modbus.Net.CodeGenerator/Modbus.Net.CodeGenerator.csproj b/Modbus.Net/Modbus.Net.CodeGenerator/Modbus.Net.CodeGenerator.csproj new file mode 100644 index 0000000..e9041c6 --- /dev/null +++ b/Modbus.Net/Modbus.Net.CodeGenerator/Modbus.Net.CodeGenerator.csproj @@ -0,0 +1,14 @@ + + + + Library + netstandard2.0 + 9.0 + true + + + + + + + diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212Controller.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212Controller.cs new file mode 100644 index 0000000..89d2788 --- /dev/null +++ b/Modbus.Net/Modbus.Net.HJ212/HJ212Controller.cs @@ -0,0 +1,10 @@ +namespace Modbus.Net.HJ212 +{ + public class HJ212Controller : FifoController + { + public HJ212Controller(string ip, int port) : base(int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime"))) + { + + } + } +} diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs index 48e0353..fdf9341 100644 --- a/Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs +++ b/Modbus.Net/Modbus.Net.HJ212/HJ212Machine.cs @@ -27,7 +27,6 @@ namespace Modbus.Net.HJ212 /// /// 设备的ID号 /// 连接地址 - /// 需要读写的地址 public HJ212Machine(TKey id, string connectionString, string st, string cn, string pw, string mn) : base(id, null, true) { diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs index 4ce6be3..6ec4256 100644 --- a/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs +++ b/Modbus.Net/Modbus.Net.HJ212/HJ212Protocol.cs @@ -13,10 +13,10 @@ namespace Modbus.Net.HJ212 /// /// 构造函数 /// - public HJ212Protocol(string connectionToken) + public HJ212Protocol(string ip) : base(0, 0, Endian.BigEndianLsb) { - ProtocolLinker = new HJ212ProtocolLinker(connectionToken); + ProtocolLinker = new HJ212ProtocolLinker(ip, int.Parse(ConfigurationReader.GetValueDirect("TCP:" + ip, "HJ212Port") ?? ConfigurationReader.GetValueDirect("TCP:Modbus", "HJ212Port") ?? "443")); } /// diff --git a/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinker.cs b/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinker.cs index 51b0932..6e4ed29 100644 --- a/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.HJ212/HJ212ProtocolLinker.cs @@ -3,12 +3,10 @@ /// /// HJ212协议连接器 /// - public class HJ212ProtocolLinker : ProtocolLinker + public class HJ212ProtocolLinker : TcpProtocolLinker { - public HJ212ProtocolLinker(string connectionToken) + public HJ212ProtocolLinker(string ip, int port) : base(ip, port) { - BaseConnector = new TcpConnector(connectionToken, 443); - ((IConnectorWithController)BaseConnector).AddController(new FifoController(1000)); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInTcpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInTcpProtocolLinker.cs index 23f5ba2..4844887 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInTcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInTcpProtocolLinker.cs @@ -24,21 +24,6 @@ namespace Modbus.Net.Modbus public ModbusAsciiInTcpProtocolLinker(string ip, int port) : base(ip, port) { - ((IConnectorWithController)BaseConnector).AddController(new FifoController(int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")), - lengthCalc: content => - { - if (content[0] != 0x3a) return 0; - for (int i = 1; i < content.Length; i++) - { - if (content[i - 1] == 0x0D && content[i] == 0x0A) return i + 1; - } - return -1; - }, - checkRightFunc: ContentCheck.LrcCheckRight, - waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null - ? int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) - : null - )); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInUdpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInUdpProtocolLinker.cs index 8324e10..bda4526 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInUdpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiInUdpProtocolLinker.cs @@ -24,22 +24,6 @@ namespace Modbus.Net.Modbus public ModbusAsciiInUdpProtocolLinker(string ip, int port) : base(ip, port) { - ((IConnectorWithController)BaseConnector).AddController(new FifoController(int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime")), - lengthCalc: content => - { - if (content[0] != 0x3a) return 0; - for (int i = 1; i < content.Length; i++) - { - if (content[i - 1] == 0x0D && content[i] == 0x0A) - return i + 1; - } - return -1; - }, - checkRightFunc: ContentCheck.LrcCheckRight, - waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null - ? int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) - : null - )); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs index c4457f2..14cb1b7 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocolLinker.cs @@ -15,22 +15,6 @@ namespace Modbus.Net.Modbus public ModbusAsciiProtocolLinker(string com, int slaveAddress) : base(com, slaveAddress) { - ((IConnectorWithController)BaseConnector).AddController(new FifoController( - int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")), - lengthCalc: content => - { - if (content[0] != 0x3a) return 0; - for (int i = 1; i < content.Length; i++) - { - if (content[i - 1] == 0x0D && content[i] == 0x0A) return i + 1; - } - return -1; - }, - checkRightFunc: ContentCheck.LrcCheckRight, - waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ? - int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) : - null - )); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusController.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusController.cs new file mode 100644 index 0000000..9a5887b --- /dev/null +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusController.cs @@ -0,0 +1,238 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Modbus.Net.Modbus +{ + /// + /// Modbus长度计算 + /// + public static class ModbusLengthCalc + { + /// + /// Modbus Ascii协议长度计算 + /// + public static Func ModbusAsciiLengthCalc => content => + { + if (content[0] != 0x3a) return 0; + for (int i = 1; i < content.Length; i++) + { + if (content[i - 1] == 0x0D && content[i] == 0x0A) return i + 1; + } + return -1; + }; + + /// + /// Modbus Rtu协议长度计算 + /// + public static Func ModbusRtuLengthCalc => content => + { + if (content[1] > 128) return 5; + else if (content[1] == 5 || content[1] == 6 || content[1] == 8 || content[1] == 11 || content[1] == 15 || content[1] == 16) return 8; + else if (content[1] == 7) return 5; + else if (content[1] == 22) return 10; + else return DuplicateWithCount.GetDuplcateFunc(new List { 2 }, 5).Invoke(content); + }; + } + + /// + /// Modbus Ascii协议控制器 + /// + public class ModbusAsciiController : FifoController + { + /// + /// 构造函数 + /// + /// 串口 + /// 从站号 + public ModbusAsciiController(string com, int slaveAddress) : base( + int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")), + lengthCalc: ModbusLengthCalc.ModbusAsciiLengthCalc, + checkRightFunc: ContentCheck.LrcCheckRight, + waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ? + int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) : + null + ) + { } + } + + /// + /// Modbus Ascii in Tcp协议控制器 + /// + public class ModbusAsciiInTcpController : FifoController + { + /// + /// 构造函数 + /// + /// ip地址 + /// 端口号 + public ModbusAsciiInTcpController(string ip, int port) : base(int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")), + lengthCalc: ModbusLengthCalc.ModbusAsciiLengthCalc, + checkRightFunc: ContentCheck.LrcCheckRight, + waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null + ? int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) + : null + ) + { } + } + + /// + /// Modbus Ascii in Udp协议控制器 + /// + public class ModbusAsciiInUdpController : FifoController + { + /// + /// 构造函数 + /// + /// ip地址 + /// 端口号 + public ModbusAsciiInUdpController(string ip, int port) : base(int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime")), + lengthCalc: ModbusLengthCalc.ModbusAsciiLengthCalc, + checkRightFunc: ContentCheck.LrcCheckRight, + waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null + ? int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) + : null + ) + { } + } + + /// + /// Modbus Rtu协议控制器 + /// + public class ModbusRtuController : FifoController + { + /// + /// 构造函数 + /// + /// 串口 + /// 从站号 + public ModbusRtuController(string com, int slaveAddress) : base( + int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")), + lengthCalc: ModbusLengthCalc.ModbusRtuLengthCalc, + checkRightFunc: ContentCheck.Crc16CheckRight, + waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ? + int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) : + null + ) + { } + } + + /// + /// Modbus Rtu in Tcp协议控制器 + /// + public class ModbusRtuInTcpController : FifoController + { + /// + /// 构造函数 + /// + /// ip地址 + /// 端口号 + public ModbusRtuInTcpController(string ip, int port) : base( + int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")), + lengthCalc: ModbusLengthCalc.ModbusRtuLengthCalc, + checkRightFunc: ContentCheck.Crc16CheckRight, + waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ? + int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) : + null + ) + { } + } + + /// + /// Modbus Rtu in Udp协议控制器 + /// + public class ModbusRtuInUdpController : FifoController + { + /// + /// 构造函数 + /// + /// ip地址 + /// 端口号 + public ModbusRtuInUdpController(string ip, int port) : base( + int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime")), + lengthCalc: ModbusLengthCalc.ModbusRtuLengthCalc, + checkRightFunc: ContentCheck.Crc16CheckRight, + waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null ? + int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) : + null + ) + { } + } + + /// + /// Modbus Tcp协议控制器 + /// + public class ModbusTcpController : ModbusEthMatchDirectlySendController + { + /// + /// 构造函数 + /// + /// ip地址 + /// 端口号 + public ModbusTcpController(string ip, int port) : base( + new ICollection<(int, int)>[] { new List<(int, int)> { (0, 0), (1, 1) } }, + lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List { 4, 5 }, 6), + waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ? + int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) : + null + ) + { } + } + + /// + /// Modbus Udp协议控制器 + /// + public class ModbusUdpController : ModbusEthMatchDirectlySendController + { + /// + /// 构造函数 + /// + /// ip地址 + /// 端口号 + public ModbusUdpController(string ip, int port) : base( + new ICollection<(int, int)>[] { new List<(int, int)> { (0, 0), (1, 1) } }, + lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List { 4, 5 }, 6), + waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null ? + int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) : + null + ) + { } + } + + /// + /// 匹配控制器,载入队列后直接发送 + /// + public class ModbusEthMatchDirectlySendController : MatchDirectlySendController + { + /// + public ModbusEthMatchDirectlySendController(ICollection<(int, int)>[] keyMatches, + Func lengthCalc = null, Func checkRightFunc = null, int? waitingListMaxCount = null) : base(keyMatches, + lengthCalc, checkRightFunc, waitingListMaxCount) + { + } + + /// + protected override MessageWaitingDef GetMessageFromWaitingList(byte[] receiveMessage) + { + MessageWaitingDef ans; + if (receiveMessage[0] == 0 && receiveMessage[1] == 0) + { + lock (WaitingMessages) + { + ans = WaitingMessages.FirstOrDefault(); + } + } + else + { + var returnKey = GetKeyFromMessage(receiveMessage); + lock (WaitingMessages) + { + ans = WaitingMessages.FirstOrDefault(p => returnKey.HasValue && p.Key == returnKey.Value.Item2); + } + } + return ans; + } + } +} + + diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInTcpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInTcpProtocolLinker.cs index ae8d1d5..270b72c 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInTcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInTcpProtocolLinker.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; - -namespace Modbus.Net.Modbus +namespace Modbus.Net.Modbus { /// /// Modbus/Rtu协议连接器Tcp透传 @@ -24,19 +22,6 @@ namespace Modbus.Net.Modbus public ModbusRtuInTcpProtocolLinker(string ip, int port) : base(ip, port) { - ((IConnectorWithController)BaseConnector).AddController(new FifoController( - int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FetchSleepTime")), - lengthCalc: content => - { - if (content[1] > 128) return 5; - else if (content[1] == 5 || content[1] == 6 || content[1] == 15 || content[1] == 16 || content[1] == 21) return 8; - else return DuplicateWithCount.GetDuplcateFunc(new List { 2 }, 5).Invoke(content); - }, - checkRightFunc: ContentCheck.Crc16CheckRight, - waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ? - int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) : - null - )); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInUdpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInUdpProtocolLinker.cs index b4365b2..d11f31f 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInUdpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuInUdpProtocolLinker.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; - -namespace Modbus.Net.Modbus +namespace Modbus.Net.Modbus { /// /// Modbus/Rtu协议连接器Udp透传 @@ -24,19 +22,6 @@ namespace Modbus.Net.Modbus public ModbusRtuInUdpProtocolLinker(string ip, int port) : base(ip, port) { - ((IConnectorWithController)BaseConnector).AddController(new FifoController( - int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FetchSleepTime")), - lengthCalc: content => - { - if (content[1] > 128) return 5; - else if (content[1] == 5 || content[1] == 6 || content[1] == 15 || content[1] == 16 || content[1] == 21) return 8; - else return DuplicateWithCount.GetDuplcateFunc(new List { 2 }, 5).Invoke(content); - }, - checkRightFunc: ContentCheck.Crc16CheckRight, - waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null ? - int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) : - null - )); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs index 859f32e..f9b3953 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusRtuProtocolLinker.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; - -namespace Modbus.Net.Modbus +namespace Modbus.Net.Modbus { /// /// Modbus/Rtu协议连接器 @@ -15,21 +13,6 @@ namespace Modbus.Net.Modbus public ModbusRtuProtocolLinker(string com, int slaveAddress) : base(com, slaveAddress) { - ((IConnectorWithController)BaseConnector).AddController(new FifoController( - int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")), - lengthCalc: content => - { - if (content[1] > 128) return 5; - else if (content[1] == 5 || content[1] == 6 || content[1] == 8 || content[1] == 11 || content[1] == 15 || content[1] == 16) return 8; - else if (content[1] == 7) return 5; - else if (content[1] == 22) return 10; - else return DuplicateWithCount.GetDuplcateFunc(new List { 2 }, 5).Invoke(content); - }, - checkRightFunc: ContentCheck.Crc16CheckRight, - waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ? - int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) : - null - )); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpMatchDirectlySendController.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpMatchDirectlySendController.cs deleted file mode 100644 index 3cfd997..0000000 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpMatchDirectlySendController.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Modbus.Net -{ - /// - /// 匹配控制器,载入队列后直接发送 - /// - public class ModbusTcpMatchDirectlySendController : MatchDirectlySendController - { - /// - public ModbusTcpMatchDirectlySendController(ICollection<(int, int)>[] keyMatches, - Func lengthCalc = null, Func checkRightFunc = null, int? waitingListMaxCount = null) : base(keyMatches, - lengthCalc, checkRightFunc, waitingListMaxCount) - { - } - - /// - protected override MessageWaitingDef GetMessageFromWaitingList(byte[] receiveMessage) - { - MessageWaitingDef ans; - if (receiveMessage[0] == 0 && receiveMessage[1] == 0) - { - lock (WaitingMessages) - { - ans = WaitingMessages.FirstOrDefault(); - } - } - else - { - var returnKey = GetKeyFromMessage(receiveMessage); - lock (WaitingMessages) - { - ans = WaitingMessages.FirstOrDefault(p => returnKey.HasValue && p.Key == returnKey.Value.Item2); - } - } - return ans; - } - } -} diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs index 949f8b6..4f678e0 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusTcpProtocolLinker.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; - -namespace Modbus.Net.Modbus +namespace Modbus.Net.Modbus { /// /// Modbus/Tcp协议连接器 @@ -23,13 +21,6 @@ namespace Modbus.Net.Modbus /// 端口 public ModbusTcpProtocolLinker(string ip, int port) : base(ip, port) { - ((IConnectorWithController)BaseConnector).AddController(new ModbusTcpMatchDirectlySendController( - new ICollection<(int, int)>[] { new List<(int, int)> { (0, 0), (1, 1) } }, - lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List { 4, 5 }, 6), - waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ? - int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) : - null - )); } /// diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusUdpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusUdpProtocolLinker.cs index a917e9a..7bd93db 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusUdpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusUdpProtocolLinker.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; - -namespace Modbus.Net.Modbus +namespace Modbus.Net.Modbus { /// /// Modbus/Udp协议连接器 @@ -23,13 +21,6 @@ namespace Modbus.Net.Modbus /// 端口 public ModbusUdpProtocolLinker(string ip, int port) : base(ip, port) { - ((IConnectorWithController)BaseConnector).AddController(new ModbusTcpMatchDirectlySendController( - new ICollection<(int, int)>[] { new List<(int, int)> { (0, 0), (1, 1) } }, - lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List { 4, 5 }, 6), - waitingListMaxCount: ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount") != null ? - int.Parse(ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "WaitingListCount")) : - null - )); } /// diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensController.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensController.cs new file mode 100644 index 0000000..e0bb902 --- /dev/null +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensController.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; + +namespace Modbus.Net.Siemens +{ + /// + /// 西门子Ppi协议控制器 + /// + public class SiemensPpiController : FifoController + { + /// + /// 构造函数 + /// + /// 串口 + /// 从站号 + public SiemensPpiController(string com, int slaveAddress) : base( + int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")), + lengthCalc: content => + { + if (content[0] == 0x10) + return 6; + else if (content[0] == 0xE5) + return 1; + else + return DuplicateWithCount.GetDuplcateFunc(new List { 1 }, 6)(content); + }, + checkRightFunc: ContentCheck.FcsCheckRight, + waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ? + int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) : + null + ) + { } + } + + /// + /// 西门子Tcp协议控制器 + /// + public class SiemensTcpController : MatchDirectlySendController + { + /// + /// 构造函数 + /// + /// ip地址 + /// 端口号 + public SiemensTcpController(string ip, int port) : base( + new ICollection<(int, int)>[] { new List<(int, int)> { (11, 11), (12, 12) } }, + lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List { 2, 3 }, 0), + waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ? + int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) : + null + ) + { } + } +} diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocolLinker.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocolLinker.cs index 7c25c67..60505d4 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocolLinker.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO.Ports; using System.Threading; using System.Threading.Tasks; @@ -23,22 +22,6 @@ namespace Modbus.Net.Siemens : null ) { - ((IConnectorWithController)BaseConnector).AddController(new FifoController( - int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "FetchSleepTime")), - lengthCalc: content => - { - if (content[0] == 0x10) - return 6; - else if (content[0] == 0xE5) - return 1; - else - return DuplicateWithCount.GetDuplcateFunc(new List { 1 }, 6)(content); - }, - checkRightFunc: ContentCheck.FcsCheckRight, - waitingListMaxCount: ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount") != null ? - int.Parse(ConfigurationReader.GetValue("COM:" + com + ":" + slaveAddress, "WaitingListCount")) : - null - )); } /// diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocolLinker.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocolLinker.cs index 25234aa..a91160b 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocolLinker.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; namespace Modbus.Net.Siemens { @@ -25,13 +24,6 @@ namespace Modbus.Net.Siemens public SiemensTcpProtocolLinker(string ip, int port) : base(ip, port) { - ((IConnectorWithController)BaseConnector).AddController(new MatchDirectlySendController( - new ICollection<(int, int)>[] { new List<(int, int)> { (11, 11), (12, 12) } }, - lengthCalc: DuplicateWithCount.GetDuplcateFunc(new List { 2, 3 }, 0), - waitingListMaxCount: ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount") != null ? - int.Parse(ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "WaitingListCount")) : - null - )); } /// diff --git a/Modbus.Net/Modbus.Net.sln b/Modbus.Net/Modbus.Net.sln index 77327bc..5b176af 100644 --- a/Modbus.Net/Modbus.Net.sln +++ b/Modbus.Net/Modbus.Net.sln @@ -45,7 +45,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Technosoftware.DaAeHdaClien EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Technosoftware.DaAeHdaClient.Com", "..\Technosoftware\DaAeHdaClient.Com\Technosoftware.DaAeHdaClient.Com.csproj", "{ACAF0A16-FC51-4369-BFA8-484FF20707D7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Modbus.Net.HJ212", "Modbus.Net.HJ212\Modbus.Net.HJ212.csproj", "{057644EF-1407-4C2B-808A-AEF0F2979EA8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Modbus.Net.HJ212", "Modbus.Net.HJ212\Modbus.Net.HJ212.csproj", "{057644EF-1407-4C2B-808A-AEF0F2979EA8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Modbus.Net.CodeGenerator", "Modbus.Net.CodeGenerator\Modbus.Net.CodeGenerator.csproj", "{D3210531-BA79-49B2-9F99-09FD0E1627B6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MachineJob.CodeGenerator", "..\Samples\MachineJob.CodeGenerator\MachineJob.CodeGenerator.csproj", "{7337BC9A-ED07-463D-8FCD-A82896CEC6BE}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -191,6 +195,22 @@ Global {057644EF-1407-4C2B-808A-AEF0F2979EA8}.Release|Any CPU.Build.0 = Release|Any CPU {057644EF-1407-4C2B-808A-AEF0F2979EA8}.Release|x64.ActiveCfg = Release|Any CPU {057644EF-1407-4C2B-808A-AEF0F2979EA8}.Release|x64.Build.0 = Release|Any CPU + {D3210531-BA79-49B2-9F99-09FD0E1627B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3210531-BA79-49B2-9F99-09FD0E1627B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3210531-BA79-49B2-9F99-09FD0E1627B6}.Debug|x64.ActiveCfg = Debug|Any CPU + {D3210531-BA79-49B2-9F99-09FD0E1627B6}.Debug|x64.Build.0 = Debug|Any CPU + {D3210531-BA79-49B2-9F99-09FD0E1627B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3210531-BA79-49B2-9F99-09FD0E1627B6}.Release|Any CPU.Build.0 = Release|Any CPU + {D3210531-BA79-49B2-9F99-09FD0E1627B6}.Release|x64.ActiveCfg = Release|Any CPU + {D3210531-BA79-49B2-9F99-09FD0E1627B6}.Release|x64.Build.0 = Release|Any CPU + {7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Debug|x64.ActiveCfg = Debug|Any CPU + {7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Debug|x64.Build.0 = Debug|Any CPU + {7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Release|Any CPU.Build.0 = Release|Any CPU + {7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Release|x64.ActiveCfg = Release|Any CPU + {7337BC9A-ED07-463D-8FCD-A82896CEC6BE}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -201,6 +221,7 @@ Global {1857DA63-3335-428F-84D8-1FA4F8178643} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A} {AA3A42D2-0502-41D3-929A-BAB729DF07D6} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A} {414956B8-DBD4-414C-ABD3-565580739646} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A} + {7337BC9A-ED07-463D-8FCD-A82896CEC6BE} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AF00D64E-3C70-474A-8A81-E9E48017C4B5} diff --git a/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs b/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs index 286cd74..3a315c9 100644 --- a/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs +++ b/Modbus.Net/Modbus.Net/Connector/BaseConnector.cs @@ -1,102 +1,12 @@ using Microsoft.Extensions.Logging; -using Nito.AsyncEx; -using System; using System.Threading.Tasks; namespace Modbus.Net { /// - public abstract class BaseConnector : BaseConnector + public abstract partial class BaseConnector : BaseConnector { - private static readonly ILogger logger = LogProvider.CreateLogger(); - - /// - /// 发送锁 - /// - protected abstract AsyncLock Lock { get; } - - /// - /// 是否为全双工 - /// - public bool IsFullDuplex { get; } - - /// - /// 发送超时时间 - /// - protected abstract int TimeoutTime { get; set; } - - /// - /// 构造器 - /// - /// 发送超时时间 - /// 是否为全双工 - protected BaseConnector(int timeoutTime = 10000, bool isFullDuplex = false) - { - IsFullDuplex = isFullDuplex; - if (timeoutTime < -1) timeoutTime = -1; - TimeoutTime = timeoutTime; - } - - /// - public override async Task SendMsgAsync(byte[] message) - { - var ans = await SendMsgInner(message); - if (ans == null) return new byte[0]; - return ans.ReceiveMessage; - } - - /// - /// 发送内部 - /// - /// 发送的信息 - /// 是否为重发消息 - /// 发送信息的定义 - protected async Task SendMsgInner(byte[] message, bool repeat = false) - { - IDisposable asyncLock = null; - try - { - if (!Controller.IsSending) - { - Controller.SendStart(); - } - var messageSendingdef = Controller.AddMessage(message); - if (messageSendingdef != null) - { - if (!IsFullDuplex) - { - asyncLock = await Lock.LockAsync(); - } - var success = messageSendingdef.SendMutex.WaitOne(TimeoutTime); - if (success) - { - await SendMsgWithoutConfirm(message); - success = messageSendingdef.ReceiveMutex.WaitOne(TimeoutTime); - if (success) - { - if (!repeat && messageSendingdef.ReceiveMessage == null) - { - asyncLock?.Dispose(); - return await SendMsgInner(message, true); - } - return messageSendingdef; - } - } - Controller.ForceRemoveWaitingMessage(messageSendingdef); - } - logger.LogInformation("Message is waiting in {0}. Cancel!", ConnectionToken); - return null; - } - catch (Exception e) - { - logger.LogError(e, "Connector {0} Send Error.", ConnectionToken); - return null; - } - finally - { - asyncLock?.Dispose(); - } - } + private static readonly ILogger logger = LogProvider.CreateLogger(); } /// diff --git a/Modbus.Net/Modbus.Net/Connector/EventHandlerConnector.cs b/Modbus.Net/Modbus.Net/Connector/EventHandlerConnector.cs index 8068bfe..5447680 100644 --- a/Modbus.Net/Modbus.Net/Connector/EventHandlerConnector.cs +++ b/Modbus.Net/Modbus.Net/Connector/EventHandlerConnector.cs @@ -1,106 +1,17 @@ using DotNetty.Transport.Channels; using Microsoft.Extensions.Logging; -using Nito.AsyncEx; using System; using System.Threading.Tasks; namespace Modbus.Net { /// - public abstract class EventHandlerConnector : EventHandlerConnector + public abstract partial class EventHandlerConnector : EventHandlerConnector { - /// - public override bool IsSharable => true; - private static readonly ILogger logger = LogProvider.CreateLogger(); - /// - /// 发送锁 - /// - protected abstract AsyncLock Lock { get; } - - /// - /// 是否为全双工 - /// - public bool IsFullDuplex { get; } - - /// - /// 发送超时时间 - /// - protected abstract int TimeoutTime { get; set; } - - /// - /// 构造器 - /// - /// 发送超时时间 - /// 是否为全双工 - protected EventHandlerConnector(int timeoutTime = 10000, bool isFullDuplex = true) - { - IsFullDuplex = isFullDuplex; - if (timeoutTime < -1) timeoutTime = -1; - TimeoutTime = timeoutTime; - } - - /// - public override async Task SendMsgAsync(byte[] message) - { - var ans = await SendMsgInner(message); - if (ans == null) return new byte[0]; - return ans.ReceiveMessage; - } - - /// - /// 发送内部 - /// - /// 发送的信息 - /// 是否为重发消息 - /// 发送信息的定义 - protected async Task SendMsgInner(byte[] message, bool repeat = false) - { - IDisposable asyncLock = null; - try - { - if (!Controller.IsSending) - { - Controller.SendStart(); - } - var messageSendingdef = Controller.AddMessage(message); - if (messageSendingdef != null) - { - if (!IsFullDuplex) - { - asyncLock = await Lock.LockAsync(); - } - var success = messageSendingdef.SendMutex.WaitOne(TimeoutTime); - if (success) - { - await SendMsgWithoutConfirm(message); - success = messageSendingdef.ReceiveMutex.WaitOne(TimeoutTime); - if (success) - { - if (!repeat && messageSendingdef.ReceiveMessage == null) - { - asyncLock?.Dispose(); - return await SendMsgInner(message, true); - } - return messageSendingdef; - } - } - Controller.ForceRemoveWaitingMessage(messageSendingdef); - } - logger.LogInformation("Message is waiting in {0}. Cancel!", ConnectionToken); - return null; - } - catch (Exception e) - { - logger.LogError(e, "Connector {0} Send Error.", ConnectionToken); - return null; - } - finally - { - asyncLock?.Dispose(); - } - } + /// + public override bool IsSharable => true; /// public override void ChannelReadComplete(IChannelHandlerContext ctx) diff --git a/Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs b/Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs new file mode 100644 index 0000000..01a61e2 --- /dev/null +++ b/Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs @@ -0,0 +1,41 @@ +using System; +using System.Reflection; + +namespace Modbus.Net +{ + /// + /// ProtocolLinker添加Controller扩展方法 + /// + public static class ControllerHelper + { + /// + /// 添加一个Controller + /// + /// ProtocolLinker实例 + /// 第一参数 + /// 第二参数 + /// Connector实例 + /// 如果没有发现控制器,报错 + public static void AddController(this IProtocolLinker protocolLinker, string param1, int param2, IConnector connector) + { + IController controller = null; + var assemblies = AssemblyHelper.GetAllLibraryAssemblies(); + string controllerName = protocolLinker.GetType().Name.Substring(0, protocolLinker.GetType().Name.Length - 14) + "Controller"; + foreach (var assembly in assemblies) + { + var controllerType = assembly.GetType(assembly.GetName().Name + "." + controllerName); + if (controllerType != null) + { + controller = assembly.CreateInstance(controllerType.FullName, true, BindingFlags.Default, null, new object[2] { param1, param2 }, null, null) as IController; + break; + } + } + if (controller != null) + { + ((IConnectorWithController)connector).AddController(controller); + return; + } + throw new NotImplementedException(controllerName + " not found exception"); + } + } +} diff --git a/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs b/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs index fca0bed..ddedad6 100644 --- a/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs @@ -31,6 +31,7 @@ namespace Modbus.Net connectionTimeout = int.Parse(connectionTimeout != null ? connectionTimeout.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "ConnectionTimeout")); isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "FullDuplex")); BaseConnector = new ComConnector(com + ":" + slaveAddress, baudRate.Value, parity.Value, stopBits.Value, dataBits.Value, handshake.Value, connectionTimeout.Value, isFullDuplex.Value); + this.AddController(com, slaveAddress, BaseConnector); } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs b/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs index d476f85..679a8af 100644 --- a/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs @@ -18,6 +18,7 @@ isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FullDuplex")); //初始化连接对象 BaseConnector = new TcpConnector(ip, port, connectionTimeout.Value, isFullDuplex.Value); + this.AddController(ip, port, BaseConnector); } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs b/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs index 7496341..056335a 100644 --- a/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs @@ -18,6 +18,7 @@ isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FullDuplex")); //初始化连接对象 BaseConnector = new UdpConnector(ip, port, connectionTimeout.Value, isFullDuplex.Value); + this.AddController(ip, port, BaseConnector); } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/Modbus.Net.csproj b/Modbus.Net/Modbus.Net/Modbus.Net.csproj index ef5cb65..8a21188 100644 --- a/Modbus.Net/Modbus.Net/Modbus.Net.csproj +++ b/Modbus.Net/Modbus.Net/Modbus.Net.csproj @@ -34,7 +34,7 @@ PreserveNewest - + @@ -47,5 +47,11 @@ + + + + \ No newline at end of file diff --git a/Samples/MachineJob.CodeGenerator/DatabaseWriteEntityCodeGenerator.cs b/Samples/MachineJob.CodeGenerator/DatabaseWriteEntityCodeGenerator.cs new file mode 100644 index 0000000..883dcfd --- /dev/null +++ b/Samples/MachineJob.CodeGenerator/DatabaseWriteEntityCodeGenerator.cs @@ -0,0 +1,33 @@ +using Microsoft.CodeAnalysis; + +namespace Modbus.Net.CodeGenerator +{ + [Generator] + public class DatabaseWriteEntityCodeGenerator : ISourceGenerator + { + public void Execute(GeneratorExecutionContext context) + { + var content = ""; + for (int i = 1; i <= 10; i++) + { + content += $@"public double? Value{i} {{ get; set; }} + "; + } + var source = $@" + +namespace MachineJob +{{ + public partial class DatabaseWriteEntity + {{ + {content} + }} +}}"; + context.AddSource("DatabaseWriteContent.g.cs", source); + } + + public void Initialize(GeneratorInitializationContext context) + { + + } + } +} diff --git a/Samples/MachineJob.CodeGenerator/MachineJob.CodeGenerator.csproj b/Samples/MachineJob.CodeGenerator/MachineJob.CodeGenerator.csproj new file mode 100644 index 0000000..7ae8fe2 --- /dev/null +++ b/Samples/MachineJob.CodeGenerator/MachineJob.CodeGenerator.csproj @@ -0,0 +1,15 @@ + + + + Library + netstandard2.0 + 9.0 + true + + + + + + + + diff --git a/Samples/MachineJob/DatabaseWrite.cs b/Samples/MachineJob/DatabaseWrite.cs index 7e0d87c..2faebfe 100644 --- a/Samples/MachineJob/DatabaseWrite.cs +++ b/Samples/MachineJob/DatabaseWrite.cs @@ -24,20 +24,11 @@ namespace MachineJob } [Table(name: "databasewrites")] - public class DatabaseWriteEntity + public partial class DatabaseWriteEntity { [Key] public int Id { get; set; } - public double? Value1 { get; set; } - public double? Value2 { get; set; } - public double? Value3 { get; set; } - public double? Value4 { get; set; } - public double? Value5 { get; set; } - public double? Value6 { get; set; } - public double? Value7 { get; set; } - public double? Value8 { get; set; } - public double? Value9 { get; set; } - public double? Value10 { get; set; } + public DateTime UpdateTime { get; set; } } } diff --git a/Samples/MachineJob/MachineJob.csproj b/Samples/MachineJob/MachineJob.csproj index cf66102..0cadf32 100644 --- a/Samples/MachineJob/MachineJob.csproj +++ b/Samples/MachineJob/MachineJob.csproj @@ -27,5 +27,8 @@ + From 7b58d7934958cb0a718d95bdd032825e482141d3 Mon Sep 17 00:00:00 2001 From: luosheng Date: Mon, 17 Jul 2023 17:43:30 +0800 Subject: [PATCH 06/15] Fix --- .../Modbus.Net.CodeGenerator/Modbus.Net.CodeGenerator.csproj | 2 +- .../MachineJob.CodeGenerator/MachineJob.CodeGenerator.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modbus.Net/Modbus.Net.CodeGenerator/Modbus.Net.CodeGenerator.csproj b/Modbus.Net/Modbus.Net.CodeGenerator/Modbus.Net.CodeGenerator.csproj index e9041c6..bdad474 100644 --- a/Modbus.Net/Modbus.Net.CodeGenerator/Modbus.Net.CodeGenerator.csproj +++ b/Modbus.Net/Modbus.Net.CodeGenerator/Modbus.Net.CodeGenerator.csproj @@ -8,7 +8,7 @@ - + diff --git a/Samples/MachineJob.CodeGenerator/MachineJob.CodeGenerator.csproj b/Samples/MachineJob.CodeGenerator/MachineJob.CodeGenerator.csproj index 7ae8fe2..f9fd585 100644 --- a/Samples/MachineJob.CodeGenerator/MachineJob.CodeGenerator.csproj +++ b/Samples/MachineJob.CodeGenerator/MachineJob.CodeGenerator.csproj @@ -8,7 +8,7 @@ - + From 8888552c0a9c6f58ce74c42f233736ea347dc87a Mon Sep 17 00:00:00 2001 From: luosheng Date: Mon, 17 Jul 2023 17:51:11 +0800 Subject: [PATCH 07/15] Fix --- Modbus.Net/Modbus.Net/Controller/FifoController.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Modbus.Net/Modbus.Net/Controller/FifoController.cs b/Modbus.Net/Modbus.Net/Controller/FifoController.cs index 81a91e2..79a1acb 100644 --- a/Modbus.Net/Modbus.Net/Controller/FifoController.cs +++ b/Modbus.Net/Modbus.Net/Controller/FifoController.cs @@ -96,6 +96,7 @@ namespace Modbus.Net /// public override void SendStop() { + Clear(); _taskCancel = true; } From 548d7da9cd85c9eb5fd293fa54cdd0e1ac78d86f Mon Sep 17 00:00:00 2001 From: luosheng Date: Mon, 17 Jul 2023 17:57:29 +0800 Subject: [PATCH 08/15] Fix --- Modbus.Net/Modbus.Net/Controller/BaseController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modbus.Net/Modbus.Net/Controller/BaseController.cs b/Modbus.Net/Modbus.Net/Controller/BaseController.cs index e33b5ff..c2491bc 100644 --- a/Modbus.Net/Modbus.Net/Controller/BaseController.cs +++ b/Modbus.Net/Modbus.Net/Controller/BaseController.cs @@ -76,7 +76,7 @@ namespace Modbus.Net /// public virtual void SendStart() { - if (SendingThread == null) + if (!IsSending) { SendingThread = Task.Run(() => SendingMessageControlInner()); } From 2e7648a8b1bf91982d0861e48a239493e10d8312 Mon Sep 17 00:00:00 2001 From: luosheng Date: Mon, 17 Jul 2023 18:01:49 +0800 Subject: [PATCH 09/15] Fix --- Modbus.Net/Modbus.Net/Controller/BaseController.cs | 4 ++-- .../Modbus.Net/Controller/MatchDirectlySendController.cs | 2 +- Modbus.Net/Modbus.Net/Interface/IController.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modbus.Net/Modbus.Net/Controller/BaseController.cs b/Modbus.Net/Modbus.Net/Controller/BaseController.cs index c2491bc..38cc46b 100644 --- a/Modbus.Net/Modbus.Net/Controller/BaseController.cs +++ b/Modbus.Net/Modbus.Net/Controller/BaseController.cs @@ -24,7 +24,7 @@ namespace Modbus.Net /// /// Ϣά߳Ƿ /// - public virtual bool IsSending => SendingThread.Status.Equals(TaskStatus.Running); + public virtual bool? IsSending => SendingThread?.Status.Equals(TaskStatus.Running); /// /// зλú @@ -76,7 +76,7 @@ namespace Modbus.Net /// public virtual void SendStart() { - if (!IsSending) + if (IsSending != true) { SendingThread = Task.Run(() => SendingMessageControlInner()); } diff --git a/Modbus.Net/Modbus.Net/Controller/MatchDirectlySendController.cs b/Modbus.Net/Modbus.Net/Controller/MatchDirectlySendController.cs index b6e1627..7401a7c 100644 --- a/Modbus.Net/Modbus.Net/Controller/MatchDirectlySendController.cs +++ b/Modbus.Net/Modbus.Net/Controller/MatchDirectlySendController.cs @@ -11,7 +11,7 @@ namespace Modbus.Net /// /// 消息维护线程是否在运行 /// - public override bool IsSending => true; + public override bool? IsSending => true; /// public MatchDirectlySendController(ICollection<(int, int)>[] keyMatches, diff --git a/Modbus.Net/Modbus.Net/Interface/IController.cs b/Modbus.Net/Modbus.Net/Interface/IController.cs index 2cb9431..c3fd62e 100644 --- a/Modbus.Net/Modbus.Net/Interface/IController.cs +++ b/Modbus.Net/Modbus.Net/Interface/IController.cs @@ -10,7 +10,7 @@ namespace Modbus.Net /// /// Ϣά߳Ƿ /// - bool IsSending { get; } + bool? IsSending { get; } /// /// Ϣ From 30c13edf0d9b6768f7ca27c48a960b569d1d7853 Mon Sep 17 00:00:00 2001 From: luosheng Date: Mon, 17 Jul 2023 18:04:45 +0800 Subject: [PATCH 10/15] Fix --- .../ConnectorWithControllerByteArrayCodeGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modbus.Net/Modbus.Net.CodeGenerator/ConnectorWithControllerByteArrayCodeGenerator.cs b/Modbus.Net/Modbus.Net.CodeGenerator/ConnectorWithControllerByteArrayCodeGenerator.cs index 74dcb4f..1eb9c69 100644 --- a/Modbus.Net/Modbus.Net.CodeGenerator/ConnectorWithControllerByteArrayCodeGenerator.cs +++ b/Modbus.Net/Modbus.Net.CodeGenerator/ConnectorWithControllerByteArrayCodeGenerator.cs @@ -112,7 +112,7 @@ namespace Modbus.Net IDisposable asyncLock = null; try { - if (!Controller.IsSending) + if (Controller.IsSending != true) { Controller.SendStart(); } From a1c96a96ca8e059d6bf12ee363c55978057d785c Mon Sep 17 00:00:00 2001 From: luosheng Date: Tue, 18 Jul 2023 04:57:09 +0800 Subject: [PATCH 11/15] Fix --- Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs | 7 +++---- Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs | 2 +- Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs | 2 +- Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs b/Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs index 01a61e2..d9942bf 100644 --- a/Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs +++ b/Modbus.Net/Modbus.Net/Helper/ControllerHelper.cs @@ -12,11 +12,10 @@ namespace Modbus.Net /// 添加一个Controller /// /// ProtocolLinker实例 - /// 第一参数 - /// 第二参数 + /// 参数 /// Connector实例 /// 如果没有发现控制器,报错 - public static void AddController(this IProtocolLinker protocolLinker, string param1, int param2, IConnector connector) + public static void AddController(this IProtocolLinker protocolLinker, object[] constructorParams, IConnector connector) { IController controller = null; var assemblies = AssemblyHelper.GetAllLibraryAssemblies(); @@ -26,7 +25,7 @@ namespace Modbus.Net var controllerType = assembly.GetType(assembly.GetName().Name + "." + controllerName); if (controllerType != null) { - controller = assembly.CreateInstance(controllerType.FullName, true, BindingFlags.Default, null, new object[2] { param1, param2 }, null, null) as IController; + controller = assembly.CreateInstance(controllerType.FullName, true, BindingFlags.Default, null, constructorParams, null, null) as IController; break; } } diff --git a/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs b/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs index ddedad6..361c6b6 100644 --- a/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net/Linker/ComProtocolLinker.cs @@ -31,7 +31,7 @@ namespace Modbus.Net connectionTimeout = int.Parse(connectionTimeout != null ? connectionTimeout.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "ConnectionTimeout")); isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("COM:" + com, "FullDuplex")); BaseConnector = new ComConnector(com + ":" + slaveAddress, baudRate.Value, parity.Value, stopBits.Value, dataBits.Value, handshake.Value, connectionTimeout.Value, isFullDuplex.Value); - this.AddController(com, slaveAddress, BaseConnector); + this.AddController(new object[2] { com, slaveAddress }, BaseConnector); } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs b/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs index 679a8af..4ef9b99 100644 --- a/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net/Linker/TcpProtocolLinker.cs @@ -18,7 +18,7 @@ isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("TCP:" + ip + ":" + port, "FullDuplex")); //初始化连接对象 BaseConnector = new TcpConnector(ip, port, connectionTimeout.Value, isFullDuplex.Value); - this.AddController(ip, port, BaseConnector); + this.AddController(new object[2] { ip, port }, BaseConnector); } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs b/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs index 056335a..6fb4d93 100644 --- a/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs +++ b/Modbus.Net/Modbus.Net/Linker/UdpProtocolLinker.cs @@ -18,7 +18,7 @@ isFullDuplex = bool.Parse(isFullDuplex != null ? isFullDuplex.ToString() : null ?? ConfigurationReader.GetValue("UDP:" + ip + ":" + port, "FullDuplex")); //初始化连接对象 BaseConnector = new UdpConnector(ip, port, connectionTimeout.Value, isFullDuplex.Value); - this.AddController(ip, port, BaseConnector); + this.AddController(new object[2] { ip, port }, BaseConnector); } } } \ No newline at end of file From d7074f0159acb5b514b959b082dc874b9a463328 Mon Sep 17 00:00:00 2001 From: luosheng Date: Tue, 18 Jul 2023 15:32:26 +0800 Subject: [PATCH 12/15] Fix --- Modbus.Net/Modbus.Net/Controller/BaseController.cs | 9 +++++++-- Modbus.Net/Modbus.Net/Controller/FifoController.cs | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Modbus.Net/Modbus.Net/Controller/BaseController.cs b/Modbus.Net/Modbus.Net/Controller/BaseController.cs index 38cc46b..b921b62 100644 --- a/Modbus.Net/Modbus.Net/Controller/BaseController.cs +++ b/Modbus.Net/Modbus.Net/Controller/BaseController.cs @@ -24,7 +24,7 @@ namespace Modbus.Net /// /// Ϣά߳Ƿ /// - public virtual bool? IsSending => SendingThread?.Status.Equals(TaskStatus.Running); + public virtual bool? IsSending => SendingThread?.Status == TaskStatus.Running || SendingThread?.Status == TaskStatus.WaitingToRun || SendingThread?.Status == TaskStatus.Created; /// /// зλú @@ -71,7 +71,12 @@ namespace Modbus.Net protected abstract void SendingMessageControlInner(); /// - public abstract void SendStop(); + public virtual void SendStop() + { + SendingThread.Dispose(); + SendingThread = null; + Clear(); + } /// public virtual void SendStart() diff --git a/Modbus.Net/Modbus.Net/Controller/FifoController.cs b/Modbus.Net/Modbus.Net/Controller/FifoController.cs index 79a1acb..a14b478 100644 --- a/Modbus.Net/Modbus.Net/Controller/FifoController.cs +++ b/Modbus.Net/Modbus.Net/Controller/FifoController.cs @@ -83,7 +83,7 @@ namespace Modbus.Net } } } - Clear(); + SendStop(); } /// @@ -96,8 +96,8 @@ namespace Modbus.Net /// public override void SendStop() { - Clear(); _taskCancel = true; + base.SendStop(); } /// From b6325f46ad7f78598cce4a8d08d8947f2b0e9611 Mon Sep 17 00:00:00 2001 From: luosheng Date: Tue, 18 Jul 2023 16:18:59 +0800 Subject: [PATCH 13/15] Fix --- ...torWithControllerByteArrayCodeGenerator.cs | 2 +- .../Modbus.Net/Connector/ComConnector.cs | 59 +++++++++++-------- .../Modbus.Net/Controller/BaseController.cs | 22 ++++--- .../Modbus.Net/Controller/FifoController.cs | 23 +------- .../Controller/MatchDirectlySendController.cs | 2 +- .../Modbus.Net/Interface/IController.cs | 2 +- 6 files changed, 51 insertions(+), 59 deletions(-) diff --git a/Modbus.Net/Modbus.Net.CodeGenerator/ConnectorWithControllerByteArrayCodeGenerator.cs b/Modbus.Net/Modbus.Net.CodeGenerator/ConnectorWithControllerByteArrayCodeGenerator.cs index 1eb9c69..74dcb4f 100644 --- a/Modbus.Net/Modbus.Net.CodeGenerator/ConnectorWithControllerByteArrayCodeGenerator.cs +++ b/Modbus.Net/Modbus.Net.CodeGenerator/ConnectorWithControllerByteArrayCodeGenerator.cs @@ -112,7 +112,7 @@ namespace Modbus.Net IDisposable asyncLock = null; try { - if (Controller.IsSending != true) + if (!Controller.IsSending) { Controller.SendStart(); } diff --git a/Modbus.Net/Modbus.Net/Connector/ComConnector.cs b/Modbus.Net/Modbus.Net/Connector/ComConnector.cs index a2a84af..8694a69 100644 --- a/Modbus.Net/Modbus.Net/Connector/ComConnector.cs +++ b/Modbus.Net/Modbus.Net/Connector/ComConnector.cs @@ -82,10 +82,6 @@ namespace Modbus.Net /// 获取线程 /// private Task _receiveThread; - /// - /// 获取线程关闭 - /// - private bool _taskCancel = false; /// /// 缓冲的字节流 @@ -276,23 +272,23 @@ namespace Modbus.Net // Release managed resources } // Release unmanaged resources - if (SerialPort != null) + Linkers?.Remove((_slave, _com)); + logger.LogInformation("Com connector {ConnectionToken} Removed", _com); + if (Linkers?.Count(p => p.Item2 == _com) == 0) { - Linkers.Remove((_slave, _com)); - logger.LogInformation("Com connector {ConnectionToken} Removed", _com); - if (Linkers.Count(p => p.Item2 == _com) == 0) + if (SerialPort?.IsOpen == true) + { + SerialPort?.Close(); + } + SerialPort?.Dispose(); + logger.LogInformation("Com interface {Com} Disposed", _com); + Controller?.SendStop(); + if (Connectors.ContainsKey(_com)) { - if (SerialPort.IsOpen) - { - SerialPort.Close(); - } - SerialPort.Dispose(); - logger.LogInformation("Com interface {Com} Disposed", _com); - Controller.SendStop(); Connectors[_com] = null; Connectors.Remove(_com); - ReceiveMsgThreadStop(); } + ReceiveMsgThreadStop(); } } @@ -365,7 +361,7 @@ namespace Modbus.Net { lock (SerialPort) { - _taskCancel = false; + ReceiveMsgThreadStop(); SerialPort.Open(); ReceiveMsgThreadStart(); Controller.SendStart(); @@ -496,18 +492,35 @@ namespace Modbus.Net /// protected override void ReceiveMsgThreadStart() { - _receiveThread = Task.Run(ReceiveMessage); + if (_receiveThread == null) + { + _receiveThread = Task.Run(ReceiveMessage); + } } /// protected override void ReceiveMsgThreadStop() { - _taskCancel = true; + _receiveThread?.Dispose(); + _receiveThread = null; + CacheClear(); + Controller?.Clear(); + } + + private void CacheClear() + { + if (CacheBytes != null) + { + lock (CacheBytes) + { + CacheBytes.Clear(); + } + } } private async Task ReceiveMessage() { - while (!_taskCancel) + while (true) { try { @@ -532,10 +545,7 @@ namespace Modbus.Net CacheBytes.Count); logger.LogError( $"Com client {ConnectionToken} cached msg: {string.Concat(CacheBytes.Select(p => " " + p.ToString("X2")))}"); - lock (CacheBytes) - { - CacheBytes.Clear(); - } + CacheClear(); } else { @@ -569,6 +579,7 @@ namespace Modbus.Net } catch (Exception e) { + CacheClear(); logger.LogError(e, "Com client {ConnectionToken} read msg error", ConnectionToken); } } diff --git a/Modbus.Net/Modbus.Net/Controller/BaseController.cs b/Modbus.Net/Modbus.Net/Controller/BaseController.cs index b921b62..0f6869b 100644 --- a/Modbus.Net/Modbus.Net/Controller/BaseController.cs +++ b/Modbus.Net/Modbus.Net/Controller/BaseController.cs @@ -24,7 +24,7 @@ namespace Modbus.Net /// /// Ϣά߳Ƿ /// - public virtual bool? IsSending => SendingThread?.Status == TaskStatus.Running || SendingThread?.Status == TaskStatus.WaitingToRun || SendingThread?.Status == TaskStatus.Created; + public virtual bool IsSending => SendingThread != null; /// /// зλú @@ -73,7 +73,8 @@ namespace Modbus.Net /// public virtual void SendStop() { - SendingThread.Dispose(); + Clear(); + SendingThread?.Dispose(); SendingThread = null; Clear(); } @@ -81,7 +82,7 @@ namespace Modbus.Net /// public virtual void SendStart() { - if (IsSending != true) + if (!IsSending) { SendingThread = Task.Run(() => SendingMessageControlInner()); } @@ -90,9 +91,12 @@ namespace Modbus.Net /// public void Clear() { - lock (WaitingMessages) + if (WaitingMessages != null) { - WaitingMessages.Clear(); + lock (WaitingMessages) + { + WaitingMessages.Clear(); + } } } @@ -196,13 +200,7 @@ namespace Modbus.Net if (def != null) { def.ReceiveMessage = message.Item1; - lock (WaitingMessages) - { - if (WaitingMessages.IndexOf(def) >= 0) - { - WaitingMessages.Remove(def); - } - } + ForceRemoveWaitingMessage(def); def.ReceiveMutex.Set(); ans.Add((message.Item1, true)); } diff --git a/Modbus.Net/Modbus.Net/Controller/FifoController.cs b/Modbus.Net/Modbus.Net/Controller/FifoController.cs index a14b478..592d3eb 100644 --- a/Modbus.Net/Modbus.Net/Controller/FifoController.cs +++ b/Modbus.Net/Modbus.Net/Controller/FifoController.cs @@ -14,8 +14,6 @@ namespace Modbus.Net private MessageWaitingDef _currentSendingPos; - private bool _taskCancel = false; - private int _waitingListMaxCount; /// @@ -40,7 +38,7 @@ namespace Modbus.Net /// protected override void SendingMessageControlInner() { - while (!_taskCancel) + while (true) { if (AcquireTime > 0) { @@ -79,25 +77,10 @@ namespace Modbus.Net catch (Exception e) { logger.LogError(e, "Controller throws exception"); - _taskCancel = true; + SendStop(); } } } - SendStop(); - } - - /// - public override void SendStart() - { - _taskCancel = false; - base.SendStart(); - } - - /// - public override void SendStop() - { - _taskCancel = true; - base.SendStop(); } /// @@ -124,7 +107,7 @@ namespace Modbus.Net { return false; } - if (_taskCancel) + if (!IsSending) { return false; } diff --git a/Modbus.Net/Modbus.Net/Controller/MatchDirectlySendController.cs b/Modbus.Net/Modbus.Net/Controller/MatchDirectlySendController.cs index 7401a7c..b6e1627 100644 --- a/Modbus.Net/Modbus.Net/Controller/MatchDirectlySendController.cs +++ b/Modbus.Net/Modbus.Net/Controller/MatchDirectlySendController.cs @@ -11,7 +11,7 @@ namespace Modbus.Net /// /// 消息维护线程是否在运行 /// - public override bool? IsSending => true; + public override bool IsSending => true; /// public MatchDirectlySendController(ICollection<(int, int)>[] keyMatches, diff --git a/Modbus.Net/Modbus.Net/Interface/IController.cs b/Modbus.Net/Modbus.Net/Interface/IController.cs index c3fd62e..2cb9431 100644 --- a/Modbus.Net/Modbus.Net/Interface/IController.cs +++ b/Modbus.Net/Modbus.Net/Interface/IController.cs @@ -10,7 +10,7 @@ namespace Modbus.Net /// /// Ϣά߳Ƿ /// - bool? IsSending { get; } + bool IsSending { get; } /// /// Ϣ From af40306be819a4d1eafc653e0b0c1506ac3b5dfe Mon Sep 17 00:00:00 2001 From: luosheng Date: Tue, 18 Jul 2023 22:08:38 +0800 Subject: [PATCH 14/15] Fix --- .../Modbus.Net/Connector/ComConnector.cs | 49 +++++++++++++++---- .../Modbus.Net/Controller/BaseController.cs | 33 +++++++++++-- .../Modbus.Net/Controller/FifoController.cs | 6 ++- .../Controller/MatchDirectlySendController.cs | 3 +- 4 files changed, 74 insertions(+), 17 deletions(-) diff --git a/Modbus.Net/Modbus.Net/Connector/ComConnector.cs b/Modbus.Net/Modbus.Net/Connector/ComConnector.cs index 8694a69..5a149f7 100644 --- a/Modbus.Net/Modbus.Net/Connector/ComConnector.cs +++ b/Modbus.Net/Modbus.Net/Connector/ComConnector.cs @@ -83,6 +83,11 @@ namespace Modbus.Net /// private Task _receiveThread; + /// + /// 终止获取线程 + /// + private CancellationTokenSource _receiveThreadCancel; + /// /// 缓冲的字节流 /// @@ -272,6 +277,8 @@ namespace Modbus.Net // Release managed resources } // Release unmanaged resources + Controller?.SendStop(); + ReceiveMsgThreadStop(); Linkers?.Remove((_slave, _com)); logger.LogInformation("Com connector {ConnectionToken} Removed", _com); if (Linkers?.Count(p => p.Item2 == _com) == 0) @@ -281,14 +288,12 @@ namespace Modbus.Net SerialPort?.Close(); } SerialPort?.Dispose(); - logger.LogInformation("Com interface {Com} Disposed", _com); - Controller?.SendStop(); + logger.LogInformation("Com interface {Com} Disposed", _com); if (Connectors.ContainsKey(_com)) { Connectors[_com] = null; Connectors.Remove(_com); - } - ReceiveMsgThreadStop(); + } } } @@ -479,7 +484,7 @@ namespace Modbus.Net message.Length); logger.LogDebug( $"Com client {ConnectionToken} send msg: {String.Concat(message.Select(p => " " + p.ToString("X2")))}"); - await Task.Run(() => SerialPort.Write(message, 0, message.Length)); + await Task.Run(() => SerialPort?.Write(message, 0, message.Length)); } catch (Exception err) { @@ -490,19 +495,39 @@ namespace Modbus.Net } /// - protected override void ReceiveMsgThreadStart() + protected override async void ReceiveMsgThreadStart() { if (_receiveThread == null) { - _receiveThread = Task.Run(ReceiveMessage); + _receiveThreadCancel = new CancellationTokenSource(); + _receiveThread = Task.Run(async ()=>await ReceiveMessage(_receiveThreadCancel.Token), _receiveThreadCancel.Token); + try + { + await _receiveThread; + } + catch (OperationCanceledException) + { } + finally + { + _receiveThreadCancel.Dispose(); + _receiveThreadCancel = null; + } } } /// protected override void ReceiveMsgThreadStop() { - _receiveThread?.Dispose(); - _receiveThread = null; + _receiveThreadCancel?.Cancel(); + if (_receiveThread != null) + { + while (!_receiveThread.IsCanceled) + { + Thread.Sleep(10); + } + _receiveThread.Dispose(); + _receiveThread = null; + } CacheClear(); Controller?.Clear(); } @@ -518,7 +543,7 @@ namespace Modbus.Net } } - private async Task ReceiveMessage() + private async Task ReceiveMessage(CancellationToken token) { while (true) { @@ -582,6 +607,10 @@ namespace Modbus.Net CacheClear(); logger.LogError(e, "Com client {ConnectionToken} read msg error", ConnectionToken); } + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } } } diff --git a/Modbus.Net/Modbus.Net/Controller/BaseController.cs b/Modbus.Net/Modbus.Net/Controller/BaseController.cs index 0f6869b..bf784f6 100644 --- a/Modbus.Net/Modbus.Net/Controller/BaseController.cs +++ b/Modbus.Net/Modbus.Net/Controller/BaseController.cs @@ -1,3 +1,4 @@ +using Quartz.Logging; using System; using System.Collections.Generic; using System.Linq; @@ -26,6 +27,8 @@ namespace Modbus.Net /// public virtual bool IsSending => SendingThread != null; + private CancellationTokenSource _sendingThreadCancel; + /// /// зλú /// @@ -68,23 +71,43 @@ namespace Modbus.Net /// /// Ϣʵڲ /// - protected abstract void SendingMessageControlInner(); + protected abstract void SendingMessageControlInner(CancellationToken token); /// public virtual void SendStop() { Clear(); - SendingThread?.Dispose(); - SendingThread = null; + _sendingThreadCancel?.Cancel(); + if (SendingThread != null) + { + while (!SendingThread.IsCanceled) + { + Thread.Sleep(10); + } + SendingThread.Dispose(); + SendingThread = null; + } Clear(); } /// - public virtual void SendStart() + public virtual async void SendStart() { if (!IsSending) { - SendingThread = Task.Run(() => SendingMessageControlInner()); + _sendingThreadCancel = new CancellationTokenSource(); + SendingThread = Task.Run(() => SendingMessageControlInner(_sendingThreadCancel.Token), _sendingThreadCancel.Token); + try + { + await SendingThread; + } + catch (OperationCanceledException) + { } + finally + { + _sendingThreadCancel.Dispose(); + _sendingThreadCancel = null; + } } } diff --git a/Modbus.Net/Modbus.Net/Controller/FifoController.cs b/Modbus.Net/Modbus.Net/Controller/FifoController.cs index 592d3eb..1e1f042 100644 --- a/Modbus.Net/Modbus.Net/Controller/FifoController.cs +++ b/Modbus.Net/Modbus.Net/Controller/FifoController.cs @@ -36,7 +36,7 @@ namespace Modbus.Net } /// - protected override void SendingMessageControlInner() + protected override void SendingMessageControlInner(CancellationToken token) { while (true) { @@ -80,6 +80,10 @@ namespace Modbus.Net SendStop(); } } + if (token.IsCancellationRequested) + { + token.ThrowIfCancellationRequested(); + } } } diff --git a/Modbus.Net/Modbus.Net/Controller/MatchDirectlySendController.cs b/Modbus.Net/Modbus.Net/Controller/MatchDirectlySendController.cs index b6e1627..73810d9 100644 --- a/Modbus.Net/Modbus.Net/Controller/MatchDirectlySendController.cs +++ b/Modbus.Net/Modbus.Net/Controller/MatchDirectlySendController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading; namespace Modbus.Net { @@ -32,7 +33,7 @@ namespace Modbus.Net } /// - protected override void SendingMessageControlInner() + protected override void SendingMessageControlInner(CancellationToken token) { //empty } From deea4373d5e2814e2f24e9db6b8114cbdfc960d9 Mon Sep 17 00:00:00 2001 From: luosheng Date: Thu, 20 Jul 2023 09:39:47 +0800 Subject: [PATCH 15/15] Version Up --- .../Modbus.Net.BigEndian3412.csproj | 2 +- .../Modbus.Net.CodeGenerator.csproj | 2 +- Modbus.Net/Modbus.Net.HJ212/Modbus.Net.HJ212.csproj | 2 +- .../Modbus.Net.Modbus.NA200H.csproj | 2 +- .../Modbus.Net.Modbus.SelfDefinedSample.csproj | 2 +- .../Modbus.Net.Modbus/Modbus.Net.Modbus.csproj | 2 +- Modbus.Net/Modbus.Net.Opc/Modbus.Net.Opc.csproj | 2 +- .../Modbus.Net.Siemens/Modbus.Net.Siemens.csproj | 2 +- Modbus.Net/Modbus.Net/Modbus.Net.csproj | 9 +++------ .../MachineJob.CodeGenerator.csproj | 2 +- Samples/MachineJob/MachineJob.csproj | 12 +++++------- Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj | 11 +++++++---- 12 files changed, 24 insertions(+), 26 deletions(-) diff --git a/Modbus.Net/Modbus.Net.BigEndian3412/Modbus.Net.BigEndian3412.csproj b/Modbus.Net/Modbus.Net.BigEndian3412/Modbus.Net.BigEndian3412.csproj index 56b1cf7..744e140 100644 --- a/Modbus.Net/Modbus.Net.BigEndian3412/Modbus.Net.BigEndian3412.csproj +++ b/Modbus.Net/Modbus.Net.BigEndian3412/Modbus.Net.BigEndian3412.csproj @@ -6,7 +6,7 @@ Modbus.Net.BigEndian3412 Modbus.Net.BigEndian3412 Modbus.Net.BigEndian3412 - 1.4.2 + 1.4.3 Chris L.(Luo Sheng) Hangzhou Delian Science Technology Co.,Ltd. Modbus.Net.Modbus diff --git a/Modbus.Net/Modbus.Net.CodeGenerator/Modbus.Net.CodeGenerator.csproj b/Modbus.Net/Modbus.Net.CodeGenerator/Modbus.Net.CodeGenerator.csproj index bdad474..e9041c6 100644 --- a/Modbus.Net/Modbus.Net.CodeGenerator/Modbus.Net.CodeGenerator.csproj +++ b/Modbus.Net/Modbus.Net.CodeGenerator/Modbus.Net.CodeGenerator.csproj @@ -8,7 +8,7 @@ - + diff --git a/Modbus.Net/Modbus.Net.HJ212/Modbus.Net.HJ212.csproj b/Modbus.Net/Modbus.Net.HJ212/Modbus.Net.HJ212.csproj index 1b05333..306c693 100644 --- a/Modbus.Net/Modbus.Net.HJ212/Modbus.Net.HJ212.csproj +++ b/Modbus.Net/Modbus.Net.HJ212/Modbus.Net.HJ212.csproj @@ -6,7 +6,7 @@ Modbus.Net.HJ212 Modbus.Net.HJ212 Modbus.Net.HJ212 - 1.4.2 + 1.4.3 Chris L.(Luo Sheng) Hangzhou Delian Science Technology Co.,Ltd. Modbus.Net.HJ212 diff --git a/Modbus.Net/Modbus.Net.Modbus.NA200H/Modbus.Net.Modbus.NA200H.csproj b/Modbus.Net/Modbus.Net.Modbus.NA200H/Modbus.Net.Modbus.NA200H.csproj index 1587249..b023755 100644 --- a/Modbus.Net/Modbus.Net.Modbus.NA200H/Modbus.Net.Modbus.NA200H.csproj +++ b/Modbus.Net/Modbus.Net.Modbus.NA200H/Modbus.Net.Modbus.NA200H.csproj @@ -6,7 +6,7 @@ Modbus.Net.Modbus.NA200H Modbus.Net.Modbus.NA200H Modbus.Net.Modbus.NA200H - 1.4.2 + 1.4.3 Chris L.(Luo Sheng) Hangzhou Delian Science Technology Co.,Ltd. Modbus.Net.Modbus diff --git a/Modbus.Net/Modbus.Net.Modbus.SelfDefinedSample/Modbus.Net.Modbus.SelfDefinedSample.csproj b/Modbus.Net/Modbus.Net.Modbus.SelfDefinedSample/Modbus.Net.Modbus.SelfDefinedSample.csproj index feb9f26..d53a0e3 100644 --- a/Modbus.Net/Modbus.Net.Modbus.SelfDefinedSample/Modbus.Net.Modbus.SelfDefinedSample.csproj +++ b/Modbus.Net/Modbus.Net.Modbus.SelfDefinedSample/Modbus.Net.Modbus.SelfDefinedSample.csproj @@ -6,7 +6,7 @@ Modbus.Net.Modbus.SelfDefinedSample Modbus.Net.Modbus.SelfDefinedSample Modbus.Net.Modbus.SelfDefinedSample - 1.4.2 + 1.4.3 Chris L.(Luo Sheng) Hangzhou Delian Science Technology Co.,Ltd. Modbus.Net.Modbus diff --git a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj index 1e0e453..f75da4b 100644 --- a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj +++ b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj @@ -6,7 +6,7 @@ Modbus.Net.Modbus Modbus.Net.Modbus Modbus.Net.Modbus - 1.4.2 + 1.4.3 Chris L.(Luo Sheng) Hangzhou Delian Science Technology Co.,Ltd. Modbus.Net.Modbus diff --git a/Modbus.Net/Modbus.Net.Opc/Modbus.Net.Opc.csproj b/Modbus.Net/Modbus.Net.Opc/Modbus.Net.Opc.csproj index e8d15dc..9068345 100644 --- a/Modbus.Net/Modbus.Net.Opc/Modbus.Net.Opc.csproj +++ b/Modbus.Net/Modbus.Net.Opc/Modbus.Net.Opc.csproj @@ -6,7 +6,7 @@ Modbus.Net.Opc Modbus.Net.Opc Modbus.Net.Opc - 1.4.2 + 1.4.3 Chris L.(Luo Sheng) Hangzhou Delian Science Technology Co.,Ltd. Modbus.Net.Opc diff --git a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj index 3ef6ebb..6cb3fd7 100644 --- a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj +++ b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj @@ -6,7 +6,7 @@ Modbus.Net.Siemens Modbus.Net.Siemens Modbus.Net.Siemens - 1.4.2 + 1.4.3 Chris L.(Luo Sheng) Hangzhou Delian Science Technology Co.,Ltd. Modbus.Net Siemens Profinet Implementation diff --git a/Modbus.Net/Modbus.Net/Modbus.Net.csproj b/Modbus.Net/Modbus.Net/Modbus.Net.csproj index 8a21188..0be88e2 100644 --- a/Modbus.Net/Modbus.Net/Modbus.Net.csproj +++ b/Modbus.Net/Modbus.Net/Modbus.Net.csproj @@ -6,7 +6,7 @@ Modbus.Net Modbus.Net Modbus.Net - 1.4.2 + 1.4.3 Modbus.Net Chris L.(Luo Sheng) Hangzhou Delian Science Technology Co.,Ltd. @@ -40,9 +40,8 @@ - + - @@ -50,8 +49,6 @@ - + \ No newline at end of file diff --git a/Samples/MachineJob.CodeGenerator/MachineJob.CodeGenerator.csproj b/Samples/MachineJob.CodeGenerator/MachineJob.CodeGenerator.csproj index f9fd585..7ae8fe2 100644 --- a/Samples/MachineJob.CodeGenerator/MachineJob.CodeGenerator.csproj +++ b/Samples/MachineJob.CodeGenerator/MachineJob.CodeGenerator.csproj @@ -8,7 +8,7 @@ - + diff --git a/Samples/MachineJob/MachineJob.csproj b/Samples/MachineJob/MachineJob.csproj index 0cadf32..70fedb1 100644 --- a/Samples/MachineJob/MachineJob.csproj +++ b/Samples/MachineJob/MachineJob.csproj @@ -8,16 +8,16 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive true - + - - + + @@ -27,8 +27,6 @@ - + diff --git a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj index 2c3705c..807224c 100644 --- a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj +++ b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj @@ -22,10 +22,13 @@ - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive +