diff --git a/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs b/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs index ca56811..0b7d66a 100644 --- a/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs +++ b/Modbus.Net/Modbus.Net.OPC/OpcProtocal.cs @@ -65,7 +65,8 @@ /// /// 读数据协议 /// - public class ReadRequestOpcProtocal : ProtocalUnit, ISpecialProtocalUnit + [SpecialProtocalUnit] + public class ReadRequestOpcProtocal : ProtocalUnit { /// /// 从对象的参数数组格式化 @@ -156,7 +157,8 @@ /// /// 写数据协议 /// - public class WriteRequestOpcProtocal : ProtocalUnit, ISpecialProtocalUnit + [SpecialProtocalUnit] + public class WriteRequestOpcProtocal : ProtocalUnit { /// /// 从对象的参数数组格式化 diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs index 5a08905..d40729f 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs @@ -146,7 +146,8 @@ namespace Modbus.Net.Siemens public byte ConfirmMessage { get; set; } } - internal class ComCreateReferenceSiemensProtocal : ProtocalUnit, ISpecialProtocalUnit + [SpecialProtocalUnit] + internal class ComCreateReferenceSiemensProtocal : ProtocalUnit { public override byte[] Format(IInputStruct message) { @@ -200,7 +201,8 @@ namespace Modbus.Net.Siemens public ushort TsapDst { get; } } - internal class CreateReferenceSiemensProtocal : ProtocalUnit, ISpecialProtocalUnit + [SpecialProtocalUnit] + internal class CreateReferenceSiemensProtocal : ProtocalUnit { public override byte[] Format(IInputStruct message) { @@ -306,7 +308,8 @@ namespace Modbus.Net.Siemens /// /// 串口消息确认协议 /// - public class ComConfirmMessageSiemensProtocal : ProtocalUnit, ISpecialProtocalUnit + [SpecialProtocalUnit] + public class ComConfirmMessageSiemensProtocal : ProtocalUnit { /// /// 格式化 diff --git a/Modbus.Net/Modbus.Net/README.md b/Modbus.Net/Modbus.Net/README.md index f096d6d..b0b2ddd 100644 --- a/Modbus.Net/Modbus.Net/README.md +++ b/Modbus.Net/Modbus.Net/README.md @@ -394,10 +394,11 @@ public class ReadDataModbusProtocal : ProtocalUnit } } ``` -There is another interface called ISpecialProtocalUnit. -If you add ISpecialProtocalUnit to ProtocalUnit, then the protocal will not run BytesExtend and BytesDecact. +There is another attribute called SpecialProtocalUnitAttribute. +If you add SpecialProtocalUnitAttribute to ProtocalUnit, then the protocal will not run BytesExtend and BytesDecact. ```C# -internal class CreateReferenceSiemensProtocal : ProtocalUnit, ISpecialProtocalUnit +[SpecialProtocalUnit] +internal class CreateReferenceSiemensProtocal : ProtocalUnit { ... } diff --git a/Modbus.Net/src/Base.Common/BaseProtocal.cs b/Modbus.Net/src/Base.Common/BaseProtocal.cs index c31b6ce..0f7acfb 100644 --- a/Modbus.Net/src/Base.Common/BaseProtocal.cs +++ b/Modbus.Net/src/Base.Common/BaseProtocal.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Threading.Tasks; @@ -37,7 +38,8 @@ namespace Modbus.Net /// 基本协议 /// public abstract class BaseProtocal : - IProtocal where TProtocalUnit : ProtocalUnit + IProtocal where TProtocalUnit : class, IProtocalFormatting + where TParamOut : class { /// /// 构造器 @@ -66,9 +68,9 @@ namespace Modbus.Net public byte MasterAddress { get; set; } /// - /// 协议的连接器 + /// 协议集合 /// - public ProtocalLinker ProtocalLinker { get; protected set; } + protected Dictionary Protocals { get; } /// /// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议 @@ -84,7 +86,9 @@ namespace Modbus.Net lock (Protocals) { if (Protocals.ContainsKey(protocalName)) + { protocalUnitReturn = Protocals[protocalName]; + } else { //自动寻找存在的协议并将其加载 @@ -94,16 +98,39 @@ namespace Modbus.Net throw new InvalidCastException($"No ProtocalUnit {nameof(TProtocalUnit)} implemented"); protocalUnit.Endian = Endian; Register(protocalUnit); - } + } } return protocalUnitReturn ?? Protocals[protocalName]; } } /// - /// 协议集合 + /// 协议的连接器 /// - protected Dictionary Protocals { get; } + public IProtocalLinker ProtocalLinker { get; protected set; } + + /// + /// 协议连接开始 + /// + /// + public abstract bool Connect(); + + /// + /// 协议连接开始(异步) + /// + /// + public abstract Task ConnectAsync(); + + /// + /// 协议连接断开 + /// + /// + public virtual bool Disconnect() + { + if (ProtocalLinker != null) + return ProtocalLinker.Disconnect(); + return false; + } /// /// 发送协议,通过传入需要使用的协议内容和输入结构 @@ -132,31 +159,21 @@ namespace Modbus.Net /// /// 写入的内容,使用对象数组描述 /// 从设备获取的字节流 - public virtual byte[] SendReceive(params object[] content) + public virtual TParamOut SendReceive(params object[] content) { return AsyncHelper.RunSync(() => SendReceiveAsync(content)); } /// - /// 发送协议内容并接收,一般方法 + /// 发送协议内容并接收,一般方法(不能使用,如需使用请继承) /// /// 写入的内容,使用对象数组描述 /// 从设备获取的字节流 - public virtual Task SendReceiveAsync(params object[] content) + public virtual Task SendReceiveAsync(params object[] content) { throw new NotImplementedException(); } - /// - /// 注册一个协议 - /// - /// 需要注册的协议 - protected void Register(TProtocalUnit linkProtocal) - { - if (linkProtocal == null) return; - Protocals.Add(linkProtocal.GetType().FullName, linkProtocal); - } - /// /// 发送协议,通过传入需要使用的协议内容和输入结构 /// @@ -185,7 +202,7 @@ namespace Modbus.Net { TParamOut receiveContent; //如果为特别处理协议的话,跳过协议扩展收缩 - if (unit is ISpecialProtocalUnit) + if (unit.GetType().GetTypeInfo().GetCustomAttributes(typeof(SpecialProtocalUnitAttribute)).Any()) receiveContent = await ProtocalLinker.SendReceiveWithoutExtAndDecAsync(formatContent); else receiveContent = await ProtocalLinker.SendReceiveAsync(formatContent); @@ -196,26 +213,13 @@ namespace Modbus.Net } /// - /// 协议连接开始 + /// 注册一个协议 /// - /// - public abstract bool Connect(); - - /// - /// 协议连接开始(异步) - /// - /// - public abstract Task ConnectAsync(); - - /// - /// 协议连接断开 - /// - /// - public virtual bool Disconnect() + /// 需要注册的协议 + protected void Register(TProtocalUnit linkProtocal) { - if (ProtocalLinker != null) - return ProtocalLinker.Disconnect(); - return false; + if (linkProtocal == null) return; + Protocals.Add(linkProtocal.GetType().FullName, linkProtocal); } } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/BaseUtility.cs b/Modbus.Net/src/Base.Common/BaseUtility.cs index ddb7331..fb1cd9b 100644 --- a/Modbus.Net/src/Base.Common/BaseUtility.cs +++ b/Modbus.Net/src/Base.Common/BaseUtility.cs @@ -44,12 +44,12 @@ namespace Modbus.Net /// 基础Api入口 /// public abstract class BaseUtility : IUtilityProperty, IUtilityMethodData - where TProtocalUnit : ProtocalUnit + where TProtocalUnit : class, IProtocalFormatting where TParamOut : class { /// /// 协议收发主体 /// - protected BaseProtocal Wrapper; + protected IProtocal Wrapper; /// /// 构造器 diff --git a/Modbus.Net/src/Base.Common/IProtocal.cs b/Modbus.Net/src/Base.Common/IProtocal.cs index 2bb48bd..0739ee7 100644 --- a/Modbus.Net/src/Base.Common/IProtocal.cs +++ b/Modbus.Net/src/Base.Common/IProtocal.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; namespace Modbus.Net { @@ -8,22 +9,52 @@ namespace Modbus.Net /// 向Connector传入的类型 /// 从Connector返回的类型 /// 协议单元的类型 - public interface IProtocal + public interface IProtocal where TProtocalUnit : IProtocalFormatting { /// - /// 发送协议内容并接收,一般方法 + /// 协议的连接器 /// - /// 写入的内容,使用对象数组描述 - /// 从设备获取的字节流 - byte[] SendReceive(params object[] content); + IProtocalLinker ProtocalLinker { get; } + + /// + /// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议 + /// + /// 协议的类的GetType + /// 协议的实例 + TProtocalUnit this[Type type] { get; } + + /// + /// 协议连接开始 + /// + /// + bool Connect(); + + /// + /// 协议连接开始(异步) + /// + /// + Task ConnectAsync(); + + /// + /// 协议连接断开 + /// + /// + bool Disconnect(); /// /// 发送协议内容并接收,一般方法 /// /// 写入的内容,使用对象数组描述 /// 从设备获取的字节流 - Task SendReceiveAsync(params object[] content); + TParamOut SendReceive(params object[] content); + + /// + /// 发送协议内容并接收,一般方法 + /// + /// 写入的内容,使用对象数组描述 + /// 从设备获取的字节流 + Task SendReceiveAsync(params object[] content); /// /// 发送协议,通过传入需要使用的协议内容和输入结构 @@ -40,5 +71,23 @@ namespace Modbus.Net /// 输入信息的结构化描述 /// 输出信息的结构化描述 Task SendReceiveAsync(TProtocalUnit unit, IInputStruct content); + + /// + /// 发送协议,通过传入需要使用的协议内容和输入结构 + /// + /// 协议的实例 + /// 输入信息的结构化描述 + /// 输出信息的结构化描述 + /// IOutputStruct的具体类型 + T SendReceive(TProtocalUnit unit, IInputStruct content) where T : class, IOutputStruct; + + /// + /// 发送协议,通过传入需要使用的协议内容和输入结构 + /// + /// 协议的实例 + /// 输入信息的结构化描述 + /// 输出信息的结构化描述 + /// IOutputStruct的具体类型 + Task SendReceiveAsync(TProtocalUnit unit, IInputStruct content) where T : class, IOutputStruct; } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/IProtocalFormatting.cs b/Modbus.Net/src/Base.Common/IProtocalFormatting.cs index b9ff233..d156e00 100644 --- a/Modbus.Net/src/Base.Common/IProtocalFormatting.cs +++ b/Modbus.Net/src/Base.Common/IProtocalFormatting.cs @@ -14,6 +14,11 @@ /// 从Connector返回的数据类型 public interface IProtocalFormatting { + /// + /// 是否为小端格式 + /// + Endian Endian { get; set; } + /// /// 从输入结构格式化 /// diff --git a/Modbus.Net/src/Base.Common/IProtocalLinker.cs b/Modbus.Net/src/Base.Common/IProtocalLinker.cs index eb1091a..2dde9e8 100644 --- a/Modbus.Net/src/Base.Common/IProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/IProtocalLinker.cs @@ -9,6 +9,34 @@ namespace Modbus.Net /// 从Connector返回的数据类型 public interface IProtocalLinker { + /// + /// 通讯字符串 + /// + string ConnectionToken { get; } + + /// + /// 设备是否连接 + /// + bool IsConnected { get; } + + /// + /// 连接设备 + /// + /// 设备是否连接成功 + bool Connect(); + + /// + /// 连接设备 + /// + /// 设备是否连接成功 + Task ConnectAsync(); + + /// + /// 断开设备 + /// + /// 设备是否断开成功 + bool Disconnect(); + /// /// 发送并接收数据 /// diff --git a/Modbus.Net/src/Base.Common/ProtocalLinker.cs b/Modbus.Net/src/Base.Common/ProtocalLinker.cs index bd7accd..9c9716c 100644 --- a/Modbus.Net/src/Base.Common/ProtocalLinker.cs +++ b/Modbus.Net/src/Base.Common/ProtocalLinker.cs @@ -71,12 +71,40 @@ namespace Modbus.Net /// 基本的协议连接器 /// public abstract class ProtocalLinker : IProtocalLinker + where TParamOut : class { /// /// 传输连接器 /// protected BaseConnector BaseConnector; + /// + /// 连接设备 + /// + /// 设备是否连接成功 + public bool Connect() + { + return BaseConnector.Connect(); + } + + /// + /// 连接设备 + /// + /// 设备是否连接成功 + public async Task ConnectAsync() + { + return await BaseConnector.ConnectAsync(); + } + + /// + /// 断开设备 + /// + /// 设备是否断开成功 + public bool Disconnect() + { + return BaseConnector.Disconnect(); + } + /// /// 通讯字符串 /// @@ -106,8 +134,7 @@ namespace Modbus.Net { var extBytes = BytesExtend(content); var receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes); - if (receiveBytes != null) return receiveBytes; - throw new NullReferenceException(); + return BytesDecact(receiveBytes); } /// @@ -132,8 +159,7 @@ namespace Modbus.Net //容错处理 var checkRight = CheckRight(receiveBytes); //返回字符 - if (checkRight == true) return receiveBytes; - throw new NullReferenceException(); + return checkRight == true ? receiveBytes : null; } /// @@ -167,32 +193,5 @@ namespace Modbus.Net { throw new NotImplementedException(); } - - /// - /// 连接设备 - /// - /// 设备是否连接成功 - public bool Connect() - { - return BaseConnector.Connect(); - } - - /// - /// 连接设备 - /// - /// 设备是否连接成功 - public async Task ConnectAsync() - { - return await BaseConnector.ConnectAsync(); - } - - /// - /// 断开设备 - /// - /// 设备是否断开成功 - public bool Disconnect() - { - return BaseConnector.Disconnect(); - } } } \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/ProtocalUnit.cs b/Modbus.Net/src/Base.Common/ProtocalUnit.cs index 5360a73..c3f308c 100644 --- a/Modbus.Net/src/Base.Common/ProtocalUnit.cs +++ b/Modbus.Net/src/Base.Common/ProtocalUnit.cs @@ -71,7 +71,8 @@ namespace Modbus.Net /// /// 特殊协议单元,写入这个协议不会执行BytesExtend和BytesDecact /// - public interface ISpecialProtocalUnit + [AttributeUsage(AttributeTargets.Class, Inherited = false)] + public class SpecialProtocalUnitAttribute : Attribute { } diff --git a/README.md b/README.md index 4aacd09..1cf4274 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ Platform Supported ### Version 1.3.8 * Change Resx to app.config or appsettings.json, now you can set default params there (Not Tested) +* Change ISpecialProtocalUnit to SpecialProtocalUnitAttribute ### Version 1.4.0 * New Protocal Pipeline System (In Road) diff --git a/Samples/AnyType/Controllers/HomeController.cs b/Samples/AnyType/Controllers/HomeController.cs index ad7d7de..3216039 100644 --- a/Samples/AnyType/Controllers/HomeController.cs +++ b/Samples/AnyType/Controllers/HomeController.cs @@ -87,7 +87,7 @@ namespace AnyType.Controllers { Console.WriteLine($"ip {returnValues.MachineId} not return value"); } - }, 15000, 60000)); + }, MachineGetDataType.CommunicationTag, 15000, 60000)); } [HttpGet] diff --git a/Samples/TaskManager/Controllers/HomeController.cs b/Samples/TaskManager/Controllers/HomeController.cs index 484df23..a481007 100644 --- a/Samples/TaskManager/Controllers/HomeController.cs +++ b/Samples/TaskManager/Controllers/HomeController.cs @@ -79,7 +79,7 @@ namespace TaskManager.Controllers { Console.WriteLine($"ip {returnValues.MachineId} not return value"); } - }, 15000, 60000)); + }, MachineGetDataType.CommunicationTag, 15000, 60000)); } [HttpGet]