diff --git a/Modbus.Net/CrossLampControl.WebApi/CrossLampControl.WebApi.csproj b/Modbus.Net/CrossLampControl.WebApi/CrossLampControl.WebApi.csproj index 02aa17f..4ba0180 100644 --- a/Modbus.Net/CrossLampControl.WebApi/CrossLampControl.WebApi.csproj +++ b/Modbus.Net/CrossLampControl.WebApi/CrossLampControl.WebApi.csproj @@ -13,13 +13,15 @@ Properties CrossLampControl.WebApi CrossLampControl.WebApi - v4.5 + v4.6 false true + + true @@ -42,13 +44,13 @@ + + - - - + @@ -102,6 +104,7 @@ True ..\packages\Microsoft.AspNet.WebPages.3.2.0\lib\net45\System.Web.WebPages.Razor.dll + True ..\packages\WebGrease.1.5.2\lib\WebGrease.dll diff --git a/Modbus.Net/CrossLampControl.WebApi/Web.config b/Modbus.Net/CrossLampControl.WebApi/Web.config index 0e8ec26..a16f83e 100644 --- a/Modbus.Net/CrossLampControl.WebApi/Web.config +++ b/Modbus.Net/CrossLampControl.WebApi/Web.config @@ -1,4 +1,4 @@ - + -
+
- + - + + - - - + + + - + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + \ No newline at end of file diff --git a/Modbus.Net/ModBus.Net/AddressCombiner.cs b/Modbus.Net/ModBus.Net/AddressCombiner.cs index cfe3150..e920b6d 100644 --- a/Modbus.Net/ModBus.Net/AddressCombiner.cs +++ b/Modbus.Net/ModBus.Net/AddressCombiner.cs @@ -4,11 +4,22 @@ using System.Linq; namespace ModBus.Net { + /// + /// 地址组合器,组合后的每一组地址将只需一次向设备进行通讯 + /// public abstract class AddressCombiner { + /// + /// 组合地址 + /// + /// 需要进行组合的地址 + /// 组合完成后与设备通讯的地址 public abstract IEnumerable Combine(IEnumerable addresses); } + /// + /// 连续的地址将组合成一组,向设备进行通讯 + /// public class AddressCombinerContinus : AddressCombiner { public override IEnumerable Combine(IEnumerable addresses) diff --git a/Modbus.Net/ModBus.Net/AddressFormater.cs b/Modbus.Net/ModBus.Net/AddressFormater.cs index b7b27a3..5c64719 100644 --- a/Modbus.Net/ModBus.Net/AddressFormater.cs +++ b/Modbus.Net/ModBus.Net/AddressFormater.cs @@ -2,11 +2,23 @@ namespace ModBus.Net { + /// + /// 地址编码器 + /// public abstract class AddressFormater { + /// + /// 编码地址 + /// + /// 地址所在的数据区域 + /// 地址 + /// 编码后的地址 public abstract string FormatAddress(string area, int address); } + /// + /// 基本的地址编码器 + /// public class AddressFormaterBase : AddressFormater { public override string FormatAddress(string area, int address) diff --git a/Modbus.Net/ModBus.Net/AddressTranslator.cs b/Modbus.Net/ModBus.Net/AddressTranslator.cs index 7187021..a226892 100644 --- a/Modbus.Net/ModBus.Net/AddressTranslator.cs +++ b/Modbus.Net/ModBus.Net/AddressTranslator.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace ModBus.Net { /// - /// 数据单元翻译器 + /// 地址翻译器 /// public abstract class AddressTranslator { @@ -18,7 +18,7 @@ namespace ModBus.Net } /// - /// 基本的单元转换器 + /// 基本的地址翻译器 /// public class AddressTranslatorBase : AddressTranslator { diff --git a/Modbus.Net/ModBus.Net/AsyncHelper.cs b/Modbus.Net/ModBus.Net/AsyncHelper.cs index e08cb07..e0676ac 100644 --- a/Modbus.Net/ModBus.Net/AsyncHelper.cs +++ b/Modbus.Net/ModBus.Net/AsyncHelper.cs @@ -13,6 +13,12 @@ namespace ModBus.Net TaskContinuationOptions.None, TaskScheduler.Default); + /// + /// Run async method syncronized + /// + /// Return type + /// Async method with return + /// Return value public static TResult RunSync(Func> func) { return AsyncHelper._myTaskFactory @@ -22,6 +28,10 @@ namespace ModBus.Net .GetResult(); } + /// + /// Run async method syncronized. + /// + /// Async method public static void RunSync(Func func) { AsyncHelper._myTaskFactory @@ -31,6 +41,12 @@ namespace ModBus.Net .GetResult(); } + /// + /// Change async task to async task with cancellation token + /// + /// Async task + /// Cancellation Token + /// Task with Cancellation token public static Task WithCancellation(this Task task, CancellationToken token) { @@ -44,8 +60,8 @@ namespace ModBus.Net } } - /// AsyncLock locks across one or several await calls. - /// + /// + /// AsyncLock locks across one or several await calls. /// public class AsyncLock { @@ -58,6 +74,10 @@ namespace ModBus.Net _releaser = Task.FromResult(new Releaser(this)); } + /// + /// Lock the async method. Call like: using (await asynclock.LockAsync()) + /// + /// public Task LockAsync() { var wait = _semaphore.WaitAsync(); @@ -88,6 +108,9 @@ namespace ModBus.Net } } + /// + /// AsyncSemaphore semaphore the multi run tasks. + /// public class AsyncSemaphore { private readonly static Task _completed = Task.FromResult(true); diff --git a/Modbus.Net/ModBus.Net/BaseConnector.cs b/Modbus.Net/ModBus.Net/BaseConnector.cs index 194bb4e..a893aad 100644 --- a/Modbus.Net/ModBus.Net/BaseConnector.cs +++ b/Modbus.Net/ModBus.Net/BaseConnector.cs @@ -5,6 +5,9 @@ namespace ModBus.Net { public abstract class BaseConnector { + /// + /// 标识Connector的连接关键字 + /// public abstract string ConnectionToken { get; } /// /// 是否处于连接状态 @@ -13,41 +16,41 @@ namespace ModBus.Net /// /// 连接PLC /// - /// + /// 是否连接成功 public abstract bool Connect(); /// /// 连接PLC,异步 /// - /// /// + /// 是否连接成功 public abstract Task ConnectAsync(); /// /// 断开PLC /// - /// + /// 是否断开成功 public abstract bool Disconnect(); /// /// 无返回发送数据 /// - /// - /// + /// 需要发送的数据 + /// 是否发送成功 public abstract bool SendMsgWithoutReturn(byte[] message); /// - /// 无返回发送数据,异步 + /// 无返回发送数据 /// - /// - /// + /// 需要发送的数据 + /// 是否发送成功 public abstract Task SendMsgWithoutReturnAsync(byte[] message); /// /// 带返回发送数据 /// - /// - /// + /// 需要发送的数据 + /// 是否发送成功 public abstract byte[] SendMsg(byte[] message); /// - /// 带返回发送数据,异步 + /// 带返回发送数据 /// - /// - /// + /// 需要发送的数据 + /// 是否发送成功 public abstract Task SendMsgAsync(byte[] message); } } diff --git a/Modbus.Net/ModBus.Net/BaseMachine.cs b/Modbus.Net/ModBus.Net/BaseMachine.cs index cd10049..03539ed 100644 --- a/Modbus.Net/ModBus.Net/BaseMachine.cs +++ b/Modbus.Net/ModBus.Net/BaseMachine.cs @@ -5,84 +5,136 @@ using System.Threading.Tasks; namespace ModBus.Net { + /// + /// 向设备设置值的方式 + /// public enum MachineSetDataType { + /// + /// 地址 + /// Address, + /// + /// 通讯标识 + /// CommunicationTag } public abstract class BaseMachine : IMachineProperty { + /// + /// 设备的Id + /// public int Id { get; set; } + /// + /// 设备所在工程的名称 + /// public string ProjectName { get; set; } + /// + /// 设备的名称 + /// public string MachineName { get; set; } - public bool IsConnected - { - get - { - return BaseUtility.IsConnected; - } - } + /// + /// 是否处于连接状态 + /// + public bool IsConnected => BaseUtility.IsConnected; - public string ConnectionToken - { - get { return BaseUtility.ConnectionToken; } - } + /// + /// 标识设备的连接关键字 + /// + public string ConnectionToken => BaseUtility.ConnectionToken; + /// + /// 地址编码器 + /// public AddressFormater AddressFormater { get; set; } + /// + /// 地址解码器 + /// public AddressCombiner AddressCombiner { get; set; } + /// + /// 地址转换器 + /// public AddressTranslator AddressTranslator { get { return BaseUtility.AddressTranslator; } set { BaseUtility.AddressTranslator = value; } } - public MachineExtend MachineExtend { get; set; } - - protected IEnumerable CommunicateAddresses - { - get { return AddressCombiner.Combine(GetAddresses); } - } + /// + /// 与设备实际通讯的连续地址 + /// + protected IEnumerable CommunicateAddresses => AddressCombiner.Combine(GetAddresses); + /// + /// 描述需要与设备通讯的地址 + /// public IEnumerable GetAddresses { get; set; } + /// + /// 是否保持连接 + /// public bool KeepConnect { get; set; } + /// + /// 设备的连接器 + /// protected BaseUtility BaseUtility { get; set; } + /// + /// 构造器 + /// + /// 需要与设备通讯的地址 protected BaseMachine(IEnumerable getAddresses) : this(getAddresses, false) { } + /// + /// 构造器 + /// + /// 需要与设备通讯的地址 + /// 是否保持连接 protected BaseMachine(IEnumerable getAddresses, bool keepConnect) { GetAddresses = getAddresses; KeepConnect = keepConnect; } + /// + /// 读取数据 + /// + /// 从设备读取的数据 public Dictionary GetDatas() { return AsyncHelper.RunSync(GetDatasAsync); } + /// + /// 读取数据 + /// + /// 从设备读取的数据 public async Task> GetDatasAsync() { try { Dictionary ans = new Dictionary(); + //检测并连接设备 if (!BaseUtility.IsConnected) { await BaseUtility.ConnectAsync(); } + //如果无法连接,终止 if (!BaseUtility.IsConnected) return null; + //遍历每一个实际向设备获取数据的连续地址 foreach (var communicateAddress in CommunicateAddresses) { + //获取数据 var datas = await BaseUtility.GetDatasAsync(2, 0, @@ -91,15 +143,19 @@ namespace ModBus.Net Math.Ceiling(communicateAddress.GetCount* BigEndianValueHelper.Instance.ByteLength[ communicateAddress.DataType.FullName])); + //如果没有数据,终止 if (datas == null || datas.Length == 0) return null; int pos = 0; + //解码数据 while (pos < communicateAddress.GetCount) { + //获取地址 var address = GetAddresses.SingleOrDefault( p => p.Area == communicateAddress.Area && p.Address == pos + communicateAddress.Address); if (address != null) { + //将获取的数据和对应的通讯标识对应 ans.Add(address.CommunicationTag, new ReturnUnit { @@ -116,10 +172,12 @@ namespace ModBus.Net } } } + //如果不保持连接,断开连接 if (!KeepConnect) { BaseUtility.Disconnect(); } + //返回数据 if (ans.Count == 0) ans = null; return ans; } @@ -130,24 +188,40 @@ namespace ModBus.Net } } + /// + /// 写入数据 + /// + /// 写入类型 + /// 需要写入的数据字典,当写入类型为Address时,键为需要写入的地址,当写入类型为CommunicationTag时,键为需要写入的单元的描述 + /// 是否写入成功 public bool SetDatas(MachineSetDataType setDataType, Dictionary values) { return AsyncHelper.RunSync(() => SetDatasAsync(setDataType, values)); } + /// + /// 写入数据 + /// + /// 写入类型 + /// 需要写入的数据字典,当写入类型为Address时,键为需要写入的地址,当写入类型为CommunicationTag时,键为需要写入的单元的描述 + /// 是否写入成功 public async Task SetDatasAsync(MachineSetDataType setDataType, Dictionary values) { try { + //检测并连接设备 if (!BaseUtility.IsConnected) { await BaseUtility.ConnectAsync(); } + //如果设备无法连接,终止 if (!BaseUtility.IsConnected) return false; List addresses = new List(); + //遍历每个要设置的值 foreach (var value in values) { - AddressUnit address = null; + //根据设置类型找到对应的地址描述 + AddressUnit address = null; switch (setDataType) { case MachineSetDataType.Address: @@ -166,32 +240,44 @@ namespace ModBus.Net if (address == null) return false; addresses.Add(address); } + //将地址编码成与实际设备通讯的地址,注意这个地址必须是连续的 var communcationUnits = new AddressCombinerContinus().Combine(addresses); + //遍历每条通讯的连续地址 foreach (var communicateAddress in communcationUnits) { List datasList = new List(); + //需要设置的字节数,计数 var setCount = (int) Math.Ceiling(communicateAddress.GetCount* BigEndianValueHelper.Instance.ByteLength[ communicateAddress.DataType.FullName]); + //总数 var allBytes = setCount; + //编码开始地址 var addressStart = AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address); while (setCount > 0) { + //编码当前地址 var address = AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address + allBytes - setCount); + //找到对应的描述地址 var addressUnit = GetAddresses.SingleOrDefault( p => p.Area == communicateAddress.Area && p.Address == communicateAddress.Address + allBytes - setCount); + //如果没有相应地址,跳过 + if (addressUnit == null) continue; + //获取写入类型 Type dataType = addressUnit.DataType; switch (setDataType) { case MachineSetDataType.Address: { + //获取要写入的值 var value = values.SingleOrDefault(p => p.Key == address); + //将要写入的值加入队列 datasList.Add(Convert.ChangeType(value.Value, dataType)); break; } @@ -204,7 +290,7 @@ namespace ModBus.Net } setCount -= (int) BigEndianValueHelper.Instance.ByteLength[dataType.FullName]; } - + //写入数据 await BaseUtility.SetDatasAsync(2, 0, addressStart, datasList.ToArray()); } } @@ -216,23 +302,41 @@ namespace ModBus.Net return true; } + /// + /// 连接设备 + /// + /// 是否连接成功 public bool Connect() { return BaseUtility.Connect(); } + /// + /// 连接设备 + /// + /// 是否连接成功 public async Task ConnectAsync() { return await BaseUtility.ConnectAsync(); } + /// + /// 断开设备 + /// + /// 是否断开成功 public bool Disconnect() { return BaseUtility.Disconnect(); } + /// + /// 将获取的数据转换成可以向设备写入的数据格式 + /// + /// 获取的数据 + /// 写入的数据 public static Dictionary MapGetValuesToSetValues(Dictionary getValues) { + if (getValues == null) return null; return (from getValue in getValues select new KeyValuePair(getValue.Key, getValue.Value.PlcValue)).ToDictionary(p=>p.Key,p=>p.Value); } @@ -251,51 +355,93 @@ namespace ModBus.Net } } + /// + /// 通讯单元 + /// public class CommunicationUnit { + /// + /// 区域 + /// public string Area { get; set; } + /// + /// 地址 + /// public int Address { get; set; } + /// + /// 获取个数 + /// public int GetCount { get; set; } + /// + /// 数据类型 + /// public Type DataType { get; set; } } + /// + /// 数据单元扩展,返回数据时会同时将其返回 + /// public class UnitExtend { } - public class MachineExtend - { - - } - + /// + /// 返回的数据单元 + /// public class ReturnUnit { + /// + /// 返回的数据 + /// public double PlcValue { get; set; } + /// + /// 数据的扩展 + /// public UnitExtend UnitExtend { get; set; } } public class AddressUnit { + /// + /// 数据单元Id + /// public int Id { get; set; } /// - /// 数据所属的区域,Modbus指通讯码,PROFINET指数据块 + /// 数据所属的区域 /// public string Area { get; set; } + /// + /// 地址 + /// public int Address { get; set; } + /// + /// 数据类型 + /// public Type DataType { get; set; } /// /// 放缩比例 /// public double Zoom { get; set; } + /// + /// 小数位数 + /// public int DecimalPos { get; set; } /// /// 通讯标识名称 /// public string CommunicationTag { get; set; } + /// + /// 名称 + /// public string Name { get; set; } + /// + /// 单位 + /// public string Unit { get; set; } - + /// + /// 扩展 + /// public UnitExtend UnitExtend { get; set; } } @@ -312,11 +458,26 @@ namespace ModBus.Net } } + /// + /// 设备的抽象 + /// public interface IMachineProperty { + /// + /// Id + /// int Id { get; set; } + /// + /// 工程名 + /// string ProjectName { get; set; } + /// + /// 设备名 + /// string MachineName { get; set; } + /// + /// 标识设备的连接关键字 + /// string ConnectionToken { get; } } } diff --git a/Modbus.Net/ModBus.Net/BaseProtocal.cs b/Modbus.Net/ModBus.Net/BaseProtocal.cs index 52b092e..9001bb9 100644 --- a/Modbus.Net/ModBus.Net/BaseProtocal.cs +++ b/Modbus.Net/ModBus.Net/BaseProtocal.cs @@ -11,12 +11,13 @@ namespace ModBus.Net public abstract class BaseProtocal { /// - /// 发送数据 + /// 协议的连接器 /// - /// 需要发送的数据 - /// 数据是否正确接收 public ProtocalLinker ProtocalLinker { get; protected set; } + /// + /// 构造器 + /// protected BaseProtocal() { Protocals = new Dictionary(); @@ -25,8 +26,8 @@ namespace ModBus.Net /// /// 协议索引器,这是一个懒加载协议,当字典中不存在协议时自动加载协议,否则调用已经加载的协议 /// - /// 协议的类的名称 - /// + /// 协议的类的GetType + /// 协议的实例 public ProtocalUnit this[Type type] { get @@ -45,8 +46,15 @@ namespace ModBus.Net } } - protected Dictionary Protocals { get; private set; } + /// + /// 协议集合 + /// + protected Dictionary Protocals { get; } + /// + /// 注册一个协议 + /// + /// 需要注册的协议 protected void Register(ProtocalUnit linkProtocal) { if (linkProtocal == null) return; @@ -56,71 +64,59 @@ namespace ModBus.Net /// /// 发送协议内容并接收,一般方法 /// - /// - /// + /// 写入的内容,使用对象数组描述 + /// 从设备获取的字节流 public virtual byte[] SendReceive(params object[] content) { return AsyncHelper.RunSync(() => SendReceiveAsync(content)); } /// - /// 发送协议内容并接收,一般方法(异步) + /// 发送协议内容并接收,一般方法 /// - /// - /// + /// 写入的内容,使用对象数组描述 + /// 从设备获取的字节流 public virtual async Task SendReceiveAsync(params object[] content) { if (ProtocalLinker == null || !ProtocalLinker.IsConnected) { await ConnectAsync(); } - return await ProtocalLinker.SendReceiveAsync(ProtocalUnit.TranslateContent(content)); + if (ProtocalLinker != null) + { + return await ProtocalLinker.SendReceiveAsync(ProtocalUnit.TranslateContent(content)); + } + else + { + return null; + } } /// /// 发送协议,通过传入需要使用的协议内容和输入结构 /// - /// - /// - /// + /// 协议的实例 + /// 输入信息的结构化描述 + /// 输出信息的结构化描述 public virtual OutputStruct SendReceive(ProtocalUnit unit, InputStruct content) { - int t = 0; - //如果为特别处理协议的话,跳过协议扩展收缩 - var formatContent = unit.Format(content); - if (formatContent != null) - { - byte[] receiveContent; - if (unit is SpecialProtocalUnit) - { - receiveContent = ProtocalLinker.SendReceiveWithoutExtAndDec(formatContent); - } - else - { - receiveContent = ProtocalLinker.SendReceive(formatContent); - } - if (receiveContent != null) - { - return unit.Unformat(receiveContent, ref t); - } - } - return null; + return AsyncHelper.RunSync(() => SendReceiveAsync(unit, content)); } /// - /// 发送协议,通过传入需要使用的协议内容和输入结构(异步) + /// 发送协议,通过传入需要使用的协议内容和输入结构 /// - /// - /// - /// + /// 协议的实例 + /// 输入信息的结构化描述 + /// 输出信息的结构化描述 public virtual async Task SendReceiveAsync(ProtocalUnit unit, InputStruct content) { - int t = 0; - //如果为特别处理协议的话,跳过协议扩展收缩 + int t = 0; var formatContent = unit.Format(content); if (formatContent != null) { byte[] receiveContent; + //如果为特别处理协议的话,跳过协议扩展收缩 if (unit is SpecialProtocalUnit) { receiveContent = await ProtocalLinker.SendReceiveWithoutExtAndDecAsync(formatContent); diff --git a/Modbus.Net/ModBus.Net/BaseUtility.cs b/Modbus.Net/ModBus.Net/BaseUtility.cs index 8ba40ed..99a845b 100644 --- a/Modbus.Net/ModBus.Net/BaseUtility.cs +++ b/Modbus.Net/ModBus.Net/BaseUtility.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace ModBus.Net @@ -12,26 +13,29 @@ namespace ModBus.Net protected BaseProtocal Wrapper; protected string ConnectionString { get; set; } - public bool IsConnected - { - get - { - if (Wrapper == null || Wrapper.ProtocalLinker == null) return false; - return Wrapper.ProtocalLinker.IsConnected; - } - } + /// + /// 设备是否已经连接 + /// + public bool IsConnected => Wrapper?.ProtocalLinker != null && Wrapper.ProtocalLinker.IsConnected; - public string ConnectionToken - { - get { return Wrapper.ProtocalLinker.ConnectionToken; } - } + /// + /// 标识设备的连接关键字 + /// + public string ConnectionToken => Wrapper.ProtocalLinker.ConnectionToken; + /// + /// 地址翻译器 + /// public AddressTranslator AddressTranslator { get; set; } + /// + /// 构造器 + /// protected BaseUtility() { AddressTranslator = new AddressTranslatorBase(); } + /// /// 设置连接类型 /// @@ -44,7 +48,7 @@ namespace ModBus.Net /// 从站地址 /// 主站地址 /// 开始地址 - /// 获取类型和个数 + /// 获取字节数个数 /// 接收到的byte数据 protected virtual byte[] GetDatas(byte belongAddress, byte masterAddress, string startAddress, int getByteCount) { @@ -52,32 +56,37 @@ namespace ModBus.Net } /// - /// 获取数据(异步) + /// 获取数据 /// /// 从站地址 /// 主站地址 /// 开始地址 - /// 获取类型和个数 + /// 获取字节数个数 /// 接收到的byte数据 protected abstract Task GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, int getByteCount); + /// + /// 获取数据 + /// + /// 从站地址 + /// 主站地址 + /// 开始地址 + /// 获取类型和个数 + /// 接收到的对应的类型和数据 public virtual object[] GetDatas(byte belongAddress, byte masterAddress, string startAddress, KeyValuePair getTypeAndCount) { - try - { - string typeName = getTypeAndCount.Key.FullName; - double bCount = BigEndianValueHelper.Instance.ByteLength[typeName]; - byte[] getBytes = GetDatas(belongAddress, masterAddress, startAddress, - (int) Math.Ceiling(bCount*getTypeAndCount.Value)); - return BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCount); - } - catch (Exception) - { - return null; - } + return AsyncHelper.RunSync(() => GetDatasAsync(belongAddress, masterAddress, startAddress, getTypeAndCount)); } + /// + /// 获取数据 + /// + /// 从站地址 + /// 主站地址 + /// 开始地址 + /// 获取类型和个数 + /// 接收到的对应的类型和数据 public virtual async Task GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, KeyValuePair getTypeAndCount) { @@ -95,21 +104,30 @@ namespace ModBus.Net } } + /// + /// 获取数据 + /// + /// 需要接收的类型 + /// 从站地址 + /// 主站地址 + /// 开始地址 + /// 获取字节数个数 + /// 接收到的对应的类型和数据 public virtual T[] GetDatas(byte belongAddress, byte masterAddress, string startAddress, int getByteCount) { - try - { - var getBytes = GetDatas(belongAddress, masterAddress, startAddress, - new KeyValuePair(typeof (T), getByteCount)); - return BigEndianValueHelper.Instance.ObjectArrayToDestinationArray(getBytes); - } - catch (Exception) - { - return null; - } + return AsyncHelper.RunSync(() => GetDatasAsync(belongAddress, masterAddress, startAddress, getByteCount)); } + /// + /// 获取数据 + /// + /// 需要接收的类型 + /// 从站地址 + /// 主站地址 + /// 开始地址 + /// 获取字节数个数 + /// 接收到的对应的类型和数据 public virtual async Task GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, int getByteCount) { @@ -125,41 +143,42 @@ namespace ModBus.Net } } + /// + /// 获取数据 + /// + /// 从站地址 + /// 主站地址 + /// 开始地址 + /// 获取类型和个数的队列 + /// 获取数据的对象数组,请强制转换成相应类型 public virtual object[] GetDatas(byte belongAddress, byte masterAddress, string startAddress, IEnumerable> getTypeAndCountList) { - try - { - int bAllCount = 0; - foreach (var getTypeAndCount in getTypeAndCountList) - { - string typeName = getTypeAndCount.Key.FullName; - double bCount = BigEndianValueHelper.Instance.ByteLength[typeName]; - bAllCount += (int)Math.Ceiling(bCount * getTypeAndCount.Value); - } - byte[] getBytes = GetDatas(belongAddress, masterAddress, startAddress, bAllCount); - return BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCountList); - } - catch (Exception) - { - return null; - } + return + AsyncHelper.RunSync(() => GetDatasAsync(belongAddress, masterAddress, startAddress, getTypeAndCountList)); } + /// + /// 获取数据 + /// + /// 从站地址 + /// 主站地址 + /// 开始地址 + /// 获取类型和个数的队列 public virtual async Task GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, IEnumerable> getTypeAndCountList) { try { - int bAllCount = 0; - foreach (var getTypeAndCount in getTypeAndCountList) - { - string typeName = getTypeAndCount.Key.FullName; - double bCount = BigEndianValueHelper.Instance.ByteLength[typeName]; - bAllCount += (int)Math.Ceiling(bCount * getTypeAndCount.Value); - } + var translateTypeAndCount = getTypeAndCountList as IList> ?? + getTypeAndCountList.ToList(); + int bAllCount = ( + from getTypeAndCount in translateTypeAndCount + let typeName = getTypeAndCount.Key.FullName + let bCount = BigEndianValueHelper.Instance.ByteLength[typeName] + select (int) Math.Ceiling(bCount*getTypeAndCount.Value)).Sum(); byte[] getBytes = await GetDatasAsync(belongAddress, masterAddress, startAddress, bAllCount); - return BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCountList); + return BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, translateTypeAndCount); } catch (Exception) { @@ -181,7 +200,7 @@ namespace ModBus.Net } /// - /// 设置数据(异步) + /// 设置数据 /// /// 从站地址 /// 主站地址 @@ -207,16 +226,28 @@ namespace ModBus.Net public abstract bool SetTime(byte belongAddress, DateTime setTime); */ + /// + /// 连接设备 + /// + /// 设备是否连接成功 public bool Connect() { return Wrapper.Connect(); } + /// + /// 连接设备 + /// + /// 设备是否连接成功 public async Task ConnectAsync() { return await Wrapper.ConnectAsync(); } + /// + /// 断开设备 + /// + /// 设备是否断开成功 public bool Disconnect() { return Wrapper.Disconnect(); diff --git a/Modbus.Net/ModBus.Net/FBox/Constants.cs b/Modbus.Net/ModBus.Net/FBox/Constants.cs index 3770b42..175cad4 100644 --- a/Modbus.Net/ModBus.Net/FBox/Constants.cs +++ b/Modbus.Net/ModBus.Net/FBox/Constants.cs @@ -38,35 +38,17 @@ namespace ModBus.Net.FBox } } - public string AuthorizeEndpoint - { - get { return BaseAddress + "/connect/authorize"; } - } + public string AuthorizeEndpoint => BaseAddress + "/connect/authorize"; - public string LogoutEndpoint - { - get { return BaseAddress + "/connect/endsession"; } - } + public string LogoutEndpoint => BaseAddress + "/connect/endsession"; - public string TokenEndpoint - { - get { return BaseAddress + "/connect/token"; } - } + public string TokenEndpoint => BaseAddress + "/connect/token"; - public string UserInfoEndpoint - { - get {return BaseAddress + "/connect/userinfo"; } - } + public string UserInfoEndpoint => BaseAddress + "/connect/userinfo"; - public string IdentityTokenValidationEndpoint - { - get {return BaseAddress + "/connect/identitytokenvalidation"; } - } + public string IdentityTokenValidationEndpoint => BaseAddress + "/connect/identitytokenvalidation"; - public string TokenRevocationEndpoint - { - get {return BaseAddress + "/connect/revocation"; } - } + public string TokenRevocationEndpoint => BaseAddress + "/connect/revocation"; public string AspNetWebApiSampleApi { diff --git a/Modbus.Net/ModBus.Net/FBox/Entity.cs b/Modbus.Net/ModBus.Net/FBox/Entity.cs index a611fe5..b0d2afa 100644 --- a/Modbus.Net/ModBus.Net/FBox/Entity.cs +++ b/Modbus.Net/ModBus.Net/FBox/Entity.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace DelinRemoteControlBoxTest +namespace ModBus.Net.FBox { public class BoxGroup { diff --git a/Modbus.Net/ModBus.Net/FBox/FBoxMachine.cs b/Modbus.Net/ModBus.Net/FBox/FBoxMachine.cs index cb1a840..a73f83d 100644 --- a/Modbus.Net/ModBus.Net/FBox/FBoxMachine.cs +++ b/Modbus.Net/ModBus.Net/FBox/FBoxMachine.cs @@ -5,11 +5,12 @@ namespace ModBus.Net.FBox { public class FBoxMachine : BaseMachine { - public FBoxMachine(FBoxType fBoxType, string connectionString, string localSequence, SignalRSigninMsg msg, IEnumerable getAddresses, bool keepConnect) : base(getAddresses, keepConnect) + public FBoxMachine(FBoxType fBoxType, string connectionString, string localSequence, SignalRSigninMsg msg, + IEnumerable getAddresses, bool keepConnect) : base(getAddresses, keepConnect) { AddressFormater = new AddressFormaterFBox(); AddressCombiner = new AddressCombinerFBox(); - BaseUtility = new FBoxUtility(fBoxType, connectionString, localSequence, CommunicateAddresses, msg); + BaseUtility = new FBoxUtility(fBoxType, connectionString, localSequence, CommunicateAddresses, msg); } } } diff --git a/Modbus.Net/ModBus.Net/FBox/FBoxUtility.cs b/Modbus.Net/ModBus.Net/FBox/FBoxUtility.cs index 56e22b7..9ec0cef 100644 --- a/Modbus.Net/ModBus.Net/FBox/FBoxUtility.cs +++ b/Modbus.Net/ModBus.Net/FBox/FBoxUtility.cs @@ -66,9 +66,9 @@ namespace ModBus.Net.FBox { var readRequestFBoxInputStruct = new ReadRequestFBoxInputStruct(startAddress, (ushort)getByteCount, AddressTranslator); var readRequestSiemensOutputStruct = - (ReadRequestFBoxOutputStruct)await - Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestFBoxProtocal)], readRequestFBoxInputStruct); - return readRequestSiemensOutputStruct.GetValue; + await + Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestFBoxProtocal)], readRequestFBoxInputStruct) as ReadRequestFBoxOutputStruct; + return readRequestSiemensOutputStruct?.GetValue; } catch (Exception) { diff --git a/Modbus.Net/ModBus.Net/FBox/SignalRConnector.cs b/Modbus.Net/ModBus.Net/FBox/SignalRConnector.cs index 14fac62..1f45b6c 100644 --- a/Modbus.Net/ModBus.Net/FBox/SignalRConnector.cs +++ b/Modbus.Net/ModBus.Net/FBox/SignalRConnector.cs @@ -5,7 +5,6 @@ using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using DelinRemoteControlBoxTest; using Microsoft.AspNet.SignalR.Client; using Newtonsoft.Json; using Thinktecture.IdentityModel.Client; @@ -45,36 +44,18 @@ namespace ModBus.Net.FBox private Timer _timer; - private string MachineId - { - get - { - return ConnectionToken.Split(',')[0]; - } - } + private string MachineId => ConnectionToken.Split(',')[0]; - private string LocalSequence { - get - { - return ConnectionToken.Split(',')[1]; - } - } + private string LocalSequence => ConnectionToken.Split(',')[1]; private static readonly AsyncLock _lock = new AsyncLock(); private bool _connected; - public override bool IsConnected { get { return _connected; } } + public override bool IsConnected => _connected; private SignalRSigninMsg Msg { get; set;} private Constants _constants; - private Constants Constants - { - get - { - if (_constants == null) _constants = new Constants(); - return _constants; - } - } + private Constants Constants => _constants ?? (_constants = new Constants()); public SignalRConnector(string machineId, string localSequence, SignalRSigninMsg msg) { diff --git a/Modbus.Net/ModBus.Net/IProtocalFormatting.cs b/Modbus.Net/ModBus.Net/IProtocalFormatting.cs index 14c995d..daafd08 100644 --- a/Modbus.Net/ModBus.Net/IProtocalFormatting.cs +++ b/Modbus.Net/ModBus.Net/IProtocalFormatting.cs @@ -8,23 +8,23 @@ /// /// 从输入结构格式化 /// - /// - /// + /// 结构化的输入数据 + /// 格式化后的字节流 byte[] Format(InputStruct message); /// /// 从对象的参数数组格式化 /// - /// - /// + /// 非结构化的输入数据 + /// 格式化后的字节流 byte[] Format(params object[] message); /// /// 把仪器返回的内容填充到输出结构中 /// - /// - /// - /// + /// 返回数据的字节流 + /// 转换标记位 + /// 结构化的输出数据 OutputStruct Unformat(byte[] messageBytes, ref int pos); } } \ 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 ad06475..a48910a 100644 --- a/Modbus.Net/ModBus.Net/ModBus.Net.csproj +++ b/Modbus.Net/ModBus.Net/ModBus.Net.csproj @@ -9,8 +9,9 @@ Properties ModBus.Net ModBus.Net - v4.5 + v4.6 512 + true diff --git a/Modbus.Net/ModBus.Net/Modbus/ModbusUtility.cs b/Modbus.Net/ModBus.Net/Modbus/ModbusUtility.cs index ab712b6..1b7f983 100644 --- a/Modbus.Net/ModBus.Net/Modbus/ModbusUtility.cs +++ b/Modbus.Net/ModBus.Net/Modbus/ModbusUtility.cs @@ -69,10 +69,12 @@ namespace ModBus.Net.Modbus { try { - var inputStruct = new ReadDataModbusInputStruct(belongAddress, startAddress, getByteCount % 2 == 0 ? (ushort)(getByteCount / 2) : (ushort)(getByteCount / 2 + 1), AddressTranslator); - var outputStruct = await - Wrapper.SendReceiveAsync(Wrapper[typeof(ReadDataModbusProtocal)], inputStruct) as ReadDataModbusOutputStruct; - return outputStruct.DataValue; + var inputStruct = new ReadDataModbusInputStruct(belongAddress, startAddress, + getByteCount%2 == 0 ? (ushort) (getByteCount/2) : (ushort) (getByteCount/2 + 1), AddressTranslator); + var outputStruct = await + Wrapper.SendReceiveAsync(Wrapper[typeof (ReadDataModbusProtocal)], inputStruct) as + ReadDataModbusOutputStruct; + return outputStruct?.DataValue; } catch { @@ -84,12 +86,12 @@ namespace ModBus.Net.Modbus { try { - var inputStruct = new WriteDataModbusInputStruct(belongAddress, startAddress, setContents, AddressTranslator); + var inputStruct = new WriteDataModbusInputStruct(belongAddress, startAddress, setContents, + AddressTranslator); var outputStruct = await - Wrapper.SendReceiveAsync(Wrapper[typeof(WriteDataModbusProtocal)], inputStruct) as - WriteDataModbusOutputStruct; - if (outputStruct.WriteCount != setContents.Length) return false; - return true; + Wrapper.SendReceiveAsync(Wrapper[typeof (WriteDataModbusProtocal)], inputStruct) as + WriteDataModbusOutputStruct; + return outputStruct?.WriteCount == setContents.Length; } catch { @@ -106,7 +108,7 @@ namespace ModBus.Net.Modbus var outputStruct = Wrapper.SendReceive(Wrapper[typeof(GetSystemTimeModbusProtocal)], inputStruct) as GetSystemTimeModbusOutputStruct; - return outputStruct.Time; + return outputStruct?.Time; } catch (Exception) { @@ -122,7 +124,7 @@ namespace ModBus.Net.Modbus var outputStruct = Wrapper.SendReceive(Wrapper[typeof(SetSystemTimeModbusProtocal)], inputStruct) as SetSystemTimeModbusOutputStruct; - return outputStruct.WriteCount > 0; + return outputStruct?.WriteCount > 0; } catch (Exception) { diff --git a/Modbus.Net/ModBus.Net/ProtocalLinker.cs b/Modbus.Net/ModBus.Net/ProtocalLinker.cs index 51cf9ff..cc34f48 100644 --- a/Modbus.Net/ModBus.Net/ProtocalLinker.cs +++ b/Modbus.Net/ModBus.Net/ProtocalLinker.cs @@ -10,31 +10,35 @@ namespace ModBus.Net { protected BaseConnector _baseConnector; - public string ConnectionToken - { - get { return _baseConnector.ConnectionToken; } - } + public string ConnectionToken => _baseConnector.ConnectionToken; - public bool IsConnected - { - get - { - if (_baseConnector == null) - return false; - return _baseConnector.IsConnected; - } - } + /// + /// 设备是否连接 + /// + public bool IsConnected => _baseConnector != null && _baseConnector.IsConnected; + /// + /// 连接设备 + /// + /// 设备是否连接成功 public bool Connect() { return _baseConnector.Connect(); } + /// + /// 连接设备 + /// + /// 设备是否连接成功 public async Task ConnectAsync() { return await _baseConnector.ConnectAsync(); } - + + /// + /// 断开设备 + /// + /// 设备是否断开成功 public bool Disconnect() { return _baseConnector.Disconnect(); @@ -82,9 +86,8 @@ namespace ModBus.Net //发送数据 byte[] receiveBytes = await _baseConnector.SendMsgAsync(content); //容错处理 - if (!CheckRight(receiveBytes)) return null; + return !CheckRight(receiveBytes) ? null : receiveBytes; //返回字符 - return receiveBytes; } /// @@ -94,12 +97,9 @@ namespace ModBus.Net /// 协议是否是正确的 public virtual bool CheckRight(byte[] content) { - if (content == null) - { - Disconnect(); - return false; - } - return true; + if (content != null) return true; + Disconnect(); + return false; } /// @@ -113,7 +113,7 @@ namespace ModBus.Net ProtocalLinkerBytesExtend bytesExtend = Assembly.Load(this.GetType().Assembly.GetName().Name).CreateInstance(this.GetType().FullName + "BytesExtend") as ProtocalLinkerBytesExtend; - return bytesExtend.BytesExtend(content); + return bytesExtend?.BytesExtend(content); } /// @@ -127,7 +127,7 @@ namespace ModBus.Net ProtocalLinkerBytesExtend bytesExtend = Assembly.Load(this.GetType().Assembly.GetName().Name).CreateInstance(this.GetType().FullName + "BytesExtend") as ProtocalLinkerBytesExtend; - return bytesExtend.BytesDecact(content); + return bytesExtend?.BytesDecact(content); } } } \ No newline at end of file diff --git a/Modbus.Net/ModBus.Net/ProtocalUnit.cs b/Modbus.Net/ModBus.Net/ProtocalUnit.cs index c0205e9..2a50700 100644 --- a/Modbus.Net/ModBus.Net/ProtocalUnit.cs +++ b/Modbus.Net/ModBus.Net/ProtocalUnit.cs @@ -5,35 +5,35 @@ namespace ModBus.Net public abstract class ProtocalUnit : IProtocalFormatting { /// - /// 格式化,将输入结构转换为字节数组 + /// 从输入结构格式化 /// - /// - /// + /// 结构化的输入数据 + /// 格式化后的字节流 public abstract byte[] Format(InputStruct message); /// - /// 格式化,将对象数组转换为字节数组 + /// 从对象的参数数组格式化 /// - /// - /// + /// 非结构化的输入数据 + /// 格式化后的字节流 public virtual byte[] Format(params object[] message) { return TranslateContent(message); } /// - /// 结构化,将字节数组转换为输出结构。 + /// 把仪器返回的内容填充到输出结构中 /// - /// - /// - /// + /// 返回数据的字节流 + /// 转换标记位 + /// 结构化的输出数据 public abstract OutputStruct Unformat(byte[] messageBytes, ref int pos); /// /// 转换静态方法,把对象数组转换为字节数组。 /// - /// - /// + /// 对象数组 + /// 字节数组 public static byte[] TranslateContent(params object[] contents) { return BigEndianValueHelper.Instance.ObjectArrayToByteArray(contents); diff --git a/Modbus.Net/ModBus.Net/Siemens/SiemensTcpProtocal.cs b/Modbus.Net/ModBus.Net/Siemens/SiemensTcpProtocal.cs index ec91abd..3a1bd7a 100644 --- a/Modbus.Net/ModBus.Net/Siemens/SiemensTcpProtocal.cs +++ b/Modbus.Net/ModBus.Net/Siemens/SiemensTcpProtocal.cs @@ -4,15 +4,15 @@ namespace ModBus.Net.Siemens { public class SiemensTcpProtocal : SiemensProtocal { - private ushort _taspSrc; - private ushort _tsapDst; - private ushort _maxCalling; - private ushort _maxCalled; - private ushort _maxPdu; - private byte _tdpuSize; + private readonly ushort _taspSrc; + private readonly ushort _tsapDst; + private readonly ushort _maxCalling; + private readonly ushort _maxCalled; + private readonly ushort _maxPdu; + private readonly byte _tdpuSize; - private string _ip; - private int connectTryCount; + private readonly string _ip; + private int _connectTryCount; public SiemensTcpProtocal(byte tdpuSize, ushort tsapSrc, ushort tsapDst, ushort maxCalling, ushort maxCalled, ushort maxPdu) : this(tdpuSize, tsapSrc, tsapDst, maxCalling, maxCalled, maxPdu, ConfigurationManager.IP) { @@ -27,7 +27,7 @@ namespace ModBus.Net.Siemens _maxPdu = maxPdu; _tdpuSize = tdpuSize; _ip = ip; - connectTryCount = 0; + _connectTryCount = 0; } public override byte[] SendReceive(params object[] content) @@ -51,12 +51,9 @@ namespace ModBus.Net.Siemens public override async Task SendReceiveAsync(ProtocalUnit unit, InputStruct content) { - if (ProtocalLinker == null || !ProtocalLinker.IsConnected) - { - if (connectTryCount > 10) return null; - return await await ConnectAsync().ContinueWith(answer => answer.Result ? base.SendReceiveAsync(unit, content) : null); - } - return await base.SendReceiveAsync(unit, content); + if (ProtocalLinker != null && ProtocalLinker.IsConnected) return await base.SendReceiveAsync(unit, content); + if (_connectTryCount > 10) return null; + return await await ConnectAsync().ContinueWith(answer => answer.Result ? base.SendReceiveAsync(unit, content) : null); } private async Task ForceSendReceiveAsync(ProtocalUnit unit, InputStruct content) @@ -71,30 +68,27 @@ namespace ModBus.Net.Siemens public override async Task ConnectAsync() { - connectTryCount++; + _connectTryCount++; ProtocalLinker = new SiemensTcpProtocalLinker(_ip); - if (await ProtocalLinker.ConnectAsync()) - { - connectTryCount = 0; - var inputStruct = new CreateReferenceSiemensInputStruct(_tdpuSize, _taspSrc, _tsapDst); - return - await await - ForceSendReceiveAsync(this[typeof (CreateReferenceSiemensProtocal)], inputStruct) - .ContinueWith(async answer => - { - if (!ProtocalLinker.IsConnected) return false; - var inputStruct2 = new EstablishAssociationSiemensInputStruct(0x0101, _maxCalling, - _maxCalled, - _maxPdu); - var outputStruct2 = - (EstablishAssociationSiemensOutputStruct) - await - SendReceiveAsync(this[typeof (EstablishAssociationSiemensProtocal)], - inputStruct2); - return true; - }); - } - return false; + if (!await ProtocalLinker.ConnectAsync()) return false; + _connectTryCount = 0; + var inputStruct = new CreateReferenceSiemensInputStruct(_tdpuSize, _taspSrc, _tsapDst); + return + await await + ForceSendReceiveAsync(this[typeof (CreateReferenceSiemensProtocal)], inputStruct) + .ContinueWith(async answer => + { + if (!ProtocalLinker.IsConnected) return false; + var inputStruct2 = new EstablishAssociationSiemensInputStruct(0x0101, _maxCalling, + _maxCalled, + _maxPdu); + var outputStruct2 = + (EstablishAssociationSiemensOutputStruct) + await + SendReceiveAsync(this[typeof (EstablishAssociationSiemensProtocal)], + inputStruct2); + return outputStruct2 != null; + }); } } } diff --git a/Modbus.Net/ModBus.Net/Siemens/SiemensUtility.cs b/Modbus.Net/ModBus.Net/Siemens/SiemensUtility.cs index 84375c7..1ae9f4e 100644 --- a/Modbus.Net/ModBus.Net/Siemens/SiemensUtility.cs +++ b/Modbus.Net/ModBus.Net/Siemens/SiemensUtility.cs @@ -23,12 +23,12 @@ namespace ModBus.Net.Siemens public class SiemensUtility : BaseUtility { - private byte _tdpuSize; - private ushort _taspSrc; - private ushort _tsapDst; - private ushort _maxCalling; - private ushort _maxCalled; - private ushort _maxPdu; + private readonly byte _tdpuSize; + private readonly ushort _taspSrc; + private readonly ushort _tsapDst; + private readonly ushort _maxCalling; + private readonly ushort _maxCalled; + private readonly ushort _maxPdu; private SiemensType _siemensType; @@ -43,14 +43,14 @@ namespace ModBus.Net.Siemens _siemensType = value; switch (_siemensType) { - case SiemensType.Ppi: - { - throw new NotImplementedException(); - } - case SiemensType.Mpi: - { - throw new NotImplementedException(); - } + //case SiemensType.Ppi: + // { + // throw new NotImplementedException(); + // } + //case SiemensType.Mpi: + // { + // throw new NotImplementedException(); + // } case SiemensType.Tcp: { Wrapper = ConnectionString == null ? new SiemensTcpProtocal(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu) : new SiemensTcpProtocal(_tdpuSize, _taspSrc, _tsapDst, _maxCalling, _maxCalled, _maxPdu, ConnectionString); @@ -88,6 +88,7 @@ namespace ModBus.Net.Siemens } case SiemensMachineModel.S7_1200: case SiemensMachineModel.S7_1500: + case SiemensMachineModel.S7_200_Smart: { _tdpuSize = 0x09; _taspSrc = 0x4b54; @@ -97,6 +98,10 @@ namespace ModBus.Net.Siemens _maxPdu = 0x00f0; break; } + default: + { + throw new NotImplementedException("没有相应的西门子类型"); + } } ConnectionType = connectionType; AddressTranslator = new AddressTranslatorSiemens(); @@ -113,9 +118,10 @@ namespace ModBus.Net.Siemens { var readRequestSiemensInputStruct = new ReadRequestSiemensInputStruct(0xd3c7, SiemensTypeCode.Byte, startAddress, (ushort)getByteCount, AddressTranslator); var readRequestSiemensOutputStruct = - (ReadRequestSiemensOutputStruct) await - Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestSiemensProtocal)], readRequestSiemensInputStruct); - return readRequestSiemensOutputStruct.GetValue; + await + Wrapper.SendReceiveAsync(Wrapper[typeof (ReadRequestSiemensProtocal)], + readRequestSiemensInputStruct) as ReadRequestSiemensOutputStruct; + return readRequestSiemensOutputStruct?.GetValue; } catch (Exception) { @@ -129,12 +135,10 @@ namespace ModBus.Net.Siemens { var writeRequestSiemensInputStruct = new WriteRequestSiemensInputStruct(0xd3c8, startAddress, setContents, AddressTranslator); var writeRequestSiemensOutputStruct = - (WriteRequestSiemensOutputStruct) await - Wrapper.SendReceiveAsync(Wrapper[typeof(WriteRequestSiemensProtocal)], writeRequestSiemensInputStruct); - if (writeRequestSiemensOutputStruct.AccessResult == SiemensAccessResult.NoError) - return true; - else - return false; + await + Wrapper.SendReceiveAsync(Wrapper[typeof (WriteRequestSiemensProtocal)], + writeRequestSiemensInputStruct) as WriteRequestSiemensOutputStruct; + return writeRequestSiemensOutputStruct?.AccessResult == SiemensAccessResult.NoError; } catch (Exception) { diff --git a/Modbus.Net/ModBus.Net/TaskManager.cs b/Modbus.Net/ModBus.Net/TaskManager.cs index ccf84fa..0014275 100644 --- a/Modbus.Net/ModBus.Net/TaskManager.cs +++ b/Modbus.Net/ModBus.Net/TaskManager.cs @@ -174,7 +174,7 @@ namespace ModBus.Net /// private HashSet _unlinkedMachines; //private TaskFactory> _tasks; - private TaskScheduler _scheduler; + //private TaskScheduler _scheduler; //private CancellationTokenSource _cts; /// @@ -186,6 +186,9 @@ namespace ModBus.Net /// private Timer _timer2; + /// + /// 保持连接 + /// private bool _keepConnect; /// @@ -208,10 +211,20 @@ namespace ModBus.Net } } + /// + /// 返回数据代理 + /// + /// public delegate void ReturnValuesDelegate(KeyValuePair> returnValue); + /// + /// 返回数据事件 + /// public event ReturnValuesDelegate ReturnValues; + /// + /// 获取间隔 + /// private int _getCycle; /// @@ -345,13 +358,17 @@ namespace ModBus.Net } } + /// + /// 将设备指定为未连接 + /// + /// 设备的id public void MoveMachineToUnlinked(int id) { IEnumerable machines; lock(_machines) { machines = _machines.Where(c => c.Id == id).ToList(); - if (machines.Count() <= 0) return; + if (!machines.Any()) return; _machines.RemoveWhere(p => p.Id == id); } lock(_unlinkedMachines) @@ -363,13 +380,17 @@ namespace ModBus.Net } } + /// + /// 将设备指定为已连接 + /// + /// 设备的id public void MoveMachineToLinked(int id) { IEnumerable machines; lock (_unlinkedMachines) { machines = _unlinkedMachines.Where(c => c.Id == id).ToList(); - if (machines.Count() <= 0) return; + if (!machines.Any()) return; _unlinkedMachines.RemoveWhere(p => p.Id == id); } lock (_machines) @@ -397,20 +418,32 @@ namespace ModBus.Net } } + /// + /// 已连接设备更新 + /// + /// private void MaintainTasks(object sender) { AsyncHelper.RunSync(MaintainTasksAsync); } + /// + /// 未连接设备更新 + /// + /// private void MaintainTasks2(object sender) { AsyncHelper.RunSync(MaintainTasks2Async); } + /// + /// 已连接设备更新 + /// + /// private async Task MaintainTasksAsync() { HashSet saveMachines = new HashSet(); - IEnumerable saveMachinesEnum = new List(); + IEnumerable saveMachinesEnum; lock (_machines) { saveMachines.UnionWith(_machines); @@ -422,6 +455,10 @@ namespace ModBus.Net } } + /// + /// 未连接设备更新 + /// + /// private async Task MaintainTasks2Async() { HashSet saveMachines = new HashSet(); @@ -444,18 +481,28 @@ namespace ModBus.Net } } - public async Task SetDatasAsync(string machineToken, MachineSetDataType setDataType, + /// + /// 设置数据 + /// + /// 设备的连接标识 + /// 设置类型 + /// 需要设置的数据 + /// 是否设置成功 + public async Task SetDatasAsync(string connectionToken, MachineSetDataType setDataType, Dictionary values) { BaseMachine machine = null; lock (_machines) { - machine = _machines.FirstOrDefault(p => p.ConnectionToken == machineToken); + machine = _machines.FirstOrDefault(p => p.ConnectionToken == connectionToken); } if (machine == null) return false; return await machine.SetDatasAsync(setDataType, values); } + /// + /// 启动TaskManager + /// public void TaskStart() { TaskStop(); @@ -464,6 +511,9 @@ namespace ModBus.Net GetCycle = TimeRestore.Restore; } + /// + /// 停止TaskManager + /// public void TaskStop() { lock (_machines) @@ -484,6 +534,11 @@ namespace ModBus.Net } } + /// + /// 执行对具体设备的数据更新 + /// + /// 设备的实例 + /// private async Task RunTask(BaseMachine machine) { try @@ -504,10 +559,7 @@ namespace ModBus.Net { MoveMachineToLinked(machine.Id); } - if (ReturnValues != null) - { - ReturnValues(new KeyValuePair>(machine.Id, ans)); - } + ReturnValues?.Invoke(new KeyValuePair>(machine.Id, ans)); } catch (Exception e) { @@ -515,10 +567,7 @@ namespace ModBus.Net { MoveMachineToUnlinked(machine.Id); } - if (ReturnValues != null) - { - ReturnValues(new KeyValuePair>(machine.Id, null)); - } + ReturnValues?.Invoke(new KeyValuePair>(machine.Id, null)); } } } diff --git a/Modbus.Net/ModBus.Net/TcpConnector.cs b/Modbus.Net/ModBus.Net/TcpConnector.cs index 917487e..478cad5 100644 --- a/Modbus.Net/ModBus.Net/TcpConnector.cs +++ b/Modbus.Net/ModBus.Net/TcpConnector.cs @@ -25,7 +25,7 @@ namespace ModBus.Net /// public class TcpConnector : BaseConnector, IDisposable { - public override string ConnectionToken { get { return _host; } } + public override string ConnectionToken => _host; private readonly string _host; @@ -60,13 +60,7 @@ namespace ModBus.Net TimeoutTime = timeoutTime; } - public override bool IsConnected - { - get - { - return _socketClient != null && _socketClient.Client != null && _socketClient.Connected; - } - } + public override bool IsConnected => _socketClient?.Client != null && _socketClient.Connected; public void Dispose() { diff --git a/Modbus.Net/ModBus.Net/ValueHelper.cs b/Modbus.Net/ModBus.Net/ValueHelper.cs index 15c75dd..720fe22 100644 --- a/Modbus.Net/ModBus.Net/ValueHelper.cs +++ b/Modbus.Net/ModBus.Net/ValueHelper.cs @@ -33,10 +33,7 @@ namespace ModBus.Net /// /// 协议中的内容构造是否小端的,默认是小端构造协议。 /// - public static bool LittleEndian - { - get { return true; } - } + public static bool LittleEndian => true; #region Factory @@ -45,17 +42,7 @@ namespace ModBus.Net /// /// ValueHelper单例的实例 /// - public static ValueHelper Instance - { - get - { - if (_Instance == null) - { - _Instance = new ValueHelper(); - } - return _Instance; - } - } + public static ValueHelper Instance => _Instance ?? (_Instance = new ValueHelper()); #endregion @@ -705,22 +692,9 @@ namespace ModBus.Net } - protected new bool LittleEndian - { - get { return false; } - } + protected new bool LittleEndian => false; - public new static BigEndianValueHelper Instance - { - get - { - if (_BigEndianInstance == null) - { - _BigEndianInstance = new BigEndianValueHelper(); - } - return _BigEndianInstance; - } - } + public new static BigEndianValueHelper Instance => _BigEndianInstance ?? (_BigEndianInstance = new BigEndianValueHelper()); public override Byte[] GetBytes(short value) { diff --git a/Modbus.Net/NA200H.UI.Console/App.config b/Modbus.Net/NA200H.UI.Console/App.config index 8e15646..2d2a12d 100644 --- a/Modbus.Net/NA200H.UI.Console/App.config +++ b/Modbus.Net/NA200H.UI.Console/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/Modbus.Net/NA200H.UI.Console/NA200H.UI.ConsoleApp.csproj b/Modbus.Net/NA200H.UI.Console/NA200H.UI.ConsoleApp.csproj index 7c88f3e..19435c2 100644 --- a/Modbus.Net/NA200H.UI.Console/NA200H.UI.ConsoleApp.csproj +++ b/Modbus.Net/NA200H.UI.Console/NA200H.UI.ConsoleApp.csproj @@ -9,8 +9,9 @@ Properties NA200H.UI.ConsoleApp NA200H.UI.ConsoleApp - v4.5 + v4.6 512 + AnyCPU diff --git a/Modbus.Net/NA200H.UI.Console/Program.cs b/Modbus.Net/NA200H.UI.Console/Program.cs index ce89941..91866d7 100644 --- a/Modbus.Net/NA200H.UI.Console/Program.cs +++ b/Modbus.Net/NA200H.UI.Console/Program.cs @@ -6,6 +6,8 @@ using System.Text; using System.Threading.Tasks; using ModBus.Net; using System.Reflection; +using ModBus.Net.Modbus; +using ModBus.Net.Siemens; namespace NA200H.UI.ConsoleApp { @@ -52,9 +54,9 @@ namespace NA200H.UI.ConsoleApp } Console.WriteLine(); Console.Read(); - Console.Read();*/ + Console.Read(); - /* + //调用方法二:自动构造 //第一步:先生成一个输入结构体,然后向这个结构体中填写数据 AddressTranslator addressTranslator = new AddressTranslatorNA200H(); @@ -119,7 +121,8 @@ namespace NA200H.UI.ConsoleApp Console.Read(); */ - /*BaseProtocal wrapper = new SiemensTcpProtocal(0x09, 0x1001, 0x1000, 0x0001, 0x0001, 0x03c0, ip); + /* + BaseProtocal wrapper = new SiemensTcpProtocal(0x09, 0x1001, 0x1000, 0x0001, 0x0001, 0x03c0, ip); if (!wrapper.ProtocalLinker.IsConnected) return; AddressTranslator addressTranslator = new AddressTranslatorSiemens(); diff --git a/Modbus.Net/NA200H.UI.WPF/App.config b/Modbus.Net/NA200H.UI.WPF/App.config index 8e15646..2d2a12d 100644 --- a/Modbus.Net/NA200H.UI.WPF/App.config +++ b/Modbus.Net/NA200H.UI.WPF/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/Modbus.Net/NA200H.UI.WPF/NA200H.UI.WPF.csproj b/Modbus.Net/NA200H.UI.WPF/NA200H.UI.WPF.csproj index 6642d11..008528e 100644 --- a/Modbus.Net/NA200H.UI.WPF/NA200H.UI.WPF.csproj +++ b/Modbus.Net/NA200H.UI.WPF/NA200H.UI.WPF.csproj @@ -9,10 +9,11 @@ Properties NA200H.UI.WPF NA200H.UI.WPF - v4.5 + v4.6 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 + AnyCPU diff --git a/Modbus.Net/NA200H.UI.WPF/Properties/Resources.Designer.cs b/Modbus.Net/NA200H.UI.WPF/Properties/Resources.Designer.cs index b26df0d..76bb4b5 100644 --- a/Modbus.Net/NA200H.UI.WPF/Properties/Resources.Designer.cs +++ b/Modbus.Net/NA200H.UI.WPF/Properties/Resources.Designer.cs @@ -1,17 +1,17 @@ //------------------------------------------------------------------------------ // // 此代码由工具生成。 -// 运行时版本: 4.0.30319.34014 +// 运行时版本:4.0.30319.42000 // // 对此文件的更改可能会导致不正确的行为,并且如果 -// 重新生成代码,这些更改将丢失。 +// 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ -namespace NA200H.UI.WPF.Properties -{ - - +namespace NA200H.UI.WPF.Properties { + using System; + + /// /// 一个强类型的资源类,用于查找本地化的字符串等。 /// @@ -22,48 +22,40 @@ namespace NA200H.UI.WPF.Properties [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources - { - + internal class Resources { + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() - { + internal Resources() { } - + /// - /// 返回此类使用的、缓存的 ResourceManager 实例。 + /// 返回此类使用的缓存的 ResourceManager 实例。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager - { - get - { - if ((resourceMan == null)) - { + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NA200H.UI.WPF.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } - + /// - /// 为所有资源查找重写当前线程的 CurrentUICulture 属性, - /// 方法是使用此强类型资源类。 + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture - { - get - { + internal static global::System.Globalization.CultureInfo Culture { + get { return resourceCulture; } - set - { + set { resourceCulture = value; } } diff --git a/Modbus.Net/NA200H.UI.WPF/Properties/Settings.Designer.cs b/Modbus.Net/NA200H.UI.WPF/Properties/Settings.Designer.cs index 08fde99..6510746 100644 --- a/Modbus.Net/NA200H.UI.WPF/Properties/Settings.Designer.cs +++ b/Modbus.Net/NA200H.UI.WPF/Properties/Settings.Designer.cs @@ -1,28 +1,24 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.34014 +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ -namespace NA200H.UI.WPF.Properties -{ - - +namespace NA200H.UI.WPF.Properties { + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default - { - get - { + + public static Settings Default { + get { return defaultInstance; } } diff --git a/Modbus.Net/Simense_S7_200.UI.WPF.TaskTest/App.config b/Modbus.Net/Simense_S7_200.UI.WPF.TaskTest/App.config index d0feca6..2d2a12d 100644 --- a/Modbus.Net/Simense_S7_200.UI.WPF.TaskTest/App.config +++ b/Modbus.Net/Simense_S7_200.UI.WPF.TaskTest/App.config @@ -1,6 +1,6 @@ - + diff --git a/Modbus.Net/Simense_S7_200.UI.WPF.TaskTest/MainWindow.xaml.cs b/Modbus.Net/Simense_S7_200.UI.WPF.TaskTest/MainWindow.xaml.cs index df88767..d7c3509 100644 --- a/Modbus.Net/Simense_S7_200.UI.WPF.TaskTest/MainWindow.xaml.cs +++ b/Modbus.Net/Simense_S7_200.UI.WPF.TaskTest/MainWindow.xaml.cs @@ -30,13 +30,13 @@ namespace Siemens_S7_200.UI.WPF.TaskTest //增加需要通信的PLC地址 List addressUnits = new List { - new AddressUnit() {Id = 0, Area = "V", Address = 0, CommunicationTag = "D1", DataType = typeof (ushort), Zoom = 1}, - new AddressUnit() {Id = 1, Area = "V", Address = 2, CommunicationTag = "D2", DataType = typeof (float), Zoom = 1} + new AddressUnit() {Id = 0, Area = "V", Address = 1, CommunicationTag = "D1", DataType = typeof (ushort), Zoom = 1}, + new AddressUnit() {Id = 1, Area = "V", Address = 3, CommunicationTag = "D2", DataType = typeof (float), Zoom = 1} }; //初始化任务管理器 TaskManager task = new TaskManager(300, true); //向任务管理器中添加设备 - task.AddMachine(new SiemensMachine(SiemensType.Tcp, "192.168.3.191",SiemensMachineModel.S7_200, addressUnits, + task.AddMachine(new SiemensMachine(SiemensType.Tcp, "192.168.3.11",SiemensMachineModel.S7_300, addressUnits, true)); //增加值返回时的处理函数 task.ReturnValues += (returnValues) => @@ -45,12 +45,12 @@ namespace Siemens_S7_200.UI.WPF.TaskTest value = new List(); if (returnValues.Value != null) { - value = from val in returnValues.Value select val.Key + val.Value; + value = from val in returnValues.Value select val.Key + " " + val.Value.PlcValue; siemensItems.Dispatcher.Invoke(() => siemensItems.ItemsSource = value); } else { - Console.WriteLine(String.Format("ip {0} not return value", returnValues.Key)); + Console.WriteLine($"ip {returnValues.Key} not return value"); } }; //启动任务 diff --git a/Modbus.Net/Simense_S7_200.UI.WPF.TaskTest/Siemens_S7_200.UI.WPF.TaskTest.csproj b/Modbus.Net/Simense_S7_200.UI.WPF.TaskTest/Siemens_S7_200.UI.WPF.TaskTest.csproj index 21f0766..91ae5fe 100644 --- a/Modbus.Net/Simense_S7_200.UI.WPF.TaskTest/Siemens_S7_200.UI.WPF.TaskTest.csproj +++ b/Modbus.Net/Simense_S7_200.UI.WPF.TaskTest/Siemens_S7_200.UI.WPF.TaskTest.csproj @@ -9,7 +9,7 @@ Properties Siemens_S7_200.UI.WPF.TaskTest Siemens_S7_200.UI.WPF.TaskTest - v4.5.1 + v4.6 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 diff --git a/README.md b/README.md index 9f47449..12d244f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Table of Content: * Siemens Tcp protocal (acturally it is the same as Profinet) * All communications can be asyncronized. * A task manager that you can easily manage multiple connections. -* .net 4.5 and Visual Studio 2013 support (In the future, it will be upgraded to .net 4.6 and Visual Studio 2015) +* .net framework 4.6 and Visual Studio 2015 support. ## Usage