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 @@ +