diff --git a/Common/Common.csproj b/Common/Common.csproj index 132c02c..b0b334f 100644 --- a/Common/Common.csproj +++ b/Common/Common.csproj @@ -1,9 +1,17 @@ - net6.0 enable enable + net6.0;net6.0-windows + + + + bin\Debug\Common.xml + + + + bin\Release\Common.xml diff --git a/Entity/Entity.csproj b/Entity/Entity.csproj index 8240d3f..2e60141 100644 --- a/Entity/Entity.csproj +++ b/Entity/Entity.csproj @@ -1,16 +1,20 @@  - net6.0 enable enable True + net6.0;net6.0-windows bin\Debug\Entity.xml + + bin\Release\Entity.xml + + diff --git a/HybirdFrameworkCore/HybirdFrameworkCore.csproj b/HybirdFrameworkCore/HybirdFrameworkCore.csproj index f8142b8..6918063 100644 --- a/HybirdFrameworkCore/HybirdFrameworkCore.csproj +++ b/HybirdFrameworkCore/HybirdFrameworkCore.csproj @@ -1,10 +1,10 @@ - net6.0 enable enable True + net6.0;net6.0-windows diff --git a/HybirdFrameworkCore/Utils/BitUtls.cs b/HybirdFrameworkCore/Utils/BitUtls.cs index ba47b50..66e21a5 100644 --- a/HybirdFrameworkCore/Utils/BitUtls.cs +++ b/HybirdFrameworkCore/Utils/BitUtls.cs @@ -224,12 +224,12 @@ public static class BitUtls { if (length < 17) { - int d = Byte2Int16(bytes, startBit, length); + int d = Byte2UInt16(bytes, startBit, length); return (float)(d * factor); } else { - var d = Byte2Int32(bytes, startBit, length); + var d = Byte2UInt32(bytes, startBit, length); return (float)(d * factor); } } diff --git a/HybirdFrameworkCore/obj/HybirdFrameworkCore.csproj.nuget.g.targets b/HybirdFrameworkCore/obj/HybirdFrameworkCore.csproj.nuget.g.targets index 5f4a838..c84dc1b 100644 --- a/HybirdFrameworkCore/obj/HybirdFrameworkCore.csproj.nuget.g.targets +++ b/HybirdFrameworkCore/obj/HybirdFrameworkCore.csproj.nuget.g.targets @@ -1,6 +1,9 @@  - + + + + \ No newline at end of file diff --git a/HybirdFrameworkDriver/Common/MsgCache.cs b/HybirdFrameworkDriver/Common/MsgCache.cs new file mode 100644 index 0000000..79dec65 --- /dev/null +++ b/HybirdFrameworkDriver/Common/MsgCache.cs @@ -0,0 +1,83 @@ +using System.Collections.Concurrent; + +namespace HybirdFrameworkDriver.Common; + +public class MsgCache +{ + private readonly ConcurrentDictionary> _dictionary = new(); + private static readonly string MsgKey = "msg_"; + + public void Add(string key, dynamic value) + { + _dictionary[key] = value; + } + + public bool TryGet(string key, out MsgPair? value) + { + return _dictionary.TryGetValue(key, out value); + } + + public void Remove(string key) + { + _dictionary.Remove(key, out var value); + } + + public void AddByMsgId(int key, MsgPair value) + { + _dictionary[MsgKey + key] = value; + } + + public bool TryGetMsgId(int key, out MsgPair? value) + { + return _dictionary.TryGetValue(MsgKey + key, out value); + } + + public void RemoveMsgId(int key) + { + _dictionary.Remove(MsgKey + key, out var value); + } +} + +public class MsgPair +{ + private readonly ManualResetEvent _lock = new(false); + private TReq? _req; + + public TReq? Req + { + get => _req; + set + { + _req = value; + ClearResp(); + } + } + + private TResp? _resp; + + public void ClearResp() + { + _resp = default; + } + + public void SetResp(TResp? resp) + { + _resp = resp; + _lock.Set(); + _lock.Reset(); + } + + public TResp? GetResp(TimeSpan? timeSpan = default) + { + if (timeSpan != null) + { + _lock.WaitOne(timeSpan.Value); + } + else + { + _lock.WaitOne(); + } + + return _resp; + } +} \ No newline at end of file diff --git a/HybirdFrameworkDriver/HybirdFrameworkDriver.csproj b/HybirdFrameworkDriver/HybirdFrameworkDriver.csproj index 310ba74..ec80420 100644 --- a/HybirdFrameworkDriver/HybirdFrameworkDriver.csproj +++ b/HybirdFrameworkDriver/HybirdFrameworkDriver.csproj @@ -1,15 +1,19 @@ - net6.0 enable enable + net6.0;net6.0-windows bin\Debug\HybirdFrameworkDriver.xml + + bin\Release\HybirdFrameworkDriver.xml + + diff --git a/HybirdFrameworkDriver/ModbusTcpMaster/ModbusTcpMaster.cs b/HybirdFrameworkDriver/ModbusTcpMaster/ModbusTcpMaster.cs index e4ad4aa..2787bca 100644 --- a/HybirdFrameworkDriver/ModbusTcpMaster/ModbusTcpMaster.cs +++ b/HybirdFrameworkDriver/ModbusTcpMaster/ModbusTcpMaster.cs @@ -12,7 +12,7 @@ public class ModbusTcpMaster private static readonly ILog Log = LogManager.GetLogger(typeof(ModbusTcpMaster)); - private ModbusTcpNet ModbusTcpNet; + private ModbusTcpNet? ModbusTcpNet; public string Ip { get; set; } = "127.0.0.1"; @@ -23,6 +23,11 @@ public class ModbusTcpMaster public int Duration { get; set; } = 1000; public bool Connected { get; set; } + /// + /// 自动重连开关 + /// + public bool AutoReConnect { get; set; } + public string connectId { get; set; } public MyReadAction? ReadAction { get; set; } @@ -36,8 +41,8 @@ public class ModbusTcpMaster public bool Connect() { + Thread.Sleep(Duration); GetLog().Info($"begin to connect {Ip}:{Port}"); - try { if (ModbusTcpNet == null) @@ -55,12 +60,20 @@ public class ModbusTcpMaster else { GetLog().Info($"connect {Ip}:{Port} failed {result.Message}"); + if (AutoReConnect) + { + return Connect(); + } } } } catch (Exception e) { GetLog().Error($"connect {Ip}:{Port} exception {e.Message}"); + if (AutoReConnect) + { + return Connect(); + } } return Connected; @@ -112,7 +125,7 @@ public class ModbusTcpMaster return null; } - public byte[]? BatchRead(int registerNo, int length) + public byte[]? BatchReadHolderRegister(int registerNo, int length) { OperateResult result = ModbusTcpNet.Read("x=3;" + registerNo, (ushort)length); if (result.IsSuccess) return result.Content; @@ -120,6 +133,58 @@ public class ModbusTcpMaster return null; } + public byte[]? BatchReadInputRegister(int registerNo, int length) + { + OperateResult result = ModbusTcpNet.Read("x=4;" + registerNo, (ushort)length); + if (result.IsSuccess) return result.Content; + + return null; + } + + /// + /// 读取线圈,需要指定起始地址,如果富文本地址不指定,默认使用的功能码是 0x01
+ /// To read the coil, you need to specify the start address. If the rich text address is not specified, the default function code is 0x01. + ///
+ /// 起始地址,格式为"1234" + /// 带有成功标志的bool对象 + public OperateResult ReadCoil(string address) => ModbusTcpNet.ReadBool(address); + + /// + /// 批量的读取线圈,需要指定起始地址,读取长度,如果富文本地址不指定,默认使用的功能码是 0x01
+ /// For batch reading coils, you need to specify the start address and read length. If the rich text address is not specified, the default function code is 0x01. + ///
+ /// 起始地址,格式为"1234" + /// 读取长度 + /// 带有成功标志的bool数组对象 + public OperateResult ReadCoil(string address, ushort length) + { + return ModbusTcpNet.ReadBool(address, length); + } + + /// + /// 读取输入线圈,需要指定起始地址,如果富文本地址不指定,默认使用的功能码是 0x02
+ /// To read the input coil, you need to specify the start address. If the rich text address is not specified, the default function code is 0x02. + ///
+ /// 起始地址,格式为"1234" + /// 带有成功标志的bool对象 + public OperateResult ReadDiscrete(string address) + { + return ModbusTcpNet.ReadDiscrete(address); + } + + /// + /// 批量的读取输入点,需要指定起始地址,读取长度,如果富文本地址不指定,默认使用的功能码是 0x02
+ /// To read input points in batches, you need to specify the start address and read length. If the rich text address is not specified, the default function code is 0x02 + ///
+ /// 起始地址,格式为"1234" + /// 读取长度 + /// 带有成功标志的bool数组对象 + public OperateResult ReadDiscrete(string address, ushort length) + { + return ModbusTcpNet.ReadDiscrete(address, length); + } + + public bool WriteValue(ModbusProperty property) { var value = property.Value; diff --git a/HybirdFrameworkDriver/Session/ModbusSession.cs b/HybirdFrameworkDriver/Session/ModbusSession.cs index 627c1b1..da750de 100644 --- a/HybirdFrameworkDriver/Session/ModbusSession.cs +++ b/HybirdFrameworkDriver/Session/ModbusSession.cs @@ -30,6 +30,6 @@ public class ModbusSession public byte[]? Read(int registerNo, int length) { - return ModbusTcpMaster.BatchRead(registerNo, length); + return ModbusTcpMaster.BatchReadHolderRegister(registerNo, length); } } \ No newline at end of file diff --git a/HybirdFrameworkDriver/TcpServer/TcpServer.cs b/HybirdFrameworkDriver/TcpServer/TcpServer.cs index 5afc53b..0faa7a8 100644 --- a/HybirdFrameworkDriver/TcpServer/TcpServer.cs +++ b/HybirdFrameworkDriver/TcpServer/TcpServer.cs @@ -2,6 +2,7 @@ using Autofac; using Autofac.Core; using DotNetty.Codecs; +using DotNetty.Common.Internal.Logging; using DotNetty.Handlers.Logging; using DotNetty.Handlers.Timeout; using DotNetty.Transport.Bootstrapping; @@ -10,6 +11,8 @@ using DotNetty.Transport.Channels.Sockets; using HybirdFrameworkCore.Autofac; using HybirdFrameworkCore.Autofac.Attribute; using log4net; +using Microsoft.Extensions.Logging; +using LogLevel = DotNetty.Handlers.Logging.LogLevel; namespace HybirdFrameworkDriver.TcpServer; @@ -27,9 +30,15 @@ public class TcpServer : IDisposable where TH : IChannelHandler private static ServerBootstrap? bootstrap; private int _port = 9000; + + public LogLevel? LogLevel { get; set; } public TcpServer() { + if (LogLevel != null) + { + InternalLoggerFactory.DefaultFactory.AddProvider(new Log4NetProvider()); + } bossGroup = new MultithreadEventLoopGroup(); workerGroup = new MultithreadEventLoopGroup(); bootstrap = new ServerBootstrap(); @@ -42,7 +51,10 @@ public class TcpServer : IDisposable where TH : IChannelHandler { var serverListenerHandler = new ServerListenerHandler(); var pipeline = channel.Pipeline; - pipeline.AddLast(new LoggingHandler("")); + if (LogLevel != null) + { + pipeline.AddLast(new LoggingHandler(LogLevel.Value)); + } pipeline.AddLast(serverListenerHandler); pipeline.AddLast(new IdleStateHandler(0, 0, 180)); //检测空闲连接 //业务handler ,这里是实际处理业务的Handler diff --git a/Repository/Repository.csproj b/Repository/Repository.csproj index 4121957..4da72d6 100644 --- a/Repository/Repository.csproj +++ b/Repository/Repository.csproj @@ -1,15 +1,19 @@ - net6.0 enable enable + net6.0;net6.0-windows bin\Debug\Repository.xml + + bin\Release\Repository.xml + + diff --git a/Service/Service.csproj b/Service/Service.csproj index 4ef4ff9..a9f9122 100644 --- a/Service/Service.csproj +++ b/Service/Service.csproj @@ -1,15 +1,19 @@  - net6.0 enable enable + net6.0;net6.0-windows bin\Debug\Service.xml + + bin\Release\Service.xml + +