diff --git a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj index 70037fd..911a4ef 100644 --- a/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj +++ b/Modbus.Net/Modbus.Net.Core/Modbus.Net.Core.csproj @@ -5,7 +5,7 @@ Modbus.Net Modbus.Net Modbus.Net.Core - 1.3.1 + 1.3.2 Modbus.Net Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. @@ -20,6 +20,10 @@ True + + bin\Debug\netstandard1.3\Modbus.Net.xml + + @@ -42,6 +46,8 @@ + + diff --git a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj index 1fee670..76b0b4f 100644 --- a/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj +++ b/Modbus.Net/Modbus.Net.Modbus/Modbus.Net.Modbus.csproj @@ -5,7 +5,7 @@ Modbus.Net.Modbus Modbus.Net.Modbus Modbus.Net.Modbus - 1.3.1 + 1.3.2 Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. Modbus.Net.Modbus @@ -19,6 +19,10 @@ True + + bin\Debug\net45\Modbus.Net.Modbus.xml + + diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs index 2e2c23a..eba6b3c 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusUtility.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; namespace Modbus.Net.Modbus { @@ -26,7 +27,7 @@ namespace Modbus.Net.Modbus /// /// Modbus基础Api入口 /// - public class ModbusUtility : BaseUtility + public class ModbusUtility : BaseUtility, IUtilityTime { /// /// Modbus协议类型 @@ -168,19 +169,18 @@ namespace Modbus.Net.Modbus } } - /* /// /// 读时间 /// /// 设备的时间 - public override DateTime GetTime() + public async Task GetTimeAsync() { try { var inputStruct = new GetSystemTimeModbusInputStruct(SlaveAddress); var outputStruct = - Wrapper.SendReceive(Wrapper[typeof(GetSystemTimeModbusProtocal)], inputStruct); - return outputStruct?.Time; + await Wrapper.SendReceiveAsync(Wrapper[typeof(GetSystemTimeModbusProtocal)], inputStruct); + return outputStruct?.Time ?? DateTime.MinValue; } catch (Exception) { @@ -193,13 +193,13 @@ namespace Modbus.Net.Modbus /// /// 需要写入的时间 /// 写入是否成功 - public override bool SetTime(DateTime setTime) + public async Task SetTimeAsync(DateTime setTime) { try { var inputStruct = new SetSystemTimeModbusInputStruct(SlaveAddress, setTime); var outputStruct = - Wrapper.SendReceive(Wrapper[typeof(SetSystemTimeModbusProtocal)], inputStruct); + await Wrapper.SendReceiveAsync(Wrapper[typeof(SetSystemTimeModbusProtocal)], inputStruct); return outputStruct?.WriteCount > 0; } catch (Exception) @@ -207,6 +207,5 @@ namespace Modbus.Net.Modbus return false; } } - */ } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj index 743be02..e208dc5 100644 --- a/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj +++ b/Modbus.Net/Modbus.Net.OPC/Modbus.Net.OPC.csproj @@ -5,7 +5,7 @@ Modbus.Net.OPC Modbus.Net.OPC Modbus.Net.OPC - 1.3.1 + 1.3.2 Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. Modbus.Net OPC Implementation @@ -19,6 +19,10 @@ True + + bin\Debug\net45\Modbus.Net.OPC.xml + + diff --git a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj index 2caf351..197f12f 100644 --- a/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj +++ b/Modbus.Net/Modbus.Net.Siemens/Modbus.Net.Siemens.csproj @@ -5,7 +5,7 @@ Modbus.Net.Siemens Modbus.Net.Siemens Modbus.Net.Siemens - 1.3.1 + 1.3.2 Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. Modbus.Net Siemens Profinet Implementation @@ -18,6 +18,10 @@ True + + bin\Debug\net45\Modbus.Net.Siemens.xml + + diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs index 622422f..84cab37 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensUtility.cs @@ -140,10 +140,10 @@ namespace Modbus.Net.Siemens break; } //MPI - //case SiemensType.Mpi: - // { - // throw new NotImplementedException(); - // } + case SiemensType.Mpi: + { + throw new NotImplementedException(); + } //Ethenet case SiemensType.Tcp: { @@ -216,17 +216,5 @@ namespace Modbus.Net.Siemens return false; } } - - /* - public override DateTime GetTime(byte slaveAddress) - { - throw new NotImplementedException(); - } - - public override bool SetTime(byte slaveAddress, DateTime setTime) - { - throw new NotImplementedException(); - } - */ } } \ 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 9579579..5487e41 100644 --- a/Modbus.Net/Modbus.Net/Modbus.Net.csproj +++ b/Modbus.Net/Modbus.Net/Modbus.Net.csproj @@ -5,7 +5,7 @@ Modbus.Net Modbus.Net Modbus.Net - 1.3.1 + 1.3.2 Modbus.Net Chris L.(Luo Sheng) Hangzhou Delian IoT Science Technology Co.,Ltd. @@ -19,6 +19,10 @@ True + + bin\Debug\net45\Modbus.Net.xml + + @@ -41,6 +45,8 @@ + + diff --git a/Modbus.Net/src/Base.Common/BaseMachine.cs b/Modbus.Net/src/Base.Common/BaseMachine.cs index d8f0d76..f3c5ec2 100644 --- a/Modbus.Net/src/Base.Common/BaseMachine.cs +++ b/Modbus.Net/src/Base.Common/BaseMachine.cs @@ -1,10 +1,37 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Threading.Tasks; namespace Modbus.Net { + /// + /// 读写设备值的方式 + /// + public enum MachineDataType + { + /// + /// 地址 + /// + Address, + + /// + /// 通讯标识 + /// + CommunicationTag, + + /// + /// 名称 + /// + Name, + + /// + /// Id + /// + Id + } + /// /// 获取设备值的方式 /// @@ -74,7 +101,7 @@ namespace Modbus.Net } } - public abstract class BaseMachine : IMachineProperty where TKey : IEquatable + public abstract class BaseMachine : IMachineData, IMachineProperty where TKey : IEquatable where TUnitKey : IEquatable { private readonly int _maxErrorCount = 3; @@ -535,6 +562,11 @@ namespace Modbus.Net return true; } + /// + /// 通过Id获取数据字段定义 + /// + /// 数据字段Id + /// 数据字段 public AddressUnit GetAddressUnitById(TUnitKey addressUnitId) { try @@ -548,6 +580,60 @@ namespace Modbus.Net } } + /// + /// 调用Utility中的方法 + /// + /// Utility实现的接口名称 + /// 返回值的类型 + /// 方法的名称 + /// 方法的参数 + /// + public TReturnType InvokeUtilityMethod(string methodName, + params object[] parameters) where TUtilityMethod : IUtilityMethod + { + if (BaseUtility is TUtilityMethod) + { + Type t = typeof(TUtilityMethod); + object returnValue = t.GetMethod(methodName, + BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public) + .Invoke(BaseUtility, parameters); + return (TReturnType) returnValue; + } + throw new InvalidCastException($"Utility未实现{typeof(TUtilityMethod).Name}的接口"); + } + + /// + /// 调用Machine中的方法 + /// + /// Machine实现的接口名称 + /// 返回值的类型 + /// 方法的名称 + /// 方法的参数 + /// + public TReturnType InvokeMachineMethod(string methodName, + params object[] parameters) where TMachineMethod : IMachineMethod + { + if (this is TMachineMethod) + { + Type t = typeof(TMachineMethod); + object returnValue = t.GetMethod(methodName, + BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public) + .Invoke(this, parameters); + return (TReturnType) returnValue; + } + throw new InvalidCastException($"Machine未实现{typeof(TMachineMethod).Name}的接口"); + } + + /// + /// 获取Utility + /// + /// Utility实现的接口名称 + /// + public TUtilityMethod GetUtility() where TUtilityMethod : class, IUtilityMethod + { + return BaseUtility as TUtilityMethod; + } + /// /// 连接设备 /// diff --git a/Modbus.Net/src/Base.Common/BaseUtility.cs b/Modbus.Net/src/Base.Common/BaseUtility.cs index fc26997..a88228e 100644 --- a/Modbus.Net/src/Base.Common/BaseUtility.cs +++ b/Modbus.Net/src/Base.Common/BaseUtility.cs @@ -17,7 +17,7 @@ namespace Modbus.Net /// /// 基础Api入口 /// - public abstract class BaseUtility + public abstract class BaseUtility : IUtilityData { /// /// 协议收发主体 @@ -215,21 +215,6 @@ namespace Modbus.Net /// 是否设置成功 public abstract Task SetDatasAsync(string startAddress, object[] setContents); - /* - /// - /// 获取PLC时间 - /// - /// PLC时间 - public abstract DateTime GetTime(); - - /// - /// 设置PLC时间 - /// - /// 设置PLC时间 - /// 设置是否成功 - public abstract bool SetTime(DateTime setTime); - */ - /// /// 连接设备 /// diff --git a/Modbus.Net/src/Base.Common/IMachineMethod.cs b/Modbus.Net/src/Base.Common/IMachineMethod.cs new file mode 100644 index 0000000..cac1f19 --- /dev/null +++ b/Modbus.Net/src/Base.Common/IMachineMethod.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Modbus.Net +{ + public interface IMachineMethod + { + + } + + /// + /// Machineݶдӿ + /// + public interface IMachineData : IMachineMethod + { + /// + /// ȡ + /// + /// 豸ȡ + Dictionary GetDatas(MachineGetDataType getDataType); + + /// + /// ȡ + /// + /// 豸ȡ + Task> GetDatasAsync(MachineGetDataType getDataType); + + /// + /// д + /// + /// д + /// Ҫдֵ䣬дΪAddressʱΪҪдĵַдΪCommunicationTagʱΪҪдĵԪ + /// Ƿдɹ + bool SetDatas(MachineSetDataType setDataType, Dictionary values); + + /// + /// д + /// + /// д + /// Ҫдֵ䣬дΪAddressʱΪҪдĵַдΪCommunicationTagʱΪҪдĵԪ + /// Ƿдɹ + Task SetDatasAsync(MachineSetDataType setDataType, Dictionary values); + } +} \ No newline at end of file diff --git a/Modbus.Net/src/Base.Common/IUtilityMethod.cs b/Modbus.Net/src/Base.Common/IUtilityMethod.cs new file mode 100644 index 0000000..8e6bca3 --- /dev/null +++ b/Modbus.Net/src/Base.Common/IUtilityMethod.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Modbus.Net +{ + public interface IUtilityMethod + { + + } + + /// + /// Utility的数据读写接口 + /// + public interface IUtilityData : IUtilityMethod + { + /// + /// 获取数据 + /// + /// 开始地址 + /// 获取字节数个数 + /// 接收到的byte数据 + Task GetDatasAsync(string startAddress, int getByteCount); + + /// + /// 获取数据 + /// + /// 开始地址 + /// 获取类型和个数 + /// 接收到的对应的类型和数据 + object[] GetDatas(string startAddress, KeyValuePair getTypeAndCount); + + /// + /// 获取数据 + /// + /// 开始地址 + /// 获取类型和个数 + /// 接收到的对应的类型和数据 + Task GetDatasAsync(string startAddress, KeyValuePair getTypeAndCount); + + /// + /// 获取数据 + /// + /// 需要接收的类型 + /// 开始地址 + /// 获取字节数个数 + /// 接收到的对应的类型和数据 + T[] GetDatas(string startAddress, int getByteCount); + + /// + /// 获取数据 + /// + /// 需要接收的类型 + /// 开始地址 + /// 获取字节数个数 + /// 接收到的对应的类型和数据 + Task GetDatasAsync(string startAddress, int getByteCount); + + /// + /// 获取数据 + /// + /// 开始地址 + /// 获取类型和个数的队列 + /// 获取数据的对象数组,请强制转换成相应类型 + object[] GetDatas(string startAddress, IEnumerable> getTypeAndCountList); + + /// GetEndian + /// 获取数据 + /// + /// 开始地址 + /// 获取类型和个数的队列 + Task GetDatasAsync(string startAddress, IEnumerable> getTypeAndCountList); + + /// + /// 设置数据 + /// + /// 开始地址 + /// 设置数据 + /// 是否设置成功 + bool SetDatas(string startAddress, object[] setContents); + + /// + /// 设置数据 + /// + /// 开始地址 + /// 设置数据 + /// 是否设置成功 + Task SetDatasAsync(string startAddress, object[] setContents); + } + + /// + /// Utility的时间读写接口 + /// + public interface IUtilityTime : IUtilityMethod + { + + /// + /// 获取PLC时间 + /// + /// PLC时间 + Task GetTimeAsync(); + + /// + /// 设置PLC时间 + /// + /// 设置PLC时间 + /// 设置是否成功 + Task SetTimeAsync(DateTime setTime); + + } +} diff --git a/Modbus.Net/src/Base.Common/TaskManager.cs b/Modbus.Net/src/Base.Common/TaskManager.cs index 8f42dae..387ff71 100644 --- a/Modbus.Net/src/Base.Common/TaskManager.cs +++ b/Modbus.Net/src/Base.Common/TaskManager.cs @@ -11,17 +11,6 @@ using System.Threading.Tasks; namespace Modbus.Net { - /// - /// 设备的读写方式 - /// - public enum MachineDataType - { - Address, - CommunicationTag, - Name, - Id - } - /// /// 返回结果的定义类 /// diff --git a/Tests/Modbus.Net.Tests/MachineUtilityMethodTest.cs b/Tests/Modbus.Net.Tests/MachineUtilityMethodTest.cs new file mode 100644 index 0000000..ebfadb2 --- /dev/null +++ b/Tests/Modbus.Net.Tests/MachineUtilityMethodTest.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Modbus.Net.Modbus; + +namespace Modbus.Net.Tests +{ + [TestClass] + public class MachineUtilityMethodTest + { + [TestMethod] + public void GetUtility() + { + BaseMachine baseMachine = new ModbusMachine(ModbusType.Tcp, "192.168.3.12", null, true, 2, 0); + var utility = baseMachine.GetUtility(); + var methods = utility.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "GetTimeAsync") != null, true); + Assert.AreEqual(methods.FirstOrDefault(method => method.Name == "SetTimeAsync") != null, true); + } + + [TestMethod] + public async Task InvokeUtility() + { + BaseMachine baseMachine = new ModbusMachine(ModbusType.Tcp, "192.168.3.12", null, true, 2, 0); + var success = baseMachine.InvokeUtilityMethod>("SetTimeAsync", DateTime.Now); + Assert.AreEqual(await success, true); + var time = baseMachine.InvokeUtilityMethod>("GetTimeAsync"); + Assert.AreEqual(((await time).ToUniversalTime() - DateTime.Now.ToUniversalTime()).Seconds < 10, true); + } + + [TestMethod] + public async Task InvokeMachine() + { + BaseMachine baseMachine = new ModbusMachine(ModbusType.Tcp, "192.168.3.12", new List> + { + new AddressUnit + { + Id = 0, + Area = "0X", + Address = 1, + SubAddress = 0, + CommunicationTag = "A1", + DataType = typeof(bool) + } + }, true, 2, 0); + var success = baseMachine.InvokeMachineMethod>("SetDatasAsync", + MachineSetDataType.Address, + new Dictionary + { + { + "0X 1.0", 1 + } + }); + Assert.AreEqual(await success, true); + var datas = baseMachine.InvokeMachineMethod>>("GetDatasAsync", MachineGetDataType.Address); + Assert.AreEqual((await datas)["0X 1.0"], 1); + } + } +} diff --git a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj index 41c27bb..022c561 100644 --- a/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj +++ b/Tests/Modbus.Net.Tests/Modbus.Net.Tests.csproj @@ -57,6 +57,7 @@ +